How to Check If a Longitude/Latitude Point Is Within a Range of Coordinates

How do I check if a longitude/latitude point is within a range of coordinates?

This is essentially the Point in polygon problem on a sphere. You can modify the ray casting algorithm so that it uses arcs of great circles instead of line segments.

  1. for each pair of adjacent coordinates that make up your polygon, draw a great circle segment between them.
  2. Choose a reference point that is not inside the polygonal zone.
  3. draw a great circle segment that begins at the reference point and ends at the vehicle point. Count how many times this segment crosses over a segment of your polygon. If the total number of times is odd, the vehicle is within the polygon. If even, the vehicle is outside of the polygon.

Alternatively, if the coordinates and vehicle are sufficiently close together, and not anywhere near the poles or international date line, you can pretend the earth is flat and use longitude and lattitude as simple x and y coordinates. That way, you can use the ray casting algorithm with simple line segments. This is preferable if you are not comfortable with non-euclidean geometry, but you'll have some distortion around the borders of your polygons since the arcs will be distorted.

EDIT: A little more on geometry on a sphere.

A great circle can be identified by the vector that lies perpendicular to the plane the circle lies on (AKA, the normal vector)

class Vector{
double x;
double y;
double z;
};

class GreatCircle{
Vector normal;
}

Any two lattitude/longitude coordinates that aren't antipodal share exactly one great circle. To find this great circle, convert the coordinates to lines that pass through the center of the earth. The cross product of those two lines is the normal vector of the coordinate's great circle.

//arbitrarily defining the north pole as (0,1,0) and (0'N, 0'E) as (1,0,0)
//lattidues should be in [-90, 90] and longitudes in [-180, 180]
//You'll have to convert South lattitudes and East longitudes into their negative North and West counterparts.
Vector lineFromCoordinate(Coordinate c){
Vector ret = new Vector();
//given:
//tan(lat) == y/x
//tan(long) == z/x
//the Vector has magnitude 1, so sqrt(x^2 + y^2 + z^2) == 1
//rearrange some symbols, solving for x first...
ret.x = 1.0 / math.sqrt(tan(c.lattitude)^2 + tan(c.longitude)^2 + 1);
//then for y and z
ret.y = ret.x * tan(c.lattitude);
ret.z = ret.x * tan(c.longitude);
return ret;
}

Vector Vector::CrossProduct(Vector other){
Vector ret = new Vector();
ret.x = this.y * other.z - this.z * other.y;
ret.y = this.z * other.x - this.x * other.z;
ret.z = this.x * other.y - this.y * other.x;
return ret;
}

GreatCircle circleFromCoordinates(Coordinate a, Coordinate b){
Vector a = lineFromCoordinate(a);
Vector b = lineFromCoordinate(b);
GreatCircle ret = new GreatCircle();
ret.normal = a.CrossProdct(b);
return ret;
}

Two great circles intersect at two points on the sphere. The cross product of the circles forms a vector that passes through one of those points. The antipode of that vector passes through the other point.

Vector intersection(GreatCircle a, GreatCircle b){
return a.normal.CrossProduct(b.normal);
}

Vector antipode(Vector v){
Vector ret = new Vector();
ret.x = -v.x;
ret.y = -v.y;
ret.z = -v.z;
return ret;
}

A great circle segment can be represented by the vectors passing through the segment's start and end points.

class GreatCircleSegment{
Vector start;
Vector end;
Vector getNormal(){return start.CrossProduct(end);}
GreatCircle getWhole(){return new GreatCircle(this.getNormal());}
};

GreatCircleSegment segmentFromCoordinates(Coordinate a, Coordinate b){
GreatCircleSegment ret = new GreatCircleSegment();
ret.start = lineFromCoordinate(a);
ret.end = lineFromCoordinate(b);
return ret;
}

You can measure the arc size of a great circle segment, or the angle between any two vectors, using the dot product.

double Vector::DotProduct(Vector other){
return this.x*other.x + this.y*other.y + this.z*other.z;
}

double Vector::Magnitude(){
return math.sqrt(pow(this.x, 2) + pow(this.y, 2) + pow(this.z, 2));
}

//for any two vectors `a` and `b`,
//a.DotProduct(b) = a.magnitude() * b.magnitude() * cos(theta)
//where theta is the angle between them.
double angleBetween(Vector a, Vector b){
return math.arccos(a.DotProduct(b) / (a.Magnitude() * b.Magnitude()));
}

You can test if a great circle segment a intersects a great circle b by:

  • find the vector c, the intersection of a's whole great circle and b.
  • find the vector d, the antipode of c.
  • if c lies between a.start and a.end, or d lies between a.start and a.end, then a intersects with b.

 

//returns true if Vector x lies between Vectors a and b.
//note that this function only gives sensical results if the three vectors are coplanar.
boolean liesBetween(Vector x, Vector a, Vector b){
return angleBetween(a,x) + angleBetween(x,b) == angleBetween(a,b);
}

bool GreatCircleSegment::Intersects(GreatCircle b){
Vector c = intersection(this.getWhole(), b);
Vector d = antipode(c);
return liesBetween(c, this.start, this.end) or liesBetween(d, this.start, this.end);
}

Two great circle segments a and b intersect if:

  • a intersects with b's whole great circle
  • b intersects with a's whole great circle

 

bool GreatCircleSegment::Intersects(GreatCircleSegment b){
return this.Intersects(b.getWhole()) and b.Intersects(this.getWhole());
}

Now you can construct your polygon and count how many times your reference line passes over it.

bool liesWithin(Array<Coordinate> polygon, Coordinate pointNotLyingInsidePolygon, Coordinate vehiclePosition){
GreatCircleSegment referenceLine = segmentFromCoordinates(pointNotLyingInsidePolygon, vehiclePosition);
int intersections = 0;
//iterate through all adjacent polygon vertex pairs
//we iterate i one farther than the size of the array, because we need to test the segment formed by the first and last coordinates in the array
for(int i = 0; i < polygon.size + 1; i++){
int j = (i+1) % polygon.size;
GreatCircleSegment polygonEdge = segmentFromCoordinates(polygon[i], polygon[j]);
if (referenceLine.Intersects(polygonEdge)){
intersections++;
}
}
return intersections % 2 == 1;
}

Check if a latitude and longitude is within a circle in PHP

I've prepared the sample code snippet for you. It's working well for me. Feel free to adapt with your own logic.

$lat1 = "10.5900627";
$lon1 = "77.1933317";

$lat2 = "10.6068507";
$lon2 = "77.117246";

function distance($lat1, $lon1, $lat2, $lon2, $unit)
{
if (($lat1 == $lat2) && ($lon1 == $lon2)) {
return 0;
}
else {
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$unit = strtoupper($unit);

if ($unit == "K") {
return ($miles * 1.609344);
} else if ($unit == "N") {
return ($miles * 0.8684);
} else {
return $miles;
}
}
}

if(distance($lat1, $lon1, $lat2, $lon2, "K") < 10)
{
echo "True";
}
else
{
echo "False";
}

If the result of 'K' is less than 10Km, then you will get the result as "True". Otherwise 'False' will return as result.

Check if a latitude and longitude is within a circle

What you basically need, is the distance between two points on the map:

float[] results = new float[1];
Location.distanceBetween(centerLatitude, centerLongitude, testLatitude, testLongitude, results);
float distanceInMeters = results[0];
boolean isWithin10km = distanceInMeters < 10000;

If you have already Location objects:

Location center;
Location test;
float distanceInMeters = center.distanceTo(test);
boolean isWithin10km = distanceInMeters < 10000;

Here is the interesting part of the API used:
https://developer.android.com/reference/android/location/Location.html

How to check if a coordinate (latitude and longitude) is in between two other coordinates in PHP?

I think only your first condition was wrong it must be > not <

According to the reference python if it is LARGER THAN epsilon then its false.

   <?// Copied from the Python solution
function isBetweenPoints($aLat, $aLng, $bLat, $bLng, $cLat, $cLng) {

$crossProduct = ($cLat - $aLat) * ($bLng - $aLng) - ($cLng - $aLng) * ($bLat - $aLat);
echo "cross_product: ". $crossProduct; //debug
if (abs($crossProduct) > PHP_FLOAT_EPSILON) { // i would rethink epsilon as you will never get TRUE ;-)
return false;
}

$dotProduct = ($cLng - $aLng) * ($bLng - $aLng) + ($cLat - $aLat)*($bLat - $aLat);
echo "<br>dotProduct: ". $dotProduct; //debug
if ($dotProduct < 0) {
return false;
}

$squaredLength = ($bLng - $aLng)*($bLng - $aLng) + ($bLat - $aLat)*($bLat - $aLat);
echo "<br>SquaredLength: " . $squaredLength; //debug
return !($dotProduct > $squaredLength);
}

$aLat = 1;
$aLng = 1;

$bLat = 3;
$bLng = 3;

$cLat = 2;
$cLng = 2;

//will give true

if (isBetweenPoints($aLat, $aLng, $bLat, $bLng, $cLat, $cLng) ==TRUE)
{echo "<br>Point IS between the other points<p>";}
else
{echo "<br>Point IS NOT between the other points<p>";}


$aLat = 1;
$aLng = 1;

$bLat = 3;
$bLng = 3;

$cLat = 2;
$cLng = 2.1;

//will give false

echo"<br>";

if (isBetweenPoints($aLat, $aLng, $bLat, $bLng, $cLat, $cLng) ==TRUE)
{echo "<br>POINT IS between the other points";}
else
{echo "<br>POINT IS NOT between the other points";}

?>

Finding a set of coordinates within a certain range from latitude and longitide

Basically what you're trying to do is find N points on the radius of a circle from a given point with a given radius. One simple way of doing it is splitting the 360 degrees of a circle in to N equal chunks, and finding the points at regular intervals.

The following should do roughly what you're after -

function findCoordinates(lat, long, range)
{
// How many points do we want? (should probably be function param..)
var numberOfPoints = 16;
var degreesPerPoint = 360 / numberOfPoints;

// Keep track of the angle from centre to radius
var currentAngle = 0;

// The points on the radius will be lat+x2, long+y2
var x2;
var y2;
// Track the points we generate to return at the end
var points = [];

for(var i=0; i < numberOfPoints; i++)
{
// X2 point will be cosine of angle * radius (range)
x2 = Math.cos(currentAngle) * range;
// Y2 point will be sin * range
y2 = Math.sin(currentAngle) * range;

// Assuming here you're using points for each x,y..
p = new Point(lat+x2, long+y2);

// save to our results array
points.push(p);

// Shift our angle around for the next point
currentAngle += degreesPerPoint;
}
// Return the points we've generated
return points;
}

The array of points you get back can then easily be used to draw the circle you wish on your google map.

If your overall goal however is just to draw a circle at a fixed radius around a point, then a far easier solution may be to use an overlay. I've found KMBox to be very easy to set up - you give it a central point, a radius and an image overlay (in your case, a transparent circle with a visible line around the edge) and it takes care of everything else, including resizing it on zoom in/out.

Check if geo-point is inside or outside of polygon

Here is a possible solution to my problem.

  1. Geographical coordinates must be stored properly. Example np.array([[Lon_A, Lat_A], [Lon_B, Lat_B], [Lon_C, Lat_C]])
  2. Create the polygon
  3. Create the point to be tested
  4. Use polygon.contains(point) to test if point is inside (True) or outside (False) the polygon.

Here is the missing part of the code:

from shapely.geometry import Point
from shapely.geometry.polygon import Polygon

lons_lats_vect = np.column_stack((lons_vect, lats_vect)) # Reshape coordinates
polygon = Polygon(lons_lats_vect) # create polygon
point = Point(y,x) # create point
print(polygon.contains(point)) # check if polygon contains point
print(point.within(polygon)) # check if a point is in the polygon

Note: the polygon does not take into account great circles, therefore it is necessary to split the edges into many segments thus increasing the number of vertices.



Special case: If point lies on borders of Polygon

E.g. print(Polygon([(0, 0), (1, 0), (1, 1)]).contains(Point(0, 0))) will fail

So one can use

print(polygon.touches(point)) # check if point lies on border of polygon 

Search for range Latitude/Longitude coordinates

Some version of what you are doing is right but I think you probably want to use the actual geometry types, especially if you are on MyISAM and can create an R-Tree spatial index. You can have columns with any supported type (ie point, polygon), or the catchall geometry type:

mysql> create table spatial_table (id int, my_spots point, my_polygons geometry);
Query OK, 0 rows affected (0.06 sec)

Then query and update with WKT syntax:

mysql> insert into spatial_table values (1, GeomFromText('POINT(1 1)'), GeomFromText('POLYGON((1 1, 2 2, 0 2, 1 1))'));
Query OK, 1 row affected (0.00 sec)

mysql> insert into spatial_table values (1, GeomFromText('POINT(10 10)'), GeomFromText('POLYGON((10 10, 20 20, 0 20, 10 10))') );
Query OK, 1 row affected (0.00 sec)

You can then do your query (ie vicinity), against the minimum bounding rectangle of a linestring with terminating points point1 = longitude - increment, lon - increment, y = longitude + increment, latitude + increment, ie here with a +- of 1:

mysql> select * from spatial_table where MBRContains(GeomFromText('LINESTRING(9 9, 11 11)'), my_spots);
+------+---------------------------+-----------------------------------------------------------------------------------+
| id | my_spots | my_polygons |
+------+---------------------------+-----------------------------------------------------------------------------------+
| 1 | $@ $@ | $@ $@ 4@ 4@ 4@ $@ $@ |
+------+---------------------------+-----------------------------------------------------------------------------------+
1 row in set (0.00 sec)

This will perform much better than doing arithmetic on a bunch of floats representing longitude and latitude. BTW at about the location of San Francisco the following constants work pretty well for converting between km and degrees longitude and latitude (ie, if you want clean square maps of Santa Cruz):

lonf 0.01132221938
latf 0.0090215040

That is, (x +- 2*lonf, y +- 2*latf) gives you the relevant $lat_floor etc values for a 2km wide boy around your point of interest.

How to check if coordinate inside certain area Python

from recommendation of @user1753919 in his/her comment, I got the answer here: Haversine Formula in Python (Bearing and Distance between two GPS points)

final code:

from math import radians, cos, sin, asin, sqrt

def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
r = 6371 # Radius of earth in kilometers. Use 3956 for miles
return c * r

center_point = [{'lat': -7.7940023, 'lng': 110.3656535}]
test_point = [{'lat': -7.79457, 'lng': 110.36563}]

lat1 = center_point[0]['lat']
lon1 = center_point[0]['lng']
lat2 = test_point[0]['lat']
lon2 = test_point[0]['lng']

radius = 1.00 # in kilometer

a = haversine(lon1, lat1, lon2, lat2)

print('Distance (km) : ', a)
if a <= radius:
print('Inside the area')
else:
print('Outside the area')

Thanks

How do I know if a Lat,Lng point is contained within a circle?

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.



Related Topics



Leave a reply



Submit