2013-08-06 333 views
4

我正在尋找一個優雅的解決方案計算幾個座標之間的center(例如,簡單地居中映射到多邊形的中心)。計算經度和緯度的中心座標

表:locations

id | city | latitude | longitude 
----------------------------------------------- 
1 | Berlin | 52.524268 | 13.406290 
----------------------------------------------- 
2 | London | 51.508129 | -0.1280050  
----------------------------------------------- 
3 | Hamburg | 53.551084 | 9.9936817 
----------------------------------------------- 
4 | Amsterdam | 52.370215 | 4.8951678 
----------------------------------------------- 

目前的計算:

function calculateCenter($array_locations) { 

    $minlat = false; 
    $minlng = false; 
    $maxlat = false; 
    $maxlng = false; 

    foreach ($array_locations as $geolocation) { 

     if ($minlat === false) { $minlat = $geolocation['lat']; } else { $minlat = ($geolocation['lat'] < $minlat) ? $geolocation['lat'] : $minlat; } 
     if ($maxlat === false) { $maxlat = $geolocation['lat']; } else { $maxlat = ($geolocation['lat'] > $maxlat) ? $geolocation['lat'] : $maxlat; } 
     if ($minlng === false) { $minlng = $geolocation['lon']; } else { $minlng = ($geolocation['lon'] < $minlng) ? $geolocation['lon'] : $minlng; } 
     if ($maxlng === false) { $maxlng = $geolocation['lon']; } else { $maxlng = ($geolocation['lon'] > $maxlng) ? $geolocation['lon'] : $maxlng; } 
    } 

    // Calculate the center 
    $lat = $maxlat - (($maxlat - $minlat)/2); 
    $lon = $maxlng - (($maxlng - $minlng)/2); 

    return array($lat, $lon); 
} 
+0

看一看的k均值算法 - HTTP:// phpir。com/clustering –

+1

你正在做最小和最大緯度/經度的平均值,如何回答所有緯度/經度的平均值? – miki

+0

@miki平均所有位置不起作用。例如,柏林是這個例子的東部,倫敦是西部最多的。如果我們增加100個城鎮,所有城市都位於柏林西部,那麼西部/東部地圖的中心位置不需要改變,但平均偏移量接近柏林。 – chux

回答

8

當您使用Google地圖時,您可以使用getBounds()方法和getCenter()方法。

我已經重新排列了你的座標以形成一個凸多邊形(所有頂點向外'離開中心)。通過將第一個座標作爲polygonCoords數組中的第一個和最後一個值來關閉多邊形。

jsfiddle

var map; 
var polygon; 
var bounds = new google.maps.LatLngBounds(); 
var i; 
var myLatLng = new google.maps.LatLng(52.5,6.6); 
var myOptions = { 
    zoom: 5, 
    center: myLatLng, 
    mapTypeId: google.maps.MapTypeId.TERRAIN 
}; 
map = new google.maps.Map(document.getElementById("map_canvas"), 
    myOptions); 

var polygonCoords = [ 
    new google.maps.LatLng(52.524268,13.406290), 
    new google.maps.LatLng(53.551084,9.9936817), 
    new google.maps.LatLng(51.508129,-0.1280050), 
    new google.maps.LatLng(52.370215,4.8951678), 
    new google.maps.LatLng(52.524268,13.406290)//Start & end point 
    ]; 

polygon = new google.maps.Polygon({ 
    paths: polygonCoords, 
    strokeColor: "#FF0000", 
    strokeOpacity: 0.8, 
    strokeWeight: 3, 
    fillColor: "#FF0000", 
    fillOpacity: 0.05 
}); 
polygon.setMap(map); 

for (i = 0; i < polygonCoords.length; i++) { 
    bounds.extend(polygonCoords[i]); 
} 

// The Center of the polygon 
var latlng = bounds.getCenter(); 

var marker = new google.maps.Marker({ 
    position: latlng, 
    map: map, 
    title:latlng.toString() 
}); 
3

平均您的經度和緯度的作品在許多情況下,但在很多情況下問題。例如,你有2個城市,東京(長= 140)和西雅圖(長-122),你的平均經度是18,在歐洲的某個地方。你會期待更接近180度的國際日期線。

最直接的,沒有問題的方法是平均矢量,就好像每個起源於地球中心。

僞代碼,(假定弧度)

for each lat,long 
    // assume 1 radii from the earth's center. 
    // covert lat, long, and radii into x,y,z (spherical to cartesian coordinates) 
    r=1, theta=pi/2 - lat, phi=long 
    x = r*sin(theta)*cos(phi) 
    y = r*sin(theta)*sin(phi) 
    z = r*cos(theta) 
    N++; 
    // accumulate x,y,z 
    sum_x += x, etc. 
// average x,y,z 
avg_x = sum_x/N, etc. 
// convert x,y,z back to spherical co-ordinates to get the lat/long center. 
rho = sqrt(avg_x*avg_x + avg_y*avg_y + avg_z*avg_z) 
lat = pi/2 - acos(avg_z/rho) // acos() results are 0 to pi 
long = atan2(avg_y, avg_x) // 4 quadrant arctangent 

[編輯校正的球面座標到直角]

+0

看起來像一個很好的答案,但是什麼是'z',並且'argx'和'argy'的意思是'avgx'和'avgy'還是缺失? – acraig5075

+0

-1:這個算法錯誤或缺失:你自己的西雅圖(48,-122)和東京(41,140)的例子給出了(193,32)的錯誤結果,並且使用OP的值經緯度是錯誤的(7.1,52.4)? – acraig5075

+0

@ acraig5075謝謝。該算法是好的,但座標映射是混亂的。我在西雅圖/東京的中點現在在白令海(56.2,-175.0)。 – chux

2

谷歌使用一個墨卡託投影,治療地球爲細長圓柱。因此,要找到該投影中心的問題。

對於每個緯度/經度對,轉換成經縮放的x,y座標(使用弧度)映射:

x = long 
y = ln(tan(pi/4 + lat/2)) // Mercator projection 

然後,對於x & Y,找到最小和最大的平均以獲得你的中心。轉換回經/緯如下

Pseudo code 
center_long = average(minimum_x, maximum_x) 
center_lat = (atan(exp(average(minimum_y, maximum_y))) - pi/4)*2 

中心經度的計算工作正常,如果不是爲圓柱投影地球的圓形性質。如果東半球和西半球都有經度(有些是負面的,有些是正面的),那麼可能需要額外的工作。

Pseudo code 
sort the longitudes into ascending order 
for each longitude 
    difference = longitude(i-1) - longitude(i) 
    // for first, use longitude(0) - longitude(last) 
    if (difference < 0) add 2*pi (360 degrees) 
    Keep track of index of minimal difference 
The pair with the minimal difference represents the pair that most tightly contains all longitudes. 
Average this pair for the center longitude. 
If this pair was index 0 & last, add pi (180 degrees) 

OP 4城市的結果:(52.4 N,7.0 E)


這是我的第二個答案,第一個沒有得到OP的帖子的癥結所在。由於它有一定的價值,它依然存在。