使用SRTM HGT文件创建地形图

时间:2017-12-22 14:29:39

标签: ios swift terrain srtm hgt

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

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

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

编辑:

我已经要求不要使用任何类型的地图。所以基本上我必须使用核心绘图创建地图,我不知道它。

像这样没有文字的东西:

enter image description here

2 个答案:

答案 0 :(得分:13)

使用iOS,您可以通过MapKit框架访问地图,直接在应用的界面中显示地图或卫星图像,您也可以通过Google Maps SDK用于iOS版Google地图,但两者都可以使用iOS地图和谷歌地图)没有地形级别。

因此,为了避免重新创建已存在的内容,您可以查看OpenStreetMaps frameworks,在这里您可以找到许多可用的框架,其中一个称为MapBox,您可以下载最新来源和示例here

正如您可以从维基页面阅读的那样,我们还有地形级别: enter image description here

我认为这是一个非常有用的库,更新并使用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()
    }
}

答案 1 :(得分:0)

  

我必须使用核心绘图

创建地图
  • 您可以从SRTM HGT文件中绘制一个Map对象 [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