使用SRTM HGT文件创建地形图

ios swift terrain srtm hgt

845 观看

2回复

1249 作者的声誉

我正在开发iOS应用程序。在此处显示某个区域的高程和地形图。我已经设法从此处下载app中的.hgt文件。

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

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

编辑:

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

像这样的没有文字的东西:

在此处输入图片说明

作者: superGokuN 的来源 发布者: 2017 年 12 月 22 日

回应 (2)


13

25545 作者的声誉

决定

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

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

正如您可以从Wiki页面读取的那样,我们还具有地形级别: 在此处输入图片说明

我认为这是一个非常有用的库,已更新并使用swift 4进行操作,在这里您可以找到一个简单的教程开始:

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()
    }
}
作者: Alessandro Ornano 发布者: 28.12.2017 09:33

0

8061 作者的声誉

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

  • 您可以从SRTM HGT文件[1]绘制Map对象。

  • 用于从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
作者: 5377037 发布者: 05.01.2018 01:53
32x32