计算纬度和经度坐标的中心

时间:2013-08-06 16:11:42

标签: php google-maps geolocation latitude-longitude

我正在寻找一个优雅的解决方案来计算几个坐标之间的center(例如,简单地将地图居中到{{{}}的中心3}}多边形)。

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

3 个答案:

答案 0 :(得分: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()
});

答案 1 :(得分: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

[编辑校正的球形坐标到笛卡儿]

答案 2 :(得分:2)

谷歌使用墨卡托投影,将地球视为一个细长的圆柱体。因此找到该投影中心的问题。

对于每个lat / long对,转换为map scaled x,y坐标(使用弧度):

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

然后,对于x&amp; y,找到获得中心的最小值和最大值的平均值。转换回lat / long如下

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的帖子的关键。因为它有一些价值,所以它仍然存在。