SuperAPI AI Directory

jts

Data & analytics

View repository

Updated 10-16 09:45

About this skill

Project URL: https://github.com/locationtech/jts

Maven Central: org.locationtech.jts:jts-core

License: Eclipse Public License 2.0 / Eclipse Distribution License 1.0 (BSD-style)

Javadoc: https://locationtech.github.io/jts/javadoc

Overview

JTS Topology Suite (JTS for short) is an open-source Java 2D vector geometry library under the LocationTech project group, and is the geometry computation core of numerous open-source GIS projects such as GeoTools and GeoServer. It provides:

  • Geometric object model:Point、LineString、Polygon、MultiPoint、MultiLineString、MultiPolygon、GeometryCollection
  • Spatial relationship determination:equals、contains、within、intersects、touches、crosses、overlaps、disjoint、relate(DE-9IM)
  • Set operations:intersection、union、difference、symDifference、buffer
  • Geometric analysis:convexHull、centroid、area、length、distance、isValid、simplify
  • Linear referencing: distance-based positioning along a line, interpolation on a line
  • Spatial indexing: STRtree, Quadtree, accelerating bulk spatial queries
  • Format read/write:WKT、WKB、GeoJSON

Environment requirements: JDK 8+


Quick integration

Maven

<properties>
    <jts.version>1.20.0</jts.version>
</properties>

<dependency>
    <groupId>org.locationtech.jts</groupId>
    <artifactId>jts-core</artifactId>
    <version>${jts.version}</version>
</dependency>

If I/O support such as GeoJSON is needed:

<dependency>
    <groupId>org.locationtech.jts.io</groupId>
    <artifactId>jts-io-common</artifactId>
    <version>${jts.version}</version>
</dependency>

Gradle

implementation 'org.locationtech.jts:jts-core:1.20.0'
implementation 'org.locationtech.jts.io:jts-io-common:1.20.0'

Project module overview

Module artifactId Purpose
jts-core jts-core ★ Core — geometric model, algorithms, spatial operations, indexing
jts-io-common jts-io-common General I/O: WKT, WKB, GeoJSON read/write
jts-io-ora jts-io-ora Oracle Spatial SDO_GEOMETRY read/write
jts-io-sde jts-io-sde ArcSDE geometry read/write

Core class overview

Class Package Purpose
GeometryFactory org.locationtech.jts.geom ★ Recommended entry point— factory for creating all geometric objects
Geometry org.locationtech.jts.geom Abstract geometry base class, providing spatial operation and relationship determination methods
Point org.locationtech.jts.geom Point (0-dimensional)
LineString org.locationtech.jts.geom LineString (1-dimensional)
LinearRing org.locationtech.jts.geom Closed LinearRing (used to construct Polygon)
Polygon org.locationtech.jts.geom Polygon (2-dimensional, with an exterior ring and optional interior rings)
MultiPoint org.locationtech.jts.geom MultiPoint collection
MultiLineString org.locationtech.jts.geom MultiLineString collection
MultiPolygon org.locationtech.jts.geom MultiPolygon collection
GeometryCollection org.locationtech.jts.geom Arbitrary GeometryCollection
Coordinate org.locationtech.jts.geom Coordinate values (x, y, z)
Envelope org.locationtech.jts.geom Envelope (MBR)
PrecisionModel org.locationtech.jts.geom Coordinate precision model
WKTReader org.locationtech.jts.io WKT format parsing
WKTWriter org.locationtech.jts.io WKT format output
WKBReader org.locationtech.jts.io WKB format parsing
WKBWriter org.locationtech.jts.io WKB format output
GeoJsonReader org.locationtech.jts.io.geojson GeoJSON parsing
GeoJsonWriter org.locationtech.jts.io.geojson GeoJSON output
STRtree org.locationtech.jts.index.strtree R-tree spatial index (bulk-loaded, efficient queries)
Quadtree org.locationtech.jts.index.quadtree Quadtree spatial index (supports dynamic insertion and deletion)
PreparedGeometry org.locationtech.jts.geom.prep Prepared geometry, accelerating repeated spatial relationship determination
PreparedGeometryFactory org.locationtech.jts.geom.prep Factory for creating PreparedGeometry
BufferOp org.locationtech.jts.operation.buffer Buffer operation (fine-grained control over end cap and join styles)
OverlayNGRobust org.locationtech.jts.operation.overlayng Robust overlay operation (recommended next-generation overlay engine)
TopologyPreservingSimplifier org.locationtech.jts.simplify Topology-preserving geometry simplification
DouglasPeuckerSimplifier org.locationtech.jts.simplify Douglas-Peucker geometry simplification
IsValidOp org.locationtech.jts.operation.valid Geometry validity checking
LengthIndexedLine org.locationtech.jts.linearref Linear referencing by length
LocationIndexedLine org.locationtech.jts.linearref Linear referencing by position

Geometry object creation

import org.locationtech.jts.geom.*;

GeometryFactory gf = new GeometryFactory();

// 点
Point point = gf.createPoint(new Coordinate(116.4, 39.9));

// 带 Z 值的点
Point point3d = gf.createPoint(new Coordinate(116.4, 39.9, 50.0));

// 线串
LineString line = gf.createLineString(new Coordinate[]{
    new Coordinate(0, 0),
    new Coordinate(10, 10),
    new Coordinate(20, 0)
});

// 线环(必须闭合)
LinearRing ring = gf.createLinearRing(new Coordinate[]{
    new Coordinate(0, 0), new Coordinate(10, 0),
    new Coordinate(10, 10), new Coordinate(0, 10),
    new Coordinate(0, 0)  // 首尾相同
});

// 面(无洞)
Polygon polygon = gf.createPolygon(new Coordinate[]{
    new Coordinate(0, 0), new Coordinate(10, 0),
    new Coordinate(10, 10), new Coordinate(0, 10),
    new Coordinate(0, 0)
});

// 面(带洞)
LinearRing shell = gf.createLinearRing(new Coordinate[]{
    new Coordinate(0, 0), new Coordinate(20, 0),
    new Coordinate(20, 20), new Coordinate(0, 20),
    new Coordinate(0, 0)
});
LinearRing hole = gf.createLinearRing(new Coordinate[]{
    new Coordinate(5, 5), new Coordinate(15, 5),
    new Coordinate(15, 15), new Coordinate(5, 15),
    new Coordinate(5, 5)
});
Polygon polygonWithHole = gf.createPolygon(shell, new LinearRing[]{hole});

// 多点
MultiPoint multiPoint = gf.createMultiPointFromCoords(new Coordinate[]{
    new Coordinate(1, 2), new Coordinate(3, 4)
});

// 多线
MultiLineString multiLine = gf.createMultiLineString(new LineString[]{line});

// 多面
MultiPolygon multiPolygon = gf.createMultiPolygon(new Polygon[]{polygon});

// 几何集合
GeometryCollection gc = gf.createGeometryCollection(new Geometry[]{point, line, polygon});

Spatial relationship determination

// 八大空间谓词
boolean eq  = geomA.equals(geomB);           // 几何相等
boolean dj  = geomA.disjoint(geomB);         // 相离
boolean ix  = geomA.intersects(geomB);       // 相交
boolean tc  = geomA.touches(geomB);          // 接触
boolean cr  = geomA.crosses(geomB);          // 穿越
boolean wn  = geomA.within(geomB);           // A 在 B 内
boolean ct  = geomA.contains(geomB);         // A 包含 B
boolean ol  = geomA.overlaps(geomB);         // 重叠

// DE-9IM 关系矩阵
boolean rel = geomA.relate(geomB, "T*F**FFF*");
String matrix = geomA.relate(geomB).toString();  // 返回 "212101212" 等

// 距离判断
boolean near = geomA.isWithinDistance(geomB, 100.0);

Set operations

// 交集
Geometry intersection = geomA.intersection(geomB);

// 合并
Geometry union = geomA.union(geomB);

// 差集
Geometry difference = geomA.difference(geomB);

// 对称差
Geometry symDiff = geomA.symDifference(geomB);

// 缓冲区
Geometry buffer = geometry.buffer(10.0);               // 默认圆弧端头
Geometry bufferFlat = geometry.buffer(10.0, 8, BufferOp.CAP_FLAT);  // 平头端

// 多几何合并(高性能)
import org.locationtech.jts.operation.union.UnaryUnionOp;
Geometry merged = UnaryUnionOp.union(geometryCollection);

// 鲁棒叠加运算(推荐)
import org.locationtech.jts.operation.overlayng.OverlayNGRobust;
Geometry robustIntersection = OverlayNGRobust.overlay(geomA, geomB, OverlayNG.INTERSECTION);
Geometry robustUnion = OverlayNGRobust.overlay(geomA, geomB, OverlayNG.UNION);

Geometric analysis

// 面积与长度
double area = polygon.getArea();
double length = line.getLength();

// 距离
double dist = geomA.distance(geomB);

// 质心
Point centroid = geometry.getCentroid();

// 内部点(保证在几何内部)
Point interiorPoint = geometry.getInteriorPoint();

// 凸包
Geometry hull = geometry.convexHull();

// 外接矩形
Envelope env = geometry.getEnvelopeInternal();

// 有效性检测
boolean valid = geometry.isValid();

// 详细有效性诊断
import org.locationtech.jts.operation.valid.IsValidOp;
IsValidOp validator = new IsValidOp(geometry);
if (!validator.isValid()) {
    System.out.println(validator.getValidationError());
}

// 几何修复
import org.locationtech.jts.geom.util.GeometryFixer;
Geometry fixed = GeometryFixer.fix(geometry);

Geometry simplification

import org.locationtech.jts.simplify.TopologyPreservingSimplifier;
import org.locationtech.jts.simplify.DouglasPeuckerSimplifier;

// 保持拓扑的简化(推荐)
Geometry simplified = TopologyPreservingSimplifier.simplify(geometry, 0.001);

// Douglas-Peucker 简化(更快,但可能产生自相交)
Geometry dpSimplified = DouglasPeuckerSimplifier.simplify(geometry, 0.001);

Precision model

// 浮点精度(默认)
PrecisionModel pmFloat = new PrecisionModel();

// 固定精度(如保留 6 位小数 → scale = 1000000)
PrecisionModel pmFixed = new PrecisionModel(1000000);

// 使用精度模型创建工厂
GeometryFactory gf = new GeometryFactory(pmFixed);

// 带 SRID 的工厂
GeometryFactory gfSrid = new GeometryFactory(pmFloat, 4326);

Format read/write

WKT(Well-Known Text)

import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;

WKTReader reader = new WKTReader();

// 读取
Geometry point = reader.read("POINT (116.4 39.9)");
Geometry line  = reader.read("LINESTRING (0 0, 10 10, 20 0)");
Geometry poly  = reader.read("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))");

// 写入
WKTWriter writer = new WKTWriter();
String wkt = writer.write(point);   // "POINT (116.4 39.9)"

// 3D WKT
WKTWriter writer3d = new WKTWriter(3);
String wkt3d = writer3d.write(gf.createPoint(new Coordinate(1, 2, 3)));

WKB(Well-Known Binary)

import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKBWriter;

// 写入
WKBWriter wkbWriter = new WKBWriter();
byte[] wkb = wkbWriter.write(geometry);

// 读取
WKBReader wkbReader = new WKBReader();
Geometry geom = wkbReader.read(wkb);

// 输出 Hex 字符串(常用于数据库交互)
String hex = WKBWriter.toHex(wkb);
byte[] fromHex = WKBReader.hexToBytes(hex);

GeoJSON

import org.locationtech.jts.io.geojson.GeoJsonReader;
import org.locationtech.jts.io.geojson.GeoJsonWriter;

// 读取
GeoJsonReader gjReader = new GeoJsonReader();
Geometry geom = gjReader.read("{\"type\":\"Point\",\"coordinates\":[116.4,39.9]}");

// 写入
GeoJsonWriter gjWriter = new GeoJsonWriter();
String json = gjWriter.write(geom);

Spatial indexing

STRtree (R-tree, recommended for bulk queries)

import org.locationtech.jts.index.strtree.STRtree;

STRtree index = new STRtree();

// 批量插入(插入后首次查询时自动构建索引)
for (Geometry geom : geometries) {
    index.insert(geom.getEnvelopeInternal(), geom);
}

// 矩形范围查询
Envelope searchEnv = new Envelope(10, 20, 10, 20);
List<?> candidates = index.query(searchEnv);

// 最近邻查询
import org.locationtech.jts.index.strtree.ItemDistance;
Object nearest = index.nearestNeighbour(
    point.getEnvelopeInternal(), point,
    (ItemDistance) (itemBoundable1, itemBoundable2) -> {
        Geometry g1 = (Geometry) itemBoundable1.getItem();
        Geometry g2 = (Geometry) itemBoundable2.getItem();
        return g1.distance(g2);
    }
);

Quadtree (quadtree, supports dynamic insertion and deletion)

import org.locationtech.jts.index.quadtree.Quadtree;

Quadtree qtree = new Quadtree();
qtree.insert(geom.getEnvelopeInternal(), geom);
List<?> results = qtree.query(searchEnv);
qtree.remove(geom.getEnvelopeInternal(), geom);

PreparedGeometry (accelerates repeated tests)

When the same geometry needs to be repeatedly tested for spatial relationships (such as determining whether a large number of points are inside a polygon), use PreparedGeometry to significantly improve performance:

import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.locationtech.jts.geom.prep.PreparedGeometryFactory;

PreparedGeometry prepared = PreparedGeometryFactory.prepare(polygon);

for (Point pt : points) {
    if (prepared.contains(pt)) {
        // 命中
    }
}

Linear referencing

import org.locationtech.jts.linearref.LengthIndexedLine;
import org.locationtech.jts.linearref.LocationIndexedLine;

LengthIndexedLine lil = new LengthIndexedLine(line);

// 按长度获取坐标
Coordinate midPoint = lil.extractPoint(line.getLength() / 2);

// 截取子线
Geometry subLine = lil.extractLine(10.0, 50.0);

// 计算某点在线上的投影位置(距起点长度)
double index = lil.indexOf(new Coordinate(5, 5));

// 按位置引用
LocationIndexedLine locLine = new LocationIndexedLine(line);

Affine transformation

import org.locationtech.jts.geom.util.AffineTransformation;

// 平移
AffineTransformation translate = AffineTransformation.translationInstance(10, 20);
Geometry moved = translate.transform(geometry);

// 旋转(弧度,绕原点)
AffineTransformation rotate = AffineTransformation.rotationInstance(Math.PI / 4);
Geometry rotated = rotate.transform(geometry);

// 缩放
AffineTransformation scale = AffineTransformation.scaleInstance(2.0, 2.0);
Geometry scaled = scale.transform(geometry);

// 组合变换
AffineTransformation combo = new AffineTransformation();
combo.translate(10, 0);
combo.rotate(Math.PI / 6);
Geometry result = combo.transform(geometry);

Typical application scenarios

Scenario Key classes / methods
Create geometry objects GeometryFactory.createPoint() / createLineString() / createPolygon()
Geofencing / point-in-polygon determination Geometry.contains() / within(), for high-frequency scenarios use PreparedGeometry
Calculate the distance between two geometries Geometry.distance()
Buffer analysis Geometry.buffer() or BufferOp
Polygon overlay analysis (intersection, union, difference) Geometry.intersection() / union() / difference()
Robust overlay operations OverlayNGRobust.overlay()
Geometry format conversion WKTReader / WKTWriter / WKBReader / WKBWriter / GeoJsonReader / GeoJsonWriter
Batch spatial query acceleration STRtree / Quadtree
Nearest neighbor search STRtree.nearestNeighbour()
Geometry simplification (thinning) TopologyPreservingSimplifier / DouglasPeuckerSimplifier
Geometry validity checking and repair IsValidOp / GeometryFixer
Linear referencing / locating along a line LengthIndexedLine / LocationIndexedLine
Convex hull computation Geometry.convexHull()
Geometry affine transformation AffineTransformation
Database WKB interaction WKBReader.hexToBytes() / WKBWriter.toHex()

Common considerations

  1. Use GeometryFactory to create geometries: do not directly new Point(), always create geometry objects through GeometryFactory 's factory methods.
  2. Polygons must be closed: the first and last coordinates of the exterior ring and interior ring coordinate arrays of a Polygon must be the same.
  3. Coordinate order: JTS uses (x, y) , i.e. (经度, 纬度) order; be careful to distinguish it from the (纬度, 经度) of some GIS systems.
  4. Geometry validity: externally imported geometry data should use geometry.isValid() to check validity; invalid geometries can be repaired with GeometryFixer.fix() .
  5. SRID does not participate in computation: JTS's SRID is only used as a metadata tag and does not affect spatial operations; all JTS computations are performed on the Cartesian plane and do not handle projections.
  6. Performance optimization: for batch spatial queries use STRtree; for repeated spatial relationship determinations use PreparedGeometry; for merging large numbers of geometries use UnaryUnionOp。
  7. Thread safety:GeometryFactory is thread-safe;Geometry objects themselves are immutable and can be shared safely; however, Reader/Writer instances are not thread-safe, and a separate instance must be created for each thread.
  8. Package name migration: in JTS 1.15+ the package name migrated from com.vividsolutions.jts to org.locationtech.jts; be careful when upgrading old code.
  9. OverlayNG: for overlay operations (intersection / union / difference), it is recommended to use OverlayNGRobust, which is more robust than the traditional overlay engine and can handle more edge cases.

Reference links