Skip to content

Commit dd13e6c

Browse files
[curved] New jts-curved module with SFA / ISO 19125-2 geometry types
Adds an opt-in module that implements the OGC SFA / ISO 19125-2 extended geometry types on top of the extension hooks added to jts-core in the prior commit. Geometry types (in org.locationtech.jts.geom.curved) - CircularString extends LineString - CompoundCurve extends LineString (member structure collapsed in this phase) - CurvePolygon extends Polygon (rings linearised on read) - MultiCurve extends MultiLineString - MultiSurface extends MultiPolygon - Triangle extends Polygon (Polygon with one 4-point ring) - PolyhedralSurface extends MultiPolygon - Tin extends PolyhedralSurface `Triangle` lives in `.geom.curved` because the existing static-utility class `org.locationtech.jts.geom.Triangle` (centroid, circumradius) is preserved unchanged. Readers / writers (in org.locationtech.jts.io.curved) - CurvedWKTReader extends WKTReader, overrides `readOtherGeometryText` to dispatch the eight new keywords. Composite types (CompoundCurve, CurvePolygon, MultiCurve, MultiSurface) iterate heterogeneous members via `lookAheadWord`-based peeking. CompoundCurve also accepts the writer's flat round-trip form. - CurvedWKTWriter extends WKTWriter; phase-1 marker. Emission already works correctly via the core `getGeometryType().toUpperCase()` change routed through the existing `instanceof` ladder. Tests - 54 round-trip tests across 8 files covering XY / XYZ / XYM / XYZM / EMPTY / round-trip / structural-validation-deferred negative cases. - All pass against the new module; full jts-core suite (2282 tests) still passes unchanged. Out of scope (deferred to later phases per the proposal) - Validation (Triangle 4-point rule, CircularString odd point count, CompoundCurve member connectivity, Tin triangle-only patches). - Member-structured CompoundCurve / CurvePolygon emission (currently collapsed to flat coordinates / linear rings). - WKBReader / WKBWriter for SFA-MM type codes. - Native curve-aware spatial operations (intersects, contains, area, buffer). Curves currently fall through to their parent type's polyline / polygon behaviour. - copy() returning the correct subclass. - JTSTestBuilder UI integration. References - Discussion: locationtech/jts#1193 - Design template: NetTopologySuite/NetTopologySuite#526
1 parent f1fb2a4 commit dd13e6c

20 files changed

Lines changed: 1404 additions & 0 deletions

‎modules/curved/pom.xml‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.locationtech.jts</groupId>
7+
<artifactId>jts-modules</artifactId>
8+
<version>1.20.1-SNAPSHOT</version>
9+
</parent>
10+
<groupId>org.locationtech.jts</groupId>
11+
<artifactId>jts-curved</artifactId>
12+
<name>${project.groupId}:${project.artifactId}</name>
13+
<packaging>jar</packaging>
14+
15+
<description>
16+
OGC SFA / ISO 19125-2 extended geometry types (CircularString,
17+
CompoundCurve, CurvePolygon, MultiCurve, MultiSurface, Triangle,
18+
PolyhedralSurface, Tin) and the corresponding WKT readers/writers.
19+
Built on top of the extension hooks in jts-core; opt-in.
20+
</description>
21+
22+
<build>
23+
<plugins>
24+
<plugin>
25+
<artifactId>maven-jar-plugin</artifactId>
26+
<configuration>
27+
<archive>
28+
<manifestEntries>
29+
<Automatic-Module-Name>org.locationtech.jts.curved</Automatic-Module-Name>
30+
</manifestEntries>
31+
<manifestSections>
32+
<manifestSection>
33+
<name>org.locationtech.jts.curved</name>
34+
<manifestEntries>
35+
<Sealed>true</Sealed>
36+
</manifestEntries>
37+
</manifestSection>
38+
</manifestSections>
39+
</archive>
40+
</configuration>
41+
</plugin>
42+
</plugins>
43+
</build>
44+
45+
<dependencies>
46+
<dependency>
47+
<groupId>org.locationtech.jts</groupId>
48+
<artifactId>jts-core</artifactId>
49+
<version>${project.version}</version>
50+
</dependency>
51+
<dependency>
52+
<groupId>org.locationtech.jts</groupId>
53+
<artifactId>jts-core</artifactId>
54+
<version>${project.version}</version>
55+
<classifier>tests</classifier>
56+
<scope>test</scope>
57+
</dependency>
58+
<dependency>
59+
<groupId>junit</groupId>
60+
<artifactId>junit</artifactId>
61+
<scope>test</scope>
62+
</dependency>
63+
</dependencies>
64+
</project>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2026 grootstebozewolf
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7+
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8+
* and the Eclipse Distribution License is available at
9+
*
10+
* http://www.eclipse.org/org/documents/edl-v10.php.
11+
*/
12+
package org.locationtech.jts.geom.curved;
13+
14+
import org.locationtech.jts.geom.CoordinateSequence;
15+
import org.locationtech.jts.geom.GeometryFactory;
16+
import org.locationtech.jts.geom.LineString;
17+
18+
/**
19+
* A connected sequence of circular arcs, where each consecutive triple of
20+
* control points (start, mid, end) defines one arc and the end point of one
21+
* arc is the start point of the next.
22+
* <p>
23+
* This is a phase-1 stand-in: the control points are stored as a single
24+
* {@link CoordinateSequence} (inherited via {@link LineString}) and spatial
25+
* operations fall through to the parent's polyline behaviour. Native
26+
* arc-aware algorithms are out of scope for this module today.
27+
*/
28+
public class CircularString extends LineString {
29+
private static final long serialVersionUID = 1L;
30+
31+
public CircularString(CoordinateSequence points, GeometryFactory factory) {
32+
super(points, factory);
33+
}
34+
35+
@Override
36+
public String getGeometryType() {
37+
return "CircularString";
38+
}
39+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2026 grootstebozewolf
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7+
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8+
* and the Eclipse Distribution License is available at
9+
*
10+
* http://www.eclipse.org/org/documents/edl-v10.php.
11+
*/
12+
package org.locationtech.jts.geom.curved;
13+
14+
import org.locationtech.jts.geom.CoordinateSequence;
15+
import org.locationtech.jts.geom.GeometryFactory;
16+
import org.locationtech.jts.geom.LineString;
17+
18+
/**
19+
* A connected sequence of {@link LineString} and {@link CircularString}
20+
* segments. Phase-1 stand-in: member structure is collapsed to a flat
21+
* concatenation of control points. A future phase will preserve segments.
22+
*/
23+
public class CompoundCurve extends LineString {
24+
private static final long serialVersionUID = 1L;
25+
26+
public CompoundCurve(CoordinateSequence points, GeometryFactory factory) {
27+
super(points, factory);
28+
}
29+
30+
@Override
31+
public String getGeometryType() {
32+
return "CompoundCurve";
33+
}
34+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2026 grootstebozewolf
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7+
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8+
* and the Eclipse Distribution License is available at
9+
*
10+
* http://www.eclipse.org/org/documents/edl-v10.php.
11+
*/
12+
package org.locationtech.jts.geom.curved;
13+
14+
import org.locationtech.jts.geom.GeometryFactory;
15+
import org.locationtech.jts.geom.LinearRing;
16+
import org.locationtech.jts.geom.Polygon;
17+
18+
/**
19+
* A polygon whose rings may be straight, circular, or compound curves.
20+
* Phase-1 stand-in: rings are linearised to {@link LinearRing}s on read.
21+
*/
22+
public class CurvePolygon extends Polygon {
23+
private static final long serialVersionUID = 1L;
24+
25+
public CurvePolygon(LinearRing shell, LinearRing[] holes, GeometryFactory factory) {
26+
super(shell, holes, factory);
27+
}
28+
29+
public CurvePolygon(GeometryFactory factory) {
30+
super(null, null, factory);
31+
}
32+
33+
@Override
34+
public String getGeometryType() {
35+
return "CurvePolygon";
36+
}
37+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2026 grootstebozewolf
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7+
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8+
* and the Eclipse Distribution License is available at
9+
*
10+
* http://www.eclipse.org/org/documents/edl-v10.php.
11+
*/
12+
package org.locationtech.jts.geom.curved;
13+
14+
import org.locationtech.jts.geom.GeometryFactory;
15+
import org.locationtech.jts.geom.LineString;
16+
import org.locationtech.jts.geom.MultiLineString;
17+
18+
/**
19+
* A collection of {@link LineString}, {@link CircularString} and
20+
* {@link CompoundCurve} members.
21+
*/
22+
public class MultiCurve extends MultiLineString {
23+
private static final long serialVersionUID = 1L;
24+
25+
public MultiCurve(LineString[] members, GeometryFactory factory) {
26+
super(members, factory);
27+
}
28+
29+
@Override
30+
public String getGeometryType() {
31+
return "MultiCurve";
32+
}
33+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2026 grootstebozewolf
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7+
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8+
* and the Eclipse Distribution License is available at
9+
*
10+
* http://www.eclipse.org/org/documents/edl-v10.php.
11+
*/
12+
package org.locationtech.jts.geom.curved;
13+
14+
import org.locationtech.jts.geom.GeometryFactory;
15+
import org.locationtech.jts.geom.MultiPolygon;
16+
import org.locationtech.jts.geom.Polygon;
17+
18+
/** A collection of {@link Polygon} and {@link CurvePolygon} members. */
19+
public class MultiSurface extends MultiPolygon {
20+
private static final long serialVersionUID = 1L;
21+
22+
public MultiSurface(Polygon[] members, GeometryFactory factory) {
23+
super(members, factory);
24+
}
25+
26+
@Override
27+
public String getGeometryType() {
28+
return "MultiSurface";
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2026 grootstebozewolf
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7+
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8+
* and the Eclipse Distribution License is available at
9+
*
10+
* http://www.eclipse.org/org/documents/edl-v10.php.
11+
*/
12+
package org.locationtech.jts.geom.curved;
13+
14+
import org.locationtech.jts.geom.GeometryFactory;
15+
import org.locationtech.jts.geom.MultiPolygon;
16+
import org.locationtech.jts.geom.Polygon;
17+
18+
/** A contiguous collection of polygonal patches that share edges. */
19+
public class PolyhedralSurface extends MultiPolygon {
20+
private static final long serialVersionUID = 1L;
21+
22+
public PolyhedralSurface(Polygon[] patches, GeometryFactory factory) {
23+
super(patches, factory);
24+
}
25+
26+
@Override
27+
public String getGeometryType() {
28+
return "PolyhedralSurface";
29+
}
30+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2026 grootstebozewolf
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7+
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8+
* and the Eclipse Distribution License is available at
9+
*
10+
* http://www.eclipse.org/org/documents/edl-v10.php.
11+
*/
12+
package org.locationtech.jts.geom.curved;
13+
14+
import org.locationtech.jts.geom.GeometryFactory;
15+
import org.locationtech.jts.geom.Polygon;
16+
17+
/** A {@link PolyhedralSurface} whose patches are all triangles (TIN). */
18+
public class Tin extends PolyhedralSurface {
19+
private static final long serialVersionUID = 1L;
20+
21+
public Tin(Polygon[] patches, GeometryFactory factory) {
22+
super(patches, factory);
23+
}
24+
25+
@Override
26+
public String getGeometryType() {
27+
return "Tin";
28+
}
29+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2026 grootstebozewolf
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7+
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8+
* and the Eclipse Distribution License is available at
9+
*
10+
* http://www.eclipse.org/org/documents/edl-v10.php.
11+
*/
12+
package org.locationtech.jts.geom.curved;
13+
14+
import org.locationtech.jts.geom.GeometryFactory;
15+
import org.locationtech.jts.geom.LinearRing;
16+
import org.locationtech.jts.geom.Polygon;
17+
18+
/**
19+
* A planar triangle as defined by OGC SFA / ISO 19125-2: a {@link Polygon}
20+
* with a single 4-point closed exterior ring and no holes.
21+
* <p>
22+
* Note: the unrelated static-utility class
23+
* {@code org.locationtech.jts.geom.Triangle} (centroid, circumradius, etc.)
24+
* is preserved unchanged in jts-core. The geometry type lives here in the
25+
* curved package to avoid that name collision.
26+
*/
27+
public class Triangle extends Polygon {
28+
private static final long serialVersionUID = 1L;
29+
30+
public Triangle(LinearRing shell, GeometryFactory factory) {
31+
super(shell, null, factory);
32+
}
33+
34+
public Triangle(GeometryFactory factory) {
35+
super(null, null, factory);
36+
}
37+
38+
@Override
39+
public String getGeometryType() {
40+
return "Triangle";
41+
}
42+
}

0 commit comments

Comments
 (0)