I went through many similar questions on Stackoverflow and other websites and I based my solution on those answers but I still can't get it to work…
My problem: I want to determine whether or not a certain GPS location P
lies within a rectangular area bounded by four given GPS coordinates A
, B
, C
, D
.
At the moment I am calculating the areas of triangles ABP
, BCP
, CDP
and DAP
. If any of those areas is bigger than zero (don't be upset, mathematicians) the point lies outside my rectangle as explained here.
Code:
private static double triangleArea(Location a, Location b, Location c) {
// (C.x*B.y-B.x*C.y)-(C.x*A.y-A.x*C.y)+(B.x*A.y-A.x*B.y)
double result = (c.getLongitude()*b.getLatitude()-b.getLongitude()*c.getLatitude())-(c.getLongitude()*a.getLatitude()-a.getLongitude()*c.getLatitude())+(b.getLongitude()*a.getLatitude()-a.getLongitude()*b.getLatitude());
return result;
}
public static boolean isInsideSquare(Location a, Location b, Location c, Location d, Location p) {
if (triangleArea(a,b,p)>0 || triangleArea(b,c,p)>0 || triangleArea(c,d,p)>0 || triangleArea(d,a,p)>0) {
return false;
}
return true;
}
But when I call this function it's always returning false
. Even when using the following coordinates (latitude, longitude):
A: (50.884706, 4.714151)
B: (50.884944, 4.716149)
C: (50.884679, 4.716228)
D: (50.884441, 4.714230)
P: (50.884538, 4.714615)
Yet when I plot those points on a map (e.g. here) I can see that point P lies within ABCD… (see below)
I've read some easy solutions where you just subtract the x, y coordinates of your points, but that would obviously only work for rectangles parallel to the x-axis and y-axis, whereas my rectangle can be oriented in any angle.
Can anyone tell me what I am doing wrong or suggest a better solution to solve this problem?
Thanks a lot!
I would use a point in polygon function. This always works, unless not overlapping the datum limit (180 to -180 jump) or at the poles.
I am curious which is faster, the approach from Gangnus or the point in poly. The Normal case is that points are far outside.
Maybe try the
java.awt.Rectangle
class.Checks whether or not this
Rectangle
contains the specifiedPoint
.If a point is inside a rectangle. On a plane. For mathematician or geodesy (GPS) coordinates
Make an equation for every li. The equation sort of:
fi(P)=0.
P is a point. For points, belonging to li, the equation is true.
So, we have to check this:
fAB(P) fAB(C) >= 0
fBC(P) fBC(D) >= 0
fCD(P) fCD(A) >= 0
fDA(P) fDA(B) >= 0
The unequations are not strict, for if a point is on the border, it belongs to the rectangle, too. If you don't need points on the border, you can change inequations for strict ones. But while you work in floating point operations, the choice is irrelevant.
The only thing left is to get an equation for a line going through two points. It is a well-known linear equation. Let's write it for a line AB and point P:
fAB(P) ≡ (xA-xB) (yP-yB) - (yA-yB) (xP-xB)
The check could be simplified - let's go along the rectangle clockwise - A, B, C, D, A. Then all correct sides will be to the right of the lines. So, we needn't compare with the side where another vertice is. And we need check a set of shorter inequations:
fAB(P) >= 0
fBC(P) >= 0
fCD(P) >= 0
fDA(P) >= 0
But this is correct for the normal, mathematician set of coordinates, where X is to the right and Y to the top. And for the geodesy coordinates, as are used in GPS, where X is to the top, and Y is to the right, we have to turn the inequations:
fAB(P) <= 0
fBC(P) <= 0
fCD(P) <= 0
fDA(P) <= 0
If you are not sure with the directions of axis, be careful with this simplified check - check for one point manually, if you have chosen the correct inequations.
BTW, the rectangle on the sphere has sense too. It is the area between two parallels and two meridians, of course, with any orientation of the main axis. But you don't need it, according to the comment.