2011-12-13 94 views
0

我已經給出了在Google Map上放置最多標記的狀態下設置中心和縮放到狀態級別的要求。我正在使用的所有數據都是點(緯度/經度)的集合。Google Maps API V3:縮放到大多數標記的狀態

我意識到我可以爲每個點進行地理位置調用(http://code.google.com/apis/maps/documentation/geocoding/index.html#GeocodingRequests - 請參閱:反向地理編碼),然後計算狀態以確定我應該顯示的內容,但由於每個地圖會有數百到數千個點,因此是不實際的。

還有什麼我可以做到的呢?有沒有什麼可能會是類似的(標記的高濃度的中心/中心)?

+0

我覺得你會因爲各種不同的狀態而受到任何數學上的絆倒......想象你的標記是在一個完美的網格中佈置的......你無法做任何事情來確定正確的狀態而沒有知道每個標記處於哪種狀態。也許你的源可以提供該部分,所以你不必爲每個點都反轉地理代碼? – 2011-12-13 19:23:05

+0

來源無法提供該數據。如果我能找到一種方法來放大標記濃度最高的區域(忽略狀態標記),我會願意推遲。我意識到這不是一個非常深思熟慮的要求,但我必須給他們一些東西。 – smp7d 2011-12-13 19:30:11

回答

1

這是一個想法。請參閱此SO Question。第一個答案有一個指向所有狀態邊界的帶有多邊形座標的XML文件的鏈接。你也可以簡化多邊形,所以沒有太多的頂點。

當一個標記添加到地圖上,您可以檢查,看它是否在使用的算法類似this的50個陣列中的一個存在:

UPDATE:我張貼的最初的功能是不是在JavaScript。這裏是一個Javascript和一個fiddle of it working

/* 
* state == array of Google LatLng objects. 
* lat == latitude to test 
* lng == longitude to test 
*/ 
function pointInPolygon(state, lat, lng) { 
    var polyCount = state.length; 
    var oddNodes = false; 
    var j = 0; 
    for (var i = 0; i < polyCount; i++) { 
     j++; 
     if (j == polyCount) { 
      j = 0; 
     } 
     latitudeBoundry = state[i].lat(); 
     longitudeBoundry = state[i].lng(); 
     latitudeBoundry2 = state[j].lat(); 
     longitudeBoundry2 = state[j].lng(); 
     if ((latitudeBoundry > lat && latitudeBoundry <= lat 
      || latitudeBoundry2 > lat && latitudeBoundry <= lat)) { 
      if (longitudeBoundry + (lat - latitudeBoundry) 
       /(latitudeBoundry2 - latitudeBoundry) 
       * (longitudeBoundry2 - longitudeBoundry) > lng) { 
       oddNodes = !oddNodes 
      } 
     } 
    } 
    return oddNodes; 
} 

如果它存在遞增計數器。

一旦找到了標記最多的狀態,就可以通過創建邊界對象來設置縮放。

//the polyArray is the array of points for the target state. 
var bounds = new google.maps.LatLngBounds(); 
for (var i = 0; i < polyArray.length; i++) 
{ 
    bounds.extend(polyArray[ i ]); 
} 

//set the map viewport 
map.fitBounds(bounds) 

我不知道這將如何擺脫性能明智,但它應該比反向地理編碼快得多。

1

這是一個示例頁面,它實現了前面提到的網格方法。這在概念上布萊恩兄弟相似,但是,因爲它只是一個簡單的劃分,以確定哪個部門在網格中,它可能是一個快一點的大型數據集(但你失去的狀態特殊性):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Auto Center</title> 
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script> 
<style> 
#wrap {width:960px;margin-right:auto;margin-left:auto;position:relative;} 
#map_canvas {width:100%;height:700px;} 
table,td {border-collapse:collapse;border:thin #000 solid;} 
</style> 
</head> 
<body> 
<div id="wrap"> 
<div id="map_canvas"></div> 
<div id="tabular"></div> 
<script type="text/javascript"> 
function randomFromTo(from, to){ 
    return Math.floor(Math.random() * (to - from + 1) + from); 
} 
    var map; 
    var placesToFilter=Array(); 
    var myOptions = {zoom: 6,mapTypeControl: false,mapTypeId: google.maps.MapTypeId.ROADMAP}; 
    //---Creating random data 
    for(i=0;i<500;i++){ 
     var a=new Object(); 
     a.lat=randomFromTo(2600,4900)/100; 
     a.lng=-randomFromTo(6600,12500)/100; 
     placesToFilter.push(a); 
    } 
    //---Get max and min latitude 
    var maxLat=placesToFilter[0].lat*1; 
    var minLat=placesToFilter[0].lat*1; 
    for (i=1;i<placesToFilter.length;i++) { 
     if (placesToFilter[i].lat*1>maxLat) {maxLat=placesToFilter[i].lat*1;} 
     if (placesToFilter[i].lat*1<minLat) {minLat=placesToFilter[i].lat*1;} 
    } 
    //---Get max and min longitude 
    var maxLng=placesToFilter[0].lng*1; 
    var minLng=placesToFilter[0].lng*1; 
    for (i=1;i<placesToFilter.length;i++) { 
     if (placesToFilter[i].lng*1>maxLng) {maxLng=placesToFilter[i].lng*1;} 
     if (placesToFilter[i].lng*1<minLng) {minLng=placesToFilter[i].lng*1;} 
    } 
    var s=8;//--------------------How many rows/columns the area gets gridded into 
    var latDelta=maxLat-minLat; 
    var lngDelta=maxLng-minLng; 
    var latStep=latDelta/s; 
    var lngStep=lngDelta/s; 
    var latBands=Array(); 
    for(i=1;i<=s;i++){latBands.push(i*latStep);} 
    var lngBands=Array(); 
    for(i=1;i<=s;i++){lngBands.push(i*lngStep);} 
    //---Keeping score in these arrays 
    var gridCount=new Array(); 
    for(var x=0;x<s;x++){ 
     for(var y=0;y<s;y++){ 
      var cell=[x,y]; 
      gridCount.push(cell); 
     } 
    } 
    for(var lt=0;lt<s;lt++){ 
     for(var lg=0;lg<s;lg++){ 
      gridCount[lt][lg]=0; 
     } 
    } 

    map = new google.maps.Map(document.getElementById('map_canvas'),myOptions); 

    for(p=0;p<placesToFilter.length;p++){ 
     //---Keeping track of which grid sector 
     var whichLat=Math.floor((placesToFilter[p].lat-minLat)/latStep); 
     var whichLng=Math.floor((placesToFilter[p].lng-minLng)/lngStep); 
     gridCount[whichLat][whichLng]++; 
     //---And placing the marker 
     var point=new google.maps.LatLng(placesToFilter[p].lat,placesToFilter[p].lng); 
     var marker = new google.maps.Marker({position: point,map: map}); 
    } 
    //---Figuring out which cell 'won' 
    var checking=gridCount[0][0]; 
    var rightLat; 
    var rightLng; 
    for(lt=0;lt<s;lt++){ 
     for(lg=0;lg<s;lg++){ 
      if(gridCount[lt][lg]>checking){ 
       checking=gridCount[lt][lg]; 
       rightLat=lt; 
       rightLng=lg; 
      } 
     } 
    } 
    //convert grid sector to lat/lng (center of sector) 
    var winningLat=maxLat-(rightLat*latStep)-(latStep/2); 
    var winningLng=minLng+(rightLng*lngStep)+(lngStep/2); 
    var newCenter=new google.maps.LatLng(winningLat,winningLng); 
    map.setCenter(newCenter); 
    showTable=true; //--------------this will display the table of data so you can see how many markers are in each sector 
    if(showTable){ 
     var table='<table>'; 
     for(row=0;row<s;row++){ 
      table+='<tr>'; 
      for(td=0;td<s;td++){ 
       table+='<td>'+gridCount[row][td]+'</td>'; 
      } 
      table+='</tr>'; 
     } 
     table+='</table>'; 
     document.getElementById('tabular').innerHTML=table; 
    } 
</script> 
</div> 
</body> 
</html>