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);
}
The latitude is the angle formed by a line going from the center of the earth to the equator at the point on the equator that is closed to the point of interest and another line that goes from the center of the earth to the parallel that goes through the point of interest.
A line can be drawn from the center of the earth out to this new x, y, z coordinate, and the point where the line intersects the surface of the earth is the geographic midpoint. This surface point is converted into the latitude and longitude for the midpoint.
The centroid of finitely many points is simply the arithmetic mean of each of the coordinates. So just sum up the latitudes and longitudes and divide by the number of points.
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()
});
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With