Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine if a point is inside a 2D convex polygon?

I have a convex polygon (typically just a rotated square), and I know all of 4 points. How do I determine if a given point (yellow/green) is inside the polygon?

enter image description here

EDIT: For this particular project, I don't have access to all of the libraries of the JDK, such as AWT.

like image 868
NPike Avatar asked Jan 04 '12 02:01

NPike


People also ask

How do you determine if a point is inside a convex polygon?

Algorithm: For a convex polygon, if the sides of the polygon can be considered as a path from any one of the vertex. Then, a query point is said to be inside the polygon if it lies on the same side of all the line segments making up the path.

How can I determine whether a 2d point is within a polygon?

One simple way of finding whether the point is inside or outside a simple polygon is to test how many times a ray, starting from the point and going in any fixed direction, intersects the edges of the polygon. If the point is on the outside of the polygon the ray will intersect its edge an even number of times.

Is point Inside non convex polygon?

To determine, whether a point is inside a non-convex polygon, we will use a ray-casting method. We create a line from the center point \varvec{C} to the testing point \varvec{P} . Then we count how many times the segment line \varvec{CP} intersects with the polygon.

How do you check if a given point lies inside or outside a polygon Python?

Use polygon. contains(point) to test if point is inside ( True ) or outside ( False ) the polygon.


2 Answers

For those who would like to understand how the method written by Dean Povey above works, here is the explanation:

The method looks at a "ray" that starts at the tested spot and extends to infinity to the right side of the X axis. For each polygon segment, it checks if the ray crosses it. If the total number of segment crossing is odd then the tested point is considered inside the polygon, otherwise - it is outside.

To understand the way the crossing is calculated, consider the following figure:

            v2             o            /           / c (intersection) o--------x----------------------> to infinity t       /        /          /      o      v1 

For the intersection to occur, tested.y must be between the y values of the segment's vertices (v1 and v2). This is the first condition of the if statement in the method. If this is what happens, then the horizontal line must intersect the segment. It only remains to establish whether the intersection happens to the right of the tested point or to the left of it. This requires finding the x coordinate of the intersection point, which is:

              t.y - v1.y c.x = v1.x + ----------- * (v2.x - v1.x)              v2.y - v1.y 

All that remains to be done is examining the subtleties:

  • If v1.y == v2.y then the ray goes along the segment and therefore the segment has no influence on the outcome. Indeed, the first part of the if statement returns false in that case.
  • The code first multiplies and only then divides. This is done to support very small differences between v1.x and v2.x, which might lead to a zero after the division, due to rounding.
  • Finally, the problem of crossing exactly on a vertex should be addressed. Consider the following two cases:
         o                    o          |                     \     o          | A1                C1 \   /          |                       \ / C2   o--------x-----------x------------x--------> to infinity         /           / \     A2 /        B1 /   \ B2       /           /     \       o           /       o                 o 

Now, to verify if it works, check for yourself what is returned for each of the 4 segments by the if condition in the method body. You should find that the segments above the ray (A1, C1, C2) receive a positive result, while those below it (A2, B1, B2) receive a negative one. This means that the A vertex contributes an odd number (1) to the crossing count, while B and C contribute an even number (0 and 2, respectively), which is exactly what is desired. A is indeed a real crossing of the polygon, while B and C are just two cases of "fly-by".

like image 28
Nadav Avatar answered Sep 23 '22 04:09

Nadav


This page: http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html shows how to do this for any polygon.

I have a Java implementation of this, but it is too big to post here in its entirety. However, you should be able to work it out:

class Boundary {     private final Point[] points; // Points making up the boundary     ...       /**      * Return true if the given point is contained inside the boundary.      * See: http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html      * @param test The point to check      * @return true if the point is inside the boundary, false otherwise      *      */     public boolean contains(Point test) {       int i;       int j;       boolean result = false;       for (i = 0, j = points.length - 1; i < points.length; j = i++) {         if ((points[i].y > test.y) != (points[j].y > test.y) &&             (test.x < (points[j].x - points[i].x) * (test.y - points[i].y) / (points[j].y-points[i].y) + points[i].x)) {           result = !result;          }       }       return result;     } } 

And here is a sketch of the Point class

/**  * Two dimensional cartesian point.  */ public class Point {   public final double x;   public final double y;   ... } 
like image 53
Dean Povey Avatar answered Sep 21 '22 04:09

Dean Povey