我有兴趣将一个简单的导航应用程序编写为宠物项目.在搜索免费地图数据后,我已经确定了美国人口普查局TIGER 2007 Line/Shapefile地图数据.数据被分成各个县的zip文件,我已经为我的区域下载了一个县的地图数据.
将这个地图数据读入可用格式的最佳方法是什么?
我应该怎么做:
读入这些文件
解析它们 - 正则表达式或某些已经可以解析这些Shapefile的库?
将数据加载到我的应用程序中 - 我应该将这些点直接加载到内存中的某些数据结构中吗?使用小型数据库?关闭地图数据的应用程序后,我不需要持久性.用户可以再次加载Shapefile.
在读完Shapefile数据后,渲染地图的最佳方法是什么?
理想情况下,我希望能够读取县地图数据shapefile并将所有多边形线渲染到屏幕上并允许旋转和缩放.
我应该怎么做:
将lat/lon点转换为屏幕坐标? - 据我所知,Shapefile使用经度和纬度作为其点.显然,我将不得不以某种方式将这些转换为屏幕坐标以显示地图功能.
以我可以轻松旋转和缩放整个地图的方式渲染地图数据(道路,边界等一系列折线)?
将整个地图渲染为一系列"图块",以便仅呈现查看区域内的要素/线条?
防爆.作为显示地图呈现的TIGER数据:
任何有经验和洞察我最好的方式阅读这些文件的人,我应该如何在我的程序中表示它们(数据库,内存数据结构),以及我应该如何渲染(使用旋转/缩放)地图数据在屏幕上将不胜感激.
编辑:澄清一下,我不想使用任何谷歌或雅虎地图API.同样,我不想使用OpenStreetMap.我正在寻找一种比使用那些apis /程序更划刮的方法.这将是一个桌面应用程序.
首先,我建议您使用2008 TIGER文件.
其次,正如其他人所指出的那样,现在有许多项目已经读入,解释,转换和使用数据.但是,为这些数据构建自己的解析器几乎是微不足道的,因此除非您计划整体使用他们的项目,否则没有理由通过另一个项目的代码并尝试提取您需要的内容.
解析
构建自己的TIGER解析器(相当简单 - 只是一个线段数据库),并在其上构建一个简单的渲染(线,多边形,字母/名称)也将相当容易.您将需要查看渲染阶段的各种地图投影类型.最常用的(因此对用户最熟悉)是墨卡托投影 - 它相当简单快速.您可能想要支持其他投影.
这将在看到如何投影地图方面提供一些"乐趣",以及如何反转该投影(例如,用户点击地图,您想要查看他们点击的纬度/经度 - 需要反转当前投影方程).
渲染
当我开发渲染器时,我决定将窗口固定在固定尺寸(嵌入式设备)和固定放大倍率上.这意味着我可以将地图置于纬度/经度中心,并且在给定的放大率下使用中心像素=中心纬度/经度,并且给定墨卡托投影,我可以计算每个纬度/经度代表哪个像素,反之亦然.
有些程序允许窗口变化,而不是使用放大率和固定点,它们使用两个固定点(通常是定义窗口的矩形的左上角和右下角).在这种情况下,确定像素到lat/lon传输变得微不足道 - 它只是一些插值计算.旋转和缩放使这种传递函数稍微复杂一些,但不应该如此 - 它仍然是一个带插值的矩形窗口,但窗口角不需要相对于北方的任何特定方向.这会增加一些极端情况(例如,您可以将地图内部翻转并像在地球内部一样查看)但这些并不繁琐,可以在处理时进行处理.
完成lat/lon到像素传输后,渲染线和多边形相当简单,除了正常的图形问题(例如线条边缘或多边形重叠不当,抗锯齿等).但渲染一个基本的丑陋地图,例如许多开源渲染器完成的地图,相当简单.
您还可以使用距离和大圆计算 - 例如,一个很好的经验法则是赤道的每个纬度或纬度大约为111.1KM - 但随着您接近任一极点而变化,另一个继续保持在111.1kM.
存储和结构
但是,如何存储和引用数据在很大程度上取决于您计划使用它的方式.如果你想在人口统计与路由中使用相同的数据库结构,会出现很多困难问题 - 给定的数据库结构和索引对于一个是快速的,对另一个则是慢的.
使用zipcodes并仅加载附近的zipcodes适用于小型地图渲染项目,但如果您需要遍布全国的路线,则需要使用不同的结构.一些实现具有"覆盖"数据库,其仅包含主要道路并且捕捉到覆盖的路线(或通过多个覆盖 - 本地,地铁,县,州,国家).这导致快速但有时低效的路由.
平铺
平铺地图实际上并不容易.在较低的放大倍率下,您可以渲染整个地图并将其剪切.在更高的放大率下,您无法一次渲染整个事物(由于内存/空间限制),因此您必须将其切片.
在瓷砖边界处切割线条以便渲染单个瓷砖会导致结果不尽如人意 - 通常所做的是线条渲染超出瓷砖边界(或者,至少保留线条末端的数据,尽管渲染一旦停止就会停止发现它已经脱落了边缘 - 这减少了线条看起来像它们穿过瓷砖时不完全匹配时发生的错误.
当你解决这个问题时,你会看到我在说什么.
找到进入给定图块的数据并非易事 - 一条线可能在给定图块之外有两端,但是穿过图块.你需要查阅有关这方面的图画书(Michael Abrash的书是开创性的参考书,现在可以在前面的链接免费获得).虽然它主要讨论游戏,但窗口,剪裁,多边形边缘,碰撞等都适用于此.
完成上述任务后(通过调整现有项目或自己完成上述项目),您可能希望使用其他方案和算法.
反向地理编码相当容易. 输入lat/lon(或点击地图)并获取最近的地址.这教会您如何解释TIGER数据中沿线段的地址.
基本的地理编码是一个难题. 编写地址解析器是一个有用且有趣的项目,然后使用TIGER数据将其转换为lat/lon是非常重要的,但是很有趣.通过要求精确的名称和格式匹配开始简单和小,然后开始研究'喜欢'匹配和语音匹配.这个领域有很多研究 - 在这里查看搜索引擎项目的一些帮助.
找到两点之间的最短路径是一个非平凡的问题. 有很多很多算法可以做到这一点,其中大部分都是专利的.我建议如果您尝试使用自己设计的简单算法,然后进行一些研究并将您的设计与现有技术进行比较.如果你进入图论,这会很有趣.
遵循一条道路并且先发制人地发出指示并不像第一次看到的那样容易.给定一组具有相关的纬度/经度对数组的指令,使用外部输入(GPS或模拟GPS)"跟踪"该路线,并开发一种算法,在用户接近每个真实交叉点时为其提供指令.请注意,由于道路弯曲等原因,纬度/经度对比指令多,您需要检测行进方向等.在尝试实现它之前,您将看不到许多角落案例.
兴趣点搜索. 这个很有趣 - 你需要在一定的距离内找到当前的位置和所有感兴趣的点(不是TIGER的一部分,制作你自己的或获得另一个来源)(如乌鸦飞行,或者更难驾驶距离)起源.这个有趣之处在于您必须将POI数据库转换为在这种情况下易于搜索的格式.您不能花时间浏览数百万条目,进行距离计算(sqrt(x ^ 2 + y ^ 2)),并返回结果.您需要有一些方法或算法来首先减少数据量.
旅行推销员. 使用多个目标路由.只是一个更难的常规路由版本.
您可以在此处找到许多项目的链接以及有关此主题的信息来源.
祝你好运,请发表你做的任何事情,无论多么简陋或丑陋,所以其他人都可以受益!
-亚当
SharpMap是WinForms和ASP.NET的开源.NET 2.0映射引擎.这可能会提供您需要的所有功能.它涉及最常见的GIS矢量和栅格数据格式,包括ESRI shapefile.
解决方案是:
地理空间服务器,如mapserver,geoserver,degree(opensource).
他们可以阅读和提供shapefile(以及许多其他东西).例如,geoserver(安装时)将来自美国人口普查局TIGER shapefile的数据作为演示提供
像openlayers这样的javascript制图库(请参阅链接文本中的示例
网上有很多使用此解决方案的示例
有趣的问题.这是我如何做到的.
无论我们采用何种格式,我都会收集所需的任何几何体.我一直在从USGS中提取数据,因此相当于一堆:
SHP文件(ESRI Shapefile技术说明)
DBF文件(Xbase数据文件(*.dbf))
然后我写了一个程序,将这些形状定义"编译"成一个有效渲染的形式.这意味着要进行有效显示数据所需的任何投影和数据格式转换.一些细节:
对于2D应用程序,您可以使用所需的任何投影:地图投影.
对于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