5

我正在寻找一种优雅的解决方案来计算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);
}
4

3 回答 3

9

当您使用 Google Maps 时,您可以使用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()
});
于 2013-08-07T23:34:08.687 回答
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

[编辑校正球面坐标为笛卡尔]

于 2013-08-06T23:30:50.110 回答
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 帖子的症结所在。因为它有一些价值,所以它仍然存在。

于 2013-08-07T18:00:43.930 回答