jts空间工具使用

JTS 简介

JTS (Java Topology Suite) 是一个开源 Java 软件库,它为欧几里得平面线性几何提供了一套对象模型以及一组基本的几何函数。JTS 主要作为矢量 GIS 软件的核心组件,也可以作为提供几何算法的通用库使用。

常用的 JTS 实现框架有 vividsolutions 以及 locationtech 两种,本文内容基于 locationtech 库。

模块总览

Java Topology Suite 核心类库由以下模块构成:

  • algorithm:封装了一些几何属性的计算算法,例如计算几何体面积、线段长度等;
  • awt:基于 Java AWT 的图形绘制工具,不常用;
  • densify:内部填充器,用于将几何体致密化;
  • dissolve:用于将几何体中的线性分量融合成一组最大长度的 Linestring;
  • edgegraph:用于描述几何体边缘
  • geom:用于描述简单几何体
  • geomgraph:用于描述地理信息
  • index:索引(数据结构相关)
  • io:用于读取并解析 WKT/WKB、KML 以及 GML 语言;
  • linearref:线性参考系;
  • math:空间计算数学工具包;
  • noding:用于计算几何体的交点;
  • operation:用于操作几何图形,例如获取几何体的 buffer、计算几何体之间的距离等;
  • planargraph:用于描述平面图形;
  • precision:用于设定精确度;
  • shape:用于快速生成一些几何模型,例如生成随机点、生成莫顿曲线等;
  • simplify:几何体简化工具;
  • triangulate:用于处理三角形相关内容;
  • util:一些工具类。

Geometry

引pom

<!-- https://mvnrepository.com/artifact/org.locationtech.jts/jts-core -->
        <dependency>
            <groupId>org.locationtech.jts</groupId>
            <artifactId>jts-core</artifactId>
            <version>1.19.0</version>
        </dependency>

几何类型

JTS 在 org.locationtech.jts.geom 包中提供了以下几种几何类型:

  • Point
  • MultiPoint
  • LineString
  • MultiLineString
  • LinearRing
  • Polygon
  • MultiPolygon
  • GeometryCollection

其架构如下:
在这里插入图片描述

创建几何类型

JTS 通过 GeometryFactory 工厂创建几何对象:

GeometryFactory geometryFactory = new GeometryFactory();

下面我们演示创建各类几何对象的方法。

创建 Point、MultiPoint

  1. 通过坐标(Coordinate)创建

    Coordinate coordinate = new Coordinate(12.654210, 69.332525);
    Point point = geometryFactory.createPoint(coordinate);
    Coordinate coordinate1 = new Coordinate(13.654210, 70.332525);
    Point point1 = geometryFactory.createPoint(coordinate1);
    MultiPoint multiPoint = geometryFactory.createMultiPoint(new Point[]{point,point1});
    
  2. 通过 WKT 创建

    WKTReader wktReader = new WKTReader(geometryFactory);
    Point point = (Point) wktReader.read("POINT (12.654210, 69.332525)");
    
    MultiPoint multiPoint = (MultiPoint) wktReader.read("MULTIPOINT (12.654210 69.332525,
    13.654210 70.332525)");
    

创建 LineString、MultiLineString

  1. 通过坐标创建

    Coordinate[] coords  = new Coordinate[] {new Coordinate(2, 2), new Coordinate(3, 3)};
    LineString lineString = geometryFactory.createLineString(coords);
    Coordinate[] coords1  = new Coordinate[] {new Coordinate(3, 3), new Coordinate(4, 4)};
    LineString lineString1 = geometryFactory.createLineString(coords1);
    
    LineString[] lineStrings = new LineString[]{lineString, lineString1};
    MultiLineString multiLineString = geometryFactory.createMultiLineString(lineStrings);
    
  2. 通过 WKT 创建

    LineString lineString = (LineString) reader.read("LINESTRING(0 0, 2 0)");
    MultiLineString multiLineString = (MultiLineString) reader.read("MULTILINESTRING((0 0, 2 0), (1 1,2 2))");
    

创建闭合线 LinearRing

LinearRing linearRing = geometryFactory.createLinearRing(
  new Coordinate[]{
    new Coordinate(0, 0), 
    new Coordinate(0, 10), 
    new Coordinate(10, 10), 
    new Coordinate(10, 0), 
    new Coordinate(0, 0)
  }
);

创建 Polygon、MultiPolygon

多边形由一个外壳 (shell) 和内部的一些孔洞 (hole) 构成

  1. 通过坐标创建

    LinearRing shell = new GeometryFactory().createLinearRing(..);
    LinearRing hole = new GeometryFactory().createLinearRing(..);
    LinearRing hole1 = new GeometryFactory().createLinearRing(..);
    Polygon polygon = geometryFactory.createPolygon(shell, 
        new LinearRing[]{hole, hole1});
    
    MultiPolygon mp = geometryFactory.createMultiPolygon(new Polygon[]{polygon, ...});
    
  2. 通过 WKT 创建

    WKTReader reader = new WKTReader(geometryFactory);
    Polygon polygon = (Polygon) reader.read("POLYGON((20 10, 30 0, 40 10, 30 20, 20 10))");
    
    MultiPolygon mpolygon = (MultiPolygon) reader.read("MULTIPOLYGON(((40 10, 30 0, 40 10, 30 20, 40 10), (30 10, 30 0, 40 10, 30 20, 30 10)))");
    

创建 GeometryCollection

Geometry[] garray = new Geometry[]{geometry1, geometry2, ...};
GeometryCollection gc = geometryFactory.createGeometryCollection(garray);

空间关系判断

DE-9IM 模型

DE-9IM 全称 Dimensionally Extended nine-Intersection Model,是一种拓扑模型,是描述两个几何图形空间关系的一种标准。在专业领域,通常将每个几何图形分为三部分:外部,边界和内部。

两个图形的关系判断,实际上就是对这三个部分的分别判断,因此就会有一个 3*3 交叉矩阵,这个矩阵就是 DE-9IM 模型,如下表:
在这里插入图片描述

以上 DE-9IM 矩阵中:

  • a^0 表示 a 内部;∂a 表示 a 边界;a^e 表示 a 外部。
  • dim()表示相交部分的维度。
    • 如果相交部分是面,则 dim = 2;
    • 如果相交部分是线,则 dim = 1;
    • 如果相交部分为一些点,则 dim = 0;
    • 如果不相交,则 dim = -1;

接下来我们找两个平面举例:
在这里插入图片描述

这两个几何体的 DE-9IM 矩阵如下:
在这里插入图片描述

以从左往右,从上往下的顺序读取这个矩阵,便可以用一个字符串来表示:212101212

空间谓词

任何基于 DE-9IM 二进制空间关系的拓扑属性都是空间谓词,为了便于使用,我们可以定义一些常用的“命名空间谓词”:

注意: 在能够忽略相交维度的情况下,空间谓词可以用布尔值来代替相交的维度:有相交部分为 T(rue),否则为 F(alse)。
在这里插入图片描述

空间关系分析

缓冲区分析 (buffer)

含义:包含所有的点在一个指定距离内的多边形或多多边形。示意图如下:
在这里插入图片描述

API 详解:

public Geometry buffer(double distance);

distance 参数:缓冲区扩展的距离(可以是正数、负数或 0):

  • 大于 0:向外扩张,示意图:

    在这里插入图片描述

  • 等于 0:buffer 即是边界,示意图:
    在这里插入图片描述

  • 小于 0:向内缩,如果内缩后 buffer 的面积小于等于 0,则返回 POLYGON EMPTY,示意图:
    在这里插入图片描述

public Geometry buffer(double distance, int quadrantSegments);
  • quadrantSegments:控制缓冲区突出位置的圆角精度

    • quadrantSegments >= 1: 手动控制逼近弧度的精度,值越大弧越精确,以下是 quadrantSegments = 2 的示意图:
      在这里插入图片描述

    • quadrantSegments < 1:JTS 自己控制逼近程度

public Geometry buffer(double distance, int quadrantSegments, int endCapStyle);

endCapStyle:端点处 buffer 形状,只对 LineString 有效

  • BufferParameters.CAP_ROUND:端点处缓冲区为圆的一部分
    在这里插入图片描述

  • BufferParameters.CAP_FLAT:端点处的缓冲区边界直接穿过端点切下来
    在这里插入图片描述

  • BufferParameters.CAP_SQUARE:端点处向外延伸出一个长方形区域
    在这里插入图片描述

除了常规的 buffer,JTS 还支持用于 LineStringSideBuffer 等,道理与普通 buffer 一样,就不展开了。

交叉分析 (Intersection)

含义:获取多边形交叉部分的共同点构成的集合。示意图如下:
在这里插入图片描述

API 详解:

public Geometry intersection(Geometry other);

geometryA.intersection(geometryB):获取两个几何体之间的交叉部分的几何体。

凸壳分析 (ConvexHull)

含义:包含几何形体的所有点的最小凸壳多边形(外包多边形)。示意图如下:
在这里插入图片描述

过大的wkt在不缺失太多精度的情况下,缩小
在这里插入图片描述

public Geometry convexHull();

获取几何体的凸壳

联合分析 (Union)

含义:获取多面体所有点的集合。示意图如下:
在这里插入图片描述

API 详解:

public Geometry union(Geometry other);

geometryA.union(geometryB):获取两个几何体之间的联合部分。

差异分析 (Difference)

含义:获取一个多面体里有,另一个多面体里没有的点的集合。示意图如下:
在这里插入图片描述

API 详解:

public Geometry difference(Geometry other);

geometryA.difference(geometryB):获取两个几何体之间的差异部分。

对称差异分析 (SymDifference)

含义:不同时在两个多面体中的所有点的集合。示意图如下:
在这里插入图片描述

API 详解:

public Geometry symDifference(Geometry other);

geometryA.symDifference(geometryB):获取不同时相交与两个几何体的部分。

构建不规则三角网 (TIN)

除了前文介绍的点、线、面等基本几何类型,GIS 系统中还广泛使用一种特殊的几何类型,即不规则三角网 (TIN, Triangulated Irregular Network)。

TIN 是在 GIS 系统和计算机图形领域中广泛使用的一种地形建模空间数据表示方法。其基本思想是将地形表面分割为许多不规则的三角形,每个三角形由地面上的三个离散点定义。示意图如下:
在这里插入图片描述

JTS 可以通过可以通过点集WKT 来创建 TIN 几何对象,相关实现位于 org.locationtech.jts.triangulate 包中。

通过点集构建 TIN

首先我们创建四个坐标点,分别是 (1,1)、(1,2)、(2,2)、(2,1),这四个点将会构成一个正方形:

/*   ^
 * 2 |      .--------.
 *   |      |        | 四个点构成一个正方形
 *   |      |        |
 * 1 |      `--------'
 *   |
 * 0 +----------------------------->
 *   0      1        2
 */
GeometryFactory geometryFactory = new GeometryFactory();
Coordinate[] coordinates = new Coordinate[] {
        new Coordinate(1, 1),
        new Coordinate(2, 1),
        new Coordinate(2, 2),
        new Coordinate(1, 2),
        // 当然,这里可以追加更多坐标点
};

然后通过 DelaunayTriangulationBuilder 创建 TIN:

// 获取 builder
DelaunayTriangulationBuilder dtb = new DelaunayTriangulationBuilder();
// 拿到点阵集合 coordinates,并注册到 builder 内
dtb.setSites(Arrays.asList(coordinates));
// 然后获取 tin 集合体
Geometry tinGeometry = dtb.getTriangles(geometryFactory);

最终得到的 TIN 几何体为 GEOMETRYCOLLECTION(POLYGON((1 2,1 1,2 1,1 2)),POLYGON((1 2,2 1,2 2,1 2))),其形状如下:
在这里插入图片描述

可见,JTS 将这个平行四边形从中间划分开,形成了由两个三角形组成的 TIN。

通过 WKT 构建 TIN

通过 WKT 创建 TIN 也很简单,还是以这四个点为例:

GeometryFactory geometryFactory = new GeometryFactory();
DelaunayTriangulationBuilder dtb = new DelaunayTriangulationBuilder();
WKTReader wktReader = new WKTReader(geometryFactory);
// 创建这四个点的 Geometry
Geometry geometry = wktReader.read("POLYGON((1 1, 1 2, 2 2, 2 1, 1 1))");
// 注册
dtb.setSites(geometry);
// 获取 tin
Geometry tinGeometry = dtb.getTriangles(geometryFactory);

首先通过 WKT 创建点集的 Geometry,然后调用 setSites 的重载方法完成注册,之后的流程就与之前一样了。

几何体致密化 (Densify)

在日常工作中,经常会遇到需要进行垂线或投影操作的情况。然而,在 JTS 中进行投影操作时,本质上是计算被投影体到目标体上最近点的距离。如果目标体上的点比较稀疏,就会产生较大的误差。为了提高投影的准确性,我们可以使用 Densify 对几何体进行致密化处理,以提升计算精度。

API 详解:

Densifer.densify(Geometry geom, double distanceTolerance);
  • geom:待处理的几何体;
  • distanceTolerance:致密化后的点距,单位为弧度。

示意图如下:
在这里插入图片描述

至此,JTS 开发的重点内容就介绍完了。

扩展:WKT 与 WKB 标记语言

WKT

Well-known text (WKT) 是一种用于表示矢量几何对象的文本标记语言,其表示的几何对象有:点、线、多边形、TIN 和多面体。下面是一些例子:

GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))
POINT ZM (1 1 5 60)
POINT M (1 1 80)
POINT EMPTY
MULTIPOLYGON EMPTY
TRIANGLE((0 0 0,0 1 0,1 1 0,0 0 0))
TIN (((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)))
POLYHEDRALSURFACE Z ( PATCHES
    ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
    ((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),
    ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
    ((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),
    ((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),
    ((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))
)
  • 几何坐标可以是 2D (x, y)、3D (x, y, z)、4D (x, y, z, m),其中 m 值是线性参考系的一部分。
  • 或者是 2D + m 值 (x, y, m)。
  • 也可以通过在类型名称后使用符号 EMPTY 来指定不包含坐标的空几何。

WKB

Well-known binary (WKB) 是 WKT 的二进制等效物,用于以更紧凑的形式传输和存储相同的信息。WKB 由 1 字节无符号整数 + 4 字节无符号整数 + 8 字节双精度数字组成:

  • 第一个字节表示字节顺序:

    1. 00:大端模式
    2. 01:小端模式
  • 接下来的四个字节表示几何类型:

    类型2DZMZM
    Geometry0000100020003000
    Point0001100120013001
    LineString0002100220023002
    Polygon0003100320033003
    MultiPoint0004100420043004
    MultiLineString0005100520053005
    MultiPolygon0006100620063006
    GeometryCollection0007100720073007
    CircularString0008100820083008
    CompoundCurve0009100920093009
    CurvePolygon0010101020103010
    MultiCurve0011101120113011
    MultiSurface0012101220123012
    Curve0013101320133013
    Surface0014101420143014
    PolyhedralSurface0015101520153015
    TIN0016101620163016
    Triangle0017101720173017
    Circle0018101820183018
    GeodesicString0019101920193019
    EllipticalCurve0020102020203020
    NurbsCurve0021102120213021
    Clothoid0022102220223022
    SpiralCurve0023102320233023
    CompoundSurface0024102420243024
    BrepSolid1025
    AffinePlacement1021102
    • 下面以存储 POINT(2.0 4.0) 为例:00 00000001 4000000000000000 4010000000000000
      • 00 :表示大端模式
      • 00000001 :表示 Point 2D (x,y) 类型数据
      • 4000000000000000 :64 位双精度浮点数,表示 x 坐标
      • 4010000000000000 :64 位双精度浮点数,表示 y 坐标
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值