6

我想从 GeoTools 镶嵌国家形状,以便在地球表面上以 3D 形式显示它。GeoTools 使用 JTS 拓扑套件,内部看起来功能丰富。

它是否包含细分某些形状的实用程序?我看到有 triangulation 包,但不知道如何将它用于带孔的形状。

我也用它不仅像这里一样连接现有顶点

在此处输入图像描述

它应该用内部的多个顶点填充形状。

更新

我发现,JTS 包含ConformingDelaunayTriangulationBuilder允许以某种方式制作所需镶嵌的类,但效果不好。首先,它只允许约束,这意味着需要额外的代码来从凹入区域中删除三角形。而且它还试图保留曲面细分的 Delaunay 特性,这会导致创建许多额外的部分。

最后,它会导致ConstraintEnforcementException复杂的形状,如国家和无法使用。

我还发现了“三角形”包,它是用 C 语言编写的,实现了Chew 的第二个算法,效果很好

在此处输入图像描述

现在我想知道,它是移植到 Java 还是封装到其中?

4

2 回答 2

4

我知道这篇文章比较老,但我最近遇到了同样的情况,需要一些 Java 库或类似的工具来对一些复杂的多边形进行三角剖分(因为我想在 OpenGL 上显示它们,它只能将三角形绘制为原始操作)。

经过相当多的搜索和测试,对我有用的库是Orbgis的 Poly2Tri您可以在此处从 Maven 获取该库*

这个库有很多特性,包括带孔的多边形、优化三角剖分的施泰纳点和其他东西。一个基本的使用示例如下(基于链接仓库的示例):

//Create the polygon passing a List of PolygonPoints
Polygon polygon = new Polygon(
    Arrays.asList(
        new PolygonPoint(0, 0, 0),
        new PolygonPoint(10, 0, 1),
        new PolygonPoint(10, 10, 2),
        new PolygonPoint(0, 10, 3)));
//Here you could add holes as needed, passing them as Polygons
polygon.addHole(someHoleYouCreated);
//Next, proceed to calculate the triangulation of the polygon 
Poly2Tri.triangulate(polygon);
//Finally, obtain the resulting triangles
List<DelaunayTriangle> triangles = polygon.getTriangles();

编辑:不知道您是否已经尝试过,但 JTS Topology Suite 也有一个DelaunayTriangulationBuilder类(即没有 Conforming 部分)。它位于org.locationtech.jts.triangulate.DelaunayTriangulationBuilder,也许它比您尝试过但表现不佳的另一个效果更好。

*注意:注意不要改用这个,就像我一开始做的那样,发现它不是正确的依赖项(不是 -core 版本)

于 2018-05-05T02:02:07.437 回答
1

这是使用JTS的一种快速而肮脏的方法:

第一的:

  • 使用 JTS 对几何进行三角测量DelaunayTriangulationBuilder
  • 准备一组站点,sites;从初始三角剖分复制顶点位置

环形:

  • 迭代三角剖分的三角形几何形状,将三角形质心添加到sites
  • 使用重新三角测量sites(现在由原始站点和新的质心站点组成)

最后:

  • 将三角剖分与原始几何相交以恢复其凹形外壳和任何孔

**对于这种肮脏的技术,我发现使用三角形质心比三角形外心产生更好的结果,即使后者倾向于用于更正式的改进(ChewRuppert等..))。

代码

static Geometry refinedTriangulation(Geometry g, int nRefinements, double tolerance) {

    DelaunayTriangulationBuilder builder = new DelaunayTriangulationBuilder();
    builder.setSites(g); // set vertex sites
    builder.setTolerance(tolerance); // set tolerance for initial triangulation only

    Geometry triangulation = builder.getTriangles(geometryFactory); // initial triangulation

    HashSet<Coordinate> sites = new HashSet<>();
    for (int i = 0; i < triangulation.getCoordinates().length; i++) {
        sites.add(triangulation.getCoordinates()[i]);
    }

    for (int refinement = 0; refinement < nRefinements; refinement++) {
        for (int i = 0; i < triangulation.getNumGeometries(); i++) {
            Polygon triangle = (Polygon) triangulation.getGeometryN(i);

            if (triangle.getArea() > 50) { // skip small triangles
                sites.add(new Coordinate(triangle.getCentroid().getX(), triangle.getCentroid().getY()));
            }
        }
        builder = new DelaunayTriangulationBuilder();
        builder.setSites(sites);
        triangulation = builder.getTriangles(geometryFactory); // re-triangulate using new centroid sites
    }

    triangulation = triangulation.intersection(g); // restore concave hull and any holes
    return triangulation;
}

您可以使用triangle.getExteriorRing().getLength() > Ntriangle.getArea() > N跳过细化已经很小的三角形。

例子

原始形状

在此处输入图像描述

JTS三角剖分

在此处输入图像描述

带交叉点的 JTS 三角测量

在此处输入图像描述

1 细化

在此处输入图像描述

3 改进

在此处输入图像描述

于 2021-01-30T16:08:50.397 回答