javapostgisjtshibernate-spatial

Incorrect result using Geometry.reverse() for XYM coordinates


We are using jts-core (org.locationtech.jts:jts-core:jar:1.19.0) together with hibernate-spatial (org.hibernate:hibernate-spatial:jar:5.6.10.Final:compile) to retrieve geometries with measured dimensions from a PostGis (14.3) database.

The query looks something like this:

Geometry geometry = (Geometry) entityManager
    .createNativeQuery("SELECT st_locatebetween(geom, :p1, :p2) as geom FROM GEOMS WHERE id = :id")
    .setParameter("id", id)
    .setParameter("p1", p1)
    .setParameter("p2", p2)
    .unwrap(NativeQuery.class)
    .addScalar("geom", new JTSGeometryType(INSTANCE_WKB_2))
    .getSingleResult();

This query works fine to retrieve a geometry, returning XYM coordinates. However, when we try to reverse the geometry using org.locationtech.jts.geom.Geometry#reverse, the M-coordinates get lost. All coordinates, except for the middle one, have a NaN value for m.

When trying this via a simple unit test using an array of org.locationtech.jts.geom.CoordinateXYM's this works fine. When debugging the query, it seems to be using org.geolatte.geom.PackedPositionSequence which returns an incorrect reversed array.

Are we doing something wrong? Or is this a bug?

If we try doing this with org.geolatte.geom.Geometry directly we seem to get the same problem:

Geometry geometry = JTS.to(Wkt.fromWkt("LINESTRING M (1 1 1, 2 2 2, 3 3 3)"));

stream(geometry.getCoordinates()).forEach(System.out::println);
stream(geometry.reverse().getCoordinates()).forEach(System.out::println);

gives below output:

(1.0, 1.0 m=1.0)
(2.0, 2.0 m=2.0)
(3.0, 3.0 m=3.0)

(3.0, 3.0 m=NaN)
(2.0, 2.0 m=2.0)
(1.0, 1.0 m=NaN)

Solution

  • This is definitely a bug. There is a mismatch between JTS's reverse() and the org.geolatte.geom.PackedCoordinateSequence. The CoordinateSequence doesn't return the correct value for the M- coordinate.

    I've created an issue for this in the geolatte-geom project.

    In the mean time you could use as a workaround a XYZM geometry with Z-coordinates set to 0.0. Then the mismatch disappears and reverse will work correctly.