diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 0000000000..f5e96dbfae --- /dev/null +++ b/web/.gitignore @@ -0,0 +1 @@ +venv \ No newline at end of file diff --git a/web/README.md b/web/README.md new file mode 100644 index 0000000000..f384c7cb25 --- /dev/null +++ b/web/README.md @@ -0,0 +1,35 @@ +# JTS Website and Documentation + + +## Material for MkDocs + +Documentation is [MkDocs-material](https://squidfunk.github.io/mkdocs-material/) which is a Markdown documentation framework written on top of [MkDocs](https://www.mkdocs.org/). + +1. For initial setup of virtual environment: + + ```bash + virtualenv venv + source venv/bin/activate + pip install -r requirements.txt + ``` + +2. To activate virtual environment: + + ```bash + source venv/bin/activate + pip install -r requirements.txt + ``` + + In the future you can update using: + + ```bash + pip3 install -r requirements.txt -U + ``` + +3. Use ***mkdocs** to preview locally: + + ```bash + mkdocs serve + ``` + +4. Preview: http://localhost:8000 diff --git a/web/docs/faq.md b/web/docs/faq.md new file mode 100644 index 0000000000..937eb9e1ba --- /dev/null +++ b/web/docs/faq.md @@ -0,0 +1,485 @@ +# JTS Frequently Asked Questions + + +## A. General + + +### 1. What Java versions does JTS work with? + +JTS is developed using Java 8. It should work with all newer versions. +With a small amount of work the library can be made to work with almost +all previous Java versions as well. + + +## B. Design and Structure + + +### 1. How can I use JTS algorithms with a different geometry model? + +The solution to this is to use Facade objects which wrap the non-JTS +geometry model classes. In order to avoid having to create and copy +large numbers of +[Coordinate](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Coordinate.html) +objects, JTS provides the +[CoordinateSequence](https://locationtech.github.io/jts/javadoc/index.html?org/locationtech/jts/geom/CoordinateSequence.html) +interface. A CoordinateSequence-based adapter can be written for +whatever structure the foreign model uses to represent sequences of +points. JTS +[Geometry](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html) +objects will still need to be created to represent the structure of the +geometries containing the points, but these are relatively lightweight +in comparison. + + +### 2. Why does JTS allow geometries to be constructed with invalid topology? + +JTS intentionally allows topologically invalid geometries to be +constructed for the following reasons: + +1. It allows a wider set of geometry to be read, stored and written + from external data sources +2. It allows geometries to be constructed and then validated +3. It avoids the costly overhead of validating topology every time a + geometry is constructed + + +### 3. What is the difference between a Point and a Coordinate? + +A +[Coordinate](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Coordinate.html) +is a relatively simple class which represents a location on the +Cartesian plane (optionally with an associated height value). +[Coordinate](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Coordinate.html)s +are usually treated as mutable objects, in order to simplify certain +algorithms. + +A [Point](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Point.html) is a +subclass of  +[Geometry](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html) +that also represents a location on the Cartesian plane. It is a +"heavy-weight" object (which for instance may contain an envelope) +which support all methods that apply to +[Geometry](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html)s. + + +### 4. Does JTS support 3D operations? + +JTS does not provide support for true 3D  +[Geometry](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html) +and operations. However, JTS does allow +[Coordinate](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Coordinate.html)s +to carry an elevation or Z value. This does not provide true 3D support, +but does allow "2.5D" uses which are required in some geospatial +applications. + + +### 5. What coordinate system and/or units does JTS use? + +JTS uses the implicit coordinate system of the input data. The only +assumption it makes is that the coordinate system is infinite, planar +and Euclidean (i.e. rectilinear and obeying the standard Euclidean +distance metric). In the same way JTS does not specify any particular +units for coordinates and geometries. Instead, the units are implicitly +defined by the input data provided. This implies that in most cases +input geometries to operations should be defined with the same +coordinate system. + + +## C. Geometry Predicates + + +### 1. How are spatial predicates computed? + +The two input geometries are decomposed into labelled topology graphs +([GeometryGraph](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geomgraph/GeometryGraph.html)s). +The labels are on the nodes and edges of the graphs. They contain full +information about the topology of the node/edge in the +points/lines/polygons of the original geometry. The labelled topology +graphs are merged. This includes merging the labels wherever there is +common nodes or edges. For each geometry at each node, the label +information is propagated to all edges incident on that node. The +resulting relationship (Intersection Matrix, or IM) is determined by the +merged label information at the nodes of the merged graph. The labelling +of each node and its incident edges is inspected, and the topological +relationship information it contributes is added to the overall IM. At +the end of this process the IM has been completely determined. + + +### 2. Why does relate(POINT(20 20), POINT(20 30), "FF0FFF0F2") = true? + +According to the SFS 1.1, section 2.1.3: + +        *The boundary of a Point is the empty set* + +Since points do not have boundaries, all the intersection matrix entries +relating to the geometry boundaries are "F". + +In some situations it is desirable to use a different definition for +determining whether geometry endpoints are on their boundary. To support +this, JTS provides the ability to specify a custom +[BoundaryNodeRule](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/BoundaryNodeRule.html) +to the +[RelateOp](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/operation/relate/RelateOp.html) +class. + + +### 3. Why is the result of a predicate different in JTS than in another software application/library? + +This is usually due to the fact that JTS predicates are computed +exactly, using the full precision of the double-precision coordinates. +Other geometry engines sometimes compute in lower precision, or round +input coordinates, or use a tolerance when determining whether two lines +intersect or cross. + +As a specific example, in the following case: + + +``` +A: POLYGON ((1368.62186660165 17722.3281808793, -1653 9287.5, +4038.14058906538 8613.02390521266, 1368.62186660165 17722.3281808793)) +``` + +``` +B: POLYGON ((-5846 9287.5, 7453 8380, 9082 16600, -6326.5 18842, -5846 +9287.5)) +``` + + +JTS reports `A.overlaps(B) = true`, whereas another application +reports false. The +[Overlaps](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#overlaps%28org.locationtech.jts.geom.Geometry%29) +result is correct - the bottom right point in the triangle B lies +outside the quadrilateral A. This is demonstrated by intersecting the +bottom edge of A + + +``` +LINESTRING (-5846 9287.5, 7453 8380) +``` + +with B. The value of the intersection is a line segment: + +``` +LINESTRING (4038.140589065375 8613.02390521266, 4038.14058906538 +8613.02390521266) +``` + +which shows that B crosses the boundary of A, and thus overlaps A. + + +## D. Robustness & Precision + + +### 1. Why is a TopologyException thrown? + +[TopologyException](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/TopologyException.html)s +are thrown when JTS encounters an inconsistency in the internal topology +structures it creates to compute certain spatial operations (in +particular, **spatial predicates** and **overlay operations**). These +inconsistencies can happen for two reasons: + +1. **Invalid input geometry**. If input geometry is invalid according + to the JTS (and OGC SFS) model, the results of operations is + undefined, and may produce exceptions. + [Geometry](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html) + validity can be checked by using the + [isValid()](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#isValid--) + method. +2. **Robustness failure** due to floating-point roundoff errors. + Floating-point errors can cause incorrect results to be computed for + internal operations (such as computing point-line orientation, + computing the intersection of two line segments, or computing the + noded arrangement of a set of line segments). + +Both of these situations can cause the topological properties of +computed geometries to become inconsistent. When this issue is detected +JTS throws a +[TopologyException](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/TopologyException.html). + +In some rare cases, it is not possible to recognize an inconsistent +topological situation. In these cases, no exception will be thrown, but +the returned geometry will not correctly reflect the true result of the +operation. JTS contains special checks to detect and prevent this from +occurring for the overwhelming majority of inputs, however. + +Unfortunately there is no guaranteed way of avoiding +[TopologyException](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/TopologyException.html)s. + +However, a heuristic which often helps is to ensure that input geometry +coordinates do not carry excessive precision. Instead of providing +coordinates with a full 16 digits of precision (which usually far +exceeds the actual accuracy of the input data), try reducing precision +to a few decimal places. Of course, correct geometry topology must still +be maintained. (This is primarily an issue for polygons, and can be +tricky to do in some pathological cases). JTS provides the +[SimpleGeometryPrecisionReducer](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/precision/SimpleGeometryPrecisionReducer.htmlhttps://locationtech.github.io/jts/javadoc/org/locationtech/jts/precision/SimpleGeometryPrecisionReducer.html) +class to do a simple reduction in coordinate precision, although this +class is not guaranteed to maintain correct geometry topology. + + +### 2. Why does the coordinate given in a `TopologyException` not appear in the input data? + +In order to reduce robustness problems during overlay operations, +JTS/[GEOS](https://trac.osgeo.org/geos/) sometimes transforms +geometry into a different coordinate system. The coordinates in a +[TopologyException](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/TopologyException.html) +message are presented in the working coordinate system, rather than the +input coordinate system. This may not match the input data. + + +### 3. What is a "robustness failure"? + +A **robustness failure** is a situation in which a JTS operation on +valid inputs either fails to complete (by throwing an exception) or +produces an incorrect answer. This situation is usually caused by the +unavoidable internal finite-precision arithmetic causing round-off +error, which in turn causes invalid geometric topology to be created at +some point during the evaluation of the algorithm. + +The operations which are notably susceptible to robustness errors are +the overlay operations (intersection, union, difference and +symDifference). The input geometries which are most likely to trigger +this behavior are ones which contain a lot of precision (e.g. 14-16 +significant digits of precision), and/or ones which contain line +segments which are nearly, but not exactly, coincident. + + +### 4. What is a "topology collapse"? + +A **topology collapse** is a situation in which the finite-precision +numerical representation used in JTS (Java's IEEE-754 double-precision +floating point) is unable to accurately represent a particular geometric +configuration exactly. This causes vertices to be slightly shifted from +their mathematically exact position. In certain geometric +configurations, this can result in the computed geometry being +topologically invalid. + +Typically this occurs in situations where polygon vertices are very +close to other line segments. If the vertex is shifted slightly it may +cross the line segment, resulting in a ring which self-intersects. + + +### 5. What is the `PrecisionModel` for? + +The `PrecisionModel` specifies the precision of the coordinates used to +define geometries. Note that JTS expects that coordinates are supplied +already rounded to the desired precision model; it does not perform this +automatically during geometry creation. +For some operations the Precision Model also specifies the precision in +which computation is performed, and in which computed results are +constructed. However, this is not uniform across all operations. For +instance, the overlay and buffer operations **do** obey the +precision model, but the spatial predicates do not. + + +### 6. Why does JTS not enforce the specified `PrecisionModel` when creating new geometry? + +The `PrecisionModel` specified in a `GeometryFactory` is not applied to the +coordinates supplied when creating geometries with the factory. This is +because: + +1. Changing the precision of coordinates is in general a non-trivial + operation, since it can cause topology collapse (see [D4](#D4)). +2. Changing coordinate values adds significant overhead, since + `CoordinateSequence`s may not be mutable, and thus would require a + full copy being made +3. Commonly the input is already precise, and thus changing precision + is not required + + + +### 7. Why do the overlay operations not obey the axioms of set theory? + +This is sometimes posed as: + +"Why is the `intersection` of two geometries not contained in either of +the originals?" + +or: "Why does the `union` of two geometries not contain either of the +originals?" + +or: "Why does `A union (B difference A) != A `" + +The axioms of geometric set theory apply in a theoretical world in which +all arithmetic is carried out exactly with infinite precision real +numbers. In this world operations such as union and intersection are +exact, which in turn means that they are commutative and associative. +This allows equations such as `A union (B difference A) = A `{.wkt} to +hold. + +JTS only approximates this ideal by simulating it using finite-precision +floating point arithmetic. JTS uses double-precision floating point +numbers to represent the coordinates of geometries (specifically, +IEEE-754 double-precision floating point, which provides 56 bits of +precision). This provides the illusion of computing using real numbers - +but it's only an illusion. The finite representation of real numbers +forces rounding to take place during arithmetic computation. This means +that operations are not commutative or associative. This in turn has the +effect that geometric axioms are not maintained. (For the same reason, +as is well known and documented, finite-precision floating-point +computation does not fully obey the axioms of arithmetic.) + +Furthermore, JTS contains code which adjusts input geometries in small +ways in order to try and prevent robustness errors from occuring. These +minor perturbations may also result in computed results which do not +necessarily obey the set theory axioms. + +However, a major JTS design goal is that the output of geometric +operations is "close" to the theoretically correct result (using some +small epsilon of tolerance and a suitable geometric distance metric.) +This is the best that can be achieved under the finite-precision +paradigm. This goal is generally met by the JTS algorithms. Moreover, +the precision of JTS geometric operations is almost always much greater +than the inherent accuracy of the input data. + + +### 8. Why is the result of `intersects` inconsistent with the result of `intersection` ? + +The inconsistent case is: + +``` + A = LINESTRING(0.0 0.0, -10.0 1.2246467991473533E-15) + B = LINESTRING(-9.999143275740073 -0.13089595571333978, -10.0 1.0535676356486768E-13) +``` + +This case produces the following inconsistent results: + +``` + A.intersects(B) = false + A.intersection(B) = POINT (-10 0.0000000000000012) +``` + +This is a specific case of D7 above. It is interesting because it shows +how simple geometric cases can reveal the limitations of +finite-precision binary floating-point arithmetic. It also highlights +the impact of design choices made in JTS. Specifically, JTS computes +spatial predicates (including `intersects`) using high-precision +arithemtic. This determines the exact spatial relationship of the input +geometries. In contrast, the overlay operations (including +`intersection`) use standard double-precision arithmetic to compute +intersection points, and the computed point is necessarily represented +in double-precision. This has the effect that there are cases where the +results of spatial predicates is not be consistent with the result of +overlay operations. + + +### 9. How can I prevent TopologyExceptions or incorrect results in overlay operations? + +[TopologyException](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/TopologyException.html)s +and incorrect results encountered during overlay computations are +symptoms of robustness issues. Robustness issues are caused by the +limitations of using finite-precision numerics in geometric algorithms. + +Currently the surest way to prevent robustness issues is to limit the +numerical precision of the input geometries to something less than the +available 16 digits. To be safe, the precision of the input geometry +coordinates should be no more than 14 decimal digits (and possibly as +few as 10 or 12). This is still plenty of precision to represent the +accuracy of real-world data. + +Reducing the precision of the input data means that result vertices will +not perfectly match the input ones. Thus this technique is particularly +useful in situations where it is not necessary to perfectly preserve +vertex-to-vertex faithfulness to the source geometry. Example use cases +are: + +- the result is only used to obtain derived quantities such as area or + length +- the result is only used for visualization purposes +- the result vertices do not need to fully match the input + + +[Coordinate](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Coordinate.html) +precision can be controlled in several ways: + +- the best way is to ensure that the original source of the input + geometries provides only as much precision as is really required. If + this is not possible to enforce, then it will be necessary to reduce + the precision of the geometries once they are created. +- the  + [SimpleGeometryPrecisionReducer](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/precision/SimpleGeometryPrecisionReducer.htmlhttps://locationtech.github.io/jts/javadoc/org/locationtech/jts/precision/SimpleGeometryPrecisionReducer.html) + class can be used to reduce the precision of geometry coordinates. + Note that this class operates in a point-wise fashion, and thus in + some situations may not maintain correct polygonal topology. If this + is an issue, see the following item. +- the + [GeometryPrecisionReducer](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/precision/GeometryPrecisionReducer.html) + reduces geometry coordinate precision, and attempts to detect and + correct invalid polygonal topology resulting from precision reduction. + +## E. Algorithms + +### 1. Are there any references which describe the algorithms used in JTS? + +Many of the details of JTS algorithms (particularly in the areas of +performance and robustness) are unique to JTS. However, the general +design of the algorithms for computing spatial predicates and spatial +overlay follow a generally accepted strategy for computing with +2-dimensional planar linear topological structures. Some papers which +present similar approaches are: + +- E. Chan, J. Ng. **A General and Efficient Implementation of Geometric + Operators and Predicates**; *Proceedings of the 5th International + Symposium on Advances in Spatial Databases, 1997.* +- Schutte, Klamer. **An edge-labeling approach to concave polygon + clipping**; *submitted to ACM Transactions on Graphics, 1995.* +- M. V. Leonov and A. G. Nikitin. **An Efficient Algorithm for a Closed + Set of Boolean Operations on Polygonal Regions in the Plane (draft + English translation).** *A. P. Ershov Institute of Informatics + Systems, Preprint 46, 1997.* +- Vatti, B.R. **A Generic Solution to Polygon Clipping**; + *Communications of the ACM, 35(7), July 1992, pp.56-63.* + +### 2. Is there a skeletonization algorithm which works with JTS? + +Yes. See the Refractions Research Skeletonizer + +### 3. How can JTS split a polygon with a linestring? + +Currently JTS does not contain a **Split Polygon By Line** operation. +Thus the only way to do this is to construct a "splitting" polygon +which contains the linestring and surrounds one side of the target +polygon without touching it. Then the overlay operations `intersection` +and `difference` can be used to extract the two sides of the target +polygon. Constructing the splitting polygon is obviously easier when the +linestring is a straight line; and simplest if it is horizontal or +vertical. + +## F. Geodetic Operations + +### 1. Does JTS support computation on the geodetic ellipsoid? + +No. JTS currently assumes that geometries are defined in a Cartesian, +planar, 2-dimensional space. Thus it cannot be used to compute accurate +metrics, predicates or constructions on the geodetic ellipsoid which is +usually used to model the surface of the Earth. + +It is hoped to provide geodetic operations in a future version. + +### 2. Can JTS be used to compute a geographically accurate range circle? + +A geographically accurate range circle is a shape on the ellipsoid +modelling the surface of the Earth which represents all points which are +a given distance from a fixed point on the ellipsoid. This is a more +complicated shape than either a circle or even an ellipsoid. In general +JTS cannot compute this shape, since JTS assumes a Cartesian coordinate +system (i.e. a two-dimensional plane extending infinitely in all +directions). This is obviously not a good approximation to the surface +of the ellipsoid, except over very small distances. Computing a true +range circle requires complex spherical mathematics as well as a richer +coordinate system model. This is outside the current scope of JTS. + +## G. Geometry Cleaning and Conflation + +### 1. How can I correct the topology of a Polygon that JTS is reporting as invalid? + +- Compute + [polygon.buffer(0)](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#buffer-double-). + The buffer operation is fairly insensitive to topological invalidity, + and the act of computing the buffer can often resolve minor issues + such as self-intersecting rings. However, in some situations the + computed result may not be what is desired. +- If holes are overlapping the shell or other holes, create individual + polygons from the shell and all the holes, and then subtract the holes + from the shell. +::::::: diff --git a/web/docs/features.md b/web/docs/features.md new file mode 100644 index 0000000000..46604d3872 --- /dev/null +++ b/web/docs/features.md @@ -0,0 +1,168 @@ +# JTS Topology Suite - Features + +A description of the features and functions provided by JTS, linked to +the relevant [Javadoc](https://locationtech.github.io/jts/javadoc/index.html){.javadoc} for the current +version. + +## Geometry Model + +- Support for all + [Geometry](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html){.javadoc} + types defined in the OGC *Simple Features for SQL* specification, + including: + - [Point](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Point.html){.javadoc} and + [MultiPoint](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/MultiPoint.html){.javadoc} + - [LineString](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/LineString.html){.javadoc} + and + [MultiLineString](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/MultiLineString.html){.javadoc} + - [Polygon](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Polygon.html){.javadoc} + and + [MultiPolygon](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/MultiPolygon.html){.javadoc} + - heterogeneous + [GeometryCollection](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/GeometryCollection.html){.javadoc} + +## Geometry Operations + +- Topological + [validity](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#isValid()) + checking +- [Area](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#getArea()) and + [Length/Perimeter](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#getLength()) +- [Distance between + geometries](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#distance(org.locationtech.jts.geom.Geometry)) + and + [isWithinDistance](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#isWithinDistance(org.locationtech.jts.geom.Geometry,%20double)){.javadoc} + predicate +- Spatial Predicates based on the Egenhofer DE-9IM model, including the + named predicates: + - [contains](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#contains(org.locationtech.jts.geom.Geometry)){.javadoc}, + [within](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#within(org.locationtech.jts.geom.Geometry)){.javadoc} + - [covers](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#covers(org.locationtech.jts.geom.Geometry)){.javadoc}, + [coveredBy](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#coveredBy(org.locationtech.jts.geom.Geometry)){.javadoc} + - [intersects](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#intersects(org.locationtech.jts.geom.Geometry)){.javadoc}, + [disjoint](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#disjoint(org.locationtech.jts.geom.Geometry)){.javadoc} + - [crosses](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#crosses(org.locationtech.jts.geom.Geometry)){.javadoc} + - [overlaps](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#overlaps(org.locationtech.jts.geom.Geometry)){.javadoc} + - [touches](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#touches(org.locationtech.jts.geom.Geometry)){.javadoc} + - [equals](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#equals(org.locationtech.jts.geom.Geometry)){.javadoc} + + and the general + [relate](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#relate(org.locationtech.jts.geom.Geometry)){.javadoc} + operation returning the DE-9IM [intersection + matrix](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/IntersectionMatrix.html). +- Overlay functions including + - [intersection](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#intersection(org.locationtech.jts.geom.Geometry)){.javadoc}, + - [difference](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#difference(org.locationtech.jts.geom.Geometry)){.javadoc}, + - [union](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#union(org.locationtech.jts.geom.Geometry)){.javadoc}, + - [symmetric + difference](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#symDifference(org.locationtech.jts.geom.Geometry)){.javadoc} + - [unary + union](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#union()){.javadoc}, + providing fast union of geometry collections +- [Buffer](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#buffer(double)) + computation (also known as Minkowski sum with a circle) + - selection of different [end-cap and + join](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#buffer(double,%20int,%20int)) + styles. +- [Convex + hull](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#convexHull()) +- [Geometric + simplification](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/simplify/package-summary.html) + including the + [Douglas-Peucker](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/simplify/DouglasPeuckerSimplifier.html) + algorithm and [topology-preserving + simplification](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/simplify/TopologyPreservingSimplifier.html) +- Geometric + [densification](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/densify/Densifier.html) +- [Linear + referencing](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/linearref/package-summary.html) + +## Precision Handling + +- Explicit coordinate [Precision + Model](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/PrecisionModel.html) +- Geometry precision reduction + +## Geometric Constructions + +- [Delaunay + triangulation](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/triangulate/DelaunayTriangulationBuilder.html) + and [Conforming Delaunay + triangulation](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/triangulate/ConformingDelaunayTriangulationBuilder.html) +- [Voronoi diagram + generation](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/triangulate/VoronoiDiagramBuilder.html) +- [Minimum + Diameter](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/MinimumDiameter.html) + of a geometry +- [Minimum Enclosing + Rectangle](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/MinimumDiameter.html#getMinimumRectangle()) +- [Minimum Bounding + Circle](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/MinimumBoundingCircle.html) + +## Metric Functions + +- [Distance between + geometries](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/operation/distance/DistanceOp.html), + with supporting points +- [Discrete + Hausdorff](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/distance/DiscreteHausdorffDistance.html) + distance +- [Area](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/match/AreaSimilarityMeasure.html) + and + [Hausdorff](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/match/HausdorffSimilarityMeasure.html) + similarity measures + +## Spatial algorithms + +- [Robust line segment + intersection](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/RobustLineIntersector.html) +- Efficient line arrangement [intersection and + noding](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/noding/package-summary.html) +- [Snap-rounding](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/noding/snapround/package-summary.html) + for noding line arrangements +- Efficient + [Point-in-Polygon](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/locate/package-summary.html) + testing + +## Mathematical Functions + +- [Angle](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/Angle.html){.javadoc} + computation +- [Vector](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/VectorMath.html) + arithmetic + +## Spatial structures + +- Spatial index structures including: + - [Quadtree](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/index/quadtree/Quadtree.html){.javadoc} + - [STR-tree](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/index/strtree/STRtree.html) + - [KD-tree](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/index/kdtree/KdTree.html) + - [Interval + R-tree](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/index/intervalrtree/package-summary.html) + - [Monotone + Chains](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/index/chain/package-summary.html) +- [Planar + graphs](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/planargraph/PlanarGraph.html) and + [graph + algorithms](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/planargraph/algorithm/package-summary.html) + +## Input/Output + +- WKT (Well-Known Text) + [reading](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/io/WKTReader.html) and + [writing](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/io/WKTWriter.html) +- WKB (Well-Known Binary) + [reading](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/io/WKBReader.html) and + [writing](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/io/WKBWriter.html) +- GML(Geography Markup Language) Version 2 + [reading](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/io/gml2/GMLReader.html) and + [writing](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/io/gml2/GMLWriter.html) +- Java Swing/AWT Shape + [writing](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/awt/package-summary.html) + +## High-Precision Arithmetic + +- [Robust evaluation of 2x2 double-precision + determinants](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/algorithm/RobustDeterminant.html) +- [DoubleDouble](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/math/DD.html) + extended-precision arithmetic diff --git a/web/docs/index.md b/web/docs/index.md new file mode 100644 index 0000000000..d92bc7b390 --- /dev/null +++ b/web/docs/index.md @@ -0,0 +1,36 @@ +# JTS Topology Suite + +The JTS Topology Suite (JTS) is an open source Java software library +that provides an object model for planar geometry together with a set of +fundamental geometric functions. JTS conforms to the Simple Features +Specification for SQL published by the Open GIS Consortium. JTS is +designed to be used as a core component of vector-based geomatics +software such as geographical information systems. It can also be used +as a general-purpose library providing algorithms in computational +geometry. + +## License + +JTS Topology Suite is open-source software. It is dual-licensed under: + +- [Eclipse Public License + 2.0](https://www.eclipse.org/legal/epl-v20.html){target="license"} +- [Eclipse Distribution License + 1.0](http://www.eclipse.org/org/documents/edl-v10.php){target="license"} + (a BSD-style license) + +## Documentation + +- [Feature Sheet](features.md) +- [FAQ](faq.md) + +## Resources + +- [LocationTech home + page](https://www.locationtech.org/projects/technology.jts) +- [Source Code + Repository](https://github.com/locationtech/jts){target="code"} +- [Mailing + List](https://locationtech.org/mailman/listinfo/jts-dev){target="list"} +- [JTS blog posts (Lin.ear + th.inking)](https://lin-ear-th-inking.blogspot.com/search/label/jts) \ No newline at end of file diff --git a/web/docs/technical/img/image1.png b/web/docs/technical/img/image1.png new file mode 100644 index 0000000000..5b5a68290c Binary files /dev/null and b/web/docs/technical/img/image1.png differ diff --git a/web/docs/technical/img/image2.png b/web/docs/technical/img/image2.png new file mode 100644 index 0000000000..dc0da78cd1 Binary files /dev/null and b/web/docs/technical/img/image2.png differ diff --git a/web/docs/technical/img/image3.png b/web/docs/technical/img/image3.png new file mode 100644 index 0000000000..eb7bb2c989 Binary files /dev/null and b/web/docs/technical/img/image3.png differ diff --git a/web/docs/technical/img/image4.png b/web/docs/technical/img/image4.png new file mode 100644 index 0000000000..9c043b1b00 Binary files /dev/null and b/web/docs/technical/img/image4.png differ diff --git a/web/docs/technical/img/image5.jpg b/web/docs/technical/img/image5.jpg new file mode 100644 index 0000000000..45077be1bc Binary files /dev/null and b/web/docs/technical/img/image5.jpg differ diff --git a/web/docs/technical/img/image6.jpg b/web/docs/technical/img/image6.jpg new file mode 100644 index 0000000000..6f3610f482 Binary files /dev/null and b/web/docs/technical/img/image6.jpg differ diff --git a/web/docs/technical/img/image7.jpg b/web/docs/technical/img/image7.jpg new file mode 100644 index 0000000000..cd54bd0431 Binary files /dev/null and b/web/docs/technical/img/image7.jpg differ diff --git a/web/docs/technical/img/image8.jpg b/web/docs/technical/img/image8.jpg new file mode 100644 index 0000000000..4590542ce0 Binary files /dev/null and b/web/docs/technical/img/image8.jpg differ diff --git a/web/docs/technical/img/image9.jpg b/web/docs/technical/img/image9.jpg new file mode 100644 index 0000000000..a37c4bdf16 Binary files /dev/null and b/web/docs/technical/img/image9.jpg differ diff --git a/web/docs/technical/index.md b/web/docs/technical/index.md new file mode 100644 index 0000000000..a2f3ed6679 --- /dev/null +++ b/web/docs/technical/index.md @@ -0,0 +1,2338 @@ +# Technical Specifications + +**Version 1.4** + +**Document Change Control** + ++------------+------------+-----------------+-------------------------------------+ +| **REVISION | **DATE OF | > **AUTHOR(S)** | **BRIEF DESCRIPTION OF CHANGE** | +| NUMBER** | ISSUE** | | | ++============+============+=================+=====================================+ +| 1.3 | March 31, | M. Davis | Updated to cover changes in JTS 1.3 | +| | 2003 | | | ++------------+------------+-----------------+-------------------------------------+ +| 1.4 | October | J. Aquino | CoordinateSequences and the | +| | 17, 2003 | | user-data field | ++------------+------------+-----------------+-------------------------------------+ +| 1.4.1 | | M Davis | • Fixed definition of contains | ++------------+------------+-----------------+-------------------------------------+ + +**Table of Contents** + +1. **OVERVIEW + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.....7** + +2. **OTHER RESOURCES + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...7** + +3. **DESIGN GOALS + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...7** + +4. **TERMINOLOGY + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...8** + +5. **NOTATION + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.....8** + +6. **JAVA + IMPLEMENTATION\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\....8** + +7. **COMPUTATIONAL GEOMETRY + ISSUES\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...9** + + 1. **PRECISION MODEL + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...9** + + 1. **Fixed + Precision\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...9** + + 2. **Floating + Precision\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 10** + + 2. **CONSTRUCTED POINTS AND DIMENSIONAL COLLAPSE + \...\...\...\...\...\...\...\... 10** + + 3. **ROBUSTNESS\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 11** + + 4. **NUMERICAL + STABILITY\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 11** + + 5. **COMPUTATIONAL + PERFORMANCE\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 12** + + 1. **Monotone + Chains\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 12** + +8. **SPATIAL + MODEL\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 13** + + 1. **DESIGN DECISIONS FOR SPATIAL MODELS + \...\...\...\...\...\...\...\...\...\...\...\...\... 13** + + 2. **GEOMETRIC + DEFINITIONS\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 14** + + 1. **Geometry\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 15** + + 2. **Empty + Geometry\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 15** + + 3. **GeometryCollection\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 15** + + 4. **Curve\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 15** + + 5. **MultiCurve + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 15** + + 6. **LineString + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 16** + + 7. **LinearRing\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 16** + + 8. **Polygon + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 16** + + 9. **MultiPolygon\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 18** + + 3. **SIMPLE FEATURE CLASSES + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 18** + + 1. **Geometry\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 18** + + 2. **GeometryCollection\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 18** + + 3. **Point + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 18** + + 4. **MultiPoint + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 18** + + 5. **Curve\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 18** + + 6. **LineString + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 18** + + 7. **Line\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 18** + + 8. **LinearRing\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 18** + + 9. **MultiCurve + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 18** + +> **8.3.10MultiLineString\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 18** +> +> **8.3.11Surface +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 18** +> +> **8.3.12Polygon\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 18** +> +> **8.3.13MultiSurface\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 19** +> +> **8.3.14MultiPolygon\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 19** + +4. **NORMAL FORM FOR + GEOMETRY\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 19** + +5. **SUPPORT + CLASSES\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 19** + + 1. **Coordinate + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 19** + + 2. **CoordinateSequence\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 20** + + 3. **Envelope\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 20** + + 4. **IntersectionMatrix\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 20** + + 5. **GeometryFactory\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 20** + + 6. **CoordinateFilter + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 20** + + 7. **GeometryFilter\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 20** + +6. **SPATIAL REFERENCE + SYSTEM\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 20** + + + +9. **BASIC GEOMETRIC ALGORITHMS AND + STRUCTURES\...\...\...\...\...\...\...\...\...\..... 21** + + 1. **POINT-LINE ORIENTATION + TEST\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 21** + + 2. **LINE INTERSECTION TEST + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 21** + + 3. **LINE INTERSECTION COMPUTATION + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 21** + + 4. **POINT-IN-RING + TEST\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 22** + + 5. **RING ORIENTATION + TEST\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 22** + +10. **TOPOLOGICAL COMPUTATION + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 22** + + 1. **TOPOLOGY GRAPHS + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 22** + + 2. **LABELS\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 22** + + 3. **COMPUTING THE INTERSECTION MATRIX FROM A + LABELING\...\...\...\...\... 23** + + 4. **THE RELATE + ALGORITHM\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 24** + +> **10.4.1Labeling isolated components +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... 24** + +5. **THE OVERLAY + ALGORITHM\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 24** + + + +11. **BINARY PREDICATES + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 25** + + 1. **GENERAL DISCUSSION + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 25** + + 2. **METHOD + SPECIFICATIONS\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 26** + +> **11.2.1Equals\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 26** +> +> **11.2.2Disjoint\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 26** +> +> **11.2.3Intersects +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 26** +> +> **11.2.4Touches +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 26** +> +> **11.2.5Crosses +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 27** +> +> **11.2.6Within +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... +> 27** +> +> **11.2.7Contains\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 27** +> +> **11.2.8Overlaps\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 27** + +12. **SPATIAL ANALYSIS + METHODS\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 27** + + 1. **GENERAL DISCUSSION + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 27** + +**1.1.1** **Representation of Computed Geometries +\...\...\...\...\...\...\...\...\...\.... 27** + +2. **CONSTRUCTIVE METHODS + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 28** + +3. **SET-THEORETIC METHODS + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 28** + +4. **METHOD + SPECIFICATIONS\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... + 29** + +> **12.4.1Buffer\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 29** +> +> **12.4.2ConvexHull +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... +> 31** +> +> **12.4.3Intersection +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 31** +> +> **12.4.4Union +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 31** +> +> **12.4.5Difference +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 31** +> +> **12.4.6SymDifference +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\... +> 31** + +13. **OTHER METHODS + \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 31** + +> **13.1.1Boundary\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... +> 31** +> +> **13.1.2IsClosed +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 32** +> +> **13.1.3IsSimple +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... +> 32** +> +> **13.1.4IsValid +> \...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... +> 33** + +14. **WELL-KNOWN TEXT + INPUT/OUTPUT\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 33** + + 1. **WELL-KNOWN TEXT + SYNTAX\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 34** + + 2. **WELL-KNOWN TEXT + READER\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 35** + + 3. **WELL-KNOWN TEXT + WRITER\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\..... + 35** + +15. **REFERENCES\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\...\.... + 36** + +## 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. 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 the design specification +for the classes, methods and algorithms implemented in the JTS Topology +Suite. + +JTS attempts to implement the OpenGIS Simple Features Specification +(SFS) as accurately as possible. In some cases the SFS is unclear or +omits a specification; in this case JTS attempts to choose a reasonable +and consistent alternative. Differences from and elaborations of the SFS +are documented in this specification. + +The detailed documentation of the class hierarchy and methods will be +presented in the form of JavaDoc for the source code. + +## 2. OTHER RESOURCES + +• *OpenGIS Simple Features Specification For SQL Revision 1.1* (referred +to as SFS in this document). This document provides the master +specification for the spatial data model and the definitions of the +spatial predicates and functions implemented by JTS. + +## 3. DESIGN GOALS + +The design of JTS is intended to fulfil the following goals: + +- The spatial model and method definitions will conform to the OpenGIS + Simple Features Specification as accurately as possible, consistent + with correct implementation. + +- The API design will follow Java conventions wherever possible. For + instance: + +> accessor functions will use the Java getX and setX convention +> predicates will use the isX convention methods will start with a +> lowercase letter + +- JTS functions will support a user-defined precision model. JTS + algorithms will be robust under that precision model. + +- Methods will return topologically and geometrically correct results + within the defined precision model wherever possible. + +- Correctness is the highest priority; space and time efficiency is + important but secondary. + +- JTS will be fast enough to be used in a production environment. + +- The algorithms and code used in JTS will be clear and well-structured, + to facilitate understanding by other developers. + +## 4. TERMINOLOGY + ++-----------------------+----------------------------------------------+ +| **Term** | > **Definition** | ++=======================+==============================================+ +| **Coordinate** | > A point in space which is exactly | +| | > representable under the defined precision | +| | > model | ++-----------------------+----------------------------------------------+ +| **Exact Computation** | > Numerical computation which maintains all | +| | > digits of numbers through all operations. | +| | > Usually requires computionally expensive | +| | > algorithms | ++-----------------------+----------------------------------------------+ +| **Node** | > A point where two lines within the same or | +| | > different geometries intersect. This point | +| | > is not necessarily representable by a | +| | > coordinate, since the output of the | +| | > computation of the intersection point in | +| | > general requires greater precision than | +| | > the input points. | ++-----------------------+----------------------------------------------+ +| **Noding (also | > The process of computing the nodes where | +| Noded)** | > one or more geometries intersect. | ++-----------------------+----------------------------------------------+ +| **Non-coordinate** | > A point which is not representable as a | +| | > coordinate | ++-----------------------+----------------------------------------------+ +| **Numerical | > The stability of an numerical algorithm is | +| Stability** | > determined by the maximum bound on the | +| | > error in its outputs. An algorithm is | +| | > considered to be stable if this bound is | +| | > small. | ++-----------------------+----------------------------------------------+ +| **Point** | > An arbitrary point in R^3^. In general, | +| | > not finitely representable. | ++-----------------------+----------------------------------------------+ +| **Proper | > An intersection between two line segments | +| intersection** | > where the intersection is a single point | +| | > and is internal to both segments | ++-----------------------+----------------------------------------------+ +| **Robust | > Numerical computation which is guaranteed | +| Computation** | > to return the correct answer for all | +| | > inputs. Usually requires algorithms which | +| | > are specially designed to handle round-off | +| | > error. | ++-----------------------+----------------------------------------------+ +| **SFS** | > OGC Simple Features Specification | ++-----------------------+----------------------------------------------+ +| **Unit of | > The smallest representable distance under | +| Resolution** | > the defined precision model. | ++-----------------------+----------------------------------------------+ +| **Vertex (pl. | > A "corner point" of a geometric object. | +| vertices)** | > These are the coordinates explicitly | +| | > stored to locate a geometric object. | ++-----------------------+----------------------------------------------+ + +## 5. NOTATION + +- Items in the specification which adhere to the SFS are indicated by + referring to the relevant section in the SFS in parentheses: (SFS 1.0) + +- Items in the specification which elaborate on or differ from the SFS + will be indicated by the term "JTS" in parentheses: (JTS) + +## 6. JAVA IMPLEMENTATION + +Java coding style is in some cases different to the coding style used in +the SFS. Where the two are different in general JTS follows Java +conventions. JTS coding style differs from SFS coding style in the +following ways: + +- the SFS sometimes uses Integer to represent a boolean value. JTS will + use a boolean in this case + +- method names in the SFS start with an uppercase letter. In JTS all + method names start with a lowercase letter + +- method names in JTS sometimes have the prefix "get" or "set" added to + them, to conform to the conventions for Java Beans. + +## 7. COMPUTATIONAL GEOMETRY ISSUES + +### 7.1 PRECISION MODEL + +All numerical computation takes place under some form of precision +model. There are several possible types of precision model: + + -------------------------------------------------------------------------- + **Fixed** Coordinates are represented as points on a grid with + uniform spacing. Computed coordinates are rounded to this + grid. + -------------- ----------------------------------------------------------- + **Floating** Coordinates are represented as floating-point numbers. + Computed coordinates may have more digits of precision than + the input values (up the maximum allowed by the finite + floating-point representation). + + **Exact** Coordinates are represented exactly (often as rational + numbers with integral numerator and denominator). + Implementing this model carries a penalty in space and time + performance, which is often considered unacceptable. + -------------------------------------------------------------------------- + +Often the precision model of a computation is not stated explicitly, but +is implied by the model used for representing the values (such as +floating point or integer). A limitation in this approach is that the +user is unable to work in a precision model with lower precision. It is +often the case that computed results are of higher precision than the +inputs. The higher precision values may not be acceptable either for +further computation or for storage in a format with the original (or +lower) precision. + +JTS deals with this problem by allowing the user to specify an explicit +precision model. The precision model allows the client to state how many +bits of precision are to be assumed in the input coordinate values, and +maintained in any computed coordinates. + +In JTS methods input Geometries may have different precision models. In +the case of methods which return Geometrys, the precision model of the +returned result is the maximum of the two input precision models (i.e. +the one with largest precision). Note that this only works if the two +precision models are compatible. Two precision models are compatible if +the scale factor of one is an integer multiple of the scale factor of +the other. No attempt is made to reconcile incompatible precision +models. + +JTS supports two basic types of precision model: Fixed and Floating. + +#### 7.1.1 Fixed Precision + +In the Fixed precision model, coordinates are assumed to fall exactly on +the intersections of a discrete grid. The size of the grid is determined +by a scale factor. The grid size is the inverse of the scale factor. The +scale factor can also be thought of as determining how many decimal +places of precision are maintained. The scale factor may be either +greater or less than 1, depending on whether the "precision point" is to +the right or left of the decimal point. + +Coordinates are made precise according to the following equations: + +jtsPt.x = round( inputPt.x \* scale ) / scale jtsPt.y = round( inputPt.y +\* scale ) / scale + +Precise coordinates will be represented internally as double-precision +values. This is known as the "precise internal representation". Since +Java uses the IEEE-754 floating point standard, this provides 53 bits of +precision. (Thus the maximum precisely representable value is +9,007,199,254,740,992). + +Input routines are responsible for rounding coordinates to the precision +model before creating JTS structures. (The input routines supplied with +JTS will perform this rounding automatically.) + +#### 7.1.2 Floating Precision + +There are two types of Floating precision model supported, double and +single precision. Both of these are based on the Java floating point +model, which in turn is based on the IEEE-754 floating point standard. +This provides approximately 16 digits of precision for double precision +and 6 digits of precision for single precision. + +In the Floating Double Precision Model, coordinates can have the full +precision available with Java double-precision floating point numbers. +Input coordinates are not assumed to be rounded off, and internal +operations which compute constructed points do not round off the +computed coordinates. Note that this does not mean that constructed +points are exact; they are still limited to the precision of +double-precision numbers, and hence may still be only an approximation +to the exact point. + +In the Floating Single Precision Model, computed coordinates are rounded +to single precision. This supports situations where the eventual +destination of computed geometry is a single-precision format (e.g. such +as Java2D). + +### 7.2 CONSTRUCTED POINTS AND DIMENSIONAL COLLAPSE + +Geometries computed by spatial analysis methods may contain constructed +points which are not present in the input Geometries. These new points +arise from intersections between line segments in the edges of the input +Geometries. In the general case it is not possible to represent +constructed points exactly. This is due to the fact that the coordinates +of an intersection point may contain as much as twice as many bits of +precision as the coordinates of the input line segments. In order to +represent these constructed points explicitly, JTS must round them to +fit the given Precision Model. + +Unfortunately, rounding coordinates moves them slightly. Line segments +which would not be coincident in the exact result may become coincident +in the truncated representation. For Line-Line combinations, this can +produce result Geometries containing points which were not in the +interior of the input Geometries. More seriously, for Line-Area +combinations, this can lead to *dimensional collapses*, which are +situations where a computed component has a lower dimension than it +would in the exact result. + +> ![](img/image1.png){width="6.4366666666666665in" +> height="1.5233333333333334in"} +> +> **1 - An example of dimensional collapse** + +JTS handles dimensional collapses as gracefully as possible, by forming +the lower-dimension Geometry resulting from the collapse. For instance, +an Area-Area intersection with a dimensional collapse would return a +Line or Point Geometry as a component of the result. + +### 7.3 ROBUSTNESS + +Geometric algorithms involve a combination of combinatorial and +numerical computation. As with all numerical computation using +finite-precision numbers, the algorithms chosen are susceptible to +problems of robustness. A robustness problem occurs when a numerical +calculation produces an inexact answer due to round-off errors. +Robustness problems are especially serious in geometric computation, +since the numerical errors can propagate into the combinatorial +computations and result in complete failure of the algorithm. (See +\[Bri98\], \[Sch91\].) + +There are many approaches to dealing with the problem of robustness in +geometric computation. Not surprisingly, most robust algorithms are +substantially more complex and less performant than the non-robust +versions. JTS attempts to deal with the problem of robustness in two +ways: + +- The important fundamental geometric algorithms (such as Line + Orientation, Line Intersection and the Point-In-Polygon test) have + been implemented using robust algorithms. In particular, the + implementation of several algorithms relies on the robust determinant + evaluation presented in \[Ava97\]). + +- The algorithms used to implement the SFS predicates and functions have + been developed to eliminate or minimize robustness problems. The + binary predicate algorithm is completely robust. The spatial overlay + and buffer algorithms are nonrobust, but will return correct answers + in the majority of cases. + +### 7.4 NUMERICAL STABILITY + +A desirable feature of numerical algorithms is that they exhibit +***stability***. The stability of a numerical algorithm is determined by +the bound on the maximum error in its outputs. An algorithm is +considered to be stable if this bound is small. + +The primary numerical algorithm used in JTS is the computation of the +intersection point between two segments. This algorithm is inherently +inexact, since the bits of precision required to represent the +intersection point is several times greater than the precision of the +inputs. A stable algorithm for this computation will always produce +approximate answers that are close to the exact answer. In particular, +the computed points should at least lie within the bounding box of the +input line segments! Ideally, the computed points will lie within a +single precision model grid unit of the exact answer. + +One way to increase the stability of numerical algorithms is to +***condition*** their inputs. + +Conditioning inputs involves numerically manipulating them in some way +that produces the same answer while preserving more precision during the +calculations. JTS uses a technique of "normalizing" the input line +segments to the line intersection computation. Normalized line segments +have been translated to be as close to the origin as possible. This has +the effect of removing common significant digits from each ordinate, and +thus increases the bits of precision available to maintain the accuracy +of the line intersection computation. + +### 7.5 COMPUTATIONAL PERFORMANCE + +Runtime performance is an important consideration for a +production-quality implementation of geometric algorithms. The most +computationally intensive algorithm used in JTS is intersection +detection. Many JTS methods need to determine both all intersection +between the line segments in a single Geometry (self-intersection) and +all intersections between the line segments of two different Geometries. + +The obvious algorithm for intersection detection, that of comparing +every segment with every other, has unacceptably slow performance. There +is a large literature of efficient algorithms for intersection +detection. Unfortunately, many of them involve substantial code +complexity. JTS tries to balance code simplicity with performance gains. +It uses some special techniques to produce substantial performance gains +for common types of input data. These techniques include in-memory +spatial indexes of various types, and sophisticated methods for +structuring data such as the technique of Monotone Chains. + +#### 7.5.1 Monotone Chains + +JTS uses the technique of "Monotone Chains" to obtain substantial +performance improvements with minimal additional code complexity. This +technique involves dividing edges into monotone chains of segments. A +monotone chain consists of a sequence of segments whose direction +vectors all lie in the same quadrant. Monotone chains have two important +properties: + +**Non-Intersection Property**: the segments within a monotone chain do +not intersect. + +**Endpoint Envelope Property**: the envelope of any contiguous subset of +the segments in a monotone chain is the envelope of the endpoints of the +subset. + +The Non-Intersection Property means that there is no need to test pairs +of segments from within the same monotone chain for intersection. The +Endpoint Envelope Property allows binary search to be used to find the +intersection points along a monotone chain. In addition, the larger +bounding boxes of monotone chains relative to individual segments act as +a form of "clustering" of segments, which reduces the overall number of +intersection tests required. + +For data with a significant percentage of monotone chains, these +properties eliminate a large number of segment comparisons. Monotone +chains are common in data that has been generated by stream digitizing +along natural features. Performance improvements of up to 100 times over +the naive algorithm have been observed. + +> ![](img/image2.png){width="5.986666666666666in" height="3.38in"} +> +> **Figure 2 - Monotone Chains** + +## 8. SPATIAL MODEL + +### 8.1 DESIGN DECISIONS FOR SPATIAL MODELS + +The SFS is just one of several spatial models in use in existing spatial +databases and APIs. + +These models are for the most part quite similar. Generally, they all +support representing 2-dimensional points, lines and polygons. There are +some subtle differences between the ways Geometrys are represented, +however. These differences represent design decisions made by the +designers of the spatial API. Some important design choices are listed +below (in each case, the choice made in the SFS and JTS is indicated). + ++----------------+-------------------------------------------------------+ +| ***Design | > **Repeated Points allowed in Geometries** | +| Decision*** | | ++================+=======================================================+ +| ***SFS | > Repeated Points are allowed | +| Choice*** | | ++----------------+-------------------------------------------------------+ +| ***JTS | > Same as SFS | +| Choice*** | | ++----------------+-------------------------------------------------------+ +| ***Comments*** | > In general spatial algorithms are not tolerant of | +| | > repeated points. Allowing repeated points causes a | +| | > performance and space penalty, since every spatial | +| | > method must check for repeated points and remove | +| | > them. JTS does support repeated points, since not | +| | > doing so is a major point of incompatibility with | +| | > the OGC model. However, there is a small memory and | +| | > performance cost to doing so. | ++----------------+-------------------------------------------------------+ + ++----------------+-------------------------------------------------------+ +| ***Design | > **Linestrings allowed to self-intersect (i.e. can | +| Decision*** | > be non-simple)** | ++================+=======================================================+ +| ***SFS | > Linestrings are allowed to self-intersect | +| Choice*** | | ++----------------+-------------------------------------------------------+ +| ***JTS | > Same as SFS | +| Choice*** | | ++----------------+-------------------------------------------------------+ +| ***Comments*** | > Allowing non-simple linestrings exacts a small | +| | > performance penalty, since it means that | +| | > linestrings must be noded before being used in | +| | > spatial methods. However, it is desirable to be | +| | > able to represent nonsimple linestrings, so if the | +| | > LineString class itself is defined to be simple, | +| | > another class must be introduced to represent | +| | > non-simple lines | +| | > | +| | > (sometimes referred to as "Spaghetti"). | ++----------------+-------------------------------------------------------+ + ++----------------+-------------------------------------------------------+ +| ***Design | > **Polygon rings can self-touch at single points.** | +| Decision*** | | ++================+=======================================================+ +| ***SFS | > Polygon rings can NOT self-touch at single points | +| Choice*** | | ++----------------+-------------------------------------------------------+ +| ***JTS | > Same as SFS | +| Choice*** | | ++----------------+-------------------------------------------------------+ +| ***Comments*** | > This decision arises from the need to support | +| | > representing polygons containing holes which touch | +| | > the shell at a single point ("inverted" polygons). | +| | > It also covers the case of representing a single | +| | > hole which contains an exterior area which is | +| | > disconnected (an "exverted" hole). In order to | +| | > represent inverted polygons and exverted holes, | +| | > either polygon rings must be allowed to self-touch | +| | > at a single point OR rings must be allowed to | +| | > mutually touch at single points. | +| | > | +| | > This design decision is a sense the dual of the | +| | > choice of whether polygon rings can mutually touch | +| | > at single points | +| | > | +| | > Unfortunately, making the choice that polygon rings | +| | > can NOT selftouch results in slightly more complex | +| | > algorithms, since the usual polygon-building | +| | > algorithm results in shells which self-touch. It is | +| | > necessary to perform a further step to convert the | +| | > boundaries of the areas isolated by the self-touch | +| | > into a hole. | ++----------------+-------------------------------------------------------+ + ++----------------+-------------------------------------------------------+ +| ***Design | > **Polygon rings can mutually touch at single | +| Decision*** | > points** | ++================+=======================================================+ +| ***SFS | > Polygon rings can mutually touch at single points | +| Choice*** | | ++----------------+-------------------------------------------------------+ +| ***JTS | > Same as SFS | +| Choice*** | | ++----------------+-------------------------------------------------------+ +| ***Comments*** | > This design decision is the dual of the decision | +| | > about whether polygon rings can self-touch at | +| | > single points. | ++----------------+-------------------------------------------------------+ + +In most cases these design choices are of no consequence to the users of +the API, since they do not change the set of Geometrys that can be +represented. However, they do have implications for the performance and +complexity of the algorithms implemented in the API. Also, it is +generally non-trivial to convert between the representations of two APIs +that have made different design choices (in particular, if two APIs make +different choices for whether polygon rings can self-touch, some +relatively complex processing is necessary to convert the polygonal +representations). + +### 8.2 GEOMETRIC DEFINITIONS + +All JTS methods assume that their arguments are valid Geometric objects, +according to the definitions given in the SFS. + +The following definitions elaborate or clarify the definitions given in +the SFS. + +#### 8.2.1 Geometry + +A Precision Model object will be a member of every Geometry object. + +According to the SFS Geometry objects can represent only closed sets. +This is a reasonable decision which allows for practical implementation. +However, there are some implications for the semantics of the spatial +analysis methods (see *Section 12 Spatial Analysis Methods*). + +JTS has a simple scheme for adding attributes to a Geometry: +applications may set a Geometry's *user data* field to any object. + +#### 8.2.2 Empty Geometry + +The SFS specifies that objects of each Geometry subclass may be empty. +It is sometimes necessary to construct an generic empty object of class +Geometry (e.g. if the exact type of the Geometry to be returned is not +known). The SFS does not define an specific class or object to represent +this generic empty Geometry. JTS uses the convention that an empty +GeometryCollection will be returned. + +#### 8.2.3 GeometryCollection + +The dimension of a heterogeneous GeometryCollection is the maximum +dimension of its elements. + +#### 8.2.4 Curve + +Curves may not be degenerate. That is, non-empty Curves must have at +least 2 points, and no two consecutive points may be equal. + +#### 8.2.5 MultiCurve + +The SFS specifies using a "Mod-2" rule for determining the boundary of a +MultiCurve. A point is on the boundary of the MultiCurve iff it is on +the boundary of an odd number of elements of the MultiCurve. It should +be noted that this leads to cases where the set of points in the SFS +boundary is larger than either intuition or point-set topology would +indicate. That is, a point with an odd number \> 1 of edges incident on +it is on the boundary according to the SFS rule, but might not +intuitively be considered as part of the boundary. This also is +inconsistent with the topological definition of boundary, which is "the +set of points which are not contained in any open subset of the set of +points in the Geometry". For example, in Figure 3 (3), the point B is in +the boundary according to SFS, but is an interior point according to +point-set topology. + +**(1)** + +**(2)** + +**(3)** + +**(4)** + +Boundary = { A, B } + +**A** + +**A** + +**A** + +**A** + +**C** + +**C** + +**C** + +**B** + +**B** + +**B** + +**B** + +**D** + +**D** + +**E** + +Boundary = { A, C } + +Boundary = { A, B, C, D } + +Boundary = { A, C, D, E } + +> **Figure 3 - Effect of the Mod-2 rule in MultiLineStrings** + +Additional logic is required in JTS to implement the Mod-2 rule. + +#### 8.2.6 LineString + +We are using the definition of LineString given in the OGC SFS. This +differs in an important way from some other spatial models (e.g. the one +use by ESRI ArcSDE). The difference is that LineStrings may be +non-simple. They may self-intersect in points or line segments. + +In fact boundary points of a curve (e.g. the endpoints) may intersect +the interior of the curve, resulting in a curve that is technically +topologically closed but not closed according to the SFS. In this case +topologically the point of intersection would not be on the boundary of +the curve. However, according to the SFS definition the point is +considered to be on the boundary. JTS follows the SFS definition. + +**A** + +**B** + +LineString: Boundary = { A, B } + +*B is a boundary point, not an* + +*interior po* + +*[i]{.underline}* + +*nt* + +> **Figure 4 - A LineString with a boundary point intersecting an +> interior point** + +#### 8.2.7 LinearRing + +LinearRings are the fundamental building block for Polygons. LinearRings +may not be degenerate; that is, a LinearRing must have at least 3 +points. Other non-degeneracy criteria are implied by the requirement +that LinearRings be simple. For instance, not all the points may be +collinear, and the ring may not self-intersect. The SFS does not specify +a requirement on the orientation of a LinearRing. JTS follows this by +allowing LinearRings to be oriented either clockwise or +counter-clockwise. + +#### 8.2.8 Polygon + +The shell and holes of a Polygon are LinearRings. The SFS definition of +Polygon has the following implications: + +- The shell and holes cannot self-intersect (this is implied by the fact + that they are LinearRings) + +- Holes can touch the shell or another hole at a single point only. This + means that holes cannot intersect one another at multiple points or in + a line segment. + +- Polygon interiors must be connected (This is implied by the previous + statement). + +- There is no requirement that a point where a hole touches the shell be + a vertex. + +Note that the SFS definition of Polygon differs from that in some other +commonly used spatial models. For instance, the ESRI ArcSDE spatial +model allows shells to self-intersect at vertices, but does not allow +holes to touch the shell. The SFS and the ArcSDE model are equivalent in +the sense that they describe exactly the same set of areas. However, +they may require different polygon structures to describe the same area. + +*[e]{.underline}* + +*This hole touches* + +*[th]{.underline}* + +*s* + +*~~h~~* + +*~~ell~~* + +*at a* + +*non-vertex* + +*This hole tou* + +*[c]{.underline}* + +*~~e~~* + +*~~s~~* + +*the* + +*[h]{.underline}* + +*shell at a vertex* + +A Polygon with 4 holes + +> **Figure 5 - An example of a Polygon containing holes** + +**(3)** + +Hole touches shell in + +line segment + +**(4)** + +The polygon interior is + +disconnected + +**(2)** + +Hole touches shell at + +more than one point + +**(1)** + +Hole crosses shell + +**(7)** + +Shell self-intersects + +**(6)** + +Holes touch in line + +segment + +**(5)** + +Holes cross + +> **Figure 6 - Examples of objects not representable as polygons** + +Empty Polygons may not contain holes. + +Since the shell and holes of Polygons are LinearRings, there is no +requirement on their orientation. They may be oriented either clockwise +or counterclockwise. + +#### 8.2.9 MultiPolygon + +The element Polygons in a MultiPolygon may touch at only a finite number +of points (e.g. they may not touch in a line segment). The interiors of +the elements must be disjoint (e.g. they may not cross). There is no +requirement that a point of intersection be a vertex. + +### 8.3 SIMPLE FEATURE CLASSES + +All Geometry classes allow empty objects to be created, and support the +isEmpty method. Empty Geometries will be represented by their internal +arrays having zero length. + +All Geometry classes support the equalsExact() method, which returns +true if two Geometry subclasses are equivalent and have identical +sequence(s) of coordinates. Two objects are "equivalent" if their +classes are identical. The only exception is LinearRing and LineString, +which JTS considers to be equivalent. + +All Geometry classes support the clone() method, which will return a +deep copy of the object. + +8.3.1 Geometry + +Geometry is non-instantiable and is implemented as an abstract class. + +8.3.2 GeometryCollection + +A GeometryCollection is implemented as an array of Geometry objects. + +8.3.3 Point + +A Point is implemented as a single Coordinate. + +8.3.4 MultiPoint + +A MultiPoint inherits the implementation of GeometryCollection, but +contains only Points. + +8.3.5 Curve + +Curve is non-instantiable and is implemented as an interface. + +8.3.6 LineString + +A LineString is implemented as an array of coordinates. + +8.3.7 Line + +JTS does not implement the Line class, since LineString offers +equivalent functionality. + +#### 8.3.8 LinearRing + +A LinearRing containing n coordinates is implemented with an array of +Coordinates containing n+1 points, and coord\[0\] = coord\[n\]. + +8.3.9 MultiCurve + +MultiCurve is non-instantiable and is implemented as an interface. + +#### 8.3.10 MultiLineString + +A MultiLineString inherits the implementation of GeometryCollection, but +contains only LineStrings. + +8.3.11 Surface + +Surface is non-instantiable and is implemented as an interface. + +#### 8.3.12 Polygon + +A Polygon is implemented as a single LinearRing for the outer shell, and +an array of + +LinearRings for the holes. The outer shell is oriented CW and the holes +are oriented CCW. + +8.3.13 MultiSurface + +MultiSurface is non-instantiable and is implemented as an interface. + +#### 8.3.14 MultiPolygon + +A MultiPolygon inherits the implementation of GeometryCollection, but +contains only Polygons. + +### 8.4 NORMAL FORM FOR GEOMETRY + +JTS defines a normal (or canonical) form for representing +[Geometry]{.underline}s. Normal form is a unique representation for +[Geometry]{.underline}s. It can be used to test whether two Geometries +are equal in a way that is independent of the ordering of the +coordinates within them. Normal form equality is a stronger condition +than topological equality, but weaker than pointwise equality. + +The definitions for normal form use the standard lexicographical +ordering for coordinates. "Sorted in order of coordinates" means the +obvious extension of this ordering to sequences of coordinates. + ++---------------------+------------------------------------------------+ +| **Geometry Class** | **Definition of normal form** | ++=====================+================================================+ +| Point | Points are always in normal form | ++---------------------+------------------------------------------------+ +| MultiPoint | Element Points are sorted in order of their | +| | coordinates | ++---------------------+------------------------------------------------+ +| LineString | Obeys the following condition: | +| | | +| | > If there is an i such that coord\[i\] != | +| | > coord \[n -- i -- 1\] then coord \[i\] \< | +| | > coord \[n -- i --1\] | ++---------------------+------------------------------------------------+ +| LinearRing | same as LineString | ++---------------------+------------------------------------------------+ +| MultiLineString | Element LineStrings are in normal form, and | +| | are sorted in order of their coordinates | ++---------------------+------------------------------------------------+ +| Polygon | The LinearRings of the Polygon are ordered | +| | such that the smallest point is first. The | +| | shell is ordered clockwise, and holes are | +| | ordered counterclockwise. Holes are sorted in | +| | order of their coordinates | ++---------------------+------------------------------------------------+ +| MultiPolygon | Element Polygons are in normal form, and are | +| | sorted in order of their coordinates | ++---------------------+------------------------------------------------+ +| GeometryCollection | Element [Geometry]{.underline}s are in normal | +| | form. | +| | | +| | The list of elements is ordered by class | +| | (using the order of this list). Within each | +| | subsequence of like class, elements are sorted | +| | in order of coordinates. | ++---------------------+------------------------------------------------+ + +### 8.5 SUPPORT CLASSES + +#### 8.5.1 Coordinate + +Coordinate is the lightweight class used to store coordinates. It is +distinct from Point, which is a subclass of Geometry. Unlike objects of +type Point (which contain additional information such as an envelope, a +precision model, and spatial reference system information), a Coordinate +only contains ordinate values and accessor methods. + +Coordinates are two-dimensional points, with an additional z-coordinate. +JTS does not support any operations on the z-coordinate except the basic +accessor functions. Constructed coordinates will have a z-coordinate of +NaN. + +Coordinate implements the standard Java interface Comparable. The +implementation uses the usual lexicographic comparison. That is, + +> *c1.compareTo(c2) =* +> +> *-1 : c1.x \< c2.x Ú ((c1.x = c2.x) Ù (c1.y \< c2.y))* + +1. *: (c1.x = c2.x) Ù (c1.y = c2.y)* + +2. *: c1.x \> c2.x Ú ((c1.x = c2.x) Ù (c1.y \> c2.y))* + +Coordinate implements equals() using the obvious implementation of +pointwise comparison. + +#### 8.5.2 CoordinateSequence + +A CoordinateSequence is the internal representation of a list of +Coordinates inside a Geometry. Because it is an interface, it is +possible to create alternatives to the default implementation (an array +of Coordinates). For example, one may choose to store the data as an +array of some entirely different coordinate class, or as an array of x's +and an array of y's. Note that non-Coordinate-array implementations will +pay a performance penalty when the #toArray method is called. + +8.5.3 Envelope + +A concrete class containing a maximum and minimum x and y value. + +#### 8.5.4 IntersectionMatrix + +An implementation of the Dimensionally Extended 9-Intersection Model +(DE-9IM) matrix. The class can be used to represent both actual +instances of a DE-9IM matrix as well as patterns for matching them. +Methods are provided to: + +- set and query the elements of the matrix in a convenient fashion + +- convert to and from the standard string representation (specified in + SFS Section + +> 2.1.13.2). + +- test to see if a matrix matches a given pattern string. + +#### 8.5.5 GeometryFactory + +A GeometryFactory supplies a set of utility methods for building +Geometry objects from lists of Coordinates. + +#### 8.5.6 CoordinateFilter + +GeometryImpl classes support the concept of applying a coordinate filter +to every coordinate in the Geometry. A coordinate filter can either +record information about each coordinate or change the coordinate in +some way. Coordinate filters implement the interface CoordinateFilter. +(CoordinateFilter is an example of the Gang-of-Four Visitor pattern). +Coordinate filters can be used to implement such things as coordinate +transformations, centroid and envelope computation, and many other +functions. + +#### 8.5.7 GeometryFilter + +GeometryImpl classes support the concept of applying a Geometry filter +to the Geometry. + +In the case of GeometryCollection subclasses, the filter is applied to +every element Geometry. A Geometry filter can either record information +about the Geometry or change the Geometry in some way. Geometry filters +implement the interface GeometryFilter. (GeometryFilter is an example of +the Gang-of-Four Visitor pattern.) + +### 8.6 SPATIAL REFERENCE SYSTEM + +JTS will support Spatial Reference System information in the simple way +defined in the SFS. A Spatial Reference System ID (SRID) will be present +in each Geometry object. Geometry will provide basic accessor operations +for this field, but no others. The SRID will be represented as an +integer. + +The SRID of constructed objects will be copied from the SRID of one of +the input objects if possible, or will be 0. + +## 9. BASIC GEOMETRIC ALGORITHMS AND STRUCTURES + +### 9.1 POINT-LINE ORIENTATION TEST + +This function is fundamental to operations such as ordering edges around +a node. Since it is essentially a geometric calculation, it is +susceptible to robustness problems unless implemented using robust +algorithms. JTS implements this method using a robust algorithm which +returns the correct result for all input values. The algorithm used is +based on the robust method of evaluating signs of determinants developed +by Avanim et. al. (\[Ava97\]). + +*\[diagram of point-line orientation\]* + +### 9.2 LINE INTERSECTION TEST + +This function tests whether two line segments intersect. It uses the +robust Point-Line Orientation function specified above. It does not +actually compute the point of intersection, and thus returns an exact +answer. The function computes full information about the topology of the +intersection, including the following data: + + ----------------------------------------------------------------------- + HasIntersection() True if the line segments intersect + ------------------------ ---------------------------------------------- + getIntersectionNum() The number of intersection points found (0, 1, + or 2) + + IsProper() True if the intersection point is proper (i.e. + is not equal to one of the endpoints) + ----------------------------------------------------------------------- + +### 9.3 LINE INTERSECTION COMPUTATION + +This function computes the intersection of two line segments. Two line +segments may intersect in a single point, a line segment, or not at all. +If the intersection is representable with coordinates in the Precision +Model, it will be computed exactly. Otherwise, an approximation will be +computed. + +Intersections which are line segments will always be representable with +coordinates, since each endpoint of the intersection segment must be +equal to an endpoint of one of the input segments. Obviously, null +intersections can also be computed exactly (although the intersection +test must be performed with robust code to be correct). Intersections +which are points may or may not be representable, since in general +computed intersections require greater precision than the input points, +and will not necessarily fall exactly on the precision model grid. + +An important property of the line intersection algorithm is that it is +numerically stable. Computed approximate points should be within the +Precision Model tolerance of the exact intersection point. + +In addition to the information computed by the Line Intersection test, +the Line Intersection Computation computes information about the actual +points of intersection: + + ----------------------------------------------------------------------- + GetIntersection(int i) The coordinate for the I'th intersection point + ------------------------ ---------------------------------------------- + + ----------------------------------------------------------------------- + +Determining the edge graph requires further information about the +precise order of intersection points along each line segment. The Line +Intersection class provides other functions to determine the order of +intersection points along each segment, and to compute the (approximate) +distance of a given intersection point along a segment. + +### 9.4 POINT-IN-RING TEST + +The Point-In-Ring predicate is implemented in a robust fashion by using +the usual stabbingline algorithm and making use of the robust Line +Intersection Test. + +In some cases it is necessary to test for the inclusion of multiple +points in a given ring (e.g. in the IsValid predicate to test for the +correct inclusion of holes). In this case performance can be gained by +using a spatial index for the line segments of the ring. JTS implements +a 1-dimensional Interval Tree to speed up the intersection tests made in +the stabbing-line algorithm. + +### 9.5 RING ORIENTATION TEST + +This test returns true if a ring of coordinates is oriented in a +clockwise direction. The test is used to determine on which side of the +rings of the shell and holes of a Polygon the interior and exterior of +the Polygon lie. + ++-----------+----------------------------------------------------------------+ +| > **10.** | **TOPOLOGICAL COMPUTATION** | ++===========+================================================================+ + +### 10.1 TOPOLOGY GRAPHS + +The computation of the Intersection Matrix relies on the use of a +structure called a "topology graph". The topology graph contains nodes +and edges corresponding to the nodes and line segments of a Geometry. +Each node and edge in the graph is labeled with its topological location +relative to the source geometry. + +Note that there is no requirement that points of self-intersection be a +vertex. Thus to obtain a correct topology graph, Geometries must be +self-noded before constructing their graphs. + +Two fundamental operations are supported by topology graphs: + +- Computing the intersections between all the edges and nodes of a + single graph + +- Computing the intersections between the edges and nodes of two + different graphs + +### 10.2 LABELS + +Topology graphs support the concept of labeling nodes and edges in the +graph. The label of a node or edge specifies its topological +relationship to one or more geometries. (In fact, since JTS operations +have only two arguments labels are required for only two geometries). A +label for a node or edge has one or two elements, depending on whether +the node or edge occurs in one or both of the input Geometries. Elements +contain attributes which categorize the topological location of the node +or edge relative to the parent Geometry; that is, whether the node or +edge is in the interior, boundary or exterior of the Geometry. +Attributes have a value from the set *{Interior, Boundary, Exterior}*. +In a node each + +element has a single attribute \<**On**\>. For an edge each element has +a triplet of attributes \<**Left, On, Right**\>. + ++-----------------------------------------------------------------------+ +| **Example 1** | ++=======================================================================+ +| If A and B are simple polygons and A contains B, the labels on their | +| edges are: | +| | +| A. A: \< **Left** = *Exterior*, **On** = *Boundary*, **Right** = | +| *Interior* \> B: \< **Left** = *Exterior*, **On** = *Exterior*, | +| **Right** = *Exterior* \> | +| | +| B. A: \< **Left** = *Interior*, **On** = *Interior*, **Right** = | +| *Interior* \> | +| | +| B: \< **Left** = *Exterior*, **On** = *Boundary*, **Right** = | +| *Interior* \> | ++-----------------------------------------------------------------------+ + +### 10.3 COMPUTING THE INTERSECTION MATRIX FROM A LABELING + +The Intersection Matrix (IM) for an overlay graph is computed from the +labeling of nodes and edges in the graph. To compute the IM, we sum the +contributions to the IM of each node and edge whose label contains +elements for *both* Geometries. The IM contribution for a node is *dim +\>= 0* for the IM entry corresponding to the topological location of the +node in the parent Geometries. (For example, a node which is in the +Interior of Geometry A and in the Boundary of Geometry B would have +*label\[0\]\[On\] = Interior* and *label\[1\]\[On\] = Boundary*, and +*IM(Interior, Boundary) = 0*.) The IM contribution for an edge is *dim +\>= 1* for the IM entry corresponding to the topological location of the +edge itself in the parent Geometries, and *dim \>= 2* for the entries +corresponding to the topological locations of the areas on the left and +right sides of the edge. + +The algorithmic expression of these rules is: + ++-----------------------------------------------------------------------+ +| **function** Node.computeIM(im : IntersectionMatrix) | +| | +| **if** (label\[0\] != null and label\[1\] != null) **then** | +| im.setAtLeast(label\[0\]\[On\], label\[1\]\[On\], 0) | +| | +| **end if** | +| | +| **end function** | +| | +| **function** Edge.computeIM(im : IntersectionMatrix) | +| | +| **if** (label\[0\] != null and label\[1\] != null) **then** | +| im.setAtLeast(label\[0\]\[On\], label\[1\]\[On\], 1) | +| im.setAtLeast(label\[0\]\[Left\], label\[1\]\[Left\], 2) | +| im.setAtLeast(label\[0\]\[Right\], label\[1\]\[Right\], 2) | +| | +| **end if end function** | ++=======================================================================+ + +For each combination of Geometries there is a maximum possible IM value. +For efficiency this maximum value can be tested after each IM summation +and the computation terminated if the value is obtained. + +It is always the case that *dim(Ext(A) n Ext(B)) = 2*. + + ----------------------------------------------------------------------- + **Example 2** + ----------------------------------------------------------------------- + Using the labels in Example 1 we have + + ----------------------------------------------------------------------- + +for the labeling of the edge of A + +IM(Boundary, Exterior) = 1 + +IM(Exterior, Exterior) = 2 + +IM(Interior, Exterior) = 2 + +for the labeling of the edge of B + +IM(Interior, Boundary) = 1 + +IM(Interior, Exterior) = 2 + +IM(Interior, Interior) = 2 + +The full IM is: 2 1 2 + +F F 1 + +F F 2 + +### 10.4 THE RELATE ALGORITHM + +The relate algorithm computes the Intersection Matrix describing the +relationship of two Geometries. The algorithm for computing relate uses +the intersection operations supported by topology graphs. Although the +relate result depends on the resultant graph formed by the computed +intersections, there is no need to explicitly compute the entire graph. +Instead the structure of the graph is computed locally at each +intersection node. + +The relate algorithm is robust, by virtue of the robustness of the +underlying operations. It is not subject to dimensional collapse +problems, since it avoids calculating intersection points which might +not lie on precise coordinates. + +The algorithm to compute relate has the following steps: + +1. Build topology graphs of the two input geometries. For each geometry + all selfintersection nodes are computed and added to the graph. + +2. Compute nodes for all intersections between edges and nodes of the + graphs. + +3. Compute the labeling for the computed nodes by merging the labels + from the input graphs. + +4. Compute the labeling for isolated components of the graph (see + below) 5. Compute the Intersection Matrix from the labels on the + nodes and edges. + +#### 10.4.1 Labeling isolated components + +Isolated components are components (edges or nodes) of an input Geometry +which do not contain any intersections with the other input Geometry. +The topological relationship of these components to the other input +Geometry must be computed in order to determine the complete labeling of +the component. This can be done by testing whether the component lies in +the interior or exterior of the other Geometry. If the other Geometry is +1dimensional, the isolated component must lie in the exterior (since +otherwise it would have an intersection with an edge of the Geometry). +If the other Geometry is 2-dimensional, a Point-In-Polygon test can be +used to determine whether the isolated component is in the interior or +exterior. + +### 10.5 THE OVERLAY ALGORITHM + +The Overlay Algorithm is used in spatial analysis methods for computing +set-theoretic operations (boolean combinations) of input Geometries. The +algorithm for computing the overlay uses the intersection operations +supported by topology graphs. To compute an overlay it is necessary to +explicitly compute the resultant graph formed by the computed +intersections. + +The algorithm to compute a set-theoretic spatial analysis method has the +following steps: + +1. Build topology graphs of the two input geometries. For each geometry + all selfintersection nodes are computed and added to the graph. + +2. Compute nodes for all intersections between edges and nodes of the + graphs. + +3. Compute the labeling for the computed nodes by merging the labels + from the input graphs. + +4. Compute new edges between the compute intersection nodes. Label the + edges appropriately + +5. Build the resultant graph from the new nodes and edges. + +6. Compute the labeling for isolated components of the graph. Add the + isolated components to the resultant graph. + +7. Compute the result of the boolean combination by selecting the node + and edges with the appropriate labels. Polygonize areas and sew + linear geometries together. + ++-----------+----------------------------------------------------------------+ +| > **11.** | **BINARY PREDICATES** | ++===========+================================================================+ + +### 11.1 GENERAL DISCUSSION + +The binary predicates can be completely specified in terms of an +Intersection Matrix pattern. In fact, their implementation is simply a +call to relate with the appropriate pattern. + +It is important to note that binary predicates are topological +operations rather than pointwise operations. Even for apparently +straightforward predicates such as Equals it is easy to find cases where +a pointwise comparison does not produce the same result as a topological +comparison. (for instance: A and B are MultiPoints with the same point +repeated different numbers of times; A is a LineString with two +collinear line segments and B is a single line segment with the same +start and endpoints; A and B are rings with identical sets of points but +which start at different points). The algorithm used for the relate +method is a topology-based algorithm which produces a topologically +correct result. + +**(1)** + +LINESTRING ( 10 10, 20 20 ) + +**(2)** + +LINESTRING ( 20 20, 15 15, 10 10 ) + +> **Figure 7 - Two Geometries that are pointwise unequal but +> topologically equal** + +As in the SFS, the term P is used to refer to 0-dimensional Geometries +(Point and + +MultiPoint), L to 1-dimensional Geometries (LineString, and +MultiLineString), and A to 2dimensional Geometries (Polygon and +MultiPolygon). The dimension of a + +GeometryCollection is equal to the maximum dimension of its components. + +In the SFS some binary predicates are stated to be undefined for some +combinations of dimensions (e.g. touches is undefined for P/P). In the +interests of simplifying the API, combinations of argument Geometries +which are not in the domain of a predicate will return false (e.g. +touches(Point, Point) =\> false). + +If either argument to a predicate is an empty Geometry the predicate +will return false. + +Because it is not clear at this time what semantics for spatial analysis +methods involving GeometryCollections would be useful, +GeometryCollections are not supported as arguments to binary predicates +or the relate method. + +### 11.2 METHOD SPECIFICATIONS + +Binary predicates are implemented as calls to relate, with the +appropriate pattern supplied for the input Geometries. The +specifications for most of the binary predicates are well described in +the SFS, and are here simply specified by their relate pattern(s). +Equals is not described in the SFS, however, so it is specified +symbolically as well. + +#### 11.2.1 Equals + +The Equals relation applies to all combinations of Geometries. Two +Geometries are topologically equal iff their interiors intersect and no +part of the interior or boundary of one Geometry intersects the exterior +of the other. Symbolically, + +*a.equals(b) Ü I(a) » I(b) µ ¸ Ù (I(a) ¼ B(a)) » E(b) = ¸ Ù (I(b) ¼ +B(b)) » E(a) = ¸* + +*Ü a.relate(b, "T\*F\*\*FFF\*")* + +Equals() is a topological relationship, and does not imply that the +Geometries have the same points or even that they are of the same class. +(This more restrictive form of equality is implemented in the +equalsExact() method.) + ++-----------------------------------+-----------------------------------+ +| > ***Argument Dimensions*** | > ***Relate Pattern*** | ++:=================================:+:=================================:+ +| > all | > T\*F\*\*FFF\* | ++-----------------------------------+-----------------------------------+ +| 11.2.2 Disjoint | | ++-----------------------------------+-----------------------------------+ +| > ***Argument Dimensions*** | > ***Relate Pattern*** | ++-----------------------------------+-----------------------------------+ +| > all | > FF\*FF\*\*\*\* | ++-----------------------------------+-----------------------------------+ + +11.2.3 Intersects + +> A.intersects(B) = ! A.disjoint(B) + +#### 11.2.4 Touches + ++-----------------------------------+-----------------------------------+ +| ***Argument Dimensions*** | ***Relate Pattern*** | ++:=================================:+:=================================:+ +| P/L, P/A, L/L, L/A, A/A | > FT\*\*\*\*\*\*\* or | +| | > F\*\*T\*\*\*\*\* or | +| | > F\*\*\*T\*\*\*\* | ++-----------------------------------+-----------------------------------+ +| P/P | undefined | ++-----------------------------------+-----------------------------------+ + +#### 11.2.5 Crosses + + ----------------------------------------------------------------------- + ***Argument Dimensions*** ***Relate Pattern*** + ----------------------------------- ----------------------------------- + P/L, P/A, L/A T\*T\*\*\*\*\*\* + + L/L 0\*\*\*\*\*\*\*\* + + P/P, A/A undefined + ----------------------------------------------------------------------- + +#### 11.2.6 Within + + ----------------------------------------------------------------------- + ***Argument Dimensions*** ***Relate Pattern*** + ----------------------------------- ----------------------------------- + all T\*F\*\*F\*\*\* + + ----------------------------------------------------------------------- + +11.2.7 Contains + +> A.contains(B) = B.within(A) + +#### 11.2.8 Overlaps + + ----------------------------------------------------------------------- + ***Argument Dimensions*** ***Relate Pattern*** + ----------------------------------- ----------------------------------- + P/P, A/A T\*T\*\*\*T\*\* + + L/L 1\*T\*\*\*T\*\* + + P/L, P/A, L/A undefined + ----------------------------------------------------------------------- + ++-----------+----------------------------------------------------------------+ +| > **12.** | **SPATIAL ANALYSIS METHODS** | ++===========+================================================================+ + +### 12.1 GENERAL DISCUSSION + +The SFS lists a number of spatial analysis methods including both +constructive operations (buffer, convex hull) and set-theoretic +operations (intersection, union, difference, symmetric difference). + +#### 1.1.1 Representation of Computed Geometries + +The SFS states that the result of a set-theoretic method is the +"point-set" result of the usual set-theoretic definition of the +operation (SFS 3.2.21.1). However, there are sometimes many ways of +representing a point set as a Geometry. + +**A** + +**B** + +**(1)** + +Topologically equivalent + +representations for the point-set + +A.union(B) + +**(2)** + +The canonical form of + +A.union(B) returned by JTS + +> **Figure 8 - Representation of computed Geometries** + +The SFS does not specify an unambiguous representation for point sets +returned from a spatial analysis method. One goal of JTS is to make this +specification precise and unambiguous. JTS uses a canonical form for +Geometries returned from spatial analysis methods. The canonical form is +a Geometry which is simple and noded: + +- **Simple** means that the Geometry returned will be simple according + to the definition in *Section 13.1.3* + +- **Noded** applies only to overlays involving LineStrings. It means + that all intersection points between the argument LineStrings will be + present as endpoints of LineStrings in the result. + +This definition implies that for non-simple geometries which are +arguments to spatial analysis methods, a line-dissolve process is +performed on them to ensure that the results are simple. + +### 12.2 CONSTRUCTIVE METHODS + +Because the convexHull() method does not introduce any new coordinates, +it is guaranteed to return a precisely correct result. Since it is not +possible to represent curved arcs exactly in JTS, the buffer() method +returns a (close) approximation to the correct answer. + +GeometryCollections are supported as arguments to the convexHull() +method, but not to the buffer() method. + +> ![](img/image3.png){width="6.006667760279965in" +> height="2.2533333333333334in"} +> +> **Figure 9 - The constructive spatial analysis methods** + +### 12.3 SET-THEORETIC METHODS + +The spatial analysis methods will return the most specific class +possible to represent the result. If the result is homogeneous, a Point, +LineString, or Polygon will be returned if the result contains a single +element; otherwise, a MultiPoint, MultiLineString, or MultiPolygon will +be returned. If the result is heterogeneous a GeometryCollection will be +returned. + +Because it is not clear at this time what semantics for set-theoretic +methods involving GeometryCollections would be useful, +GeometryCollections are not supported as arguments to the set-theoretic +methods. + +> ![](img/image4.png){width="5.986666666666666in" height="4.24in"} +> +> **Figure 10 - The set-theoretic spatial analysis methods** + +For certain inputs, the Difference and SymDifference methods may compute +non-closed sets. This can happen when the arguments overlap and have +different dimensions. Since JTS Geometry objects can represent only +closed sets, the spatial analysis methods are specified to return the +closure of the point-set-theoretic result. + +**A** + +**B** + +**(1)** + +A - B : the set-theoretic result + +( + +a non-closed set + +) + +**(2)** + +A.difference(B) + +( + +a closed set + +) + +> **Figure 11 - JTS always returns closed Geometries** + +### 12.4 METHOD SPECIFICATIONS + +#### 12.4.1 Buffer + +The buffer of a Geometry at a distance d is the Polygon or MultiPolygon +which contains all points within a distance d of the Geometry. The +distance d is interpreted according to the Precision Model of the +Geometry. Both positive and negative distances are supported. + +> *a.buffer(d) = d \> 0 : { x ³ ¥^2^ \| dist(x, a) ã d }* +> +> *d \< 0 : { x ³ ¥^2^ \| x ³ a Ù dist(x, boundary(a)) \> d }* + +In mathematical terms, buffering is defined as taking the Minkowski sum +or difference of the Geometry with a disc of radius equal to the +absolute value of the buffer distance. Positive and negative buffering +is also referred to as **dilation** or **erosion**. In CAD/CAM terms, +buffering is referred to as computing an offset curve. + +![](img/image5.jpg){width="1.815in" height="1.8666666666666667in"} +![](img/image6.jpg){width="1.825in" height="1.835in"} + +> **Figure 12 -- Positive and Negative buffers** + +JTS allows specifying different **end cap styles** for buffers of lines. +The end cap style is available when using the BufferOp class directly. +The following end cap styles are supported: + + ----------------------------------------------------------------------- + ***Style ***Description*** + Name*** + -------------- -------------------------------------------------------- + CAP_ROUND The usual round end caps + + CAP_BUTT End caps are truncated flat at the line ends + + CAP_SQUARE 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: + + ------------------------------------------------------------------------------------------------------------------------------------------------ + ![](img/image7.jpg){width="1.9333333333333333in" ![](img/image8.jpg){width="1.855in" + ![](img/image9.jpg){width="1.995in" + height="1.5816666666666668in"} height="1.5383333333333333in"} height="1.6666666666666667in"} + -------------------------------------------------------- ------------------------------------------- ------------------------------------------- + **CAP_ROUND** **CAP_BUTT** **CAP_SQUARE** + + ------------------------------------------------------------------------------------------------------------------------------------------------ + +#### 12.4.2 ConvexHull + +The convex hull of a Geometry is the smallest convex Polygon that +contains all the points in the Geometry. If the convex hull contains +fewer than 3 points, a lower dimension Geometry is returned, specified +as follows: + + ----------------------------------------------------------------------- + **Number of Points in convex **Geometry Class of result** + hull** + ------------------------------- --------------------------------------- + 0 empty GeometryCollection + + 1 Point + + 2 LineString + + 3 or more Polygon + ----------------------------------------------------------------------- + +JTS will return a Geometry with the minimal number of points needed to +represent the convex hull. In particular, no more than two consecutive +points will be collinear. + +#### 12.4.3 Intersection + +The intersection of two Geometries A and B is the set of all points +which lie in both A and B. + +> *a.intersection(b) = { x ³ ¥^2^ \| x ³ a Ù x ³ b }* + +#### 12.4.4 Union + +The union of two Geometries A and B is the set of all points which lie +in A or B. + +> *a.union(b) = { x ³ ¥^2^ \| x ³ a Ú x ³ b }* + +#### 12.4.5 Difference + +The difference between two Geometries A and B is the set of all points +which lie in A but not in B. This method returns the closure of the +resultant Geometry. + +> *a.difference(b) = closure( { x ³ ¥^2^ \| x ³ a Ú x ´ b } )* + +#### 12.4.6 SymDifference + +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. This method returns the +closure of the resultant Geometry. + +> *a.symDifference(b) = closure( { x ³ ¥^2^ \| (x ³ a Ù x ´ b) Ú (x ´ a +> Ù x ³ b) } )* + ++-----------+----------------------------------------------------------------+ +| > **13.** | **OTHER METHODS** | ++===========+================================================================+ + +#### 13.1.1 Boundary + +As stated in SFS Section 2.1.13.1, "the boundary of a Geometry is a set +of Geometries of the next lower dimension." JTS uses GeometryCollections +to represent sets of Geometries. + +For all empty [Geometry]{.underline}s, boundary(G) = empty +GeometryCollection (JTS). + +For non-empty Geometries, the boundaries are defined as follows: + + ----------------------------------------------------------------------- + **Geometry Class** **Definition of boundary()** + --------------------- ------------------------------------------------- + Point empty GeometryCollection + + MultiPoint empty GeometryCollection + + LineString if closed: empty MultiPoint if not closed: + MultiPoint containing the two endpoints. + + LinearRing empty MultiPoint + + MultiLineString MultiPoint obtained by applying the Mod-2 rule to + the boundaries of the element LineStrings + + Polygon MultiLineString containing the LinearRings of the + shell and holes, in that order (SFS 2.1.10) + + MultiPolygon MultiLineString containing the LinearRings for + the boundaries of the element polygons, in the + same order as they occur in the MultiPolygon (SFS + 2.1.12/JTS) + + GeometryCollection (SFS Section 2.1.13.1) "The boundary of an + arbitrary collection of geometries whose + interiors are disjoint consist of geometries + drawn from the boundaries of the element + geometries by application of the Mod-2 rule." + ----------------------------------------------------------------------- + +#### 13.1.2 IsClosed + +The SFS meaning of "closed" is different to the topological meaning of +closed. The SFS "isClosed" method applies to Curves only. It tests +whether the start point and end point of the Curve are the same point. +In contrast, topological closure depends on whether a geometry contains +its boundary. As discussed earlier, all instances of SFS geometry +classes are topologically closed by definition. + +For empty Curves, isClosed is defined to have the value false. + +#### 13.1.3 IsSimple + +In general, the SFS specifications of simplicity seem to follow the +rule: + +> *A Geometry is simple if and only if the only self-intersections are +> at boundary points.* + +For Point, MultiPolygon and GeometryCollection the SFS does not provide +a specification for simplicity. JTS provides a specification for these +Geometry types based on the above rule. + +For all empty [Geometry]{.underline}s, isSimple = true. (JTS) + + ----------------------------------------------------------------------- + **Geometry Class** **Definition of isSimple()** + --------------------- ------------------------------------------------- + Point true (JTS) + + MultiPoint true if no two Points in the MultiPoint are equal + (SFS 2.1.4) + + LineString true if the curve does not pass through the same + point twice (excepting the endpoints, which may + be identical) (SFS 2.1.5) + + LinearRing true (SFS 2.1.6) + + MultiLineString true iff all of its element LineStrings are + simple and the only intersections between any two + elements occur at points that are on the + boundaries of both LineStrings. + + (SFS 2.1.7) + + Polygon true (SFS 2.1.10) + + MultiPolygon true (JTS) + + GeometryCollection true if all its elements are simple and the only + intersections between any two elements occur at + points that are on the boundaries of both + elements. (JTS) + ----------------------------------------------------------------------- + +#### 13.1.4 IsValid + +Since JTS Geometry objects are constructed out of user-supplied point +sequences, it is possible that a Geometry object does not in fact +specify a topologically valid Geometry according to the SFS. JTS does +not validate Geometries when they are constructed, for reasons of +efficiency. The isValid() method is provided to test whether a Geometry +is valid according to the SFS spec. + +The validation rules checked are as follows: + ++-------------------+------------------------------------------+-----------+ +| **Rule** | **Description** | **Applies | +| | | To** | ++===================+==========================================+:=========:+ +| Valid Coordinates | Coordinates must contain valid numeric | > All | +| | values | | ++-------------------+------------------------------------------+-----------+ +| Valid Point Count | Coordinate sequences must contain a | > All | +| | valid number of points for their | | +| | containing geometry: LineString -- 0 or | | +| | 2 or more | | +| | | | +| | LinearRing -- 0 or 4 or more | | ++-------------------+------------------------------------------+-----------+ +| No Invalid Self- | Any two rings may intersect in at most a | > A | +| | single point. | | +| Intersections | | | ++-------------------+------------------------------------------+-----------+ +| No Duplicate | Rings within an area must not be | > A | +| Rings | duplicated. Duplicate rings are rings | | +| | which have identical point sequences up | | +| | to order. | | ++-------------------+------------------------------------------+-----------+ +| No | Rings must not self-intersect. | > LR, A | +| Self-Intersecting | | | +| Rings | | | ++-------------------+------------------------------------------+-----------+ +| Holes Contained | Holes must be contained within their | > A | +| In Shell | parent shell. | | ++-------------------+------------------------------------------+-----------+ +| Holes Not Nested | Holes must not be nested. | > A | ++-------------------+------------------------------------------+-----------+ +| Shells Not Nested | Shells must not be nested. | > mA | ++-------------------+------------------------------------------+-----------+ +| Interiors | The interior of a Polygon must be | > A | +| Connected | connected. | | ++-------------------+------------------------------------------+-----------+ +| Interiors | The interior of a Polygon must be | > A | +| Connected | connected. | | ++-------------------+------------------------------------------+-----------+ +| Invalid | The interior of a Polygon must be | > A | +| Coordinates | connected. | | ++-------------------+------------------------------------------+-----------+ + +JTS also provides the IsValidOp class, which performs the same checks as +isValid but which returns the exact nature and location of a validation +failure. + ++-----------+----------------------------------------------------------------+ +| > **14.** | **WELL-KNOWN TEXT INPUT/OUTPUT** | ++===========+================================================================+ + +The Well-Known Text format for SFS Features is defined in SFS Section +3.2.5. The WellKnown Text Reader and Writer will parse and output this +format. + +Note that there is an inconsistency in the SFS. The WKT grammar states +that MultiPoints are represented by "MULTIPOINT ( ( x y), (x y) )", but +the examples show MultiPoints as "MULTIPOINT ( x y, x y )". Other +implementations follow the latter syntax, so JTS will adopt it as well. + +The SFS does not define a WKT representation for Linear Rings. JTS has +extended the WKT syntax to support these, using the keyword LINEARRING. +d + +### 14.1 SYNTAX FOR WELL-KNOWN TEXT + +The syntax for the Well-known Text representation of Geometry is defined +below. + +*The notation {}\* denotes 0 or more repetitions of the tokens within +the braces. The braces do not appear in the output token list.* + +\ := + +\ + +\| \ + +\| \ + +\| \ + +\| \ + +\| \ + +\| \ + +\| \ + +\ := + +POINT \ + +\ := + +LINESTRING \ + +\ := + +LINEARRING \ + +\ := + +POLYGON \ + +\ := + +MULTIPOINT \ + +\ := + +MULTILINESTRING \ + +\ := + +MULTIPOLYGON \ + +\ := + +GEOMETRYCOLLECTION \ + +\ := EMPTY \| ( \ ) + +\ := \ \ + +\ := double precision literal + +\ := double precision literal + +\ := EMPTY + +\| ( \ {, \ }\* ) + +\ := EMPTY + +\| ( \ {, \ }\*) + +\ := EMPTY + +\| ( \ {, \ }\* ) + +\ := EMPTY + +\| ( \ {, \ }\* ) + +\ := EMPTY + +\| ( \ {, \ }\* ) + +\ := EMPTY + +\| ( \ + +### 14.2 WELL-KNOWN TEXT READER + +The Well-Known Text reader (WKTReader) is designed to allow extracting +Geometry objects from either input streams or internal strings. This +allows it to function as a parser to read Geometry objects from text +blocks embedded in other data formats (e.g. XML). + +A WKTReader is parameterized by a GeometryFactory, to allow it to create +Geometry objects of the appropriate implementation. In particular, the +GeometryFactory will determine the PrecisionModel and SRID that is used. + +The WKTReader will convert the input numbers to the precise internal +representation. + +### 14.3 WELL-KNOWN TEXT WRITER + +The Well-Known Text writer outputs the textual representation of a +Geometry object to a Java Writer. + +The WKTWriter will output coordinates rounded to the precision model. No +more than the maximum number of necessary decimal places will be output. + ++-----------+----------------------------------------------------------------+ +| > **15.** | **REFERENCES** | ++===========+================================================================+ + ++-----------+-------------------------------------------------------------------------+ +| \[AS\] | The OpenGIS Abstract Specification: An Object Model for Interoperable | +| | Geoprocessing, Revision 1, OpenGIS Consortium, Inc, OpenGIS Project | +| | Document Number 96-015R1, 1996. | ++===========+=========================================================================+ +| \[Ava97\] | F. Avnaim, J-D. Boissonnat, O. Devillers, F. Preparata and M. Yvinec. | +| | | +| | *"*Evaluating signs of determinants using single-precision arithmetic" | +| | \[prisme- | +| | | +| | 2306a. In *Algorithmica*, Vol. 17, pp. 111-132, 1997. | +| | [http://wwwsop.inria.fr/prisme/publis/abdpy-esdus-97.ps.gz]{.underline} | ++-----------+-------------------------------------------------------------------------+ +| \[Bri98\] | A. Brinkmann, K. Hinrichs. "Implementing exact line segment | +| | intersection in map overlay". In *Proceedings of the 8th International | +| | Symposium on Spatial Data Handling Vancouver, July 11-15, 1998*, pp. | +| | 569-579, 1998. | ++-----------+-------------------------------------------------------------------------+ +| \[Sch97\] | Stefan Schirra. \"Precision and robustness in geometric computations\". | +| | In | +| | | +| | *Algorithmic Foundations of Geographic Information Systems*, M. van | +| | Kreveld, J. Nievergelt, T. Roos, and P. Widmayer Eds., LNCS 1340, | +| | Springer, pp. 255287, 1997. | ++-----------+-------------------------------------------------------------------------+ +| \[SFS\] | OpenGIS Simple Features Specification For SQL Revision 1.1. Open GIS | +| | Consortium, Inc. OpenGIS project Document 99-049. | ++-----------+-------------------------------------------------------------------------+ + +> [http://www.opengis.org/techno/specs/99-049.pdf]{.underline} diff --git a/web/docs/user/img/AdifferenceB.png b/web/docs/user/img/AdifferenceB.png new file mode 100644 index 0000000000..9efaae95fc Binary files /dev/null and b/web/docs/user/img/AdifferenceB.png differ diff --git a/web/docs/user/img/AintersectionB.png b/web/docs/user/img/AintersectionB.png new file mode 100644 index 0000000000..9a3eacdab4 Binary files /dev/null and b/web/docs/user/img/AintersectionB.png differ diff --git a/web/docs/user/img/AsymDifferenceB.png b/web/docs/user/img/AsymDifferenceB.png new file mode 100644 index 0000000000..0dbb6b9e1a Binary files /dev/null and b/web/docs/user/img/AsymDifferenceB.png differ diff --git a/web/docs/user/img/AunionB.png b/web/docs/user/img/AunionB.png new file mode 100644 index 0000000000..1d40aa386a Binary files /dev/null and b/web/docs/user/img/AunionB.png differ diff --git a/web/docs/user/img/BdifferenceA.png b/web/docs/user/img/BdifferenceA.png new file mode 100644 index 0000000000..7785cc6758 Binary files /dev/null and b/web/docs/user/img/BdifferenceA.png differ diff --git a/web/docs/user/img/buffer.png b/web/docs/user/img/buffer.png new file mode 100644 index 0000000000..0b7e06bc63 Binary files /dev/null and b/web/docs/user/img/buffer.png differ diff --git a/web/docs/user/img/cap_butt.png b/web/docs/user/img/cap_butt.png new file mode 100644 index 0000000000..c305fcc2e9 Binary files /dev/null and b/web/docs/user/img/cap_butt.png differ diff --git a/web/docs/user/img/cap_round.png b/web/docs/user/img/cap_round.png new file mode 100644 index 0000000000..b51fc11828 Binary files /dev/null and b/web/docs/user/img/cap_round.png differ diff --git a/web/docs/user/img/cap_square.png b/web/docs/user/img/cap_square.png new file mode 100644 index 0000000000..43bfa8d81c Binary files /dev/null and b/web/docs/user/img/cap_square.png differ diff --git a/web/docs/user/img/merge_input.png b/web/docs/user/img/merge_input.png new file mode 100644 index 0000000000..c090c0d5d1 Binary files /dev/null and b/web/docs/user/img/merge_input.png differ diff --git a/web/docs/user/img/merge_output.png b/web/docs/user/img/merge_output.png new file mode 100644 index 0000000000..124260237d Binary files /dev/null and b/web/docs/user/img/merge_output.png differ diff --git a/web/docs/user/img/negative_buffer.png b/web/docs/user/img/negative_buffer.png new file mode 100644 index 0000000000..8c68d95c51 Binary files /dev/null and b/web/docs/user/img/negative_buffer.png differ diff --git a/web/docs/user/img/noded_3.png b/web/docs/user/img/noded_3.png new file mode 100644 index 0000000000..bf6b703cec Binary files /dev/null and b/web/docs/user/img/noded_3.png differ diff --git a/web/docs/user/img/noded_9.png b/web/docs/user/img/noded_9.png new file mode 100644 index 0000000000..485b930b9d Binary files /dev/null and b/web/docs/user/img/noded_9.png differ diff --git a/web/docs/user/img/overlay.png b/web/docs/user/img/overlay.png new file mode 100644 index 0000000000..0d2013d346 Binary files /dev/null and b/web/docs/user/img/overlay.png differ diff --git a/web/docs/user/img/polygonization_input.png b/web/docs/user/img/polygonization_input.png new file mode 100644 index 0000000000..d1d07a2782 Binary files /dev/null and b/web/docs/user/img/polygonization_input.png differ diff --git a/web/docs/user/img/polygonization_output.png b/web/docs/user/img/polygonization_output.png new file mode 100644 index 0000000000..7ae212f1ba Binary files /dev/null and b/web/docs/user/img/polygonization_output.png differ diff --git a/web/docs/user/img/quadrant_segment_20.png b/web/docs/user/img/quadrant_segment_20.png new file mode 100644 index 0000000000..c8032766f6 Binary files /dev/null and b/web/docs/user/img/quadrant_segment_20.png differ diff --git a/web/docs/user/img/quadrant_segment_3.png b/web/docs/user/img/quadrant_segment_3.png new file mode 100644 index 0000000000..7075d7e901 Binary files /dev/null and b/web/docs/user/img/quadrant_segment_3.png differ diff --git a/web/docs/user/img/quadrant_segment_8.png b/web/docs/user/img/quadrant_segment_8.png new file mode 100644 index 0000000000..c1be0ca032 Binary files /dev/null and b/web/docs/user/img/quadrant_segment_8.png differ diff --git a/web/docs/user/index.md b/web/docs/user/index.md new file mode 100644 index 0000000000..da9bce7c5b --- /dev/null +++ b/web/docs/user/index.md @@ -0,0 +1,291 @@ +# JTS User Guide + +## 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. + +### Resources + +* *OpenGIS Simple Features Specification For SQL Revision 1.1* (referred to as SFS in this document). The reference specification for the spatial data model and the spatial predicates and functions implemented by JTS. +* *JTS JavaDoc*. Documentation for all of the packages, classes and methods in JTS. +* *JTS Technical Specifications*. The design specification for the classes, methods and algorithms implemented in the JTS Topology Suite. + +## 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: + +```java +Geometry g1 = new WKTReader().read("LINESTRING (0 0, 10 10, 20 20)"); +``` + +A specification for WKT is given in the *JTS Technical Specifications*. Many examples of WKT may be found in the files in the *test* directory. + +In a real program, it’s better to use a `GeometryFactory`, because you don’t need to build up a WKT string; rather, you work with the objects directly: + +```java +Coordinate[] coordinates = new Coordinate[] { + new Coordinate(0, 0), new Coordinate(10, 10), new Coordinate(20, 20) }; +Geometry g1 = new GeometryFactory().createLineString(coordinates); +``` + +Once you’ve made a Geometry, there are many things you can do with it. You can easily find the intersection of two geometries: + +```java +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 `org.loctiontech.jts.geom` +package, as well as subsequent sections in this document. + +## Spatial Relationships + +An important application of JTS is computing the spatial relationships between Geometries. Various methods of computing relationships are provided. JTS follows the **Dimensionally Extended 9 Intersection Matrix** model specified by the OGC. To compute the DE-9IM for two Geometries, use the relate method: + +```java +Geometry a = ... +Geometry b = ... +IntersectionMatrix m = a.relate(b); +``` + +Most relationships of interest can be specified as a pattern which matches a set of intersection matrices. JTS also provides a set of boolean predicates which compute common spatial relationships directly. These are: + +| *Method* | *Meaning* | +| ----- | ----- | +| Equals | The Geometries are topologically equal | +| Disjoint | The Geometries have no point in common | +| Intersects | The Geometries have at least one point in common (the inverse of Disjoint) | +| Touches | The Geometries have at least one boundary point in common, but no interior points | +| Crosses | The Geometries share some but not all interior points, and the dimension of the intersection is less than that of at least one of the Geometries. | +| Within | Geometry A lies in the interior of Geometry B | +| Contains | Geometry B lies in the interior of Geometry A (the inverse of Within) | +| Overlaps | The Geometries share some but not all points in common, and the intersection has the same dimension as the Geometries themselves | + +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. + +## Overlay Operations + +The previous section discussed functions that return true or false, like Intersects and Contains. We will now present the JTS **overlay operations**, some of which are illustrated in Figure 4-1 below. + +| Overlay | | | +| :---: | :---: | :---: | +| ![](img/overlay.png) | ![](img/AintersectionB.png) | ![](img/AunionB.png) | +| | A.intersection(B) | A.union(B) | +| ![](img/AdifferenceB.png) | ![](img/BdifferenceA.png) | ![](img/AsymDifferenceB.png) | +| A.difference(B) | B.difference(A) | A.symDifference(B) | + +**Figure 4-1 – Overlay Operations** + +Descriptions for the overlay operations are tabulated below. + +| *Method* | *Meaning* | +| ----- | ----- | +| Buffer | 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. | +| ConvexHull | The smallest convex Polygon that contains all the points in the Geometry. | +| Intersection | The intersection of two Geometries A and B is the set of all points which lie in both A and B. | +| Union | The union of two Geometries A and B is the set of all points which lie in A or B. | +| Difference | The difference between two Geometries A and B is the set of all points which lie in A but not in B. | +| SymDifference | 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. + +## Buffering + +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 +`GeometryCollection`s). 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`. + +![](img/buffer.png) ![](img/negative_buffer.png) + +**Figure 5-1 – Positive and Negative Buffers** + +Buffer distances of 0 are also supported. You can use this to perform an efficient union of multiple polygons. + +### Basic Buffers + +To compute a buffer for a given distance, call the `buffer()` method on the `Geometry`: + +```java +Geometry g = ... +Geometry buffer = g.buffer(100.0); +``` + +### End Cap Styles + +Buffer polygons can be computed with different line **end cap +styles**. The end cap style determines how the line work for the buffer +polygon is constructed at the ends of `lineString`s. The following +different kinds of end cap styles are supported: + +| *Style Name* | *Description* | +| :---- | :---- | +| CAP_ROUND | The usual round end caps | +| CAP_BUTT | End caps are truncated flat at the line ends | +| CAP_SQUARE | 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: + +| ![](img/cap_round.png) | ![](img/cap_butt.png) | ![](img/cap_square.png) | +| :---: | :---: | :---: | +| **CAP_ROUND** | **CAP_BUTT** | **CAP_SQUARE** | + +**Figure 5-2 \- Different End Cap Styles** + +To specify the buffer end cap style, the `BufferOp` class in the package + +`org.locationtech.jts.operation.buffer` is used directly: + +```java +Geometry g = ... +BufferOp bufOp = new BufferOp(g); +bufOp.setEndCapStyle(BufferOp.CAP_BUTT); +Geometry buffer = bufOp.getResultGeometry(distance); +``` + +### Quantization Approximation + +The exact buffer outline of a Geometry usually contains circular +sections. These must be approximated by the linear geometry +supported by JTS. The degree of approximation can be controlled by the +user. 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 buffer geometry. + +To specify a value for the quadrant segments, use the Geometry buffer method with a second argument: + +```java +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. + +| ![](img/quadrant_segment_3.png) | ![](img/quadrant_segment_8.png) | ![](img/quadrant_segment_20.png) | +| :---: | :---: | :---: | +| ***Quadrant Segments = 3*** | ***Quadrant Segments = 8 (default)*** | ***Quadrant Segments = 20*** | + +**Figure 5-3 \- Using Different Curve Approximation Levels** + +## 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. + +```java +Collection lines = new ArrayList(); + +lines.add(read("LINESTRING (0 0 , 10 10)")); +// isolated edge lines.add(read("LINESTRING (185 221, 100 100)")); +//dangling edge lines.add(read("LINESTRING (185 221, 88 275, 180 316)")); + +lines.add(read("LINESTRING (185 221, 292 281, 180 316)")); +lines.add(read("LINESTRING (189 98, 83 187, 185 221)")); +lines.add(read("LINESTRING (189 98, 325 168, 185 221)")); +polygonizer.add(lines); + +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). + +| ![](img/polygonization_input.png) | ![](img/polygonization_output.png) | +| :---: | :---: | +| ***Input – a set of fully noded LineStrings*** | ***Output – Polygons, dangling lines and cut lines*** | + +**Figure 6-1 \- The Polygonization Operation** + +## Merging Lines + +Sometimes a spatial operation such as \#union will produce chains of small LineStrings. The JTS LineMerger is a simple utility to sew these small LineStrings together, as shown below. + +| ![](img/merge_input.png) | ![](img/merge_output.png) | +| :---: | :---: | +| ***Input – a set of fully noded LineStrings*** | ***Output – Merged LineStrings*** | + +**Figure 7-1 – The Line-Merging Operation** + +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. + +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: + +```java +LineMerger lineMerger = new LineMerger(); +Collection lineStrings = . . . +lineMerger.add(lineStrings); +Collection mergedLineStrings = lineMerger.getMergedLineStrings(); +``` + +## Custom Coordinate Sequences + +By default JTS uses arrays of Coordinates to represent the points and lines of Geometries. There are some cases in which you might want Geometries to store their points using some other implementation. For example, to save memory you may want to use a more compact sequence implementation, such as an array of x’s and an array of y’s. Another possibility is to use a custom coordinate class to store extra information on each coordinate, such as measures for linear referencing. + +You can do this by implementing the `CoordinateSequence` and +`CoordinateSequenceFactory` interfaces. You would then create a `GeometryFactory` parameterized by your +`CoordinateSequenceFactory`, and use this `GeometryFactory` to create new `Geometries`. All of these new +`Geometries` will use your `CoordinateSequence` implementation. + +For an example, see the following sample programs in the + +org.locationtech.jtsexample.geom package: + +| ExtendedCoordinateExample | An example of using adding information to the basic coordinate representation | +| :---- | :---- | +| TwoArrayCoordinateSequenceExample | An example of using a more memory-efficient sequence implementation | + +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. + +## Tips & Techniques + +### Noding Lines + +Many spatial operations expect 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. + +The noding process splits `LineStrings` that cross into smaller `LineStrings` that meet at a point, or +**node**, as illustrated below. + +| ![](img/noded_3.png) | ![](img/noded_9.png) | +| :---: | :---: | +| ***Not noded (3 LineStrings)*** | ***Noded (9 LineStrings)*** | + +**Figure 9-1 – Before and After Noding** + +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`: + +```java +Collection lineStrings = . . . +Geometry nodedLineStrings = (LineString) lineStrings.get(0); +for (int i = 1; i \< lineStrings.size(); i++) { + nodedLineStrings = nodedLineStrings.union((LineString)lineStrings.get(i)); +} +``` + + diff --git a/web/mkdocs.yml b/web/mkdocs.yml new file mode 100644 index 0000000000..3904000355 --- /dev/null +++ b/web/mkdocs.yml @@ -0,0 +1,121 @@ +# Project information +site_name: JTS Topology Suite +site_description: JTS Project +site_dir: target/html +site_url: https://locationtech.github.io/jts/ + +# Repository +repo_name: jts +repo_url: http://github.com/locationtech/jts +edit_uri: edit/master/web/docs + +# Copyright +copyright: Copyright © 2001 - 2025 Martin Davis and others + +# extra_css: +# - assets/stylesheets/extra.css + +# Configuration +theme: + name: material + language: en + custom_dir: overrides + logo: assets/images/jts_logo.png + favicon: assets/images/jts_logo.png + icon: + repo: fontawesome/brands/github + palette: + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: blue + toggle: + icon: material/weather-night + name: Switch to dark mode + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/weather-sunny + name: Switch to light mode + features: + - toc.follow + - navigation.tracking + - navigation.top + - navigation.tabs + - navigation.tabs.sticky + - navigation.prune + - navigation.indexes + - navigation.footer + - header.autohide + - content.tabs.link + - content.code.copy + - content.action.view + - content.action.edit + - announce.dismiss + +# Plugins - install using: pip3 install -r requirements.txt +plugins: + - search + +# Customizations +extra: + version: + provider: mike + default: stable + alias: true + homepage: http://github.com/locationtech/jts/ + social: + - icon: fontawesome/brands/github + link: https://github.com/locationtech/jts/ + +# For use with --strict to produce failures on build warnings +validation: + nav: + omitted_files: warn + not_found: warn + absolute_links: warn + links: + not_found: warn + absolute_links: warn + unrecognized_links: warn + +# Extensions +# - These are carefully chosen to work with pandoc markdown support for whole document translation +markdown_extensions: + - admonition + - attr_list + - def_list + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg +# options: +# custom_icons: +# - overrides/.icons + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.smartsymbols + - pymdownx.snippets + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - tables + - md_in_html + +# Page tree +nav: + - 'Home': + - index.md + - 'User Guide': user/index.md + - 'Features': features.md + - 'FAQ': faq.md + - 'Technical Reference': technical/index.md diff --git a/web/overrides/assets/images/jts_logo.png b/web/overrides/assets/images/jts_logo.png new file mode 100644 index 0000000000..f71e7e8193 Binary files /dev/null and b/web/overrides/assets/images/jts_logo.png differ diff --git a/web/requirements.txt b/web/requirements.txt new file mode 100644 index 0000000000..f8d38ef41c --- /dev/null +++ b/web/requirements.txt @@ -0,0 +1,4 @@ +mkdocs-material>=9.5.3 +mkdocs-static-i18n>=1.0.5 +mkdocs-include-markdown-plugin +mkdocs-exclude \ No newline at end of file