【问题标题】:What is the best way to read, represent and render map data?读取、表示和渲染地图数据的最佳方式是什么?
【发布时间】:2010-09-18 08:57:39
【问题描述】:

我有兴趣将一个简单的导航应用程序编写为一个宠物项目。在搜索了免费的地图数据后,我选择了US Census Bureau TIGER 2007 Line/Shapefile 地图数据。数据被分成各个县的 zip 文件,我已经下载了我所在地区的单个县地图数据。

将此地图数据读入可用格式的最佳方法是什么?

我应该怎么做:

  • 读入这些文件
  • 解析它们 - 正则表达式或一些已经可以解析这些 Shapefile 的库?
  • 将数据加载到我的应用程序中 - 我应该将点直接加载到内存中的某些数据结构中吗?使用小型数据库?一旦您关闭地图数据的应用程序,我就不需要持久性。用户可以再次加载 Shapefile。

读取 Shapefile 数据后,渲染地图的最佳方式是什么?

理想情况下,我希望能够读取县地图数据 shapefile 并将所有折线渲染到屏幕上并允许旋转和缩放。

我应该怎么做:

  • 将纬度/经度点转换为屏幕坐标? - 据我所知,Shapefile 使用经度和纬度作为其点。所以很明显,我将不得不以某种方式将这些转换为屏幕坐标以显示地图功能。
  • 以我可以轻松旋转和缩放整个地图的方式渲染地图数据(道路、边界等的一系列折线)?
  • 将我的整个地图渲染为一系列“图块”,以便仅渲染查看区域内的要素/线?

例如。 TIGER 数据呈现为显示地图:

任何对我阅读这些文件的最佳方式、我应该如何在我的程序中表示它们(数据库、内存数据结构)以及我应该如何渲染(旋转/缩放)有一定经验和洞察力的人屏幕上的地图数据将不胜感激。

编辑:澄清一下,我不想使用任何 Google 或 Yahoo 地图 API。同样,我不想使用 OpenStreetMap。我正在寻找一种比使用那些 api/程序更从头开始的方法。这将是一个桌面应用程序。

【问题讨论】:

  • 好的,已经两年了。应用在哪里?

标签: java .net graphics rendering maps


【解决方案1】:

虽然您已经决定使用 TIGER 数据,但您可能对OSM (Open Street Map) 感兴趣,因为 OSM 已完整导入其中的 TIGER 数据,并包含用户贡献的数据。如果您坚持使用 TIGER 格式,您的应用程序对国际用户将毫无用处,而使用 OSM,您可以立即获得 TIGER 和其他所有内容。

OSM 是一个开放项目,具有协作编辑的免费世界地图。您可以获取所有这些数据以及结构化的 XML,或者查询一个区域,或者将整个世界下载到一个大文件中。

有一些适用于 OSM 的地图渲染器可用于各种编程语言,其中大部分是开源的,但仍有许多工作要做。

还有一个OSM routing service 可用。它有一个 Web 界面,也可以通过 Web 服务 API 进行查询。再说一遍,这还没有结束。用户绝对可以使用基于此构建的桌面或移动路由应用程序。

即使您不决定参与该项目,您也可以从中获得很多灵感。只需查看project wiki 以及所涉及的各种软件项目的来源(您可以在 wiki 中找到指向它们的链接)。

【讨论】:

    【解决方案2】:

    有趣的问题。这是我的做法。

    我以任何格式收集我需要的任何几何图形。我一直在从 USGS 提取数据,所以这相当于一堆:

    然后我编写了一个程序,将这些形状定义“编译”成一种可以高效渲染的形式。这意味着进行有效显示数据所需的任何投影和数据格式转换。一些细节:

    • 对于 2D 应用程序,您可以使用所需的任何投影:Map Projections
    • 对于 3D,您希望将这些纬度/经度转换为 3D 坐标。下面是一些关于如何做到这一点的数学:transformation from spherical coordinates to normal rectangular coordinates
    • 将所有基元分解为四叉树/八叉树 (2D/3D)。此树中的叶节点包含对与该叶节点(轴对齐)边界框相交的所有几何图形的引用。 (这意味着一个几何图形可以被多次引用。)
    • 然后将几何图形拆分为顶点表和绘图命令表。这是 OpenGL 的理想格式。可以使用顶点缓冲区 (Vertex Buffer Objects) 通过glDrawArrays 发出命令。
    • 一般访问者模式用于遍历四叉树/八叉树。行走涉及测试访问者是否与树的给定节点相交,直到遇到叶节点。访问者包括:绘图、碰撞检测和选择。 (因为树叶可能包含对几何图形的重复引用,所以walker 将节点标记为已访问并在此后忽略它们。在进行下一次遍历之前,必须重置或以其他方式更新这些标记。)
    • 使用空间分区系统(其中一棵树)和高效的绘图表示对于实现高帧率至关重要。我发现在这些类型的应用程序中,您希望帧速率尽可能高,至少为 20 fps。更不用说大量性能将为您提供很多机会来创建更好看的地图。 (我的远非好看,但总有一天会到达那里。)
    • 空间分区通过减少发送到处理器的绘制命令的数量来提高渲染性能。但是,有时用户实际上想要查看整个数据集(可能是 arial 视图)。在这种情况下,您需要一个详细程度的控制系统。由于我的应用程序涉及街道,因此我优先考虑高速公路和较大的道路。我的绘图代码知道在我的帧速率下降之前我可以绘制多少个图元。基元也按此优先级排序。我只绘制了第一个 x 项目,其中 x 是我可以在所需帧速率下绘制的基元数。

    剩下的就是你想要显示的任何数据的相机控制和动画。

    以下是我现有实现的一些示例:

    Picture http://seabusmap.com/assets/Picture%205.pngPicture http://seabusmap.com/assets/Picture%207.png

    【讨论】:

    • “使用空间分区系统(其中一棵树)和绘图效率高的表示”你能详细说明吗?我曾经尝试使用 openglto 渲染一个非常大的数据集(欧盟的所有道路),但我被困在某个地方,因为在我看来,我需要将所有行简化为更简单的行。
    • @Simucal 这个问题很有趣,因为处理数据的最佳方式完全取决于您对最终应用程序的期望。是 3D 显示器还是 2D 显示器?您是否使用高度图显示地理数据?查看器是否需要缩小以包含整个数据集?很多问题...
    • @Jonke 空间分区用于限制您需要处理的数量 - 对于绘图,这是视图体积裁剪。现在,如果用户尝试使用/查看整个数据集,则必须施加某种形式的 LOD 控制。
    • @Frank Krueger,2d,没有高度图。想想道路/边界数据的最基本绘图(包括缩放/缩放和旋转)。我一次最多加载几个县,所以在任何给定时间都没有太多数据。
    • @Simucal,那么,听从我的建议。 ;-) 这可能看起来有点矫枉过正,但我​​发现你的地图绘制代码值得你进行每一次优化。有关更多信息,请参阅游戏编程文献。
    【解决方案3】:

    当我给出这个答案时,问题被标记为

    “在 .Net 中用折线渲染 Shapefile(地图数据)的最佳方式是什么?”

    现在这是一个不同的问题,但我将我的答案留在原来的问题上。

    我写了一个可以画画的.net版本 矢量数据(例如来自 一个 shp 文件)在 c# 中使用普通的 GDI+。它 很有趣。

    原因是我们需要 处理不同版本的 几何和属性很多 额外的信息,所以我们可以 不使用商业地图组件或 一个开源的。

    这样做的主要内容是 建立视口和 转换/转换 WGIS84 坐标 到一个缩小和 GDI+ x,y 坐标并等待投影 如果您甚至需要重新投影。

    【讨论】:

      【解决方案4】:

      对墨卡托投影或其他投影的一种简化是假设纬度和经度的转换因子不变。将纬度乘以 69.172 英里;对于经度,选择地图区域的中纬度并将(180 经度)乘以余弦(middle_latitude)*69.172。转换为英里后,您可以使用另一组转换来获取屏幕坐标。

      这就是 1979 年对我有用的东西。

      My source for the number of miles per degree.

      【讨论】:

        【解决方案5】:

        首先,我建议您使用2008 TIGER files

        其次,正如其他人指出的那样,现在有很多项目已经读入、解释、转换和使用数据。不过,为这些数据构建自己的解析器几乎是微不足道的,所以没有理由去检查另一个项目的代码并尝试提取你需要的东西,除非你打算将他们的项目作为一个整体来使用。

        如果你想从底层开始

        解析

        构建您自己的 TIGER 解析器(相当简单 - 只是一个线段数据库),并在此之上构建一个简单的渲染(线条、多边形、字母/名称)也将相当容易。您需要查看渲染阶段的各种map projection types。最常用(因此也是用户最熟悉的)是Mercator projection - 它相当简单和快速。您可能想要支持其他预测。

        这将在查看如何投影地图以及如何反转该投影方面提供一些“乐趣”(例如,用户单击地图,您想查看他们单击的纬度/经度 - 需要反转当前投影方程)。

        渲染

        当我开发我的渲染器时,我决定将我的窗口建立在固定大小(嵌入式设备)和固定放大率上。这意味着我可以将地图以纬度/经度居中,并且中心像素=中心纬度/经度在给定的放大倍率下,并且给定墨卡托投影,我可以计算哪个像素代表每个纬度/经度,反之亦然。

        有些程序允许窗口变化,而不是使用放大率和一个固定点,它们使用两个固定点(通常是定义窗口的矩形的左上角和右下角)。在这种情况下,确定像素到纬度/经度的传输变得微不足道——这只是一些插值计算。旋转和缩放使这个传递函数稍微复杂一些,但不应该如此复杂——它仍然是一个带插值的矩形窗口,但窗口角不需要相对于北方处于任何特定方向。这增加了一些极端情况(例如,您可以将地图翻过来并像从地球内部一样查看它),但这些并不繁琐,并且可以在您处理它时进行处理。

        一旦完成经纬度到像素的转换,渲染线条和多边形就相当简单了,除了正常的图形问题(例如线条边缘或多边形重叠不当、抗锯齿等)。但是像许多开源渲染器那样渲染一个基本的丑陋地图是相当简单的。

        您还可以玩距离和大圆计算 - 例如,一个很好的经验法则是赤道上的每一度纬度或经度大约为 111.1 公里 - 但当您靠近任一度数时,就会发生变化杆,而另一个继续保持在 111.1kM。

        存储和结构

        但是,您如何存储和引用数据在很大程度上取决于您打算如何处理这些数据。如果您想对人口统计和路由使用相同的数据库结构,则会出现很多难题 - 给定的数据库结构和索引对于一个来说会很快,而对另一个来说会很慢。

        使用邮政编码并仅加载附近的邮政编码适用于小型地图渲染项目,但如果您需要穿越全国的路线,则需要不同的结构。一些实现具有“覆盖”数据库,其中仅包含主要道路并将路线捕捉到覆盖(或通过多个覆盖 - 本地、地铁、县、州、国家)。这会导致快速但有时效率低下的路由。

        平铺

        平铺地图实际上并不容易。在较低的放大倍率下,您可以渲染整个地图并将其切割。在更高的放大倍率下,您无法一次渲染整个事物(由于内存/空间限制),因此您必须将其切片。

        在图块边界处切割线,以便您可以渲染单个图块,但结果并不完美 - 通常所做的是将线渲染到图块边界之外(或者,至少保留线端的数据,尽管渲染一旦发现它从边缘掉下来就停止) - 这减少了线条在穿过瓷砖时看起来不太匹配而发生的错误。

        当你解决这个问题时,你会明白我在说什么。

        找到进入给定图块的数据也并非易事 - 一条线的两端可能在给定图块之外,但会穿过该图块。您需要查阅有关此的图形书籍(Michael Abrash's book is the seminal reference,现在可在前面的链接中免费获得)。虽然它主要谈论游戏,但窗口、裁剪、多边形边缘、碰撞等都适用于此。

        不过,您可能想玩更高级别的游戏。

        完成上述工作后(通过调整现有项目,或自己完成上述工作),您可能想要使用其他场景和算法。

        反向地理编码相当容易。输入纬度/经度(或点击地图)并获取最近的地址。这将教您如何沿 TIGER 数据中的线段解释地址。

        基本的地理编码是一个难题。 编写地址解析器是一个有用且有趣的项目,然后使用 TIGER 数据将其转换为纬度/经度并非易事,但非常有趣.从需要精确的名称和格式匹配开始,然后开始研究“like”匹配和语音匹配。在这方面有很多研究 - 在这里查看搜索引擎项目以获得一些帮助。

        找到两点之间的最短路径是一个非常重要的问题。有很多很多算法可以做到这一点,其中大多数已获得专利。我建议如果您尝试使用您自己设计的简单算法,然后进行一些研究并将您的设计与最先进的技术进行比较。如果你喜欢图论,那会很有趣。

        循序渐进并先发制人并不像乍一看那么容易。给定一组带有相关纬度/经度对数组的指令,使用外部输入(GPS 或模拟 GPS)“跟随”路线,并开发一种算法,在用户接近每个真实交叉口时为用户提供指令。请注意,由于弯曲的道路等,纬度/经度对多于说明,您需要检测行进方向等。在您尝试实施之前,您不会看到很多极端情况。

        兴趣点搜索。这个很有趣 - 您需要在一个原点的一定距离(如乌鸦飞行,或更难的驾驶距离)。这很有趣,因为您必须将 POI 数据库转换为在这种情况下易于搜索的格式。您不能花时间遍历数百万个条目,进行距离计算 (sqrt(x^2 + y^2)),然后返回结果。你需要有一些方法或算法首先减少数据量。

        旅行推销员。 多个目的地的路线。只是常规路由的更难版本。

        您可以在here这个主题上找到许多项目和信息来源的链接。

        祝你好运,无论你做什么,无论多么简陋或丑陋,都请发表,让其他人受益!

        -亚当

        【讨论】:

        • 哇,这是一个很好的答案。感谢您的努力。
        【解决方案6】:

        如果您不介意为解决方案付费,Safe Software 会生成一个名为 FME 的产品。该工具将帮助您将数据从任何格式转换为几乎任何其他格式。包括 Google Earth 格式的 KML 或将其呈现为 JPEG(或一系列 JPEG)。转换数据后,您可以使用他们的API 将 google earth 嵌入到您的应用程序中,或者只显示平铺图像。

        另一方面,FME 是一个非常强大的平台,因此在进行翻译时,您可以添加或删除您不一定需要的部分数据。如果您有多个来源,请合并来源。转换坐标(我不记得谷歌地球到底使用了什么)。将备份存储在数据库中。但说真的,如果你愿意花几块钱,你应该考虑一下。

        您还可以创建包含位置(放置位置)和有关该位置的其他数据/cmets 的标志(很像您的示例地图)。这些旗帜有多种形状和大小。

        【讨论】:

          【解决方案7】:

          为了在本地存储 Tiger 数据,我会选择 Postgresqlpostgis 工具。

          他们拥有令人印象深刻的工具集合,尤其是 Tiger Geocoder 为您提供了导入和使用老虎数据的好方法。

          你需要看看与 postgis 交互的工具,很可能是某种mapserver

          来自http://postgis.refractions.net/documentation/

          现在有几个开源工具可以与 PostGIS 一起使用。 uDig 项目正在开发一个可以直接使用 PostGIS 的完整读/写桌面环境。对于互联网制图,明尼苏达大学地图服务器可以使用 PostGIS 作为数据源。 GeoTools Java GIS 工具包支持 PostGIS,GeoServer Web Feature Server 也是如此。 GRASS 支持将 PostGIS 作为数据源。 JUMP Java 桌面 GIS 查看器有一个简单的插件用于读取 PostGIS 数据,QGIS 桌面有很好的 PostGIS 支持。 PostGIS 数据可以使用 OGR C++ 库和命令行工具(当然还有捆绑的 Shape 文件转储器)导出为多种输出 GIS 格式。当然,任何可以与 PostgreSQL 一起使用的语言都可以与 PostGIS 一起使用——列表包括 Perl、PHP、Python、TCL、C、C++、Java、C# 等等。

          编辑:尽管地图服务器的名称中有 SERVER 一词,但它可以在桌面环境中使用。

          【讨论】:

            【解决方案8】:

            一种解决方案是使用 MapXtreme。他们有用于 Java 和 C# 的 API。 API 能够加载这些文件并呈现它们。

            对于 Java:

            http://www.mapinfo.com/products/developer-tools/desktop%2c-mobile-%26-internet-offering/mapxtreme-java

            对于 .NET:

            http://www.mapinfo.com/products/developer-tools/desktop%2c-mobile-%26-internet-offering/mapxtreme-2008

            我在桌面应用程序中使用了这个解决方案,效果很好。它提供的不仅仅是渲染信息。

            现在从头开始可能需要相当长的时间。他们确实有一个您可以下载的评估版。我认为它只是在地图上打印“MAPXTREME”作为水印,但其他情况下它完全可用

            【讨论】:

              【解决方案9】:

              解决办法是:

              • 地理空间服务器,例如 mapserver、geoserver、degree(开源)。

              他们可以读取和提供 shapefile(以及许多其他东西)。例如,geoserver(安装后)提供来自美国人口普查局 TIGER shapefile 的数据作为演示

              • 一个像openlayers这样的javascript制图库(参见link text的例子

              网络上有很多使用此解决方案的示例

              【讨论】:

              • 我应该指出这将是一个桌面应用程序。这对您的回复有何影响?
              • 这些“服务器”中的大多数都可以在本地运行,并且确实可以使用一些参数来运行以吐出您需要的图像然后退出。尽管如此,要让多个软件像这样协同工作还需要做更多的工作。
              【解决方案10】:

              您还可以使用 Microsoft 的可视地球地图应用程序和 api 或使用 Google 的 api。我一直使用 ESRI 产品进行商业编程,并没有过多地使用开放 api。

              另外,您可能想看看 Maker!和查找器!它们是相对较新的程序,但我认为它们是免费的。可能受限于嵌入数据。Maker 可以在这里找到。

              问题是空间处理在非商业规模上是相当新的。

              【讨论】:

                【解决方案11】:

                SharpMap 是用于 WinForms 和 ASP.NET 的开源 .NET 2.0 映射引擎。这可能会提供您需要的所有功能。它处理最常见的 GIS 矢量和栅格数据格式,包括 ESRI shapefile。

                【讨论】:

                • SharpMap 很棒,但如果你使用来自 ex a shp/dbf 的未修改数据集,如果你有一个非常大的数据集,你可能会遇到性能问题。
                猜你喜欢
                • 1970-01-01
                • 2022-01-22
                • 2010-09-24
                • 1970-01-01
                • 2012-06-20
                • 2011-08-05
                • 1970-01-01
                • 2021-12-29
                • 1970-01-01
                相关资源
                最近更新 更多