最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Generating heatmap layer for milions of points - Stack Overflow

programmeradmin2浏览0评论

I'm using heatmap layer from Google Maps to display a heatmap, however, I now have too many points and it stopped working, because browser cannot handle it anymore. I've found that they provide Fusion Tables, but they're also limited: to 100k rows, which is way too low. I need to render heatmap of milions or maybe even more points. I'd be perfect if my server can have some PHP script to render a heatmap, for example, once a day. And then a client from js will just download a preloaded heatmap (on the map like google maps, but may be different map too). Is this possible with some existing technology (can be mercial)?

I'm using heatmap layer from Google Maps to display a heatmap, however, I now have too many points and it stopped working, because browser cannot handle it anymore. I've found that they provide Fusion Tables, but they're also limited: to 100k rows, which is way too low. I need to render heatmap of milions or maybe even more points. I'd be perfect if my server can have some PHP script to render a heatmap, for example, once a day. And then a client from js will just download a preloaded heatmap (on the map like google maps, but may be different map too). Is this possible with some existing technology (can be mercial)?

Share Improve this question asked May 15, 2018 at 7:08 MakaleleMakalele 7,5315 gold badges58 silver badges83 bronze badges 8
  • Do you really need to show ALL points at ALL times? Could you not load only the points that fall within the viewport, maybe limit the minimum zoom level, the map container dimensions, etc.? – MrUpsidown Commented May 17, 2018 at 15:04
  • Yes and no. For now, all points are around one city and I want to see the whole city (about 1.5 mil points as for today). Later on, it'll be available for other cities so then I can think of it, but as I said it's still too much for one city. I need prerendered heatmap :) – Makalele Commented May 18, 2018 at 6:20
  • Mapbox pretends you can load millions of points on a map. Have a look at their blog. I found this post and this post. Might be worth trying. – MrUpsidown Commented May 18, 2018 at 8:00
  • You can add an image overlay. Here is a link to the google maps developer documentation: developers.google./maps/documentation/javascript/… Pre-generate heat maps and add to the javascript as an overlay. – Jeff Harris Commented May 18, 2018 at 18:37
  • I've tried MapBox: mapbox./mapbox-gl-js/example/heatmap-layer but it loads points from json file. Well it could barely work with 100 000 points after really long loading. – Makalele Commented May 21, 2018 at 12:20
 |  Show 3 more ments

2 Answers 2

Reset to default 10 +50

All you need is to pre-clusterize your points into smaller number of points and pass these groups to Google Maps as if it were your original points. So, if you had 3 nearby points with values 3, 5 and 10, you create one point with value 18 at weighted average of their coordinates. Do it for all your dataset and you will reduce it 3 times. Change 3 to any appropriate value to further reduce your dataset.

The easy way to cluster your data is to use geohashing[1]. Here is nice geohashing library for PHP[2]. You may calculate a set of geohashes of different precision for each of your points only once when adding, and then use desired precision to reduce your dataset using simple GROUP BY. Example (meta):

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/wiki/Geohash
  2. https://github./lvht/geohash

I use heatmap.js for visualization. It's really fast and can handle alot of points. Not sure though if 1.5 mil points will work.

What I can imagine is to use one of the Javascript solutions with node.js to prerender. A quick google search about 'heatmap js nodejs prerender' found me this https://github./substack/node-heatmap and this https://mango-is./blog/engineering/pre-render-d3-js-charts-at-server-side/

发布评论

评论列表(0)

  1. 暂无评论