如何用JTS的DelaunayTriangulationBuilder将三角网转为顶点索引结构?
解决方案
要将JTS Delaunay三角剖分的结果转换成唯一顶点列表+三角形索引列表的结构,核心是先对所有顶点去重建立映射,再批量转换每个三角形的顶点为索引。以下是高效实现的步骤和代码:
核心思路
- 顶点去重与映射:遍历所有三角形的顶点,按设置的精度阈值合并重复顶点,同时建立「坐标→索引」的映射表,同步收集唯一顶点到列表。
- 生成三角形索引:再次遍历每个三角形,将顶点坐标通过映射表转换成索引,保留原顶点的顺/逆时针顺序。
代码实现
import com.vividsolutions.jts.geom.*; import java.util.*; // 假设已通过DelaunayTriangulationBuilder得到triangulation对象 Geometry triangulation = builder.getTriangles(new GeometryFactory()); double tolerance = 0.0000001; // 与剖分时设置的tolerance一致 // 1. 构建唯一顶点列表和坐标-索引映射 List<Coordinate> uniqueVertices = new ArrayList<>(); Map<String, Integer> coordIndexMap = new HashMap<>(); for (int i = 0; i < triangulation.getNumGeometries(); i++) { Polygon triangle = (Polygon) triangulation.getGeometryN(i); Coordinate[] triangleCoords = triangle.getExteriorRing().getCoordinates(); // 跳过最后一个闭合点(JTS多边形的环首尾坐标重复) for (int j = 0; j < triangleCoords.length - 1; j++) { Coordinate coord = triangleCoords[j]; // 按精度阈值格式化坐标,避免浮点误差导致的重复 String coordKey = String.format("%.7f,%.7f,%.7f", coord.x, coord.y, coord.z); if (!coordIndexMap.containsKey(coordKey)) { coordIndexMap.put(coordKey, uniqueVertices.size()); uniqueVertices.add(coord); } } } // 2. 生成三角形索引列表(每个元素是长度为3的索引数组) List<int[]> triangleIndices = new ArrayList<>(); for (int i = 0; i < triangulation.getNumGeometries(); i++) { Polygon triangle = (Polygon) triangulation.getGeometryN(i); Coordinate[] triangleCoords = triangle.getExteriorRing().getCoordinates(); int[] indices = new int[3]; for (int j = 0; j < 3; j++) { Coordinate coord = triangleCoords[j]; String coordKey = String.format("%.7f,%.7f,%.7f", coord.x, coord.y, coord.z); indices[j] = coordIndexMap.get(coordKey); } // JTS生成的多边形顶点默认是逆时针顺序,若需要顺时针可反转数组 // Arrays.reverse(indices); triangleIndices.add(indices); }
关键细节说明
- 精度处理:通过
String.format按7位小数格式化坐标(与设置的tolerance=1e-7匹配),避免浮点运算误差导致的相同顶点被重复存储。 - 闭合点跳过:JTS的
Polygon外环坐标数组首尾元素相同,遍历需跳过最后一个元素,避免重复处理。 - 顶点顺序:JTS遵循OGC规范,生成的多边形顶点默认是逆时针顺序。如果你的3D应用要求顺时针索引,只需反转每个三角形的索引数组即可。
- 效率优化:使用HashMap存储坐标映射,遍历两次所有三角形(总顶点数约为3×三角形数量),时间复杂度为O(N),属于高效处理方式。
内容的提问来源于stack exchange,提问作者Elbbard
相关产品推荐
相关产品推荐

