Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello

I looked at GIS::Distance to measure distances between two geo locations. But now I want to determine the longitude and latitude of a location at a given distance and direction from a given location.

E.g. given a location at 50.754444 6.020833, I want to determine the latitude and longitude at 75 kilometer east of that location. How can I do that?

Thanks

  • Comment on Determine lat/lon of geo location at given distance from other location

Replies are listed 'Best First'.
Re: Determine lat/lon of geo location at given distance from other location
by holli (Abbot) on Jun 26, 2019 at 10:08 UTC
    holli@HOLLI-DESKTOP:~$ perl -MData::Dumper -MGeo::Calc -e 'print Dumpe +r( Geo::Calc->new( lat => 50.754444, lon => 6.020833 )->destination_p +oint( 90, 75 ) );' $VAR1 = { 'final_bearing' => '90.000823', 'lat' => '50.754444', 'lon' => '6.021896' };
    Edit: Updated the code to a runable one liner. I couldn't do that before because, boy this module is depency hell. I installed it to a fresh perl and it installed at least a 100 dependent modules or so. Most of which seems to be coming from Moose though. Which is kind of a must have nowadays anyway.


    holli

    You can lead your users to water, but alas, you cannot drown them.
Re: Determine lat/lon of geo location at given distance from other location
by bliako (Abbot) on Jun 26, 2019 at 10:33 UTC
    #!/usr/bin/env perl use strict; use warnings; use Geo::Ellipsoid; print "\nUsing Geo::Ellipsoid\n"; my $gel = Geo::Ellipsoid->new( ellipsoid => 'WGS84', units => 'degrees', distance_units => 'meter', longitude => 0, bearing => 0, ); my @curlatlon1 = (37.889086, 41.129166); my @curlatlon2 = (39.668930, 66.993292); # displacement from 1 to 2 my ($x,$y) = $gel->displacement(@curlatlon1, @curlatlon2); print "displacement from @curlatlon1 to @curlatlon2 = ($x,$y)\n"; my @newlatlon = $gel->location(@curlatlon1, $x, $y); print "moving from @curlatlon1 by ($x,$y) gets me to @newlatlon (corre +ct is @curlatlon2)\n"; print "dist: ".sqrt($x*$x+$y*$y) .", bearing: ".180*atan2($y,$x)/3.14." degrees\n"; # from 2 to 1 ($x,$y) = $gel->displacement(@curlatlon2, @curlatlon1); print "displacement from @curlatlon2 to @curlatlon1 = ($x,$y)\n"; @newlatlon = $gel->location(@curlatlon2, $x, $y); print "moving from @curlatlon2 by ($x,$y) gets me to @newlatlon (corre +ct is @curlatlon1)\n"; print "dist: ".sqrt($x*$x+$y*$y) .", bearing: ".180*atan2($y,$x)/3.14." degrees\n"; use Geo::Calc; print "\nUsing Geo::Calc\n"; my $cur1 = Geo::Calc->new(lat=>$curlatlon1[0], lon=>$curlatlon1[1]); my $bear = $cur1->bearing_to({lat=>$curlatlon2[0], lon=>$curlatlon2[1] +}); my $dist = $cur1->distance_to({lat=>$curlatlon2[0], lon=>$curlatlon2[1 +]}); my $newlatlon = $cur1->destination_point($bear, $dist); print "from (" .$cur1->get_lat().",".$cur1->get_lon() .") moving by $dist m and $bear degrees got me to (" .$newlatlon->{'lat'}.",".$newlatlon->{'lon'} .")\n";

      I've been playing with this source for several days and have mixed results to show for it.

      Using Geo::Ellipsoid Initial location is 50.754444 6.020833 New location is 50.7496017030457 7.08357125653985 diff is 1.06273825653985 sanity check for earth assuming a sphere ratio is 111.319444444444 km/degree distance is 118.303432307874 dist is 74.9999999999233 $ cat 2.geo.pl #!/usr/bin/env perl use 5.011; use warnings; use Geo::Ellipsoid; print "\nUsing Geo::Ellipsoid\n"; my $gel = Geo::Ellipsoid->new( ellipsoid => 'WGS84', #default value units => 'degrees', distance_units => 'kilometer', longitude => 6.020833, bearing => 0, ); my @ini_lat_lon1 = ( 50.754444, 6.020833 ); say "Initial location is @ini_lat_lon1"; my ( $x, $y ) = ( 75, 0 ); my @new_lat_lon = $gel->location( @ini_lat_lon1, $x, $y ); say "New location is @new_lat_lon"; my $diff = $new_lat_lon[1] - $ini_lat_lon1[1]; say "diff is $diff"; say "sanity check for earth assuming a sphere"; my $circum = 40075; #km my $circle = 360; #degrees my $ratio = $circum / $circle; say "ratio is $ratio km/degree"; my $distance = $diff * $ratio; say "distance is $distance"; ## trying another method # my $dist = $geo->range( @origin, @destination ); my $dist = $gel->range( @ini_lat_lon1, @new_lat_lon ); say "dist is $dist"; __END__ $

      My sanity check fails. The documentation warns of non-Euclidean effects: the cpan listing

      NOTE: The x and y displacements are only approximations and only valid between two locations that are fairly near to each other. Beyond 10 kilometers or more, the concept of X and Y on a curved surface loses its meaning.

      Also, for those who want to replicate these things, it does take a lot of time for dependencies to be satisfied. I like to know that I have it all ready to go for when I get stranded on an island in the Pacific.

Re: Determine lat/lon of geo location at given distance from other location
by daxim (Curate) on Jun 26, 2019 at 08:22 UTC
Re: Determine lat/lon of geo location at given distance from other location
by Eily (Monsignor) on Jun 26, 2019 at 09:50 UTC

    Good question! There doesn't seem to be a module to do that. What you can do however, is to find the distance between (50.754444, 6.020833) and (50.754444, 7.020833), get the length of a degree, and use $distance/$degree_length to know how many degrees a given distance is.

    Edit: my bad, there actually is a module that does that :)

      longitude distance/degree changes with latitude so your suggestion is only correct moving strictly east or west and introduces errors that are a function of the north or south component of the displacement.

      Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
Re: Determine lat/lon of geo location at given distance from other location
by BillKSmith (Monsignor) on Jun 26, 2019 at 14:06 UTC
    bliako's last example is probably what you need. You still should verify that it meets (or exceeds) your accuracy requirements. Is the module's definition of 'bearing' consistent with yours? Note that the exact answer depends not only on your model for the shape of the earth, but possibly on the constants used in that model.
    Bill

      holli beat me to it by a few minutes but mine will get you from Batman to Samarkand and leave you off by the sides of the Tashkent road. 2271 Km in under 2 seconds!