4

I was wondering if a JTS expert would be able to explain how to detect the below intersection of an inner polygon inside an outer polygon.

I would have thought that at least the "contains" check be false due to the point at 1000/500 being along the right-edge of Polygon1.

Polygon1: POLYGON ((0 0, 1000 0, 1000 1000, 0 1000, 0 0))

Polygon2: POLYGON ((500 500, 1000 500, 600 600, 500 600, 500 500))

Results in:

polygon1.contains(polygon2) = true

polygon1.covers(polygon2) = true

polygon1.touches(polygon2) = false

The only way I can detect this this inner polygon touching the edge of polygon 1 is by iterating through polygon2 points and creating separate points and checking: polygon1.touches(eachPolygon2Point) but I'm worried about the performance impacts of doing this on a routine basis. Note sometimes polygon2 might be outside polygon1 so I don't really want to rely on say creating polygon2 as an inner ring of polygon1 every time either.

2 Answers 2

3

Touch is a bit odd when considered naively, but if you look at the JavaDocs you will see the problem with the way you are looking at it. (Emphasis added):

Tests whether this geometry touches the argument geometry. The touches predicate has the following equivalent definitions:

The geometries have at least one point in common, but their interiors do not intersect.

The DE-9IM Intersection Matrix for the two geometries matches at least one of the following patterns

[FT*******]
[F**T*****]
[F***T****]

If both geometries have dimension 0, the predicate returns false, since points have only interiors. This predicate is symmetric.

In your case the interiors of the two polygons do intersect so the polygons are said to not touch.

If you change polygon 2 to be "POLYGON ((1500 500, 1000 500, 1500 600, 1600 600, 1500 500))" then it does touch polygon 1.

Update

If you want to find polygons that are entirely within a polygon and not touching the boundary, I set up a quick test using the relate method and a 2nd polygon that doesn't touch polygon1.

WKTReader2 reader = new WKTReader2();
Polygon p1 = (Polygon) reader.read("POLYGON ((0 0, 1000 0, 1000 1000, 0 1000, 0 0))");
Polygon p2 = (Polygon) reader.read("POLYGON ((500 500, 1000 500, 600 600, 500 600, 500 500))");
Polygon p3 = (Polygon) reader.read("POLYGON ((500 500,  600 600, 500 600, 500 500))");

IntersectionMatrix relate1 = p1.relate(p2);
System.out.println("relate " + relate1);
IntersectionMatrix relate2 = p1.relate(p3);
System.out.println("relate " + relate2);

This gives:

relate 212F01FF2
relate 212FF1FF2

And there is a difference, so referring to the wikipedia page for DE-9IM, I can find out that this is saying that in one case the boundaries have a point (0 dimension) in common and do not interact in the other (F).

I don't think there is a named operation for this but you could use relate.get(1,1) >= 0 to check for interactions (False returns -1).

2
  • Thanks Ian, yes touch is about not sharing interior but I thought contains is meant to not share any boundary so I'm surprised that this result comes out true? Is there a method that can detect a polygon being completing within another polygon and not sharing any boundary/edge points or lines?
    – Nick B
    Commented Jul 24, 2020 at 7:08
  • Thanks very much for the update Ian, perfect. I will use relate.isContains() && relate.get(1, 1) < 0 to detect this situation.
    – Nick B
    Commented Jul 25, 2020 at 1:07
1

The OGC named predicates don't cover all topological situations of interest, and this is one of those. As it happens, JTS does implement this relationship test in PreparedGeometry (and as a bonus that is optimized for repeated tests). See Javadoc here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.