2013-01-22 1 views
12

Google API v3으로 히트 맵을 만들고 있습니다. 예를 들어 보겠습니다. 지진의 크기를 고려하십시오. 각 포인트에 가중치를 지정하여 크기를 지정합니다. 그러나 Google은 축소 할 때 점의 밀도를 고려합니다. 더 많은 포인트가있는 곳은 빨갛게됩니다. 예를 들어 두 개의 지진이 서로 수 마일 내에서 발생했다면 하나는 크기가 3이고 다른 하나는 크기가 8 인 경우 첫 번째 것은 녹색/파란색이어야하고 두 번째는 빨간색이어야합니다. 그러나 일단 축소하고지도에서 두 지점이 가까워지면 google지도는 가중치 대신 점의 수를 고려하므로 결과는 읽혀집니다. 나는 그것을 평균 즉, (3 + 8) /2=5.5 ... 어떤 색으로 표현하길 원합니다. 이것이 가능한가?히트 맵은 데이터 포인트 수가 아닌 평균 가중치를 기반으로합니다.

답변

2

히트 맵 포인트 밀도뿐만 아니라 각 지점에 할당 된 가중치를 고려합니다. 적어도 Google의 열지도는 내가 아는 한이 방법으로 작업합니다. 실제로 필요한 것은 히트 맵이 아니라 값에 따라 색칠 될 점의 맵입니다.

지도를 색칠하기 위해 Google 히트 맵이 고려한 비율 밀도/무게를 변경해야했지만 어떤 방식으로도 찾지 못했습니다. 히트 맵의 주요 요소는 밀도이며 중량의 변화는 색상에 작은 영향을 미칩니다. 나는 PointCount를 저장하는 _organiseData 기능을 수정했습니다 https://github.com/pa7/heatmap.js

는 하나의 긴/위도 지점에서 평균을 얻으려면 :

2

는 부분적인 해결책으로, 나는 다음과 같은 프로젝트에서 heatmap.js을 수정 한 각 x, y 위치에 대한 PointSum; 이 값들을 사용하면 다음과 같은 점에서 평균을 얻을 수 있습니다.

store [store] [x] [y]/storePointCount [x] [y];

여러 x, y 좌표가 다양한 맵 해상도로 스택 될 때 "블렌드"를 수정하는 방법을 아직 연구 중입니다 ... 알아낼 수 있다면 게시 할 것입니다.

환호

~ 아론

당신이 나 같은 및 오버레이를 생성하는 처리 시간 또는 전원이없는 당신은 어떤 기존의 라이브러리를 변경할 수없는 경우 다소 괜찮은 해결 방법은
+1

*** 업데이트 *** 사용 된 "첨가제 알파 블렌딩"은 HTML 명세에 의해 정의 된 (및 제어) 인 것처럼이 나타나고, 이는 근본적으로 특정 열에서 그린 색상을 결정 무엇 지도 - 그리고 아마도 대부분의 다른 사람들은 고성능 특성 때문입니다. 불행히도 "평균 그라디언트 알파 블렌드"를 수행하는 방법을 찾을 수 없었습니다. 컨텍스트 globalCompositeOperation 설정이 유망 해 보였지만 전통적인 혼합을 지원하는 것으로 보입니다. 누구든지 이것을 더 탐구하고 싶다면 관찰자의 두 가지 주요 기능은 _drawAlpha와 _getPointTemplate입니다. –

3

너의 취향.

Google지도 히트 맵 라이브러리를 사용하고 maxIntensity를 설정하고 소실하는 것은 잘못된 것입니다. maxIntensity를 원하는 값으로 설정하면 heatmap-points가 0 또는 설정된 값 대신에 서로 관련되어 표시되는 문제를 해결할 수 있습니다. 소실을 false로 설정하면 줌 레벨을 변경할 때 발생하는 자동 반경 설정이 비활성화됩니다.

다음으로 확대/축소 수준이 변경 될 때마다 이벤트를 만들었습니다.이 경우 해당 확대/축소 수준에서 가장 정확한 방식으로 내 데이터를 나타내는 것처럼 반경을 설정했습니다.

맵의 데이터 포인트가 섞여 큰 빨간 얼룩으로 합쳐지는 문제를 없애기 위해 필자는 사용하려는 모든 확대/축소 레벨에 대해지도에서 별도의 눈금을 만들기로 결정했습니다.동일한 격자 점 안에 박스로 묶인 모든 값의 평균을 구해서 그리드가 겹치지 않도록 히트 맵 점을 유지할만큼 충분히 크지 만 원의 묶음처럼 보이지 않을만큼 작게 만드는지 확인하십시오. (그리드가 매끄러운 외모를 위해 맵상의 열점 반경의 약 0.4 배가되어야 함을 발견했습니다.)

히트 맵 포인트의 반경은 픽셀 단위로 Google에서 설정합니다. 위도/경도로 픽셀을 변환하는 방법을 알지 못했기 때문에 특정 반경을 가진 선을 지나서 선을 그어 측정하고 이러한 선 사이의 거리를 측정했습니다. 소규모 국가를 훨씬 더 매핑하는 계획이 없다면이 변환 방법을 사용할 수 있습니다.

성능이 현명한 것은 내가 생각했던 것처럼 나쁘지 않습니다. 대략 2300 포인트를로드 중이며 모든 줌 레벨에 대해 그리드를 작성하기 전에 최대한 빨리 맵을로드하며 줌 레벨을 변경하면 실제로 데이터 포인트가 새로 고쳐지지 않습니다.

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

줌 레벨에 따라 변경 그리드 및 반경 :

지도 설정 : 내 그리드가 생성됩니다

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는 모든 사람들에게 다르게 보일 것입니다. 예를 들어, 여기에 제가 사용하는 함수가 있습니다 :

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; 
} 

안타깝게도 현재 회사의 고객에게 공개되어 있으므로지도를 표시 할 수 없지만 공개적으로 사용할 수있게되면이 방법이 얼마나 효과적인지 알 수 있도록 링크를 추가 할 것입니다. .

희망이 있으면 도움이됩니다.

루카스

관련 문제