12

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

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

我应该如何:

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

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

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

我应该如何:

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

前任。呈现为显示地图的 TIGER 数据:
替代文字

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

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

4

11 回答 11

24

首先,我建议您使用2008 TIGER 文件

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

如果你想从较低的级别开始

解析

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

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

渲染

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

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

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

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

存储和结构

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

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

平铺

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

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

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

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

但是,您可能想玩更高的级别。

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

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

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

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

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

兴趣点搜索。 这个很有趣——你需要找到当前位置,以及一定距离内的所有兴趣点(不是 TIGER 的一部分,自己制作或获取其他来源)(如乌鸦飞过,或更难的驾驶距离)的起源。这很有趣,因为您必须将 POI 数据库转换为在这种情况下易于搜索的格式。您不能花时间遍历数百万个条目,进行距离计算 (sqrt(x^2 + y^2)),然后返回结果。您需要有一些方法或算法来首先减少数据量。

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

您可以在此处找到许多项目的链接以及有关此主题的信息来源。

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

-亚当

于 2009-01-28T15:59:21.760 回答
14

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

于 2008-10-21T17:44:44.490 回答
7

解决方案是:

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

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

网上有很多使用这个解决方案的例子

于 2009-01-27T09:45:47.317 回答
5

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

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

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

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

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

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

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

于 2009-01-30T05:54:20.680 回答
2

为了在本地存储 Tiger 数据,我会选择带有postgis工具的Postgresql 。

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

您需要查看与 postgis 交互的工具,很可能是某种地图服务器

来自http://postgis.refracions.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,但这将在桌面环境中使用。

于 2009-01-28T08:16:47.853 回答
2

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

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

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

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

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

于 2009-01-29T17:55:51.660 回答
1

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

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

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

于 2008-10-21T18:30:35.973 回答
1

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

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

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

我编写了一个 .net 版本,它可以使用 c# 中的普通 GDI+ 绘制矢量数据(例如 shp 文件中的几何图形)。这很有趣。

原因是我们需要处理具有大量附加信息的不同版本的几何图形和属性,因此我们无法使用商业地图组件或开源地图组件。

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

于 2008-10-25T16:37:32.090 回答
1

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

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

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

于 2009-01-28T16:29:30.077 回答
1

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

这就是 1979 年对我有用的方法。

我的每度英里数的来源。

于 2009-01-28T23:53:02.973 回答
0

一种解决方案是使用 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”作为水印,但在其他情况下它完全可用

于 2009-01-27T10:30:47.663 回答