TransWikia.com

JTS Geometry "Contains" not detecting point of an Inner polygon on edge of Outer Polygon

Geographic Information Systems Asked on December 3, 2021

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

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.

Answered by dr_jts on December 3, 2021

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).

Answered by Ian Turton on December 3, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP