Calculate the center of latitude and longitude coordinates

拥有回忆 提交于 2019-12-10 09:40:26

问题


I'm looking for a elegant solution that calculates the center between several latitude-longitude coordinates (for example, to simply center a map to the center of a google-maps polygon).

Table: 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
-----------------------------------------------

The current calculation:

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

回答1:


As you are using Google Maps you can use getBounds() method and getCenter() method.

I have rearranged your coordinates to form a Convex Polygon (All the vertices point 'outwards', away from the center).The polygon is closed by having the first coordinate as the first and last value in polygonCoords array.

See 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:


Averaging your latitudes and longitudes works in many cases, but have problems in a number of cases. Example, you have 2 cites, Tokyo (long = 140) and Seattle (long -122), your average longitude is 18, somewhere in Europe. You would expect something closer to the international date line, 180 degrees away.

The most direct, no problem method, is to average the vectors as if each originated from the earth's center.

Pseudo code, (assumes radians)

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

[Edit Corrected spherical co-ordinates to cartesian]




回答3:


Google uses a Mercator projection, treating the earth as an elongated cylinder. Thus the problem to to find the center of that projection.

For each lat/long pair, convert to map scaled x,y co-ordinates (using radians):

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

Then, for x & y, find the average of the minimum and maximum to get your center. Convert back to lat/long as follows

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

The calculation of the center longitude works fine were it not for the circular nature of the cylindric Earth projection. If the longitudes are in both the Eastern and Western hemispheres (some negative, some positive), than additional work may be needed.

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 city result: (52.4 N, 7.0 E)


This is my second answer, for the first does not get the the crux of OP's post. Since it has some value it remains.



来源:https://stackoverflow.com/questions/18085275/calculate-the-center-of-latitude-and-longitude-coordinates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!