Geometry equality in Java tests
springmeyer opened this issue · 6 comments
Context
JTS geometries are used for the Java geometry representation. JTS geometries have sophisticated equality methods as is needed given the complexity of geometry storage:
See:
- https://docs.geotools.org/latest/userguide/library/jts/equals.html.
- https://github.com/locationtech/jts/blob/master/modules/core/src/test/java/org/locationtech/jts/geom/GeometryImplTest.java#L126-L139
Currently in our tests we use Junit assertEqual
.
Problem
The results of assertEqual(mltgeometry, mvtgeometry)
do not match always match assertEquals(true, mltgeometry.equals(mvtgeometry))
Which raises the question of what assertEqual
is doing under the hood? Is it converting to strings to compare objects? Is it using geom.equals
? Something else?
Next steps
Overall goal here is to ensure that our Java tests are correctly asserting that MVT geometries can be perfectly round-tripped between MVT and MLT. In other words, that their representations are identical after both are decoded into a given in-memory representation.
I think this is already the case, but we should double-check/ensure it is by ensuring our tests are correctly asserting on equality.
So, how about?
- Move to
assertEquals(true, mltgeometry.equals(mvtgeometry))
orassertTrue( mltgeometry.equals(mvtgeometry))
?- Fix failures that arise
- Or consider some other approach?
/cc @mactrem @ebrelsford
Perhaps also @msbarry has some insight here? Testing issues that lead to this ticket came from #168 (comment)
Started to look into this a bit. Found that mvtGeometry.equals(mltGeometry)
throws while mvtGeometry.equalsExact(mltGeometry)
does not throw (and passes). The difference is that the former checks for topological equality
while the latter checks for structural equality
. I think what may be happening is that the geometries are equal/identical (and therefore the structural equality
test passes as it should) but they are invalid in some way so that topological equality
test cannot cope and fails to finish.
they are invalid in some way
Visualizing the WKT https://wktmap.com in shows that most of the failing geometries are polygons which have collapsed to zero area lines. So this problem appears to be coming from either the input geometries (likely) or the handling of them in https://github.com/ElectronicChartCentre/java-vector-tile.
So, I think the solution here is to use mvtGeometry.equalsExact(mltGeometry)
#180 implements explicit structural equality
check.
JTS geometry does something kind of weird, it has 2 methods public boolean equals(Geometry g)
(alias for equalsTopo
) and public boolean equals(Object o)
(alias for equalsExact
). Junit assertEquals should be using the latter, but if you just write geometry.equals(otherGeometry)
it will resolve to the former with different behavior.
For a exact comparison I think you'd want assertEquals(geom1, geom2)
but for planetiler I wanted looser comparisons in a few places so I added an assertTopologicallyEquivalentFeature
method that compared using equalsTopo
@msbarry great, thanks for the followup info. Above you'll see I implemented an explicit structural equality
test (aka Geometry.equalsExact( Geometry g )
) in #180. I'm happy with doing this and not depending on what assertEquals
matches to, but it is great to know you think it matches to Geometry.equals( Object o )
.