我有兴趣编写一个简单的导航应用程序作为我的宠物项目。 在搜索免费地图数据后,我选择了 美国人口普查局TIGER 2007 线/Shapefile 地图数据。 数据被分成各个县的 zip 文件,我已经下载了我所在地区的单个县地图数据。
将此地图数据读入可用格式的最佳方法是什么?
我应该如何:
- 读入这些文件
- 并解析它们 - 正则表达式或某些已经可以解析这些形状文件的库?
- 将数据加载到我的应用程序中 - 我应该将点直接加载到内存中的某些数据结构中吗? 使用小型数据库? 一旦你关闭了地图数据的应用,我就不需要持久化了。 用户可以再次加载 Shapefile。
一旦我读取了 Shapefile 数据,渲染地图的最佳方法是什么?
理想情况下,我希望能够读取县地图数据 shapefile 并渲染所有折线到屏幕上并允许旋转和缩放。
我应该如何:
- 将纬度/经度点转换为屏幕坐标? - 据我所知,形状文件使用经度和纬度作为其点。 显然,我必须以某种方式将它们转换为屏幕坐标才能显示地图功能。
- 以一种可以轻松旋转和缩放整个地图的方式渲染地图数据(道路、边界等的一系列折线)?
- 将整个地图渲染为一系列“图块”,以便仅渲染查看区域内的要素/线条?
前任。 渲染为显示地图的 TIGER 数据:
对我阅读这些文件的最佳方式有一定经验和见解的任何人,我应该如何表示它们(数据库,内存数据结构)在我的程序中,以及我应该如何在屏幕上渲染(旋转/缩放)地图数据将不胜感激。
编辑:澄清一下,我不想使用任何 Google 或 Yahoo 地图 API。 同样,我不想使用 OpenStreetMap。 我正在寻找一种比利用这些 api/程序更从头开始的方法。 这将是一个桌面应用程序。
I am interested in writing a simplistic navigation application as a pet project. After searching around for free map-data I have settled on the US Census Bureau TIGER 2007 Line/Shapefile map data. The data is split up into zip files for individual counties and I've downloaded a single counties map-data for my area.
What would be the best way to read in this map-data into a useable format?
How should I:
- Read in these files
- Parse them - Regular expression or some library that can already parse these Shapefiles?
- Load the data into my application - Should I load the points directly into some datastructure in memory? Use a small database? I have no need for persistence once you close the application of the map data. The user can load the Shapefile again.
What would be the best way to render the map once I have read the in the Shapefile data?
Ideally I'd like to be able to read in a counties map data shapefile and render all the poly-lines onto the screen and allow rotating and scaling.
How should I:
- Convert lat/lon points to screen coordinates? - As far as I know the Shapefile uses longitude and latitude for its points. So obviously I'm going to have to convert these somehow to screen coordinates to display the map features.
- Render the map data (A series of polylines for roads, boundaries, etc) in a way that I can easily rotate and scale the entire map?
- Render my whole map as a series of "tiles" so only the features/lines within the viewing area are rendered?
Ex. of TIGER data rendered as a display map:
Anyone with some experience and insight into what the best way for me to read in these files, how I should represent them (database, in memory datastructure) in my program, and how I should render (with rotating/scaling) the map-data on screen would be appreciated.
EDIT: To clarify, I do not want to use any Google or Yahoo maps API. Similarly, I don't want to use OpenStreetMap. I'm looking for a more from-scratch approach than utilizing those apis/programs. This will be a desktop application.
发布评论
评论(11)
墨卡托投影或其他投影的一种简化是假设纬度和经度的转换因子恒定。 将纬度乘以 69.172 英里; 对于经度,选择地图区域的中纬度并将(180 经度)乘以余弦(中纬度)*69.172。 转换为英里后,您可以使用另一组转换来获取屏幕坐标。
这就是 1979 年对我有用的方法。
我的数据来源每度英里。
One simplification over a Mercator or other projection is to assume a constant conversion factor for the latitude and longitude. Multiply the degrees of latitude by 69.172 miles; for the longitude, pick the middle latitude of your map area and multiply (180-longitude) by cosine(middle_latitude)*69.172. Once you've converted to miles, you can use another set of conversions to get to screen coordinates.
This is what worked for me back in 1979.
My source for the number of miles per degree.
当我给出这个答案时,问题被标记为
“在 .Net 中使用折线渲染 Shapefile(地图数据)的最佳方式是什么?”
现在这是一个不同的问题,但我将答案保留在原来的问题上。
When I gave this answer the question was labeled
"What would be the best way to render a Shapefile (map data) with polylines in .Net?"
Now it is a different question but I leave my answer to the original question.
一种解决方案是使用 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”作为水印,但在其他情况下它是完全可用的
One solution is to use MapXtreme. They have API's for Java and C#. The API is able to load these files and render them.
For Java:
http://www.mapinfo.com/products/developer-tools/desktop%2c-mobile-%26-internet-offering/mapxtreme-java
For .NET:
http://www.mapinfo.com/products/developer-tools/desktop%2c-mobile-%26-internet-offering/mapxtreme-2008
I used this solution in a Desktop application and it worked well. It offers a lot more that only rendering information.
Now doing this from scratch could take quite a while. They do have an evaluation version that you can download. I think it just prints "MAPXTREME" over the map as a watermark, but it is completely usable otherwise
首先,我建议您使用 2008 TIGER 文件。
其次,正如其他人指出的那样,现在有很多项目已经读入、解释、转换和使用数据。 不过,为这些数据构建您自己的解析器几乎是微不足道的,因此没有理由浏览另一个项目的代码并尝试提取您需要的内容,除非您计划将他们的项目作为一个整体使用。
如果您想从较低级别开始
解析
构建自己的 TIGER 解析器(相当简单 - 只需一个线段数据库),并在此基础上构建一个简单的渲染(线、多边形、字母/名称)也将相当容易。 您需要查看各种地图投影类型渲染阶段。 最常用(因此用户最熟悉)的是 墨卡托投影 - 它相当简单且快速。 您可能想尝试支持其他投影。
这将为了解如何投影地图以及如何反转该投影提供一些“乐趣”(假设用户单击地图,您想查看他们单击的纬度/经度 - 需要反转当前投影方程)。
渲染
当我开发渲染器时,我决定将窗口基于固定尺寸(嵌入式设备)和固定放大倍率。 这意味着我可以将地图以纬度/经度为中心,并且在给定的放大倍率下中心像素=中心纬度/经度,并且给定墨卡托投影,我可以计算哪个像素代表每个纬度/经度,反之亦然。
有些程序允许窗口变化,并且不使用放大倍数和固定点,而是使用两个固定点(通常是定义窗口的矩形的左上角和右下角)。 在这种情况下,确定像素到纬度/经度的传输变得微不足道 - 这只是一些插值计算。 旋转和缩放使该传递函数变得更加复杂,但应该不会太复杂 - 它仍然是一个带有插值的矩形窗口,但窗口角不需要相对于北处于任何特定方向。 这增加了一些极端情况(例如,您可以将地图翻过来并像从地球内部一样查看它),但这些并不繁重,并且可以在您处理它时处理。
一旦完成了纬度/经度到像素的传输,渲染线条和多边形就相当简单了,除了正常的图形问题(例如线条或多边形的边缘不恰当地重叠、抗锯齿等)。 但是渲染一个基本的丑陋地图(例如许多开源渲染器所做的那样)是相当简单的。
您还可以进行距离和大圆计算 - 例如,一个很好的经验法则是,赤道的每一度纬度或经度大约为 111.1KM - 但当您靠近任一极时,它会发生变化,而另一个继续保持在111.1kM。
存储和结构
然而,您如何存储和引用数据在很大程度上取决于您计划如何使用它。 如果您想对人口统计和路由使用相同的数据库结构,就会出现很多难题 - 给定的数据库结构和索引对于一个来说很快,而另一个则很慢。
使用邮政编码并仅加载附近的邮政编码适用于小型地图渲染项目,但如果您需要穿越全国的路线,则需要不同的结构。 一些实现具有“覆盖”数据库,其中仅包含主要道路和捕捉到覆盖的路线(或通过多个覆盖 - 本地、地铁、县、州、国家)。 这会导致快速但有时效率低下的路由。
平铺
平铺地图实际上并不容易。 在较低的放大倍率下,您可以渲染整个地图并将其剪切。 在较高的放大倍率下,您无法一次渲染整个物体(由于内存/空间限制),因此您必须将其切成薄片。
在图块边界处切割线,以便渲染单个图块会导致不太完美的结果 - 通常所做的是将线渲染到图块边界之外(或者,至少保留线端的数据,尽管渲染一旦停止就会停止)发现它从边缘掉下来) - 这减少了当线条穿过瓷砖时看起来不太匹配时出现的错误。
当你解决这个问题时,你就会明白我在说什么。
查找进入给定图块的数据也并非易事 - 一条线的两端可能都在给定图块之外,但会穿过该图块。 您需要查阅有关此内容的图形书籍(Michael Abrash 的书是开创性的参考资料,现在可以通过前面的链接免费获得)。 虽然它主要讨论游戏,但窗口、裁剪、多边形边缘、碰撞等都适用于此。
但是,您可能想玩更高级别的游戏。
完成上述操作后(通过调整现有项目或自己执行上述操作),您可能想尝试其他场景和算法。
反向地理编码相当简单。输入纬度/经度(或单击地图)并获取最近的地址。 这将教您如何解释 TIGER 数据中线段的地址。
基本地理编码是一个难题。编写地址解析器是一个有用且有趣的项目,然后使用 TIGER 数据将其转换为纬度/经度,这并不简单,但很有趣。 从简单而小的开始,要求精确的名称和格式匹配,然后开始研究“类似”匹配和语音匹配。 该领域有很多研究 - 请查看搜索引擎项目以获取一些帮助。
找到两点之间的最短路径是一个不平凡的问题。有很多很多算法可以做到这一点,其中大多数都已申请专利。 我建议,如果您尝试这样做,请使用您自己设计的简单算法,然后进行一些研究并将您的设计与最先进的技术进行比较。 如果您热衷于图论,这会很有趣。
遵循路径并先发制人地给出指示并不像乍一看那么容易。 给定一组具有关联的纬度/经度对数组的指令,使用外部输入(GPS 或模拟 GPS)“遵循”路线,并开发一种算法,在用户接近每个真实交叉路口时向用户提供指令。 请注意,由于弯曲的道路等原因,纬度/经度对比指令多,并且您需要检测行进方向等。 在尝试实现之前,您不会看到很多极端情况。
兴趣点搜索。这个很有趣 - 你需要找到当前位置以及一定距离内的所有兴趣点(不是 TIGER 的一部分,可以自己制作或获取其他来源)(正如乌鸦飞过,或更难 - 行驶距离)的原点。 这个很有趣,因为在这种情况下你必须将 POI 数据库转换成一种易于搜索的格式。 您无法花时间浏览数百万个条目,进行距离计算 (sqrt(x^2 + y^2)),然后返回结果。 首先你需要有一些方法或算法来减少数据量。
旅行推销员。具有多个目的地的路线。 只是常规路由的更难版本。
您可以在此处找到有关此主题的许多项目和信息源的链接。
祝你好运,无论你做什么,无论多么初级或丑陋,请发表,以便其他人受益!
-亚当
First, I recommend that you use the 2008 TIGER files.
Second, as others point out there are a lot of projects out there now that already read in, interpret, convert, and use the data. Building your own parser for this data is almost trivial, though, so there's no reason to go through another project's code and try to extract what you need unless you plan on using their project as a whole.
If you want to start from the lower level
Parsing
Building your own TIGER parser (reasonably easy - just a DB of line segments), and building a simple render on top of that (lines, polygons, letters/names) is also going to be fairly easy. You'll want to look at various map projection types for the render phase. The most frequently used (and therefore most familiar to users) is the Mercator projection - it's fairly simple and fast. You might want to play with supporting other projections.
This will provide a bit of 'fun' in terms of seeing how to project a map, and how to reverse that projection (say a user clicks on the map, you want to see the lat/lon they clicked - requires reversing the current projection equation).
Rendering
When I developed my renderer I decided to base my window on a fixed size (embedded device), and a fixed magnification. This meant that I could center the map at a lat/lon, and with the center pixel=center lat/lon at a given magnification, and given the mercator projection I could calculate which pixel represented each lat/lon, and vice-versa.
Some programs instead allow the window to vary, and instead of using magnification and a fixed point, they use two fixed points (often the upper left and lower right corners of a rectangle defining the window). In this case it becomes trivial to determine the pixel to lat/lon transfer - it's just a few interpolation calculations. Rotating and scaling make this transfer function a little more complex, but shouldn't be considerably so - it's still a rectangular window with interpolation, but the window corners don't need to be in any particular orientation with respect to north. This adds a few corner cases (you can turn the map inside out and view it as if from inside the earth, for instance) but these aren't onerous, and can be dealt with as you work on it.
Once you've got the lat/lon to pixel transfer done, rendering lines and polygons is fairly simple except for normal graphics issues (such as edges of lines or polygons overlapping inappropriately, anti-aliasing, etc). But rendering a basic ugly map such as it done by many open source renderers is fairly straightforward.
You'll also be able to play with distance and great circle calculations - for instance a nice rule of thumb is that every degree of lat or lon at the equator is approximately 111.1KM - but one changes as you get closer to either pole, while the other continues to remain at 111.1kM.
Storage and Structures
How you store and refer to the data, however, depends greatly on what you plan on doing with it. A lot of difficult problems arise if you want to use the same database structure for demographics vs routing - a given data base structure and indexing will be fast for one, and slow for the other.
Using zipcodes and loading only the nearby zipcodes works for small map rendering projects, but if you need a route across the country you need a different structure. Some implementations have 'overlay' databases which only contain major roads and snaps routes to the overlay (or through multiple overlays - local, metro, county, state, country). This results in fast, but sometimes inefficient routing.
Tiling
Tiling your map is actually not easy. At lower magnifications you can render a whole map and cut it up. At higher magnifications you can't render the whole thing at once (due to memory/space constraints), so you have to slice it up.
Cutting lines at boundaries of tiles so you can render individual tiles results in less than perfect results - often what is done is lines are rendered beyond the tile boundary (or, at least the data of the line end is kept, though rendering stops once it finds it's fallen off the edge) - this reduces error that occurs with lines looking like they don't quite match as they travel across tiles.
You'll see what I'm talking about as you work on this problem.
It isn't trivial to find the data that goes into a given tile as well - a line may have both ends outside a given tile, but travel across the tile. You'll need to consult graphics books about this (Michael Abrash's book is the seminal reference, freely available now at the preceding link). While it talks mostly about gaming, the windowing, clipping, polygon edges, collision, etc all apply here.
However, you might want to play at a higher level.
Once you have the above done (either by adapting an existing project, or doing the above yourself) you may want to play with other scenarios and algorithms.
Reverse geocoding is reasonably easy. Input lat/lon (or click on map) and get the nearest address. This teaches you how to interpret addresses along line segments in TIGER data.
Basic geocoding is a hard problem. Writing an address parser is a useful and interesting project, and then converting that into lat/lon using the TIGER data is non-trivial, but a lot of fun. Start out simple and small by requiring exact name and format matching, and then start to look into 'like' matching and phonetic matching. There's a lot of research in this area - look at search engine projects for some help here.
Finding the shortest path between two points is a non-trivial problem. There are many, many algorithms for doing that, most of which are patented. I recommend that if you try this go with an easy algorithm of your own design, and then do some research and compare your design to the state of the art. It's a lot of fun if you're into graph theory.
Following a path and pre-emptively giving instructions is not as easy as it looks on first blush. Given a set of instructions with an associated array of lat/lon pairs, 'follow' the route using external input (GPS, or simulated GPS) and develop an algorithm that gives the user instructions as they approach each real intersection. Notice that there are more lat/lon pairs than instructions due to curving roads, etc, and you'll need to detect direction of travel and so forth. Lots of corner cases you won't see until you try to implement it.
Point of interest search. This one is interesting - you need to find the current location, and all the points of interest (not part of TIGER, make your own or get another source) within a certain distance (as the crow flies, or harder - driving distance) of the origin. This one is interesting in that you have to convert the POI database into a format that is easy to search in this circumstance. You can't take the time to go through millions of entries, do the distance calculation (sqrt(x^2 + y^2)), and return the results. You need to have some method or algorithm to cut the amount of data down first.
Traveling salesman. Routing with multiple destinations. Just a harder version of regular routing.
You can find a number of links to many projects and sources of information on this subject here.
Good luck, and please publish whatever you do, no matter how rudimentary or ugly, so others can benefit!
-Adam
SharpMap 是一个用于 WinForms 和 ASP.NET 的开源 .NET 2.0 映射引擎。 这可能会提供您需要的所有功能。 它处理最常见的 GIS 矢量和栅格数据格式,包括 ESRI shapefile。
SharpMap is an open-source .NET 2.0 mapping engine for WinForms and ASP.NET. This may provide all the functionality that you need. It deals with most common GIS vector and raster data formats including ESRI shapefiles.
解决方案是:
他们可以读取和提供形状文件(以及许多其他东西)。 例如,geoserver(安装后)提供来自美国人口普查局 TIGER shapefile 的数据,作为演示
网络上有很多使用此解决方案的示例
the solution is :
They can read and serve shapefiles (and many other things). For example, geoserver (when installed) serve data from US Census Bureau TIGER shapefiles as demo
There are plenty of examples on the web using this solution
有趣的问题。 我是这样做的。
我以任何格式收集我需要的任何几何图形。我一直从 USGS 提取数据,所以这相当于一堆:
然后我编写了一个程序,将这些形状定义“编译”为以下形式:渲染效率高。 这意味着进行有效显示数据所需的任何投影和数据格式转换。 一些细节:
球坐标到普通直角坐标。
剩下的就是相机控制和您想要显示的任何数据的动画。
以下是我现有实施的一些示例:
图片 http://seabusmap.com/assets/Picture% 205.png 图片 http://seabusmap.com/assets/Picture%207。 .png
Funny question. Here's how I do it.
I gather whatever geometry I need in whatever formats they come in. I've been pulling data from USGS, so that amounts to a bunch of:
I then wrote a program that "compiles" those shape definitions into a form that is efficient to render. This means doing any projections and data format conversions that are necessary to efficiently display the data. Some details:
spherical coordinates to normal rectangular coordinates.
x
items wherex
is the number of primitives I can draw at my desired framerate.The rest is camera control and animation of whatever data you want to display.
Here are some examples of my existing implementation:
Picture http://seabusmap.com/assets/Picture%205.png Picture http://seabusmap.com/assets/Picture%207.png
为了在本地存储老虎数据,我会选择 Postgresql 和 postgis 工具。
他们有一系列令人印象深刻的工具,特别是 Tiger Geocoder提供了导入和使用老虎数据的好方法。
您需要查看与 postgis 交互的工具,很可能是
来自 mapserver 的工具="http://postgis.refractions.net/documentation/" rel="nofollow noreferrer">http://postgis.refractions.net/documentation/:
编辑:尽管mapserver 的名称中含有“SERVER”一词,但这将可在桌面环境中使用。
for storing tiger data locally, I would chose Postgresql with the postgis tools.
they have an impressive collection of tools, for you especially the Tiger Geocoder offers good way of importing and using the tiger data.
you will need to take a look at the tools that interact with postgis, most likely some sort of mapserver
from http://postgis.refractions.net/documentation/:
edit: depite mapserver having the word SERVER in its name, this will be usable in a desktop environment.
尽管您已经决定使用 TIGER 数据,但您可能对 OSM(开放街道地图) 感兴趣,因为 OSM 有完全导入其中的 TIGER 数据,并通过用户贡献的数据进行丰富。 如果您坚持使用 TIGER 格式,您的应用程序对于国际用户来说将毫无用处,而使用 OSM,您可以立即获得 TIGER 和其他所有内容。
OSM 是一个开放项目,以协作编辑的免费世界地图为特色。 您可以获取所有这些数据以及结构化的 XML,可以查询某个区域,也可以将整个世界下载到一个大文件中。
OSM 的地图渲染器有多种编程语言可供使用,其中大多数都是开源的,但仍有很多工作要做。
还有一个可用的OSM 路由服务。 它有一个 Web 界面,也可以通过 Web 服务 API 进行查询。 再说一次,一切还没有结束。 用户绝对可以使用在此基础上构建的桌面或移动路由应用程序。
即使您不决定参与该项目,您也可以从中获得很多灵感。 只需查看项目 wiki 以及所涉及的各种软件项目的源代码(您会发现维基百科中的链接)。
Though you already decided to use the TIGER data, you might be interested in OSM (Open Street Map), beacuse OSM has a complete import of the TIGER data in it, enriched with user contributed data. If you stick to the TIGER format, your app will be useless to international users, with OSM you get TIGER and everything else at once.
OSM is an open project featuring a collaboratively edited free world map. You can get all this data as well structured XML, either query for a region, or download the whole world in a large file.
There are some map renderers for OSM available in various programming languages, most of them open source, but still there is much to be done.
There also is an OSM routing service avaliable. It has a web-interface and might also be queriable via a web service API. Again, it's not all finished. Users could definitely use a desktop or mobile routing application built on top of this.
Even if you don't decide to go with that project, you can get lots of inspiration from it. Just have a look at the project wiki and at the sources of the various software projects which are involved (you will find links to them inside the wiki).
您还可以使用 Microsoft 的视觉地球地图应用程序和 api 或使用 Google 的 api。 我一直使用 ESRI 产品进行商业编程,并没有过多地使用开放 API。
另外,您可能想看看 Maker! 和查找器! 它们是相对较新的程序,但我认为它们是免费的。 嵌入数据可能受到限制。Maker 可以在此处找到。
问题在于,空间处理在非商业规模上是相当新的。
You could also work with Microsoft's visual earth mapping application and api or use Google's api. I have always programmed commercially with ESRI products and have not played with the open api's that much.
Also, you might want to look at Maker! and Finder! They are relatively new programs but I think they are free. Might be limited on embedding the data.Maker can be found here.
The problem is that spatial processing is fairly new in the non commercial scale.
如果您不介意购买解决方案,Safe Software 会生产一款名为 FME 的产品。 该工具将帮助您将数据从任何格式转换为几乎任何其他格式。 包括 KML Google Earth 格式或将其渲染为 JPEG(或 JPEG 系列)。 转换数据后,您可以使用其 API 将 google 地球嵌入到您的应用程序中,或者仅显示平铺图像。
另一方面,FME 是一个非常强大的平台,因此在进行翻译时,您可以添加或删除不一定需要的部分数据。 如果您有多个源,请合并源。 转换坐标(我不记得Google Earth到底使用什么)。 将备份存储在数据库中。 但说实话,如果你愿意花几美元,你应该研究一下这个。
您还可以创建包含位置(放置位置)和有关该位置的其他数据/注释的标志(非常类似于示例地图中的标志)。 这些旗帜有多种形状和尺寸。
If you don't mind paying for a solution Safe Software produces a product called FME. This tool will help you translate data from any format to just about any other. Including KML the Google Earth Format or render it as a JPEG (or series of JPEGs). After converting the data you can embed google earth into your application using their API or just display the tiled images.
As a side not FME is a very powerful platform so while doing your translations you can add or remove parts of data that you don't necessarily need. Merge sources if you have more than one. Convert coordinates (I don't remember what exactly Google Earth uses). Store backups in a database. But seriously if your willing to shell out a few bucks you should look into this.
You can also create flags (much like in your sample map) which contain a location (where to put it) and other data/comments about the location. These flags come in many shapes and sizes.