【问题标题】:Creating Terrain Map with SRTM HGT File使用 SRTM HGT 文件创建地形图
【发布时间】:2018-06-05 04:52:20
【问题描述】:

我正在开发一个 iOS 应用程序。我在哪里显示某个区域的高程和地形图。我已经设法从here 下载了应用内的.hgt 文件。

到目前为止,我能够从 hgt 文件中提取高程。现在我还必须显示该区域的地形图。我一直在搜索它,我认为我无法在 iOS 应用程序中直接使用 hgt 文件创建地形图。我必须使用 GRASS GIS、SRTM2OSM 或 TileMill 来创建地形图,然后在应用程序中使用它。

请任何人指导我在这里可以做什么以及如何进行。

编辑:

我已要求不要为此使用任何类型的地图。所以基本上我必须使用核心绘图来创建地图,我对此一无所知。

没有文字的类似这样的:

【问题讨论】:

  • 请添加一个您希望它的外观示例。
  • 所以如果我理解这就是你需要做的:你有 hgt 文件,你需要从它创建一个位图(UIImage),并将它放置在某个区域的真实地图上。正确的?高度图到位图的转换既简单又有趣。你需要知道最终结果应该是什么样子。请用一些示例图片更新您的问题。
  • @JurajAntas 仅此而已。位图或图形。我想要这样的trails.com/images/topo/topo_sample2.jpg 没有文字,只是显示海拔的线条。主要问题是我们不能使用任何类型的地图来显示这一点。所以我们必须用核心绘图来绘制所有这些,我不知道该怎么做。

标签: ios swift terrain srtm hgt


【解决方案1】:

使用 iOS,您可以通过 MapKit 框架访问地图,以直接从您的应用界面显示地图或卫星图像,您还可以通过 Google Maps SDK 使用适用于 iOS 的 Google 地图,但两者(iOS 地图和 Google 地图)都不能没有地形级别。

所以为了避免重新创建已经存在的东西,你可以看看OpenStreetMaps frameworks,在这里你可以找到许多可用的框架,其中一个叫做MapBox,你可以下载最新的源代码和示例here

正如您可以从 wiki 页面中看到的,我们还有地形级别:

我认为这是一个非常有用的库,已更新并与 swift 4 一起使用,here 你可以找到一个简单的教程来开始:

import Mapbox
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let mapView = MGLMapView(frame: view.bounds)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        mapView.setCenter(CLLocationCoordinate2D(latitude: 40.74699, longitude: -73.98742), zoomLevel: 9, animated: false)
        view.addSubview(mapView)
        // to show the terrain level 
        mapView.styleURL = MGLStyle.outdoorsStyleURL()
    }
}

【讨论】:

  • 您好,我知道我可以使用 Mapkit 和其他应用程序(如 TileMill 或 MapBox Studio)来创建地图。但我要求不要使用任何类型的地图。
  • 嗨,伙计,在这种情况下,您可以找到一个很好的教程来更好地了解如何从手写地图(瓷砖)开始。看看this guide。如果您需要其他帮助,可以问我。
  • 感谢您的参考。我在这里使用非常有限的选项。很抱歉在解释情况时如此笨拙。我不能透露应用程序背后的想法。此应用程序将在无法访问 Internet 的区域运行,并且客户已严格要求不要使用任何类型的地图。所以基本上我只剩下核心绘图来绘制图像并应用阴影和阴影来创建类似的东西。这超出了我的小脑袋:(
  • 不客气。还可以查看this 文章,也许可以有趣地解决您在离线地图方面的问题。本教程也有它的github页面here
【解决方案2】:

我必须使用核心绘图来创建地图

  • 您可以从 SRTM HGT 文件中绘制地图对象[1]

  • 用于从 SRTM HGT 文件中读取插值高度 [2]

  • 下面是使用 .cpp 文件的代码,您可以了解如何从 SRTM 中绘制它[3]

#include "generator/srtm_parser.hpp"

#include "coding/endianness.hpp"
#include "coding/zip_reader.hpp"

#include "base/logging.hpp"

#include <iomanip>
#include <sstream>

namespace generator
{
namespace
{
size_t constexpr kArcSecondsInDegree = 60 * 60;
size_t constexpr kSrtmTileSize = (kArcSecondsInDegree + 1) * (kArcSecondsInDegree + 1) * 2;

struct UnzipMemDelegate : public ZipFileReader::Delegate
{
  UnzipMemDelegate(std::string & buffer) : m_buffer(buffer), m_completed(false) {}

  // ZipFileReader::Delegate overrides:
  void OnBlockUnzipped(size_t size, char const * data) override { m_buffer.append(data, size); }

  void OnStarted() override
  {
    m_buffer.clear();
    m_completed = false;
  }

  void OnCompleted() override { m_completed = true; }

  std::string & m_buffer;
  bool m_completed;
};
}  // namespace

// SrtmTile ----------------------------------------------------------------------------------------
SrtmTile::SrtmTile()
{
  Invalidate();
}

SrtmTile::SrtmTile(SrtmTile && rhs) : m_data(move(rhs.m_data)), m_valid(rhs.m_valid)
{
  rhs.Invalidate();
}

void SrtmTile::Init(std::string const & dir, ms::LatLon const & coord)
{
  Invalidate();

  std::string const base = GetBase(coord);
  std::string const cont = dir + base + ".SRTMGL1.hgt.zip";
  std::string file = base + ".hgt";

  UnzipMemDelegate delegate(m_data);
  try
  {
    ZipFileReader::UnzipFile(cont, file, delegate);
  }
  catch (ZipFileReader::LocateZipException const & e)
  {
    // Sometimes packed file has different name. See N39E051 measure.
    file = base + ".SRTMGL1.hgt";

    ZipFileReader::UnzipFile(cont, file, delegate);
  }

  if (!delegate.m_completed)
  {
    LOG(LWARNING, ("Can't decompress SRTM file:", cont));
    Invalidate();
    return;
  }

  if (m_data.size() != kSrtmTileSize)
  {
    LOG(LWARNING, ("Bad decompressed SRTM file size:", cont, m_data.size()));
    Invalidate();
    return;
  }

  m_valid = true;
}

feature::TAltitude SrtmTile::GetHeight(ms::LatLon const & coord)
{
  if (!IsValid())
    return feature::kInvalidAltitude;

  double ln = coord.lon - static_cast<int>(coord.lon);
  if (ln < 0)
    ln += 1;
  double lt = coord.lat - static_cast<int>(coord.lat);
  if (lt < 0)
    lt += 1;
  lt = 1 - lt;  // from North to South

  size_t const row = kArcSecondsInDegree * lt;
  size_t const col = kArcSecondsInDegree * ln;

  size_t const ix = row * (kArcSecondsInDegree + 1) + col;

  if (ix >= Size())
    return feature::kInvalidAltitude;
  return ReverseByteOrder(Data()[ix]);
}

std::string SrtmTile::GetBase(ms::LatLon coord)
{
  std::ostringstream ss;
  if (coord.lat < 0)
  {
    ss << "S";
    coord.lat *= -1;
    coord.lat += 1;
  }
  else
  {
    ss << "N";
  }
  ss << std::setw(2) << std::setfill('0') << static_cast<int>(coord.lat);

  if (coord.lon < 0)
  {
    ss << "W";
    coord.lon *= -1;
    coord.lon += 1;
  }
  else
  {
    ss << "E";
  }
  ss << std::setw(3) << static_cast<int>(coord.lon);
  return ss.str();
}

void SrtmTile::Invalidate()
{
  m_data.clear();
  m_data.shrink_to_fit();
  m_valid = false;
}

// SrtmTileManager ---------------------------------------------------------------------------------
SrtmTileManager::SrtmTileManager(std::string const & dir) : m_dir(dir) {}
feature::TAltitude SrtmTileManager::GetHeight(ms::LatLon const & coord)
{
  std::string const base = SrtmTile::GetBase(coord);
  auto it = m_tiles.find(base);
  if (it == m_tiles.end())
  {
    SrtmTile tile;
    try
    {
      tile.Init(m_dir, coord);
    }
    catch (RootException const & e)
    {
      LOG(LINFO, ("Can't init SRTM tile:", base, "reason:", e.Msg()));
    }

    // It's OK to store even invalid tiles and return invalid height
    // for them later.
    it = m_tiles.emplace(base, std::move(tile)).first;
  }

  return it->second.GetHeight(coord);
}
}  // namespace generator

【讨论】:

    猜你喜欢
    • 2011-10-04
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多