Мы используем jts-core
(org.locationtech.jts:jts-core:jar:1.19.0
) вместе с hibernate-spatial
(org.hibernate:hibernate-spatial:jar:5.6.10.Final:compile
) для извлечения геометрии с измеренными размерами из базы данных PostGis (14.3
).
Запрос выглядит примерно так:
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();
Этот запрос отлично работает для получения геометрии, возвращая координаты XYM. Однако, когда мы пытаемся изменить геометрию с помощью org.locationtech.jts.geom.Geometry#reverse
, M-координаты теряются. Все координаты, кроме средней, имеют значение NaN
для m
.
При попытке этого с помощью простого модульного теста с использованием массива org.locationtech.jts.geom.CoordinateXYM
это работает нормально. При отладке запроса, похоже, используется org.geolatte.geom.PackedPositionSequence
, который возвращает неверный перевернутый массив.
Мы делаем что-то не так? Или это ошибка?
Если мы попытаемся сделать это с помощью org.geolatte.geom.Geometry
напрямую, мы получим ту же проблему:
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);
дает ниже вывод:
(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)
Это определенно ошибка. Существует несоответствие между JTS reverse()
и org.geolatte.geom.PackedCoordinateSequence
. CoordinateSequence
не возвращает правильное значение координаты M.
Для этого я создал задачу в проекте geolatte-geom.
В то же время вы можете использовать в качестве обходного пути геометрию XYZM с Z-координатами, установленными на 0,0. Тогда несоответствие исчезнет и реверс будет работать корректно.
Спасибо! В качестве обходного пути я уже сделал что-то подобное, что, похоже, тоже помогает:
geometryFactory.createLineString(geometry.getCoordinates()).reverse()
.