JTS Developer Guide
JTS Developer Guide
JTS Developer Guide
Developers Guide
Version 1.4
GDBC/CTI-S GeoConnections
Page 2
GDBC/CTI-S GeoConnections
Table of Contents
1. OVERVIEW ..................................................................................... 4 1.1 2. 3. 4. 5. OTHER RESOURCES...................................................................... 4
GETTING STARTED ........................................................................... 4 COMPUTING SPATIAL RELATIONSHIPS ................................................... 5 COMPUTING OVERLAY OPERATIONS ..................................................... 5 COMPUTING BUFFERS ....................................................................... 7 5.1 5.2 5.3 BASIC BUFFERING........................................................................ 7 END CAP STYLES ......................................................................... 7 SPECIFYING THE APPROXIMATION QUANTIZATION............................... 8
6. 7. 8. 9.
POLYGONIZATION ............................................................................ 9 MERGING A SET OF LINESTRINGS ....................................................... 10 USING CUSTOM COORDINATE SEQUENCES ............................................ 11 TIPS & TECHNIQUES ....................................................................... 11 9.1 9.2 NODING A SET OF LINESTRINGS .................................................... 11 UNIONING MANY POLYGONS EFFICIENTLY ERROR! BOOKMARK NOT DEFINED.
Page 3
GDBC/CTI-S GeoConnections
1. OVERVIEW
The JTS Topology Suite is a Java API that implements a core set of spatial data operations using an explicit precision model and robust geometric algorithms. It provides a complete model for specifying 2-D linear Geometry. Many common operations in computational geometry and spatial data processing are exposed in a clear, consistent and integrated API. JTS is intended to be used in the development of applications that support the validation, cleaning, integration and querying of spatial datasets. This document is intended for developers who would like to use JTS to accomplish their spatial data processing requirements. It describes common uses of the JTS API and gives code examples.
2. GETTING STARTED
The most common JTS tasks involve creating and using Geometry objects. The easiest way to create a Geometry by hand is to use a WKTReader to generate one from a Well-Known Text (WKT) string. For example: Geometry g1 = new WKTReader().read("LINESTRING (0 0, 10 10, 20 20)"); A precise specification for WKT is given in the JTS Technical Specifications. And many examples of WKT may be found in the files in the test directory. In a real program, its easier to use a GeometryFactory, because you dont need to build up a WKT string; rather, you work with the objects directly: Coordinate[] coordinates = new Coordinate[] { new Coordinate(0, 0), new Coordinate(10, 10), new Coordinate(20, 20) }; Geometry g1 = new GeometryFactory().createLineString(coordinates); Once youve made your Geometry, there are many things you can do with it. You can easily find the intersection of two Geometries:
Page 4
GDBC/CTI-S GeoConnections
Geometry g3 = g1.intersection(g2); Other computations built into Geometries include: area, envelope, centroid, and buffer. For more information about what a Geometry can do, see the JavaDoc for Geometry in the com.vividsolutions.jts.geom package, as well as subsequent sections in this document.
In some cases the precise definition of the predicates is subtle. You should refer to the JTS Technical Specifications to determine exactly what will be returned in any given case.
Page 5
GDBC/CTI-S GeoConnections
(2) A.intersection(B)
(3) A.union(B)
(4) A.difference(B)
(5) B.difference(A)
(6) A.symDifference(B)
Descriptions for the overlay operations are tabulated below. Method Buffer Meaning The Polygon or MultiPolygon which contains all points within a specified distance of the Geometry. For more information, see 5 Computing Buffers on page 7. The smallest convex Polygon that contains all the points in the Geometry. The intersection of two Geometries A and B is the set of all points which lie in both A and B. The union of two Geometries A and B is the set of all points which lie in A or B. The difference between two Geometries A and B is the set of all points which lie in A but not in B. The symmetric difference of two Geometries A and B is the set of all points which lie in either A or B but not both.
As with the spatial relationships described in the previous section, these overlay operations have precise definitions given in the JTS Technical Specifications.
Page 6
GDBC/CTI-S GeoConnections
5. COMPUTING BUFFERS
In GIS, buffering is an operation which in GIS is used to compute the area containing all points within a given distance of a Geometry. In mathematical terms, this is called computing the Minkowski sum of the Geometry with a disc of radius equal to the buffer distance. Finding positive and negative buffers is sometimes referred to as the operations of erosion and dilation. In CAD/CAM buffer curves are called offset curves. You can use JTS to compute the buffer of a Geometry using the Geometry buffer method or the BufferOp class. The input Geometry to the buffer operation may be of any type (including arbitrary GeometryCollections). The result of a buffer operation is always an area type (Polygon or MultiPolygon). The result may be empty (for example, a negative buffer of a LineString). You can compute buffers with both positive and negative buffer distances. Buffers with a positive buffer distance always contain the input Geometry. Buffers with a negative buffer distance are always contained within the input Geometry. A negative buffer of a LineString or a Point results in an empty Geometry.
Buffer distances of 0 are also supported. You can use this to perform an efficient union of multiple polygons.
5.2
Buffer polygons can be computed with different line end cap styles. The end cap style determines how the linework for the buffer polygon is constructed at the ends of linestrings. The following different kinds of end cap styles are supported: Style Name Description
Page 7
GDBC/CTI-S GeoConnections
The usual round end caps End caps are truncated flat at the line ends End caps are squared off at the buffer distance beyond the line ends
The following diagrams illustrate the effects of specifying different end cap styles:
CAP_ROUND
CAP_BUTT
Figure 5-2 - Different End Cap Styles
CAP_SQUARE
To specify the buffer end cap style, the BufferOp class in the package com.vividsolutions.jts.operation.buffer is used directly: Geometry g = . . . BufferOp bufOp = new BufferOp(g); bufOp.setEndCapStyle(BufferOp.CAP_BUTT); Geometry buffer = bufOp.getResultGeometry(distance);
5.3
Since the exact buffer outline of a Geometry usually contains circular sections, the buffer must be approximated by the linear Geometry supported by JTS. The degree of approximation may be controlled by the user. In JTS this is done by specifying the number of quadrant segments used to approximate a quarter-circle. Specifying a larger number of segments results in a better approximation to the actual area, but also results in a larger number of line segments in the computed polygon. To specify a value for the quadrant segments, use the Geometry buffer method with a second argument: Geometry g = . . . Geometry buffer = g.buffer(100.0, 16); The default number of segments is 8. This gives less than a 2% maximum error in the distance of the computed curve approximation to the actual buffer curve. This error can be reduced to less than 1% by using a value of 12. The diagram below shows the effect of increasing the number of approximation curve segments.
Page 8
GDBC/CTI-S GeoConnections
Quadrant Segments = 3
Quadrant Segments = 20
6.
POLYGONIZATION
Polygonization is the process of forming polygons from linework which encloses areas. Linework to be formed into polygons must be fully noded that is, linestrings must not cross and must touch only at endpoints. JTS provides the Polygonizer class to perform Polygonization. The Polygonizer takes a set of fully noded LineStrings and forms all the polygons which are enclosed by the lines. Polygonization errors such as dangling lines or cut lines can be identified and reported. Collection lines = new ArrayList(); lines.add(read("LINESTRING lines.add(read("LINESTRING lines.add(read("LINESTRING lines.add(read("LINESTRING lines.add(read("LINESTRING lines.add(read("LINESTRING polygonizer.add(lines); (0 0 (185 (185 (185 (189 (189 , 10 10)")); // isolated edge 221, 100 100)")); //dangling edge 221, 88 275, 180 316)")); 221, 292 281, 180 316)")); 98, 83 187, 185 221)")); 98, 325 168, 185 221)"));
Collection polys = polygonizer.getPolygons(); Collection dangles = polygonizer.getDangles(); Collection cuts = polygonizer.getCutEdges(); If the set of lines is not correctly noded the Polygonizer will still operate on them, but the resulting polygonal Geometries will not be valid. The MultiLineString union technique can be used to node a set of LineStrings (see 9.1 Noding A Set Of LineStrings on page 11).
Page 9
GDBC/CTI-S GeoConnections
The LineMerger assumes that the input LineStrings are noded (i.e. they do not cross; only their endpoints can touch. See 9.1 Noding A Set Of LineStrings on page 11). Note that the output LineStrings are also noded.
Page 10
GDBC/CTI-S GeoConnections
If LineStrings to be merged do not have the same direction, the direction of the resulting LineString will be that of the majority. The LineMerger is used as follows: LineMerger lineMerger = new LineMerger(); Collection lineStrings = . . . lineMerger.add(lineStrings); Collection mergedLineStrings = lineMerger.getMergedLineStrings();
A note on performance: If your CoordinateSequence is not based on an array of the standard JTS Coordinates (or a subclass of Coordinate), it may incur a small performance penalty. This is due to the marshalling and unmarshalling required for JTS to convert the user coordinates into arrays of JTS coordinates.
Many spatial operations assume that their input data is noded, meaning that LineStrings never cross. For example, the JTS Polygonizer and the JTS LineMerger described earlier assume that their input is noded.
Page 11
GDBC/CTI-S GeoConnections
The noding process splits LineStrings that cross into smaller LineStrings that meet at a point, or node, as illustrated below.
Noded (9 LineStrings)
A simple trick for noding a group of LineStrings is to union them together. It turns out that the unioning process will node the LineStrings for us. For example, the following code will node a collection of LineStrings: Collection lineStrings = . . . Geometry nodedLineStrings = (LineString) lineStrings.get(0); for (int i = 1; i < lineStrings.size(); i++) {
nodedLineStrings = nodedLineStrings.union((LineString)lineStrings.get(i));
10.
Calling Polygon#union repeatedly is one way to union several Polygons together. But heres a trick that can be significantly faster (seconds rather than minutes) add the Polygons to a GeometryCollection, then apply a buffer with zero distance: Polygon[] polygons = . . . GeometryCollection polygonCollection = geometryFactory.createGeometryCollection(polygons); Geometry union = polygonCollection.buffer(0);
Page 12