Skip to content

Instantly share code, notes, and snippets.

@miquels
Forked from tlhunter/average-geolocation.js
Last active August 9, 2019 08:10
Show Gist options
  • Save miquels/17fb27dd8a93fb13350f58afe6eb93be to your computer and use it in GitHub Desktop.
Save miquels/17fb27dd8a93fb13350f58afe6eb93be to your computer and use it in GitHub Desktop.
Calculate the center/average of multiple GeoLocation coordinates
#
# Calculate the center/average of multiple GeoLocation coordinates
# Expects an array of array refs: ([lat, long], [lat, long]).
#
# @url http://stackoverflow.com/a/14231286/538646
#
use warnings;
use strict;
sub PI() { 4 * atan2(1, 1) }
sub DEG_TO_RAD() { PI / 180 }
sub RAD_TO_DEG() { 180 / PI }
sub average_geolocation {
return ($_[0][0], $_[0][1]) if @_ == 1;
my ($x, $y, $z, $total) = (0.0, 0.0, 0.0, 0);
foreach my $coord (@_) {
my $lat = $coord->[0] * DEG_TO_RAD;
my $long = $coord->[1] * DEG_TO_RAD;
my $count = $coord->[2] // 1;
$x += $count * cos($lat) * cos($long);
$y += $count * cos($lat) * sin($long);
$z += $count * sin($lat);
$total += $count;
}
$x /= $total;
$y /= $total;
$z /= $total;
my $central_long = atan2($y, $x);
my $central_sqrt = sqrt($x * $x + $y * $y);
my $central_lat = atan2($z, $central_sqrt);
($central_lat * RAD_TO_DEG, $central_long * RAD_TO_DEG);
}
# expect ~ 37.790831, -122.407169
my @sf = ([ 37.797749, -122.412147], [37.789068, -122.390604], [37.785269, -122.421975]);
printf("sf: (%f, %f)\n", average_geolocation(@sf));
# expect ~ 19.214172, -176.730317
my @globe = (
# Japan
[ 37.928969, 138.979637],
# Nevada
[ 39.029788, -119.594585],
# New Zealand
[-39.298237, 175.717917],
);
printf("globe: (%f, %f)\n", average_geolocation(@globe));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment