15

Ok pretty self explanatory. I'm using google maps and I'm trying to find out if a lat,long point is within a circle of radius say x (x is chosen by the user).

Bounding box will not work for this. I have already tried using the following code:

distlatLng = new google.maps.LatLng(dist.latlng[0],dist.latlng[1]);
var latLngBounds = circle.getBounds();
if(latLngBounds.contains(distlatLng)){
      dropPins(distlatLng,dist.f_addr);
}

This still results in markers being places outside the circle.

I'm guess this is some simple maths requiring the calculation of the curvature or an area but I'm not sure where to begin. Any suggestions?

Stuart Beard
  • 180
  • 1
  • 2
  • 12
  • [This](http://stackoverflow.com/questions/2344165/calculate-gps-coordinates-to-form-a-radius-of-given-size) SO post might give you the insight you need. – npinti Dec 16 '10 at 18:09

5 Answers5

10

Unfortunately Pythagoras is no help on a sphere. Thus Stuart Beard's answer is incorrect; longitude differences don't have a fixed ratio to metres but depend on the latitude.

The correct way is to use the formula for great circle distances. A good approximation, assuming a spherical earth, is this (in C++):

/** Find the great-circle distance in metres, assuming a spherical earth, between two lat-long points in degrees. */
inline double GreatCircleDistanceInMeters(double aLong1,double aLat1,double aLong2,double aLat2)
    {
    aLong1 *= KDegreesToRadiansDouble;
    aLat1 *= KDegreesToRadiansDouble;
    aLong2 *= KDegreesToRadiansDouble;
    aLat2 *= KDegreesToRadiansDouble;
    double cos_angle = sin(aLat1) * sin(aLat2) + cos(aLat1) * cos(aLat2) * cos(aLong2 - aLong1);

    /*
    Inaccurate trig functions can cause cos_angle to be a tiny amount
    greater than 1 if the two positions are very close. That in turn causes
    acos to give a domain error and return the special floating point value
    -1.#IND000000000000, meaning 'indefinite'. Observed on VS2008 on 64-bit Windows.
    */
    if (cos_angle >= 1)
        return 0;

    double angle = acos(cos_angle);
    return angle * KEquatorialRadiusInMetres;
    }

where

const double KPiDouble = 3.141592654;
const double KDegreesToRadiansDouble = KPiDouble / 180.0;

and

/**
A constant to convert radians to metres for the Mercator and other projections.
It is the semi-major axis (equatorial radius) used by the WGS 84 datum (see http://en.wikipedia.org/wiki/WGS84).
*/
const int32 KEquatorialRadiusInMetres = 6378137;
Graham Asher
  • 1,648
  • 1
  • 24
  • 34
  • Completely agree that this is correct. However at the time accuracy was not 100% required. – Stuart Beard Aug 15 '14 at 08:46
  • 2
    You've still selected an answer that is dangerously wrong near the poles, @StuartBeard, I'm all for approximations where appropriate, but I think your selection of a cartesian distance in a non-cartesian space as the "Answer" is irresponsible. – Carl F. Feb 17 '16 at 14:43
5

Use Google Maps API geometry library to calculate distance between circle's center and your marker, and then compare it with your radius.

var pointIsInsideCircle = google.maps.geometry.spherical.computeDistanceBetween(circle.getCenter(), point) <= circle.getRadius();
zavidovych
  • 4,718
  • 2
  • 24
  • 22
5

It's very simple. You just have to calculate distance between centre and given point and compare it to radius. You can Get Help to calculate distance between two lat lang from here

Ashutosh
  • 604
  • 5
  • 17
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/10494480) – fasteque Dec 09 '15 at 07:12
  • Thanks for info @fasteque :) – Ashutosh Dec 09 '15 at 07:32
  • @fasteque the solution he mentioned is simple enough. It's better to include more detail in your question/suggestion to what exactly you are want or looking for. – Bhargav Nanekalva Feb 16 '16 at 05:19
  • @NBhargav it's better to include the relevant part of the external link or provide a code sample if that becomes unreachable. It's clearly written in the Answering guidelines: http://stackoverflow.com/help/how-to-answer – fasteque Feb 16 '16 at 07:10
4

The following code works for me: my marker cannot be dragged outside the circle, instead it just hangs at its edge (in any direction) and the last valid position is preserved.

The function is the eventhandler for the markers 'drag' event.

_markerDragged : function() {
    var latLng = this.marker.getPosition();
    var center = this.circle.getCenter();
    var radius = this.circle.getRadius();
    if (this.circleBounds.contains(latLng) &&
        (google.maps.geometry.spherical.computeDistanceBetween(latLng, center) <= radius)) {
        this.lastMarkerPos = latLng;
        this._geocodePosition(latLng);
    } else {
        // Prevent dragging marker outside circle
        // see (comments of) http://unserkaiser.com/code/google-maps-marker-check-if-in-circle/
        // see http://www.mvjantzen.com/blog/?p=3190 and source code of http://mvjantzen.com/cabi/trips4q2012.html
        this.marker.setPosition(this.lastMarkerPos);
    }
},

Thanks to http://unserkaiser.com/code/google-maps-marker-check-if-in-circle/ and http://www.mvjantzen.com/blog/?p=3190 .

Risadinha
  • 16,058
  • 2
  • 88
  • 91
1

I've been a bit silly really. Thinking about it we can use Pythagorus' theorem.

We have a maximum distance away from a point (X miles), and two latitudes and two longitudes. If we form a triangle using these then we can solve for the distance from the point.

So say we know point1 with coordinates lat1,lng1 is the center of the circle and point2 with coordinates lat2,lng2 is the point we are trying to decide is in the circle or not.

We form a right angled triangle using a point determined by point1 and point2. This, point3 would have coordinates lat1,lng2 or lat2,lng1 (it doesn't matter which). We then calculate the differences (or if you prefer) distances - latDiff = lat2-lat1 and lngDiff = lng2-lng1

we then calculate the distance from the center using Pythagorus - dist=sqrt(lngDiff^2+latDiff^2).

We have to translate everything into meters so that it works correctly with google maps so miles are multiplied by 1609 (approx) and degrees of latitude/longitude by 111000 (approx). This isn't exactly accurate but it does an adequate job.

Hope that all makes sense.

Stuart Beard
  • 180
  • 1
  • 2
  • 12
  • 2
    A bit late to the party here, but did you take any consideration to the fact that the map projection used distorts the shapes and distances of things? – nyaray Aug 09 '13 at 14:46
  • 2
    This completely ignores map projections. Latitude and Longitude are not equally spaced! It won't work at all in nothern or southern latitudes. Only near the equator. It's WRONG. – Carl F. Jul 12 '14 at 14:16
  • @CarlF. yes, that's right. There is a better solution while working with maps. See this answer http://stackoverflow.com/a/10428729/1202145 – Bhargav Nanekalva Feb 16 '16 at 07:49
  • @NBhargav, Your link is *much* closer to the right answer! It may still have problems. I haven't checked the math, but watch out for approximating an arc as a straight line. Could make Sydney, AU appear much closer to Boston, USA. – Carl F. Feb 17 '16 at 14:38