2

Following piece of java code is a solution to determine whether a 2D Point is within a Polygon or not (taken from here). I think this code has some problems. For example for this polygon:

Point[] polygon = new Point[5];
polygon[0] = new Point(30,20);
polygon[1] = new Point(80,10);
polygon[2] = new Point(75,100);
polygon[3] = new Point(40,100);
polygon[4] = new Point(55,65);

It returns true (inside) for (76,82) but this point is on the edge (Code returns false correctly for another point on the edge : (45,17)). Also it returns false (not inside) for (45,90) but it is inside of the polygon. What is the problem?

public boolean IsPointInPolygon(Point p, Point[] polygon)
{
    double minX = polygon[0].x;
    double maxX = polygon[0].x;
    double minY = polygon[0].y;
    double maxY = polygon[0].y;
    for ( int i = 1 ; i < polygon.length; i++ )
    {
        Point q = polygon[i];
        minX = Math.min(q.x, minX);
        maxX = Math.max(q.x, maxX);
        minY = Math.min(q.y, minY);
        maxY = Math.max(q.y, maxY);
    }

    if ( p.x <= minX || p.x >= maxX || p.y <= minY || p.y >= maxY )
    {
        return false;
    }

    boolean inside = false;
    int j = polygon.length - 1;
    for (int i = 0 ;i < polygon.length ; j = i++)
    {
        if (( polygon[i].y > p.y ) != ( polygon[j].y > p.y) &&
                p.x <= (polygon[j].x - polygon[i].x ) * ( p.y - polygon[i].y ) / ( polygon[j].y - polygon[i].y ) + polygon[i].x)
        {
            inside = !inside;
        }
    }
    return inside;
}

I think I should change my code to below, but I am not sure !

float tempX = ((float)((polygon[i].x - polygon[j].x) * (p.y - polygon[i].y)) / (polygon[i].y - polygon[j].y)) + polygon[i].x;
if (p.x < tempX) {
    inside = !inside;
}
else if (p.x == tempX) {
    return false;
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
hamed
  • 23
  • 1
  • 4
  • I suggest you use a debugger and step line by line until you find the operation that doesn't do what you think it should. – user1803551 Aug 13 '17 at 10:01
  • (1) The author of the linked page writes that for edge points, the result is either true or false. Therefore the behaviour for your first two test cases is to be expected. (2) You are using `p.x <= ...` where the original code uses `<`. (3) Did you try to repeat the 1st point at the end of the array? The author writes that it is optional in your case, but still I would try. – Frank Puffer Aug 13 '17 at 10:02
  • (2) I am using p.x <=... because my code did'nt work for some cases like (45,17) (3) yes I repeat it. – hamed Aug 13 '17 at 10:48
  • I think I should change my code to below, but I am not sure ! float tempX = ((float)((polygon[i].x - polygon[j].x) * (p.y - polygon[i].y)) / (polygon[i].y - polygon[j].y)) + polygon[i].x; if (p.x < tempX) { inside = !inside; } else if (p.x == tempX) { return false; } – hamed Aug 13 '17 at 12:59

1 Answers1

0

This algorithm

if ( p.x <= minX || p.x >= maxX || p.y <= minY || p.y >= maxY )
{
        return false;
}

Is wrong. It only checks if the point is within a rectangle, bounded by minX, maxX, minY, maxY You can't test if a point is within a polygon without using all the polygon vertices.

Use java.awt.Polygon :

public boolean isPointInPolygon(Point p, Point[] points)
    {

        Polygon polygon = new Polygon();//java.awt.Polygon

        for(Point point : points) {

            polygon.addPoint(point.x, point.y);
        }

        return polygon.contains(p);
    }

Testing it with

    Point[] points = new Point[5];
    points[0] = new Point(30,20);
    points[1] = new Point(80,10);
    points[2] = new Point(75,100);
    points[3] = new Point(40,100);
    points[4] = new Point(55,65);

    System.out.println(isPointInPolygon(new Point(76,82), points) );

prints out false.

c0der
  • 18,467
  • 6
  • 33
  • 65
  • But you _can_ quickly determine that a point is **not** within a polygon this way. For example, if all vertices of the polygon have `x` coordinates >= 0 and the `x` coordinate of the test point is -2, then it is certain that the point lies outside the polygon. – Kirby Aug 13 '17 at 16:20
  • This code returns true for points on edges, but I want to return false. – hamed Aug 14 '17 at 06:19
  • Hi c0der, what if the the co-ordinates are negative? If I have `(-119.2342399, +35.23423234)` as a coordinate of polygon. The `points[0] = new Point(30,20);` doesnt seem to accept negative values. – Mike Jan 17 '19 at 10:32
  • Can you suggest how to find then? – Mike Jan 17 '19 at 10:32
  • @Michael Sorry, how to find what ? `java.awt.Point` does accept negative values, but only integers : `points[0] = new Point(-119, +35);`. If you need a solution for `double` values, post a new question, and leave me a message here. – c0der Jan 17 '19 at 11:29