Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate the latlng of a point a certain distance away from another?

To draw a circle on map I have a center GLatLng (A) and a radius (r) in meters.

Here's a diagram:

           -----------         --/           \--       -/                 \-      /                     \     /                       \    /                   r     \    |            *-------------*    \             A           / B     \                       /      \                     /       -\                 /-         --\           /--            ----------- 

How to calculate the GLatLng at position B? Assuming that r is parallel to the equator.

Getting the radius when A and B is given is trivial using the GLatLng.distanceFrom() method - but doing it the other way around not so. Seems that I need to do some heavier math.

like image 301
Rene Saarsoo Avatar asked Apr 14 '10 11:04

Rene Saarsoo


People also ask

How do you find the distance between two Latlng?

from math import cos, asin, sqrt, pi def distance(lat1, lon1, lat2, lon2): p = pi/180 a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2 return 12742 * asin(sqrt(a)) #2*R*asin... And for the sake of completeness: Haversine on Wikipedia.

How do I calculate the distance between two points specified by latitude and longitude?

For this divide the values of longitude and latitude of both the points by 180/pi. The value of pi is 22/7. The value of 180/pi is approximately 57.29577951. If we want to calculate the distance between two places in miles, use the value 3, 963, which is the radius of Earth.


2 Answers

We will need a method that returns the destination point when given a bearing and the distance travelled from a source point. Luckily, there is a very good JavaScript implementation by Chris Veness at Calculate distance, bearing and more between Latitude/Longitude points.

The following has been adapted to work with the google.maps.LatLng class:

Number.prototype.toRad = function() {    return this * Math.PI / 180; }  Number.prototype.toDeg = function() {    return this * 180 / Math.PI; }  google.maps.LatLng.prototype.destinationPoint = function(brng, dist) {    dist = dist / 6371;      brng = brng.toRad();       var lat1 = this.lat().toRad(), lon1 = this.lng().toRad();     var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +                          Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));     var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *                                 Math.cos(lat1),                                  Math.cos(dist) - Math.sin(lat1) *                                 Math.sin(lat2));     if (isNaN(lat2) || isNaN(lon2)) return null;     return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg()); } 

You would simply use it as follows:

var pointA = new google.maps.LatLng(25.48, -71.26);  var radiusInKm = 10;  var pointB = pointA.destinationPoint(90, radiusInKm); 

Here is a complete example using Google Maps API v3:

<!DOCTYPE html> <html>  <head>     <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>     <title>Google Maps Geometry</title>     <script src="http://maps.google.com/maps/api/js?sensor=false"             type="text/javascript"></script>  </head>  <body>     <div id="map" style="width: 400px; height: 300px"></div>      <script type="text/javascript">        Number.prototype.toRad = function() {          return this * Math.PI / 180;       }        Number.prototype.toDeg = function() {          return this * 180 / Math.PI;       }        google.maps.LatLng.prototype.destinationPoint = function(brng, dist) {          dist = dist / 6371;            brng = brng.toRad();             var lat1 = this.lat().toRad(), lon1 = this.lng().toRad();           var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +                                Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));           var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *                                       Math.cos(lat1),                                        Math.cos(dist) - Math.sin(lat1) *                                       Math.sin(lat2));           if (isNaN(lat2) || isNaN(lon2)) return null;           return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());       }        var pointA = new google.maps.LatLng(40.70, -74.00);   // Circle center       var radius = 10;                                      // 10km        var mapOpt = {           mapTypeId: google.maps.MapTypeId.TERRAIN,          center: pointA,          zoom: 10       };        var map = new google.maps.Map(document.getElementById("map"), mapOpt);        // Draw the circle       new google.maps.Circle({          center: pointA,          radius: radius * 1000,       // Convert to meters          fillColor: '#FF0000',          fillOpacity: 0.2,          map: map       });        // Show marker at circle center       new google.maps.Marker({          position: pointA,          map: map       });        // Show marker at destination point       new google.maps.Marker({          position: pointA.destinationPoint(90, radius),          map: map       });    </script>  </body>  </html> 

Screenshot:

Google Maps Geometry

UPDATE:

In reply to Paul's comment below, this is what happens when the circle wraps around one of the poles.

Plotting pointA near the north pole, with a radius of 1,000km:

  var pointA = new google.maps.LatLng(85, 0);   // Close to north pole   var radius = 1000;                            // 1000km 

Screenshot for pointA.destinationPoint(90, radius):

Close to north pole

like image 191
Daniel Vassallo Avatar answered Sep 24 '22 08:09

Daniel Vassallo


To calculate a lat,long point at a given bearing and distance from another you can use google´s JavaScript implementation:

var pointA = new google.maps.LatLng(25.48, -71.26);  var distance = 10; // 10 metres var bearing = 90; // 90 degrees var pointB = google.maps.geometry.spherical.computeOffset(pointA, distance, bearing); 

See https://developers.google.com/maps/documentation/javascript/reference#spherical For documentation

like image 29
Fredrik Harloff Avatar answered Sep 25 '22 08:09

Fredrik Harloff