热图基于平均权重而不是数据点数 [英] Heatmap based on average weights and not on the number of data points

查看:90
本文介绍了热图基于平均权重而不是数据点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Google API v3制作热图.我举一个例子.让我们考虑地震震级.我为每个点分配权重以指定其大小.但是,当您缩小地图时,Google会考虑点的密度.一个位置上的点越多,它就会变得越红.例如,如果发生在彼此之间数英里之内的两次土拨鼠,一次为3级,另一次为8级,则第一个应为绿色/蓝色,第二个应为红色.但是,一旦缩小并在地图上使两个点更接近,谷歌地图就会考虑点的数量而不是权重,因此,它看起来像已读.我希望它是平均值,即(3 + 8)/2=5.5 ...表示的是哪种颜色.这可能吗?

I am making a heatmap with Google API v3. I'll give an example. Lets consider earthquake magnitudes. I assign weights to each point to specify their magnitude. However google considers the density of points when you zoom out. The more points are in a place, the redder it gets. For example if two earthqueaks happened within miles of each other, one with magnitude 3 and another with magnitude 8, the first one should be green/blue and the 2nd one would be red. But once you zoom out and the two points get closer in the map, google maps considers the number of points instead of the weights and as a result, it appears read. I want it to be the average i.e. (3+8)/2=5.5...whatever color that represents. Is this possible?

推荐答案

如果您像我一样,没有处理时间或能力来生成覆盖图,并且无法修改任何现有的覆盖图,则有一个不错的解决方法您喜欢的图书馆.

There is a somewhat decent workaround if you are like me and don't have the processing time or power to generate an overlay and you can't modify any existing libraries to your liking.

我使用了Google Maps热图库,并将maxIntensity设置为false.将maxIntensity设置为您选择的值将解决热图点相对于彼此变色而不是变为0或设置值的问题.将耗散设置为false会禁用更改缩放级别时发生的自动半径设置.

I used the google maps heatmap library and set maxIntensity and dissipating to false. Setting the maxIntensity to a value of your choosing will solve the problem of your heatmap-points getting colored in relation to eachother instead of to 0 or a set value. Setting dissipating to false will disable the automatic radius settings that happen when you change zoom levels.

接下来,每次缩放级别更改时,我都会创建一个事件,在这种情况下,我将半径设置为一个值,该值似乎可以最准确地代表该缩放级别的数据.

Next I made an event for every time the zoom level changed and in that event I set the radius to a value that seemed to represent my data in the most accurate way for that zoom level.

现在要摆脱地图上数据点混合并添加到一个大红色斑点中的问题,我决定为要使用的每个缩放级别在地图上创建一个单独的网格.我对在同一网格点内装箱的所有值求平均值,并确保网格足够大以防止热图点重叠,但又要足够小以免看起来像一堆圆. (我发现网格应为地图上热点半径的大约0.4倍,以使外观平滑).

Now to get rid of the problem where datapoints on the map blend and get added together into a big red blob, I decided to make a seperate grid on my map for every zoom level I want to use. I average all the values that are boxed inside the same grid point and make sure that the grid is large enough to keep heatmap points from overlapping, but small enough to not look like a bunch of circles. (I found that the grid should be about 0.4 times the size of the heatpoint radius on the map for smooth looks).

热图点的半径由Google以像素为单位设置.我不知道如何将像素转换为纬度/经度,因此我只是通过画一条经过一定半径的圆的线并测量这些线之间的距离来对其进行测量.如果您不打算在一个较小的国家/地区进行地图绘制,那么这种转换方法将非常有效.

The radius of the heatmap point is set by google in pixels. I didn't know how to convert pixels to Lat/Long so I just measured it by drawing lines past a circle with a certain radius and measured the distance between these lines. That conversion method will work pretty well if you aren't planning on mapping much more than a small country.

就性能而言,这并不像我想的那样糟糕.我正在加载大约2300个点,并且地图的加载速度与为每个缩放级别制作网格之前的加载速度一样快,并且在更改缩放级别时,您实际上看不到数据点正在刷新.

Performance wise this isn't as bad as I thought it would be. I'm loading about 2300 points and the map loads as fast as it did before I made a grid for every zoom level, and you don't actually see the data points being refreshed as you change zoom levels.

以下是上述所有代码的一部分:

Here are some pieces of code for all of the above:

地图设置:

map.heatmap.set('maxIntensity', 12000);
map.heatmap.set('dissipating', false);

更改每个缩放级别的网格和半径:

Change grid and radius per zoom level:

map._on({
    obj: map.gMap,
    event: "zoom_changed",
    callback: function(){
        var zoomLevel = map.zoom();
        switch(zoomLevel){
            case 7:
                map.heatmap.setData(gridData[zoomLevel]);
                map.heatmap.set('radius', 0.04);
                break;
            case 8:
                map.heatmap.setData(gridData[zoomLevel]);
                map.heatmap.set('radius', 0.03);
                break;
            case 9:
                map.heatmap.setData(gridData[zoomLevel]);
                map.heatmap.set('radius', 0.02);
                break;
            case 10:
                map.heatmap.setData(gridData[zoomLevel]);
                map.heatmap.set('radius', 0.01);
                break;
            case 11:
                map.heatmap.setData(gridData[zoomLevel]);
                map.heatmap.set('radius', 0.005);
                break;
            case 12:
                map.heatmap.setData(gridData[zoomLevel]);
                map.heatmap.set('radius', 0.0025);
                break;
            case 13:
                map.heatmap.setData(gridData[zoomLevel]);
                map.heatmap.set('radius', 0.00225);
                break;
            default:
                map.heatmap.setData(gridData[zoomLevel]);
                map.heatmap.set('radius', 0.000625);
        }
    }
});

我的网格是用PHP生成的,每个人的外观可能都不同,但是仅作为示例,这是我使用的功能:

My grids are generated in PHP which will probably look different for everyone, but just as an example, here's the function I use:

function getHeatGrid($gridSize){
$mapGrid = false;
$mapData = false;
$radius = $gridSize * 2.8 * 0.3; //grid size is multiplied by 2.8 to convert from the heat map radius to lat/long values(works for my lat/long, maybe not yours). * 0.3 is arbitrary to avoid seeing the grid on the map.
$string = file_get_contents("mapData.json");
$json_a = json_decode($string, true);

forEach($json_a as $key => $value){
    $row = intval(round(($value['center_longitude'] / $radius)));
    $column = intval(round(($value['center_latitude'] / $radius)/68*111)); //around 52.0;5.0 latitude needs to be scaled to make a square grid with the used longitude grid size
    if(isset($mapGrid[$row][$column])){
        $mapGrid[$row][$column] = round(($value['solarValue'] + $mapGrid[$row][$column]) / 2);
    } else {
        $mapGrid[$row][$column] = $value['solarValue'];
    }
}

forEach($mapGrid as $long => $array){
    forEach($array as $lat => $weight){
        $mapData[] = array(
            "center_longitude" => $long * $radius,
            "center_latitude" => ($lat * $radius)/111*68,
            "solarValue" => $weight
        );
    }
}
return $mapData;
}

很遗憾,我现在无法显示该地图,因为该地图目前不公开给我所在公司的客户使用,但是如果该地图公开可用,我将添加一个链接,以便您可以看到此方法的效果.

Unfortunately I can't display the map right now as it is currently kept private for clients of the company that I work at, but if it becomes available publically I will add a link so you can see how well this method works.

希望这对某人有帮助.

卢卡斯

这篇关于热图基于平均权重而不是数据点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆