google maps api v3 的服务器端集群
Posted
技术标签:
【中文标题】google maps api v3 的服务器端集群【英文标题】:Server-side clustering for google maps api v3 【发布时间】:2011-11-23 15:25:10 【问题描述】:我目前正在开发一种谷歌地图概览小部件,它将位置显示为地图上的标记。标记的数量从数百个到数千个(10000 个)不等。现在我正在使用 MarkerClusterer for google maps v3 1.0 和 google maps javascript api v3 (premier),它可以说是一百个标记。由于标记的数量会增加,我需要一种新的标记聚类方法。从我读到的保持性能的唯一方法是将集群从客户端移动到服务器端。有谁知道一个好的 php5 库可以为我完成这项工作?
Atm 我正在深入挖掘谷歌地图的图层机制。也许还有一些我可以开始检查的领先 PHP 库?我也遇到过 FusionTables,但由于我需要集群,我认为这可能不是正确的解决方案。
提前致谢!
【问题讨论】:
根据我使用 markerclusterer 的经验,谷歌处理单个标记而不是在集群开启时显示它们 所以你会说markerclusterer能够正确显示如此大量的标记而无需花费太长时间来渲染它们?自从您谈论您使用 markerclusterer 的一般经验以来,您聚集了多少个标记? 我在不是很快的计算机上渲染的最大数字是大约 5000,多达一千它非常顺利地更新标记数量,后来标记数量在添加数百后开始更新,但没有任何明显的损失性能 因此,即使最初未加载标记弹出窗口的实际数据,当显示超过 5000 个标记时,地图也会变得非常慢。不幸的是,我没有找到太多关于服务器端集群的信息。我不知道谷歌地图是如何获取这些集群数据的,以及我是否需要一个额外的 javascript 库,比如 markerclusterer 来对它们进行集群?我有点迷失在这个主题上... 看起来像:***.com/questions/986852/… 【参考方案1】:我不知道可以为您完成这项工作的服务器端库。不过,我可以给你一些关于如何自己实现的建议。
聚类的基本方法是简单地计算标记之间的距离,当其中两个足够接近时,将它们替换为位于两者中点的单个标记。
您不仅可以限制彼此标记的接近程度,还可以(或改为)选择限制所需的集群/标记的数量。
要做到这一点,您可以计算所有标记对之间的距离,对它们进行排序,然后从顶部合并,直到您拥有任意数量的标记/集群。
要在形成集群时优化中点定位,您可以考虑要合并的两者中的每一个所代表的实际标记的数量。将该数字视为重量,将两个标记之间的线视为比例。然后不要总是选择中点,而是选择能够平衡刻度的点。
我猜如果您的标记数量有限,这种简单的聚类形式就足够了。如果您的数据集(标记的数量及其位置)大致是静态的,您可以偶尔在服务器上计算集群,缓存它,然后直接从缓存中服务器客户端。
但是,如果您需要支持可能在世界各地使用标记的大规模场景,您将需要更复杂的方法。
上述集群算法无法扩展。事实上,它的计算成本通常会随着标记的数量呈指数增长。
要解决这个问题,您可以将世界分割成多个分区并计算集群并从每个分区为客户端提供服务。这确实支持扩展,因为工作负载可以由几个(大致)独立的服务器拆分和执行。
那么问题是如何找到一个好的分区方案。您可能还需要考虑在不同的缩放级别提供不同的标记聚类,并且您的分区方案也应该包含这一点以允许缩放。
Google 将地图划分为具有 x、y 和 z 坐标的图块,其中 x 和 y 是图块从北开始的水平和垂直位置-地图的西角,其中 z 是缩放级别。
在最小缩放级别(零)下,整个地图由单个图块组成。 (所有图块都是 256x256 像素)。在下一个缩放级别,该图块分为四个子图块。这继续,因此在缩放级别 2 中,这四个图块中的每一个都被划分为四个子图块,这给了我们总共 16 个图块。缩放级别 3 有 64 个图块,级别 4 有 256 个图块,依此类推。 (任意缩放级别的瓦片数都可以表示为4^z
。)
使用此分区方案,您可以从最低缩放级别(最高 z 坐标)开始计算每个图块的聚类,直至到达顶部。
要为单个图块聚类的标记集是其四个子图块的所有标记(其中一些可能代表聚类)的联合。
这为您提供了有限的计算成本,还为您提供了一种将要发送到客户端的数据分块的好方法。客户端可以在将标记加载到地图时逐块请求标记,而不是请求给定缩放级别的所有标记(不会缩放)。
但是,这种方法存在一个缺陷:考虑两个相邻的图块,一个在左侧,一个在右侧。如果左边的瓦片在其最右侧包含一个标记/集群,而右边的瓦片在其最左侧包含一个标记/集群,那么这两个标记/集群应该合并,但不会因为我们正在执行聚类每个图块单独的机制。
要解决此问题,您可以在对已聚类的图块进行后处理,以便合并位于四个边上的标记/聚类,同时考虑给定图块的八个相邻图块中的每一个。这种合并后机制只有在我们可以假设没有一个集群足够大来影响不在同一个子图块中的周围标记时才会起作用。然而,这是一个合理的假设。
最后一点:使用横向扩展的方法,您会让客户提出几个小请求。这些请求将具有局部性(即,图块不是随机请求的,而是通常一起访问地理上彼此接近的图块)。
为了提高查找/查询性能,您将受益于使用也具有此局部性属性的搜索键(表示切片)(因为这会将相邻切片的数据存储在磁盘上的相邻数据块中 - 提高读取时间和缓存利用率) .
您可以使用 tile/sub tile 分区方案形成这样的密钥。让顶部图块(跨越整个地图的单个图块)将空字符串作为键。接下来,让其每个子图块具有键 A、B、C 和 D。下一层将具有键 AA、AB、AC、AD、BA、BC、...、DC、DD。
递归地应用这个,你最终会得到一个分区键,它可以识别你的瓦片,允许快速转换到 x、y、z 坐标并具有局部性属性。这种密钥命名方案有时被称为 Quad Key,因为分区方案形成了 Quad Tree。局部性属性与使用 Z 阶曲线将 2D 值映射到 1D 值时获得的属性相同。
如果您需要更多详细信息,请告诉我。
【讨论】:
【参考方案2】:本文有一些标记聚类的PHP示例:
http://www.appelsiini.net/2008/11/introduction-to-marker-clustering-with-google-maps
【讨论】:
【参考方案3】:你可以试试我的免费集群应用。它比客户端 google maps api 拥有更多的 pin。它为 kmeans 提供了基于网格的聚类。
https://github.com/biodiv/anycluster
【讨论】:
以上是关于google maps api v3 的服务器端集群的主要内容,如果未能解决你的问题,请参考以下文章
Esri Feature Services和Google Maps API v3
Google Maps API V3 使用限制是按网站访问者还是按 Web 服务器?