需要有关必须显示 250 000 条折线的 Google 地图应用程序的指导
我正在为我正在开发的使用 Google 地图的应用程序寻求建议。
摘要: 用户具有用于搜索满足条件的街道段的条件列表。街道段将用 3 种颜色来表示,分别是低于平均水平、平均水平和高于平均水平。然后,用户单击街道路段,查看一个信息窗口,显示该特定路段的属性,隐藏那些未选择的路段,直到他/她关闭窗口并且其他折线再次可见。这看起来很像孩之宝几个月前制作的大富翁城市街道游戏,区别在于我不使用 Flash,我不能使用开放街道地图,因为它没有列出街道段(如果列出了,ID 将不会是无论如何都是一样的)而且我不必展示谷歌草图的构建。
信息: 我有一个包含 ID、折线点和质心的街道段数据库。 该数据库中有 6,000,000 条街道记录。为了缩小生成的数据范围,我们重点关注城市。我们必须展示的最大城市有 250,000 个街道段。这意味着要显示 250,000 条线段折线。
我们最长的折线使用 9600 个字符,存储在 SQL Server 2008 中的两个 8000 个 varchar 列中。
我们需要使用 API v3,因为它比 API v2 更快,并且应用程序将移植到 iPhone。目前它是一个带有 SQl Server 2008 的 ASP.NET 3.5 应用程序。 性能是重中之重。
问题: 大多数执行此操作的演示项目都是使用 API v2 制作的。因此,除了 Google API v3 参考页上的教程之外,我没有什么可以比较性能或技术使用来实现我的目标。 目前还没有适用于 API v3 的可用 .NET 包装器。
生成 250,000 条线段折线会创建一个繁重的文件,需要时间来传输和解析。 (我发现了一个包含 390,000 个点的折线的演示。我认为编码器的效率会低得多,使用更多的折线和更少的点,因为舍入会更少。) 由于街道段是根据标准显示的,因此必须动态创建折线并且无法使用缓存。
一些想法:
KML/KMZ:
优点: 由于它是一个标准,我们可以轻松加载 Bing 地图、Yahoo!地图、Google 地图、Google 地球,具有相同的 KML 文件。数据生成是相同的。
缺点: KML 中的 LineString 无法像 Google 地图 API 那样编码折线。因此它可能会更大并且显示速度更慢。压缩文件的大小会花费更多的处理时间,并需要客户端解压缩数据,我不太确定 iPhone 将如何处理 250,000 个数据,以及服务器如何处理 40 个用户同时浏览。
JavaScript 文件:
优点: JavaScript 文件可以包含编码折线,并且会显着减少要传输的文件。
缺点: 必须创建我自己的 API v3 的精简版本来添加叠加层、创建折线等。它比仅仅创建 KML 文件并指向源更复杂。
GeoRSS: 我认为这个选项不适合我的需要,但我可能是错的。
地图服务器: 我看到一些帖子建议使用 MapServer 生成叠加层。不太确定与我们的数据库的连接及其所提供的性能。另外它需要一个插件来生成 KML。在我看来,它不会让我比创建自己的 KML 或 JavaScript 文件做得更好。没有的话维护会更简单。
垄断城市街道: 游戏现在结束了,但对于那些知道我在说什么的人来说,《垄断城市街道》在最大缩放级别仅显示质心位于窗口范围内的街道。移动地图是向服务器发送请求以显示新街道。虽然我认为这很巧妙,但我不知道如何实现类似的东西。我唯一想到的就是比较长线是否在地图区域 X 的边界内并且与 Y 相同。虽然这可以在高缩放级别显着提高性能,但在显示整个城市时这不会给出任何结果。
聚类: 虽然聚类对于标记来说非常棒,但我们似乎无法对折线进行聚类。我希望有类似 MarkerClusterer 的东西折线并能够通过我的 3 种折线颜色进行聚类。这可能会一直停留在“本来就很棒但忘了它”的状态。
箭头: 我将在未来的版本中显示折线的方向,并且必须在质心处显示箭头。加载图像或标记只会使我的数据加倍,因此创建自定义叠加可能是我唯一的选择。我发现 演示 可以实现我想要实现的类似目标。不幸的是,演示速度非常慢,但我只想为每条折线显示 1 个箭头,而不是像演示那样显示多个箭头。此功能将取决于数据的格式,因为我认为 KML 不支持自定义叠加。
标准: 虽然该应用程序是使用 ASP.NET 3.5 完成的,但到 iPhone 的移植不会使用 Web 来显示该应用程序,并且在选择条件时会受到屏幕尺寸的限制。这就是为什么我更倾向于根据参数中传递的标准生成文件的服务或页面。该服务将生成我需要在地图上显示折线的文件。我还可以创建一个 aspx 页面来执行此操作。 aspx页面比service方式有更多的文档记录。应该是有原因的。
问题:
- 我应该创建一个 Web 服务来返回街道段文件,还是创建一个返回该文件的 aspx 页面?
- 基于最大经度/纬度折线有 9600 个字符并且我必须渲染最多 250,000 条线段折线这一事实,我应该创建一个带有编码折线的 JavaScript 文件还是一个带有经度/纬度的 KML 文件。或者我应该使用生成叠加层的地图服务器?
- 我能否在下一个版本中在折线上显示简单的箭头?
- 在生成 KML 的情况下,使用 XDocument、XmlDocument、XmlWriter 手动创建文件或仅序列化流中的街道段是否更快?
这更像是一个集思广益的 Stack Overflow 问题,而不是一个实际的代码问题。任何有助于缩小可能性的答案都与拥有所有知识的人为我指出更好的选择一样好。
I am looking for advice for an application I am developing that uses Google Map.
Summary:
A user has a list of criteria for searching a street segment that fulfills the criteria. The street segments will be colored with 3 colors for showing those below average, average and over average. Then the user clicks on the street segment to see an information window showing the properties of that specific segment hiding those not selected until he/she closes the window and other polyline becomes visible again. This looks quite like the Monopoly City Streets game Hasbro made some month ago the difference being I do not use Flash, I can’t use Open Street Map because it doesn’t list street segment (if it does the IDs won’t be the same anyway) and I do not have to show Google sketch building over.
Information:
I have a database of street segments with IDs, polyline points and centroid.
The database has 6,000,000 street segment records in it. To narrow the generated data a bit we focus on city. The largest city we must show has 250,000 street segments. This means 250,000 line segment polyline to show.
Our longest polyline uses 9600 characters which is stored in two 8000 varchar columns in SQL Server 2008.
We need to use the API v3 because it is faster than the API v2 and the application will be ported to iPhone. For now it's an ASP.NET 3.5 with SQl Server 2008 application.
Performance is a priority.
Problems:
Most of the demo projects that do this are made with API v2. So besides tutorial on the Google API v3 reference page I have nothing to compare performance or technology use to achieve my goal.
There is no available .NET wrapper for the API v3 yet.
Generating a 250,000 line segment polyline creates a heavy file which takes time to transfer and parse. (I have found a demo of one polyline of 390,000 points. I think the encoder would be far less efficient with more polylines with less points since there will be less rounding.)
Since streets segments are shown based on criteria, polylines must be dynamically created and cache can't be used.
Some thoughts:
KML/KMZ:
Pros:
Since it is a standard we can easily load Bing maps, Yahoo! maps, Google maps, Google Earth, with the same KML file. The data generation would be the same.
Cons:
LineString in KML cannot be encoded polyline like the Google map API can handle. So it would probably be bigger and slower to display. Zipping the file at the size it will take more processing time and require the client side to uncompress the data and I am not quite sure with 250,000 data how an iPhone would handle this and how a server would handle 40 users browsing at the same time.
JavaScript file:
Pros:
JavaScript file can have encoded polyline and would significantly reduce the file to transfer.
Cons:
Have to create my own stripped version of API v3 to add overlays, create polyline, etc. It is more complex than just create a KML file and point to the source.
GeoRSS:
This option isn't adapted for my needs I think, but I could be wrong.
MapServer:
I saw some post suggesting using MapServer to generate overlays. Not quite sure for the connection with our database and the performance it would give. Plus it requires a plugin for generating KML. It seems to me that it wouldn't allow me to do better than creating my own KML or JavaScript file. Maintenance would be simpler without.
Monopoly City Streets:
The game is now over, but for those who know what I am talking about Monopoly City Streets was showing at max zoom level only the streets that the centroid was inside the Bounds of the window. Moving the map was sending request to the server for the new streets to show. While I think this was ingenious, I have no idea how to implement something similar. The only thing I thought about was to compare if the long was inside the bound of map area X and same with Y. While this could improve performance significantly at high zoom level, this would give nothing when showing a whole city.
Clustering:
While cluster is awesome for marker, it seems we cannot cluster polylines. I would have liked something like MarkerClusterer for polylines and be able to cluster by my 3 polyline colors. This will probably stay as a “would have been freaking awesome but forget it”.
Arrow:
I will have in a future version to show a direction for the polyline and will have to show an arrow at the centroid. Loading an image or marker will only double my data so creating a custom overlay will probably be my only option. I have found that demo for something similar I would like to achieve. Unfortunately, the demo is very slow, but I only wish to show 1 arrow per polyline and not multiple like the demo. This functionality will depend on the format of data since I don't think KML support custom overlays.
Criteria:
While the application is done with ASP.NET 3.5, the port to the iPhone won't use the web to show the application and be limited in screen size for selecting the criteria. This is why I was more orienting on a service or page generating the file based on criteria passed in parameters. The service would than generate the file I need to display the polylines on the map. I could also create an aspx page that does this. The aspx page is more documented than the service way. There should be a reason.
Questions:
- Should I create a web service to returns the street segments file or create an aspx page that return the file?
- Should I create a JavaScript file with encoded polyline or a KML with longitude/latitude based on the fact that maximum longitude/latitude polyline have 9600 characters and I have to render maximum 250,000 line segment polyline. Or should I go with a MapServer that generate the overlay?
- Will I be able to display simple arrow on the polyline on the next version.
- In case of KML generation is it faster to create the file with
XDocument
, XmlDocument,XmlWriter
and this manually or just serialize the street segment in the stream?
This is more a brainstorming Stack Overflow question than an actual code problem. Any answer helping narrow the possibilities is as good as someone having all the knowledge to point me out a better choice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
大量短 GPolylines 的运行速度大大慢于少量长 GPolylines。
Google Maps v2 和 Google Maps v3 之间的速度差异不会很大,因为大部分 CPU 时间将被浏览器的实际图形系统占用。 Google 地图使用 VML、SVG 或 Canvas 图形系统,具体取决于浏览器。其中,VML 是迄今为止最慢的,只要浏览器是 MSIE,就会使用它。
在开始处理 250,000 条线段之前,我建议您看一下200 条随机折线的快速测试。尝试在 MSIE 中缩放和平移该地图。
然后,还要考虑需要从服务器发送到客户端的数据量,以指定 250,000 个线段。数据量会有所不同,具体取决于您选择 KML、JSON 还是 GeoRSS,但如果最终每个线段有 20 字节,则在 1 兆位宽带连接上需要 50 秒才能获取。考虑一下您的用户是否愿意等待 50 秒。
唯一真正有意义的解决方案是像 Google 那样对其流量叠加进行操作,将线条绘制到服务器中的图块上,并将这些图块显示为客户端中的 GTileLayerOverlay。
您需要的是一个空间感知数据库和一个服务器端图形库(如 gd 或 ImageMagik)。客户端向服务器请求图块。如果缩放高于特定级别,服务器将扫描数据库以查找具有与所请求图块的边界框重叠的边界框的线段,并使用图形库来绘制它们。
缩放级别限制是为了限制数据库和服务器需要执行的工作量。您不希望最终在单个缩小的图块上绘制 250,000 条线段,因为这对服务器来说是一项艰巨的工作,而且对用户来说意义不大。
关于点击处理:
最简单的做法是监听地图上的点击,而不是对象上的点击,并将点击详细信息发送到服务器。然后,服务器使用单击位置来搜索空间感知数据库,并返回被单击对象的详细信息(如果有)。客户端代码执行此操作:
更困难的事情是当指针位于折线上方时处理光标的变化。有一种已知的技术可以对小标记进行光标更改,其工作原理如下:
每当获取图块时,.getTileUrl() 还会调用服务器,返回该图块的热点框列表。随着鼠标的移动,客户端不断计算鼠标移到了哪个图块上,然后扫描相应的热点框列表。
Google 自己在其 GLayer() 代码中添加了执行四叉树搜索的复杂性,以加快对图块内热点的搜索,但在自己的代码中实现此策略的其他人认为这是没有必要的,并且线性扫描热点列表的速度足够快。
我不知道如何将其扩展到处理折线检测上的光标。
Large numbers of short GPolylines run massively slower than small numbers of long GPolylines.
The speed difference between Google Maps v2 and Google Maps v3 is not going to be significant, because most of the CPU time will be taken up by the actual graphics system of the browser. Google Maps uses the VML, SVG or Canvas graphics systems, depending on the browser. Of these, VML is by far the slowest, and that gets used whenever the browser is MSIE.
Before embarking on tackling 250,000 line segments, I suggest you take a look at this quick speed test of 200 random polylines. Try zooming and paning that map in MSIE.
Then, also consider the amount of data that needs to be sent from the server to the client to specify 250,000 line segments. The amount of data will vary depending on whether you choose KML or JSON or GeoRSS, but if you end up with 20 bytes per line segment that would take 50 seconds to fetch on a 1 megabit broadband connection. Consider whether your users would be prepared to sit around for 50 seconds.
The only solution that really makes sense is to do what Google do for their traffic overlay, and draw the lines onto tiles in the server, and have those tiles be displayed as a GTileLayerOverlay in the client.
What you need is a spatially aware database, and a server-side graphics library like gd or ImageMagik. The client asks for a tile from the server. If the zoom is above a certain level the server scans the database for line segments that have bounding boxes that overlap the bounding box of the requested tile and use the graphics library to draw them.
The zoom level limit is there to limit the amount of work that your database and server needs to do. You don't want to end up drawing 250,000 line segments onto a single zoomed out tile because that's an awful lot of hard work for the server, and isn't going to mean very much to the user.
Regarding click handling:
The easy thing to do is to listen for clicks on the map, rather than on the objects, and send the click details to a server. The server then uses the click location to search the spatially aware database and returns the details of the clicked object if there is one. The client code does this:
The harder thing to do is to handle the changing of the cursor when the pointer is over the polylines. There's a known technique for doing cursor changes for small markers, which works like this:
Whenever a tile is fetched, the .getTileUrl() also makes a call to a server that returns a list of hotspot boxes for that tile. As the mouse moves, the client constantly calculates which tile the mouse is over, and then scans the corresponding list of hotspot boxes.
Google themselves, in their GLayer() code, add the sophistication of performing a quadtree search to speed up the search for hotspots within a tile, but other people who have implemented this strategy in their own code reckon that's not necessary, and a linear scan of the hotspot list is fast enough.
I've no idea how to extend that to handling cursor over polyline detection.