2013-01-22 13 views
12

Tworzę mapę termiczną za pomocą Google API v3. Dam przykład. Przyjrzyjmy się wielkościom trzęsień ziemi. Przypisuję wagi do każdego punktu, aby określić ich wielkość. Jednak Google bierze pod uwagę gęstość punktów podczas pomniejszania. Im więcej punktów jest w danym miejscu, tym bardziej czerwony. Na przykład, jeśli dwa zrzuty ziemi miały miejsce w odległości kilku mil od siebie, jeden o jasności 3, a drugi o jasności 8, pierwszy powinien być zielony/niebieski, a drugi czerwony. Jednak po zmniejszeniu i zbliżeniu dwóch punktów na mapie, mapy google uwzględniają liczbę punktów zamiast ciężarów, w wyniku czego wydaje się czytać. Chcę, aby była to średnia, tj. (3 + 8)/2=5.5 ... niezależnie od koloru, który reprezentuje. czy to możliwe?Mapa termiczna oparta na średnich wagach, a nie na liczbie punktów danych

Odpowiedz

2

termiczna z definicji uważa gęstość punktową, a także wagę przypisaną do każdego punktu. Przynajmniej mapa ciepła Google działa w ten sposób, o ile wiem, z pracy z nimi. To, czego naprawdę potrzebujesz, to nie mapa cieplna, ale mapa punktów, które będą kolorowe w zależności od wartości.

Potrzebowałem również zmienić stosunek gęstości/wagi, które mapy ciepła Google uwzględniają w celu pokolorowania mapy, ale nie znalazłem żadnego sposobu. Obecnie głównym czynnikiem cieplnym jest gęstość, a zmiana masy ma niewielki wpływ na kolor.

2

Jako częściowe rozwiązanie, mam zmodyfikowano heatmap.js z poniższego projektu: https://github.com/pa7/heatmap.js

Aby uzyskać średnio w jednym punkcie długich/Lat mam zmodyfikowano funkcję _organiseData do przechowywania i PointCount PointSum dla każdej pozycji x, y; i przy tych wartościach otrzymuję średnią w punkcie:

sklep [x] [y] = storePointSum [x] [y]/storePointCount [x] [y];

Wciąż pracuję nad tym, jak zmodyfikować "mieszankę", gdy wiele stosów współrzędnych x, y na różnych rozdzielczościach mapy ... Jeśli to rozwiążę, opublikuję go.

okrzyki

~ Aaron

+1

*** *** zmiana Wydaje się jakby „dodatek do łączenia alfa” stosuje się określone (i kontroli) w specyfikacji html, i to zasadniczo określa barwę przedstawione w tym szczególnym ciepło map - i prawdopodobnie większość innych ze względu na swój wysoce wydajny charakter. Niestety nie byłem w stanie znaleźć sposobu na "przeciętne gradientowe mieszanie alfa"; ustawienie kontekstu globalCompositeOperation wydawało się obiecujące, ale wydaje się, że obsługuje tylko tradycyjne mieszanki. Jeśli ktoś chciałby zbadać to dalej, dwiema kluczowymi funkcjami obserwatora są _drawAlpha i _getPointTemplate. –

3

Jest nieco godnej obejście jeśli jesteś podobny do mnie i nie mają czasu przetwarzania lub moc generowania nakładkę i nie można modyfikować żadnych istniejących bibliotek lubisz.

Użyłem mapy map ciepła google i ustawię maxIntensity i rozpraszam na false. Ustawienie maxIntensity na wybraną wartość rozwiąże problem twoich punktów temperaturowych, które będą kolorowe w stosunku do siebie nawzajem zamiast do 0 lub wartości zadanej. Ustawienie rozproszenia na false spowoduje wyłączenie automatycznych ustawień promienia, które zachodzą po zmianie poziomów powiększenia.

Następnie wykonałem wydarzenie za każdym razem, gdy zmienia się poziom powiększenia iw tym przypadku ustawiłem promień na wartość, która wydawała się reprezentować moje dane w najbardziej dokładny sposób dla tego poziomu powiększenia.

Teraz, aby pozbyć się problemu, w którym punkty danych na mapie mieszają się i łączą się w dużą czerwoną kroplę, postanowiłem utworzyć osobną siatkę na mojej mapie dla każdego poziomu powiększenia, którego chcę użyć.Średnio wszystkie wartości są umieszczone w tym samym punkcie siatki i upewnij się, że siatka jest wystarczająco duża, aby punkty termowizyjne nie zachodziły na siebie, ale na tyle małe, aby nie wyglądały jak kilka okręgów. (Stwierdziłem, że siatka powinna być około 0,4 razy większa od promienia punktu ogrzewania na mapie, aby uzyskać gładki wygląd).

Promień punktu termowizyjnego jest ustalany przez google w pikselach. Nie wiedziałem, jak konwertować piksele na szerokość/szerokość, więc zmierzyłem je, rysując linie za okręgiem o pewnym promieniu i mierząc odległość między tymi liniami. Ta metoda konwersji będzie działać całkiem dobrze, jeśli nie planujesz mapowania znacznie większego niż mały kraj.

Wydajność to nie jest tak źle, jak myślałem. Ładuję około 2300 punktów, a mapa ładuje się tak szybko, jak przed utworzeniem siatki dla każdego poziomu powiększenia, a nie widzisz punktów danych odświeżanych podczas zmiany poziomów powiększenia.

Oto niektóre fragmenty kodu dla wszystkich powyższych:

Mapa ustawieniami:

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

Zmiana siatki i promień na poziom powiększenia:

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

Moi ruszty są generowane w PHP, który prawdopodobnie będzie wyglądał inaczej dla wszystkich, ale jako przykład, oto funkcja, której używam:

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

Niestety nie mogę wyświetlić mapy teraz, ponieważ jest ona obecnie przechowywana prywatnie dla klientów firmy, nad którą pracuję, ale jeśli stanie się dostępna publicznie, dodam link, aby zobaczyć, jak dobrze działa ta metoda .

Mam nadzieję, że to komuś pomaga.

Lukas

Powiązane problemy