Given a set of latitude and longitude points, how can I calculate the latitude and longitude of the center point of that set (aka a point that would center a view on all poi
This is is the same as a weighted average problem where all the weights are the same, and there are two dimensions.
Find the average of all latitudes for your center latitude and the average of all longitudes for the center longitude.
Caveat Emptor: This is a close distance approximation and the error will become unruly when the deviations from the mean are more than a few miles due to the curvature of the Earth. Remember that latitudes and longitudes are degrees (not really a grid).
Thanks! Here is a C# version of OP's solutions using degrees. It utilises the System.Device.Location.GeoCoordinate class
public static GeoCoordinate GetCentralGeoCoordinate(
IList<GeoCoordinate> geoCoordinates)
{
if (geoCoordinates.Count == 1)
{
return geoCoordinates.Single();
}
double x = 0;
double y = 0;
double z = 0;
foreach (var geoCoordinate in geoCoordinates)
{
var latitude = geoCoordinate.Latitude * Math.PI / 180;
var longitude = geoCoordinate.Longitude * Math.PI / 180;
x += Math.Cos(latitude) * Math.Cos(longitude);
y += Math.Cos(latitude) * Math.Sin(longitude);
z += Math.Sin(latitude);
}
var total = geoCoordinates.Count;
x = x / total;
y = y / total;
z = z / total;
var centralLongitude = Math.Atan2(y, x);
var centralSquareRoot = Math.Sqrt(x * x + y * y);
var centralLatitude = Math.Atan2(z, centralSquareRoot);
return new GeoCoordinate(centralLatitude * 180 / Math.PI, centralLongitude * 180 / Math.PI);
}
I found this post very useful so here is the solution in PHP. I've been using this successfully and just wanted to save another dev some time.
/**
* Get a center latitude,longitude from an array of like geopoints
*
* @param array data 2 dimensional array of latitudes and longitudes
* For Example:
* $data = array
* (
* 0 = > array(45.849382, 76.322333),
* 1 = > array(45.843543, 75.324143),
* 2 = > array(45.765744, 76.543223),
* 3 = > array(45.784234, 74.542335)
* );
*/
function GetCenterFromDegrees($data)
{
if (!is_array($data)) return FALSE;
$num_coords = count($data);
$X = 0.0;
$Y = 0.0;
$Z = 0.0;
foreach ($data as $coord)
{
$lat = $coord[0] * pi() / 180;
$lon = $coord[1] * pi() / 180;
$a = cos($lat) * cos($lon);
$b = cos($lat) * sin($lon);
$c = sin($lat);
$X += $a;
$Y += $b;
$Z += $c;
}
$X /= $num_coords;
$Y /= $num_coords;
$Z /= $num_coords;
$lon = atan2($Y, $X);
$hyp = sqrt($X * $X + $Y * $Y);
$lat = atan2($Z, $hyp);
return array($lat * 180 / pi(), $lon * 180 / pi());
}
Out of object in PHP. Given array of coordinate pairs, returns center.
/**
* Calculate center of given coordinates
* @param array $coordinates Each array of coordinate pairs
* @return array Center of coordinates
*/
function getCoordsCenter($coordinates) {
$lats = $lons = array();
foreach ($coordinates as $key => $value) {
array_push($lats, $value[0]);
array_push($lons, $value[1]);
}
$minlat = min($lats);
$maxlat = max($lats);
$minlon = min($lons);
$maxlon = max($lons);
$lat = $maxlat - (($maxlat - $minlat) / 2);
$lng = $maxlon - (($maxlon - $minlon) / 2);
return array("lat" => $lat, "lon" => $lng);
}
Taken idea from #4
As an appreciation for this thread, here is my little contribution with the implementation in Ruby, hoping that I will save someone a few minutes from their precious time:
def self.find_center(locations)
number_of_locations = locations.length
return locations.first if number_of_locations == 1
x = y = z = 0.0
locations.each do |station|
latitude = station.latitude * Math::PI / 180
longitude = station.longitude * Math::PI / 180
x += Math.cos(latitude) * Math.cos(longitude)
y += Math.cos(latitude) * Math.sin(longitude)
z += Math.sin(latitude)
end
x = x/number_of_locations
y = y/number_of_locations
z = z/number_of_locations
central_longitude = Math.atan2(y, x)
central_square_root = Math.sqrt(x * x + y * y)
central_latitude = Math.atan2(z, central_square_root)
[latitude: central_latitude * 180 / Math::PI,
longitude: central_longitude * 180 / Math::PI]
end
Here is the Android version based on @Yodacheese's C# answer using Google Maps api:
public static LatLng GetCentralGeoCoordinate(List<LatLng> geoCoordinates) {
if (geoCoordinates.size() == 1)
{
return geoCoordinates.get(0);
}
double x = 0;
double y = 0;
double z = 0;
for(LatLng geoCoordinate : geoCoordinates)
{
double latitude = geoCoordinate.latitude * Math.PI / 180;
double longitude = geoCoordinate.longitude * Math.PI / 180;
x += Math.cos(latitude) * Math.cos(longitude);
y += Math.cos(latitude) * Math.sin(longitude);
z += Math.sin(latitude);
}
int total = geoCoordinates.size();
x = x / total;
y = y / total;
z = z / total;
double centralLongitude = Math.atan2(y, x);
double centralSquareRoot = Math.sqrt(x * x + y * y);
double centralLatitude = Math.atan2(z, centralSquareRoot);
return new LatLng(centralLatitude * 180 / Math.PI, centralLongitude * 180 / Math.PI);
}
in app build.gradle add:
implementation 'com.google.android.gms:play-services-maps:17.0.0'