Создание слоя тепловой карты для миллионов точек
Я использую слой тепловой карты из Google Maps для отображения тепловой карты, однако теперь у меня слишком много точек, и он перестал работать, потому что браузер больше не может его обрабатывать. Я обнаружил, что они предоставляют таблицы слияния, но они также ограничены: до 100k строк, что слишком низко. Мне нужно сделать тепловую карту миллионов или, может быть, даже больше очков. Я был бы идеален, если бы мой сервер мог иметь PHP-скрипт для рендеринга тепловой карты, например, один раз в день. И тогда клиент из js просто загрузит предварительно загруженная тепловая карта (на карте, как Google maps, но может быть и другая карта). Возможно ли это с какой-то существующей технологией (может быть коммерческой)?
2 ответов
все, что вам нужно, это предварительно кластеризировать ваши точки в меньшее количество точек и передать эти группы В Google Maps, как если бы это были ваши исходные точки. Итак, если у вас было 3 близлежащие точки со значениями 3, 5 и 10, вы создаете одну точку со значением 18 при средневзвешенном значении их координат. Сделайте это для всего вашего набора данных, и вы уменьшите его в 3 раза. Измените 3 на любое подходящее значение, чтобы уменьшить набор данных.
простой способ кластеризации данных - использовать geohashing[1]. Здесь хорошая библиотека geohashing для PHP[2]. Вы можете рассчитать набор геохешей различной точности для каждой из ваших точек только один раз при добавлении, а затем использовать требуемую точность для уменьшения набора данных с помощью simple 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}"]);
}
}
}
Я использую карта.js для наглядности. Это очень быстро и может обрабатывать много очков. Не уверен, хотя если 1,5 мил точек будет работать.
что я могу себе представить, это использовать одно из решений Javascript с node.JS на пререндер. Быстрый поиск google о "heatmap JS nodejs prerender" нашел меня это https://github.com/substack/node-heatmap и это https://mango-is.com/blog/engineering/pre-render-d3-js-charts-at-server-side/