如何用Delaunay三角剖分处理地图经纬度点?JTS使用问题求助
用JTS库进行Delaunay三角剖分仅生成一个三角形的解决方案
问题根源分析
- 代码逻辑错误:重复创建
DelaunayTriangulationBuilder实例后,错误地继续使用原始点集dal而非带噪声的dalWithNoise,且误用builder.toVertices(dalWithNoise)方法——该方法是用来提取三角剖分结果的顶点,而非设置输入点集。 - 点集共线问题:若原始4个点共线或近似共线,Delaunay三角剖分只会生成单个三角形(或退化的三角网),过小的噪声无法打破这种共线性。
修正后的代码
import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.triangulate.DelaunayTriangulationBuilder; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.Arrays; public class DelaunayExample { public static void main(String[] args) { GeometryFactory gf = new GeometryFactory(); List<Coordinate> dal = new ArrayList<>(); // 替换为实际的位置坐标 dal.add(new Coordinate(1.0, 1.0)); dal.add(new Coordinate(2.0, 2.0)); dal.add(new Coordinate(3.0, 1.0)); dal.add(new Coordinate(2.0, 0.0)); // 原始点集的三角剖分 DelaunayTriangulationBuilder builder1 = new DelaunayTriangulationBuilder(); builder1.setSites(dal); builder1.setTolerance(0.00001); Geometry tri1 = builder1.getTriangles(gf); System.out.println("原始点集三角剖分输出: " + tri1); System.out.println("原始点集生成的三角形数量: " + tri1.getNumGeometries()); // 添加噪声后的点集三角剖分 Random random = new Random(); List<Coordinate> dalWithNoise = new ArrayList<>(); for (Coordinate c : dal) { // 增大正负噪声幅度,确保打破共线性 double noiseX = random.nextDouble() * 0.01 - 0.005; double noiseY = random.nextDouble() * 0.01 - 0.005; dalWithNoise.add(new Coordinate(c.x + noiseX, c.y + noiseY)); } DelaunayTriangulationBuilder builder2 = new DelaunayTriangulationBuilder(); builder2.setSites(dalWithNoise); // 正确传入带噪声的点集 builder2.setTolerance(0.000000001); Geometry tri2 = builder2.getTriangles(gf); if (tri2 == null) { System.out.println("错误: 三角剖分生成失败"); return; } System.out.println("带噪声点集生成的三角形数量: " + tri2.getNumGeometries()); for (int i = 0; i < tri2.getNumGeometries(); i++) { Geometry subGeometry = tri2.getGeometryN(i); System.out.println("三角形 " + (i + 1) + " 顶点: " + Arrays.toString(subGeometry.getCoordinates())); } // 遍历输出每个三角形的顶点 for (int i = 0; i < tri2.getNumGeometries(); i++) { Geometry g = tri2.getGeometryN(i); Coordinate[] coords = g.getCoordinates(); for (int j = 0; j < coords.length - 1; j++) { System.out.println("x: " + coords[j].x + ", y: " + coords[j].y); } } // 检查原始点集是否共线 LineString line = gf.createLineString(dal.toArray(new Coordinate[0])); double totalDistance = dal.get(0).distance(dal.get(1)) + dal.get(1).distance(dal.get(2)) + dal.get(2).distance(dal.get(3)); System.out.println("点集是否共线: " + Math.abs(line.getLength() - totalDistance) < 1e-6); } }
关键修正说明
- 修复点集传入逻辑:第二次三角剖分必须调用
setSites(dalWithNoise)来使用带噪声的点,摒弃错误的toVertices调用。 - 优化噪声策略:将噪声改为正负范围(-0.005到0.005),确保足够打破点的共线性。
- 避免变量重复定义:将重复的
builder、tri变量改为不同命名,避免编译错误。 - 新增共线检测:通过计算点集的直线长度与逐点距离和的差值,判断是否存在共线问题。
内容的提问来源于stack exchange,提问作者user447551
相关产品推荐
相关产品推荐

