8

How can I test if a LatLng point is within the bounds of a circle? (Google Maps JavaScript v3)

The getBounds() method returns the bounding box for the circle, which is a rectangle, so if a point falls outside the circle but within the bounding box, you'll get the wrong answer.

Danny Lin
  • 180
  • 8
Michael Schade
  • 408
  • 1
  • 5
  • 14
  • Try my solution at: https://stackoverflow.com/questions/7997627/google-maps-how-to-get-the-distance-between-two-point-in-metre/46188650#46188650 – Nguyen Chi Thanh Sep 13 '17 at 04:06

6 Answers6

15

Use the spherical geometry library (be sure to include it with the API)

function pointInCircle(point, radius, center)
{
    return (google.maps.geometry.spherical.computeDistanceBetween(point, center) <= radius)
}
geocodezip
  • 158,664
  • 13
  • 220
  • 245
3

You could just do the distance comparison manually, fairly trivially.

(x1 - x2)^2 + (y1 - y2)^2 <= D^2 
sheu
  • 5,653
  • 17
  • 32
  • 1
    beware this does not take into consideration spherical mapping on the earth. Lat/Lng are not equal and therefore this is wrong near the poles (but more accurate near the equator). – toobulkeh Dec 13 '15 at 22:34
  • also, this does not take the curvature of earth into consideration, nor the projection used. – m_x Dec 22 '15 at 14:15
2

You might use the Circle object to show it;

new google.maps.Circle({
            map : map,
            center : new google.maps.LatLng(lat,lng),
            strokeColor:'#00FFCC',
            strokeWeight:2,
            fillOpacity:0,
            radius:radiusm
        });

And apply the Pythagorean theorem to coordinates: but in this case to make it a "real" circle since the ration between 1° of lat and longitude varies across latitudes, you should at the very least adjust them like:

var kmRadius = 100; //(radius of 100 km)
var lat_gap = kmRadius/111.1;
var lng_gap = lat_gap / Math.cos(lat / (Math.PI/180));
Riccardo Zorn
  • 5,590
  • 1
  • 20
  • 36
1

Why don't you simple calculate this with Pythagorean theorem? You know a²+b²=c². If c is lower than r (radius) you know it is inside.

var isInside=Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) >= r*r;
rekire
  • 47,260
  • 30
  • 167
  • 264
  • Thanks, that's what I ended up doing, using the API's built-in functions. It would be easier if the circle object had a containsLocation() method. (I would also love a fitBounds() method!) You can see the code here: [Circle Selection for Google Maps](http://www.mvjantzen.com/blog/?p=3190). – Michael Schade Jan 31 '13 at 05:27
  • 2
    beware this does not take into consideration spherical mapping on the earth. Lat/Lng are not equal and therefore this is wrong near the poles (but more accurate near the equator). – toobulkeh Dec 13 '15 at 22:34
  • also, this does not take the curvature of earth into consideration, nor the projection used. – m_x Dec 22 '15 at 14:15
0

Something like this should do the trick (code not tested):

public boolean pointInCircle(Circle c, LatLng coord) {
  Rectangle r = c.getBounds();
  double rectX = r.getX();
  double rectY = r.getY();
  double rectWidth = r.getWidth();
  double rectHeight = r.getHeight();

  double circleCenterX = rectX + rectWidth/2;
  double circleCenterY = rectY + rectHeight/2;

  double lat = coord.getLatitude();
  double lon = coord.getLongitude();

  // Point in circle if (x−h)^2 + (y−k)^2 <= r^2
  double rSquared = Math.pow(rectWidth/2, 2);
  double point = Math.pow(lat - circleCenterX, 2) + Math.pow(lon - circleCenterY, 2);

  return (point <= rSquared) ? true : false;
}
lumiera
  • 1
  • 1
  • 2
    beware this does not take into consideration spherical mapping on the earth. Lat/Lng are not equal and therefore this is wrong near the poles (but more accurate near the equator). – toobulkeh Dec 13 '15 at 22:35
  • also, this does not take the curvature of earth into consideration, nor the projection used. – m_x Dec 22 '15 at 14:16
0

Try this (Javascript):

const toRadians = (val) => {
   return val * Math.PI / 180;
}
const toDegrees = (val) => {
   return val * 180 / Math.PI;
}
// Calculate a point winthin a circle
// circle ={center:LatLong, radius: number} // in metres
const pointInsideCircle = (point, circle) => {
    let center = circle.center;
    let distance = distanceBetween(point, center);

    return distance < circle.radius; // Use '<=' if you want to get all points in the border
};

const distanceBetween = (point1, point2) => {
    var R = 6371e3; // metres
    var φ1 = toRadians(point1.latitude);
    var φ2 = toRadians(point2.latitude);
    var Δφ = toRadians(point2.latitude - point1.latitude);
    var Δλ = toRadians(point2.longitude - point1.longitude);

    var a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
            Math.cos(φ1) * Math.cos(φ2) *
            Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return R * c;
}

References: http://www.movable-type.co.uk/scripts/latlong.html

This npm helper module does the same thing and returns a boolean as to whether the item is in the circle.

https://www.npmjs.com/package/fencery

hkd987
  • 3
  • 3
  • Since you're using es6: `const toRadians = val => val * Math.PI / 180;` `const toDegrees = val => val * 180 / Math.PI;` – pmrotule Oct 24 '17 at 07:02