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.
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.
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.
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:
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)
:
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
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