使用Geometry.reverse()处理XYM坐标时结果异常问题咨询
Geolatte Geom反转XYM几何时M坐标丢失问题
问题现象
使用Hibernate Spatial(5.6.10.Final)搭配JTS Core(1.19.0)从PostGIS(14.3)获取XYM类型几何数据后,调用org.geolatte.geom.Geometry#reverse方法时,首尾坐标的M值丢失变为NaN,仅中间坐标保留正确M值。直接用Geolatte Geom测试也能复现该问题:
测试代码:
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)
原因分析
这是Geolatte Geom的PackedPositionSequence实现bug:
- 当反转带M维度的位置序列时,没有正确复制首尾坐标的M值,仅处理了中间坐标。
- JTS原生的
CoordinateXYM数组测试无此问题,说明问题出在Geolatte的序列实现上,而Hibernate Spatial默认使用Geolatte的位置序列来处理几何数据。
解决方案
1. 转用JTS原生Geometry反转
将Geolatte几何转换为JTS原生几何,利用JTS的reverse方法(该方法能正确保留M值),再按需转回Geolatte几何:
// 从Geolatte转JTS org.locationtech.jts.geom.Geometry jtsGeom = JTS.from(geometry); // JTS原生反转 org.locationtech.jts.geom.Geometry reversedJts = jtsGeom.reverse(); // 转回Geolatte(如果业务需要) org.geolatte.geom.Geometry reversedGeom = JTS.to(reversedJts);
2. 手动反转坐标序列
手动遍历并反转坐标,确保M值被正确复制:
PositionSequence<?> originalSeq = geometry.getPositions(); int size = originalSeq.size(); CoordinateXYM[] reversedCoords = new CoordinateXYM[size]; for (int i = 0; i < size; i++) { Position pos = originalSeq.get(size - 1 - i); reversedCoords[i] = new CoordinateXYM(pos.getX(), pos.getY(), pos.getM()); } // 构建反转后的LineString(根据几何类型调整) org.geolatte.geom.Geometry reversedGeom = GeometryFactory.default().createLineString(reversedCoords);
3. 升级Geolatte Geom版本
检查是否有Geolatte Geom的新版本修复了该bug。Hibernate Spatial 5.6.x依赖的Geolatte版本较低,可尝试升级依赖(注意兼容性):
<dependency> <groupId>org.geolatte</groupId> <artifactId>geom</artifactId> <version>1.8.0</version> <!-- 替换为最新稳定版 --> </dependency>
内容的提问来源于stack exchange,提问作者wjans
相关产品推荐
相关产品推荐

