Skip to content

Polygon contain point returns false when inside, true when outside #15

Closed
@rrauenza

Description

@rrauenza

I wanted to add this issue for others to lookup because it was so confounding -- our code was working fine and then we did some refactoring and changed our coordinate system a little. Then SimplePolygon2D.contains stopped working.

I was about to file a bug to see if we were crazy and found this which I think resolves it:

https://sourceforge.net/p/geom-java/discussion/618722/thread/6372ebe7/

Here's the background -- We graphed the polygon here:

https://www.desmos.com/calculator/fqfjo4mas0

Point: Point2D(500.0, 492.0)
Polygon:
  Point2D(1004.8166973359963, 657.5808589179162)
  Point2D(1048.4349833808149, 677.6169544086146)
  Point2D(1073.480102744188, 623.0940968525913)
  Point2D(1029.8618166993692, 603.0580013618929)
  Point2D(1017.1841976564538, 544.4126436990506)
  Point2D(995.3750546340445, 534.3945959537014)
  Point2D(915.8070777146482, 563.8723341463516)
  Point2D(895.7709822239499, 607.4906201911701)
  Point2D(925.2487204166001, 687.0585971105664)
  Point2D(968.8670064614187, 707.0946926012648)

Dumped it when contains() was True

public boolean contains(Point2D point) {
		for (SimplePolygon2D poly : polygons()) {
			if (poly.contains(point)) {
				System.out.print("Point: ");
				System.out.print(point);
				System.out.print("\n");
				System.out.print("Polygon:\n");
				for (Point2D pt : poly.vertices()) {
					System.out.print("  ");
					System.out.print(pt);
					System.out.print("\n");
				}
				return true;
			}
		}
		return false;
	}

Turns out our polygon is now defined CW due to some other changes we made.

In the above link, David says:

Hi,

this is because your polygon is oriented Clockwise (CW). The convention in the library is to consider point within polygon by taking into account polygon orientation. This allows working with polygon with holes.

You can solve your problem by several ways:

  • check both contains and getSignedArea method. The point is isinside the enclosing area if the condition is met:
    boolean z = p.contains(136.0,124.0) ^ p.getSignedArea()<0;
  • use the complement of the polygon (method p.complement())

regards,
David

And the original poster fixed it by doing:

The problem is solved when I make sure the polygon is oriented counter-clockwise:

if (p.getSignedArea()<0)
p = p.complement();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions