【问题标题】:Calculate the center of latitude and longitude coordinates计算经纬度坐标的中心
【发布时间】:2013-08-07 18:15:10
【问题描述】:

我正在寻找一种优雅的解决方案,它可以计算多个 坐标之间的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);
}

【问题讨论】:

  • 看看kmeans算法-phpir.com/clustering
  • 您正在计算最小和最大纬度/经度的平均值,如何计算所有纬度/经度的平均值?
  • @miki 平均所有位置不起作用。例如。柏林是最东部的例子,伦敦是最西部的例子。如果我们添加 100 个城镇,都在柏林以西一点,地图的西/东中心不需要改变,但平均移动靠近柏林。

标签: latitude-longitude google-maps php google-maps geolocation latitude-longitude


【解决方案1】:

当您使用谷歌地图时,您可以使用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()
});

【讨论】:

    【解决方案2】:

    平均您的纬度和经度在许多情况下有效,但在许多情况下会出现问题。例如,您有 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
    

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

    【讨论】:

    • 看起来是个不错的答案,但 z 是什么,argxargy 是指 avgxavgy 还是缺少什​​么?
    • -1:此算法有问题或缺失:您自己的西雅图 (48,-122) 和东京 (41,140) 示例给出了 (193,32) 的错误结果并使用了 OP 的值纬度/经度是错误的 (7.1,52.4)?
    • @acraig5075 谢谢。算法没问题,但坐标映射搞砸了。我的中点西雅图/东京现在 (56.2, -175.0) 在白令海。
    • 我反对我自己的帖子以支持第二个答案。此方法可以很好地找到位置的平均值,但不是 OP 要求的中心。有关详细信息,请参阅其他帖子。叹息
    【解决方案3】:

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

    对于每个纬度/经度对,转换为地图缩放的 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 帖子的症结所在。因为它有一些价值,所以它仍然存在。

    【讨论】:

      猜你喜欢
      • 2011-10-04
      • 2015-10-04
      • 2014-12-16
      • 2016-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多