【问题标题】:Generating heatmap layer for milions of points为数百万个点生成热图图层
【发布时间】:2018-05-15 07:08:12
【问题描述】:

我正在使用 Google 地图中的热图图层来显示热图,但是,我现在有太多点并且它停止工作,因为浏览器无法再处理它了。我发现它们提供了 Fusion Tables,但它们也受到限制:100k 行,这太少了。我需要渲染数百万甚至更多点的热图。如果我的服务器可以有一些 PHP 脚本来呈现热图,例如,每天一次,那我就完美了。然后来自 js 的客户端将只下载预加载的热图(在地图上,如谷歌地图,但也可能是不同的地图)。这是否可以通过一些现有技术实现(可以商业化)?

【问题讨论】:

  • 您真的需要在所有时间显示所有点吗?你能不能只加载落在视口内的点,也许限制最小缩放级别、地图容器尺寸等?
  • 是和不是。目前,所有点都在一个城市周围,我想查看整个城市(今天大约 150 万点)。以后其他城市也可以用,那我就想到了,不过我说了,一个城市还是太多了。我需要预渲染的热图 :)
  • Mapbox 假装您可以在地图上加载数百万个点。看看他们的博客。我找到了this postthis post。可能值得一试。
  • 您可以添加图像叠加层。这是 google maps 开发者文档的链接:developers.google.com/maps/documentation/javascript/… 预生成热图并作为覆盖添加到 javascript。
  • 我试过 MapBox:mapbox.com/mapbox-gl-js/example/heatmap-layer 但它从 json 文件加载点。好吧,经过很长时间的加载,它几乎无法使用 100 000 点。

标签: javascript php google-maps heatmap google-fusion-tables


【解决方案1】:

您只需将您的点预聚类为较少数量的点,然后将这些组传递给 Google 地图,就好像它们是您的原始点一样。因此,如果您附近有 3 个值分别为 3、5 和 10 的点,您可以在其坐标的加权平均值处创建一个值为 18 的点。对所有数据集执行此操作,您将减少 3 倍。将 3 更改为任何适当的值以进一步减少您的数据集。

对数据进行聚类的简单方法是使用 geohashing[1]。这是 PHP[2] 的不错的 geohashing 库。您可以在添加时只为每个点计算一组不同精度的地理哈希,然后使用简单的GROUP BY 使用所需的精度来减少数据集。示例(元):

use Lvht\GeoHash;

class DataPoint extends ActiveRecord {
    public geo_hash_precision4, geo_hash_precision5, geo_hash_precision6;
    public function save() {
        $this->geo_hash_precision4 = GeoHash::encode($this->lat,$this->lon, 0.0001);
        $this->geo_hash_precision5 = GeoHash::encode($this->lat,$this->lon, 0.00001);
        $this->geo_hash_precision6 = GeoHash::encode($this->lat,$this->lon, 0.000001);
        parent::save();
    }
}

class DataSet extends ActiveQuery {
    /**
     * @param int $p Desired precision
     */
    public function getValues($p = 6) {
        $data = $this->rawQuery("SELECT geo_hash_precision{$p}, SUM(value) FROM {$this->table} GROUP BY geo_hash_precision{$p}");
        // Add bounding box WHERE to reduce set for map size
        foreach ($data as $row) {
            list($minLon, $maxLon, $minLat, $maxLat) = GeoHash::decode($row["geo_hash_precision{$p}"]);
            $row['lat'] = ($maxLat - $minLat) / 2;
            $row['lon'] = ($maxLon - $minLon) / 2;
            unset($row["geo_hash_precision{$p}"]);
        }
    }
}
  1. https://en.wikipedia.org/wiki/Geohash
  2. https://github.com/lvht/geohash

【讨论】:

  • 我现在无法测试这个答案,但它看起来是解决我的问题的最佳解决方案 :)
  • 请注意,这是一种伪代码,可以让您有所了解,实际实现将根据您的数据库、ORM 和框架而有所不同。随时提出其他问题。
【解决方案2】:

我使用heatmap.js 进行可视化。它真的很快,可以处理很多点。不确定150万点是否有效。

我可以想象的是使用带有 node.js 的 Javascript 解决方案之一进行预渲染。关于“heatmap js nodejs prerender”的快速谷歌搜索发现了我这个 https://github.com/substack/node-heatmap 和这个https://mango-is.com/blog/engineering/pre-render-d3-js-charts-at-server-side/

【讨论】:

  • 未来可以上千万点。它可以在cron任务的php服务器上运行吗?
  • 那么 nodejs 可以安装在 linux 服务器上,并且可以通过 cron 任务运行。我发现的唯一 PHP 热图服务器端渲染是 fusion-tables,您已经提到它不符合您的要求。因此,设置一个小型 nodejs 脚本并尝试使用它生成热图可能是您的最佳选择。
猜你喜欢
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 2011-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多