4
* The JTS Topology Suite is a collection of Java classes that
5
* implement the fundamental operations required to validate a given
6
* geo-spatial data set to a known topological specification.
8
* Copyright (C) 2001 Vivid Solutions
10
* This library is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU Lesser General Public
12
* License as published by the Free Software Foundation; either
13
* version 2.1 of the License, or (at your option) any later version.
15
* This library is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
* Lesser General Public License for more details.
20
* You should have received a copy of the GNU Lesser General Public
21
* License along with this library; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
* For more information, contact:
28
* 2328 Government Street
33
* www.vividsolutions.com
35
package com.vividsolutions.jts.geom;
37
import java.io.Serializable;
38
import java.util.Collection;
39
import java.util.Iterator;
41
import com.vividsolutions.jts.algorithm.*;
42
import com.vividsolutions.jts.io.WKTWriter;
43
import com.vividsolutions.jts.operation.buffer.BufferOp;
44
import com.vividsolutions.jts.operation.distance.DistanceOp;
45
import com.vividsolutions.jts.operation.overlay.OverlayOp;
46
import com.vividsolutions.jts.operation.predicate.RectangleIntersects;
47
import com.vividsolutions.jts.operation.predicate.RectangleContains;
48
import com.vividsolutions.jts.operation.relate.RelateOp;
49
import com.vividsolutions.jts.operation.valid.IsValidOp;
50
import com.vividsolutions.jts.util.Assert;
52
* Basic implementation of <code>Geometry</code>. <P>
54
* <code>clone</code> returns a deep copy of the object.
56
* <H3>Binary Predicates</H3>
57
* Because it is not clear at this time
58
* what semantics for spatial
59
* analysis methods involving <code>GeometryCollection</code>s would be useful,
60
* <code>GeometryCollection</code>s are not supported as arguments to binary
61
* predicates (other than <code>convexHull</code>) or the <code>relate</code>
64
* <H3>Set-Theoretic Methods</H3>
66
* The spatial analysis methods will
67
* return the most specific class possible to represent the result. If the
68
* result is homogeneous, a <code>Point</code>, <code>LineString</code>, or
69
* <code>Polygon</code> will be returned if the result contains a single
70
* element; otherwise, a <code>MultiPoint</code>, <code>MultiLineString</code>,
71
* or <code>MultiPolygon</code> will be returned. If the result is
72
* heterogeneous a <code>GeometryCollection</code> will be returned. <P>
74
* Because it is not clear at this time what semantics for set-theoretic
75
* methods involving <code>GeometryCollection</code>s would be useful,
76
* <code>GeometryCollections</code>
77
* are not supported as arguments to the set-theoretic methods.
79
* <H4>Representation of Computed Geometries </H4>
81
* The SFS states that the result
82
* of a set-theoretic method is the "point-set" result of the usual
83
* set-theoretic definition of the operation (SFS 3.2.21.1). However, there are
84
* sometimes many ways of representing a point set as a <code>Geometry</code>.
87
* The SFS does not specify an unambiguous representation of a given point set
88
* returned from a spatial analysis method. One goal of JTS is to make this
89
* specification precise and unambiguous. JTS will use a canonical form for
90
* <code>Geometry</code>s returned from spatial analysis methods. The canonical
91
* form is a <code>Geometry</code> which is simple and noded:
93
* <LI> Simple means that the Geometry returned will be simple according to
94
* the JTS definition of <code>isSimple</code>.
95
* <LI> Noded applies only to overlays involving <code>LineString</code>s. It
96
* means that all intersection points on <code>LineString</code>s will be
97
* present as endpoints of <code>LineString</code>s in the result.
99
* This definition implies that non-simple geometries which are arguments to
100
* spatial analysis methods must be subjected to a line-dissolve process to
101
* ensure that the results are simple.
103
* <H4> Constructed Points And The Precision Model </H4>
105
* The results computed by the set-theoretic methods may
106
* contain constructed points which are not present in the input <code>Geometry</code>
107
* s. These new points arise from intersections between line segments in the
108
* edges of the input <code>Geometry</code>s. In the general case it is not
109
* possible to represent constructed points exactly. This is due to the fact
110
* that the coordinates of an intersection point may contain twice as many bits
111
* of precision as the coordinates of the input line segments. In order to
112
* represent these constructed points explicitly, JTS must truncate them to fit
113
* the <code>PrecisionModel</code>. <P>
115
* Unfortunately, truncating coordinates moves them slightly. Line segments
116
* which would not be coincident in the exact result may become coincident in
117
* the truncated representation. This in turn leads to "topology collapses" --
118
* situations where a computed element has a lower dimension than it would in
119
* the exact result. <P>
121
* When JTS detects topology collapses during the computation of spatial
122
* analysis methods, it will throw an exception. If possible the exception will
123
* report the location of the collapse. <P>
125
* #equals(Object) and #hashCode are not overridden, so that when two
126
* topologically equal Geometries are added to HashMaps and HashSets, they
127
* remain distinct. This behaviour is desired in many cases.
131
public abstract class Geometry
132
implements Cloneable, Comparable, Serializable
134
private static final long serialVersionUID = 8763622679187376702L;
137
* The bounding box of this <code>Geometry</code>.
139
protected Envelope envelope;
141
private final static Class[] sortedClasses = new Class[] {
146
MultiLineString.class,
149
GeometryCollection.class
152
private final static GeometryComponentFilter geometryChangedFilter = new GeometryComponentFilter() {
153
public void filter(Geometry geom) {
154
geom.geometryChangedAction();
158
public Geometry(GeometryFactory factory) {
159
this.factory = factory;
160
this.SRID = factory.getSRID();
163
private GeometryFactory factory;
165
// MD - no longer used. Remove in next version
166
//private static final GeometryFactory INTERNAL_GEOMETRY_FACTORY = new GeometryFactory();
169
* The ID of the Spatial Reference System used by this <code>Geometry</code>
174
* Returns the name of this object's <code>com.vivid.jts.geom</code>
177
*@return the name of this <code>Geometry</code>s most specific <code>com.vividsolutions.jts.geom</code>
180
//I wonder if we need this method, now that we have renamed the classes to
181
//what their old interfaces were named. Now we can perhaps simply use
182
//getClass().getName(). Who calls this method anyway? [Jon Aquino]
183
public abstract String getGeometryType();
186
* Returns true if the array contains any non-empty <code>Geometry</code>s.
188
*@param geometries an array of <code>Geometry</code>s; no elements may be
190
*@return <code>true</code> if any of the <code>Geometry</code>s
191
* <code>isEmpty</code> methods return <code>false</code>
193
protected static boolean hasNonEmptyElements(Geometry[] geometries) {
194
for (int i = 0; i < geometries.length; i++) {
195
if (!geometries[i].isEmpty()) {
203
* Returns true if the array contains any <code>null</code> elements.
205
*@param array an array to validate
206
*@return <code>true</code> if any of <code>array</code>s elements are
209
protected static boolean hasNullElements(Object[] array) {
210
for (int i = 0; i < array.length; i++) {
211
if (array[i] == null) {
221
* Returns the ID of the Spatial Reference System used by the <code>Geometry</code>.
224
* JTS supports Spatial Reference System information in the simple way
225
* defined in the SFS. A Spatial Reference System ID (SRID) is present in
226
* each <code>Geometry</code> object. <code>Geometry</code> provides basic
227
* accessor operations for this field, but no others. The SRID is represented
230
*@return the ID of the coordinate space in which the <code>Geometry</code>
233
* @deprecated use {@link getUserData} instead
235
public int getSRID() {
239
* Sets the ID of the Spatial Reference System used by the <code>Geometry</code>.
240
* @deprecated use {@link setUserData} instead
242
public void setSRID(int SRID) {
246
private Object userData = null;
249
* Gets the factory which contains the context in which this geometry was created.
251
* @return the factory for this geometry
253
public GeometryFactory getFactory() {
258
* Gets the user data object for this geometry, if any.
260
* @return the user data object, or <code>null</code> if none set
262
public Object getUserData() {
267
* Returns the number of {@link Geometry}s in a {@link GeometryCollection}
268
* (or 1, if the geometry is not a collection).
270
* @return the number of geometries contained in this geometry
272
public int getNumGeometries() {
277
* Returns an element {@link Geometry} from a {@link GeometryCollection}
278
* (or <code>this</code>, if the geometry is not a collection).
280
* @param n the index of the geometry element
281
* @return the n'th geometry contained in this geometry
283
public Geometry getGeometryN(int n) {
289
* A simple scheme for applications to add their own custom data to a Geometry.
290
* An example use might be to add an object representing a Coordinate Reference System.
292
* Note that user data objects are not present in geometries created by
293
* construction methods.
295
* @param userData an object, the semantics for which are defined by the
296
* application using this Geometry
298
public void setUserData(Object userData) {
299
this.userData = userData;
304
* Returns the <code>PrecisionModel</code> used by the <code>Geometry</code>.
306
*@return the specification of the grid of allowable points, for this
307
* <code>Geometry</code> and all other <code>Geometry</code>s
309
public PrecisionModel getPrecisionModel() {
310
return factory.getPrecisionModel();
314
* Returns a vertex of this <code>Geometry</code>.
316
*@return a {@link Coordinate} which is a vertex of this <code>Geometry</code>.
317
* Returns <code>null</code> if this Geometry is empty
319
public abstract Coordinate getCoordinate();
321
* Returns this <code>Geometry</code> s vertices. If you modify the coordinates
322
* in this array, be sure to call #geometryChanged afterwards.
323
* The <code>Geometry</code>s contained by composite <code>Geometry</code>s
324
* must be Geometry's; that is, they must implement <code>getCoordinates</code>.
326
*@return the vertices of this <code>Geometry</code>
328
public abstract Coordinate[] getCoordinates();
331
* Returns the count of this <code>Geometry</code>s vertices. The <code>Geometry</code>
332
* s contained by composite <code>Geometry</code>s must be
333
* Geometry's; that is, they must implement <code>getNumPoints</code>
335
*@return the number of vertices in this <code>Geometry</code>
337
public abstract int getNumPoints();
340
* Returns false if the <code>Geometry</code> not simple.
341
* Subclasses provide their own definition of "simple". If
342
* this <code>Geometry</code> is empty, returns <code>true</code>. <P>
344
* In general, the SFS specifications of simplicity seem to follow the
347
* <LI> A Geometry is simple iff the only self-intersections are at
350
* For all empty <code>Geometry</code>s, <code>isSimple</code> = <code>true</code>.
352
*@return <code>true</code> if this <code>Geometry</code> has any points of
353
* self-tangency, self-intersection or other anomalous points
355
public abstract boolean isSimple();
358
* Tests the validity of this <code>Geometry</code>.
359
* Subclasses provide their own definition of "valid".
361
*@return <code>true</code> if this <code>Geometry</code> is valid
365
public boolean isValid()
367
IsValidOp isValidOp = new IsValidOp(this);
368
return isValidOp.isValid();
372
* Returns whether or not the set of points in this <code>Geometry</code> is
375
*@return <code>true</code> if this <code>Geometry</code> equals the empty
378
public abstract boolean isEmpty();
381
* Returns the minimum distance between this <code>Geometry</code>
382
* and the <code>Geometry</code> g
384
*@param g the <code>Geometry</code> from which to compute the distance
386
public double distance(Geometry g)
388
return DistanceOp.distance(this, g);
392
* Tests whether the distance from this <code>Geometry</code>
393
* to another is less than or equal to a specified value.
395
* @param geom the Geometry to check the distance to
396
* @param distance the distance value to compare
397
* @return <code>true</code> if the geometries are less than <code>distance</code> apart.
399
public boolean isWithinDistance(Geometry geom, double distance)
401
double envDist = getEnvelopeInternal().distance(geom.getEnvelopeInternal());
402
if (envDist > distance)
404
// NOTE: this could be implemented more efficiently
405
double geomDist = this.distance(geom);
406
if (geomDist > distance)
411
public boolean isRectangle()
413
// Polygon overrides to check for actual rectangle
418
* Returns the area of this <code>Geometry</code>.
419
* Areal Geometries have a non-zero area.
420
* They override this function to compute the area.
423
*@return the area of the Geometry
425
public double getArea()
431
* Returns the length of this <code>Geometry</code>.
432
* Linear geometries return their length.
433
* Areal geometries return their perimeter.
434
* They override this function to compute the area.
437
*@return the length of the Geometry
439
public double getLength()
445
* Computes the centroid of this <code>Geometry</code>.
447
* is equal to the centroid of the set of component Geometries of highest
448
* dimension (since the lower-dimension geometries contribute zero
449
* "weight" to the centroid)
451
* @return a {@link Point} which is the centroid of this Geometry
453
public Point getCentroid()
455
if (isEmpty()) { return null; }
456
Coordinate centPt = null;
457
int dim = getDimension();
459
CentroidPoint cent = new CentroidPoint();
461
centPt = cent.getCentroid();
464
CentroidLine cent = new CentroidLine();
466
centPt = cent.getCentroid();
469
CentroidArea cent = new CentroidArea();
471
centPt = cent.getCentroid();
473
return createPointFromInternalCoord(centPt, this);
478
* Computes an interior point of this <code>Geometry</code>.
479
* An interior point is guaranteed to lie in the interior of the Geometry,
480
* if it possible to calculate such a point exactly. Otherwise,
481
* the point may lie on the boundary of the geometry.
483
* @return a {@link Point} which is in the interior of this Geometry
485
public Point getInteriorPoint()
487
Coordinate interiorPt = null;
488
int dim = getDimension();
490
InteriorPointPoint intPt = new InteriorPointPoint(this);
491
interiorPt = intPt.getInteriorPoint();
494
InteriorPointLine intPt = new InteriorPointLine(this);
495
interiorPt = intPt.getInteriorPoint();
498
InteriorPointArea intPt = new InteriorPointArea(this);
499
interiorPt = intPt.getInteriorPoint();
501
return createPointFromInternalCoord(interiorPt, this);
505
* Returns the dimension of this <code>Geometry</code>.
507
*@return the dimension of the class implementing this interface, whether
508
* or not this object is the empty geometry
510
public abstract int getDimension();
512
* Returns the boundary, or the empty geometry if this <code>Geometry</code>
513
* is empty. For a discussion of this function, see the OpenGIS Simple
514
* Features Specification. As stated in SFS Section 2.1.13.1, "the boundary
515
* of a Geometry is a set of Geometries of the next lower dimension."
517
*@return the closure of the combinatorial boundary of this <code>Geometry</code>
519
public abstract Geometry getBoundary();
522
* Returns the dimension of this <code>Geometry</code>s inherent boundary.
524
*@return the dimension of the boundary of the class implementing this
525
* interface, whether or not this object is the empty geometry. Returns
526
* <code>Dimension.FALSE</code> if the boundary is the empty geometry.
528
public abstract int getBoundaryDimension();
531
* Returns this <code>Geometry</code>s bounding box. If this <code>Geometry</code>
532
* is the empty geometry, returns an empty <code>Point</code>. If the <code>Geometry</code>
533
* is a point, returns a non-empty <code>Point</code>. Otherwise, returns a
534
* <code>Polygon</code> whose points are (minx, miny), (maxx, miny), (maxx,
535
* maxy), (minx, maxy), (minx, miny).
537
*@return an empty <code>Point</code> (for empty <code>Geometry</code>s), a
538
* <code>Point</code> (for <code>Point</code>s) or a <code>Polygon</code>
539
* (in all other cases)
541
public Geometry getEnvelope() {
542
return getFactory().toGeometry(getEnvelopeInternal());
546
* Returns the minimum and maximum x and y values in this <code>Geometry</code>
547
* , or a null <code>Envelope</code> if this <code>Geometry</code> is empty.
549
*@return this <code>Geometry</code>s bounding box; if the <code>Geometry</code>
550
* is empty, <code>Envelope#isNull</code> will return <code>true</code>
552
public Envelope getEnvelopeInternal() {
553
if (envelope == null) {
554
envelope = computeEnvelopeInternal();
560
* Notifies this Geometry that its Coordinates have been changed by an external
561
* party (using a CoordinateFilter, for example). The Geometry will flush
562
* and/or update any information it has cached (such as its {@link Envelope} ).
564
public void geometryChanged() {
565
apply(geometryChangedFilter);
569
* Notifies this Geometry that its Coordinates have been changed by an external
570
* party. When #geometryChanged is called, this method will be called for
571
* this Geometry and its component Geometries.
572
* @see #apply(GeometryComponentFilter)
574
protected void geometryChangedAction() {
579
* Returns <code>true</code> if the DE-9IM intersection matrix for the two
580
* <code>Geometry</code>s is FF*FF****.
582
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
583
*@return <code>true</code> if the two <code>Geometry</code>s are
586
public boolean disjoint(Geometry g) {
587
return ! intersects(g);
591
* Returns <code>true</code> if the DE-9IM intersection matrix for the two
592
* <code>Geometry</code>s is FT*******, F**T***** or F***T****.
594
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
595
*@return <code>true</code> if the two <code>Geometry</code>s touch;
596
* Returns false if both <code>Geometry</code>s are points
598
public boolean touches(Geometry g) {
599
// short-circuit test
600
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
602
return relate(g).isTouches(getDimension(), g.getDimension());
606
* Returns <code>true</code> if <code>disjoint</code> returns false.
608
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
609
*@return <code>true</code> if the two <code>Geometry</code>s intersect
611
public boolean intersects(Geometry g) {
612
// short-circuit envelope test
613
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
615
// optimizations for rectangle arguments
617
return RectangleIntersects.intersects((Polygon) this, g);
619
if (g.isRectangle()) {
620
return RectangleIntersects.intersects((Polygon) g, this);
623
return relate(g).isIntersects();
627
* Returns <code>true</code> if the DE-9IM intersection matrix for the two
628
* <code>Geometry</code>s is
630
* <LI> T*T****** (for a point and a curve, a point and an area or a line
632
* <LI> 0******** (for two curves)
636
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
637
*@return <code>true</code> if the two <code>Geometry</code>s cross.
638
* For this function to return <code>true</code>, the <code>Geometry</code>
639
* s must be a point and a curve; a point and a surface; two curves; or a
640
* curve and a surface.
642
public boolean crosses(Geometry g) {
643
// short-circuit test
644
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
646
return relate(g).isCrosses(getDimension(), g.getDimension());
650
* Returns <code>true</code> if the DE-9IM intersection matrix for the two
651
* <code>Geometry</code>s is T*F**F***.
653
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
654
*@return <code>true</code> if this <code>Geometry</code> is within
657
public boolean within(Geometry g) {
658
return g.contains(this);
662
* Returns <code>true</code> if <code>other.within(this)</code> returns
665
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
666
*@return <code>true</code> if this <code>Geometry</code> contains
669
public boolean contains(Geometry g) {
670
// short-circuit test
671
if (! getEnvelopeInternal().contains(g.getEnvelopeInternal()))
673
// optimizations for rectangle arguments
675
return RectangleContains.contains((Polygon) this, g);
678
return relate(g).isContains();
682
* Returns <code>true</code> if the DE-9IM intersection matrix for the two
683
* <code>Geometry</code>s is
685
* <LI> T*T***T** (for two points or two surfaces)
686
* <LI> 1*T***T** (for two curves)
690
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
691
*@return <code>true</code> if the two <code>Geometry</code>s overlap.
692
* For this function to return <code>true</code>, the <code>Geometry</code>
693
* s must be two points, two curves or two surfaces.
695
public boolean overlaps(Geometry g) {
696
// short-circuit test
697
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
699
return relate(g).isOverlaps(getDimension(), g.getDimension());
703
* Returns <code>true</code> if the elements in the DE-9IM intersection
704
* matrix for the two <code>Geometry</code>s match the elements in <code>intersectionPattern</code>
710
* <LI> T ( = 0, 1 or 2)
712
* <LI> * ( = -1, 0, 1 or 2)
714
* For more information on the DE-9IM, see the OpenGIS Simple Features
717
*@param other the <code>Geometry</code> with which to compare
718
* this <code>Geometry</code>
719
*@param intersectionPattern the pattern against which to check the
720
* intersection matrix for the two <code>Geometry</code>s
721
*@return <code>true</code> if the DE-9IM intersection
722
* matrix for the two <code>Geometry</code>s match <code>intersectionPattern</code>
724
public boolean relate(Geometry g, String intersectionPattern) {
725
return relate(g).matches(intersectionPattern);
729
* Returns the DE-9IM intersection matrix for the two <code>Geometry</code>s.
731
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
732
*@return a matrix describing the intersections of the interiors,
733
* boundaries and exteriors of the two <code>Geometry</code>s
735
public IntersectionMatrix relate(Geometry g) {
736
checkNotGeometryCollection(this);
737
checkNotGeometryCollection(g);
738
return RelateOp.relate(this, g);
742
* Returns <code>true</code> if the DE-9IM intersection matrix for the two
743
* <code>Geometry</code>s is T*F**FFF*.
745
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
746
*@return <code>true</code> if the two <code>Geometry</code>s are equal
748
public boolean equals(Geometry g) {
749
// short-circuit test
750
if (! getEnvelopeInternal().equals(g.getEnvelopeInternal()))
752
return relate(g).isEquals(getDimension(), g.getDimension());
755
//<<PERHAPS:DESIGN>> Override Object#equals [Jon Aquino]
757
public String toString() {
762
* Returns the Well-known Text representation of this <code>Geometry</code>.
763
* For a definition of the Well-known Text format, see the OpenGIS Simple
764
* Features Specification.
766
*@return the Well-known Text representation of this <code>Geometry</code>
768
public String toText() {
769
WKTWriter writer = new WKTWriter();
770
return writer.write(this);
774
* Returns a buffer region around this <code>Geometry</code> having the given
776
* The buffer of a Geometry is
777
* the Minkowski sum or difference
778
* of the Geometry with
779
* a disc of radius <code>distance</code>.
781
*@param distance the width of the buffer, interpreted according to the
782
* <code>PrecisionModel</code> of the <code>Geometry</code>
783
*@return all points whose distance from this <code>Geometry</code>
784
* are less than or equal to <code>distance</code>
786
public Geometry buffer(double distance) {
787
return BufferOp.bufferOp(this, distance);
791
* Returns a buffer region around this {@link Geometry} having the given
792
* width and with a specified number of segments used to approximate curves.
793
* The buffer of a Geometry is the Minkowski sum of the Geometry with
794
* a disc of radius <code>distance</code>. Curves in the buffer polygon are
795
* approximated with line segments. This method allows specifying the
796
* accuracy of that approximation.
798
*@param distance the width of the buffer, interpreted according to the
799
* <code>PrecisionModel</code> of the <code>Geometry</code>
800
*@param quadrantSegments the number of segments to use to approximate a quadrant of a circle
801
*@return all points whose distance from this <code>Geometry</code>
802
* are less than or equal to <code>distance</code>
804
public Geometry buffer(double distance, int quadrantSegments) {
805
return BufferOp.bufferOp(this, distance, quadrantSegments);
809
* Returns the smallest convex <code>Polygon</code> that contains all the
810
* points in the <code>Geometry</code>. This obviously applies only to <code>Geometry</code>
811
* s which contain 3 or more points; the results for degenerate cases are
812
* specified as follows:
815
* <TH> Number of <code>Point</code>s in argument <code>Geometry</code> </TH>
816
* <TH> <code>Geometry</code> class of result </TH>
820
* <TD> empty <code>GeometryCollection</code> </TD>
823
* <TD> <code>Point</code> </TD>
827
* <TD> <code>LineString</code> </TD>
830
* <TD> 3 or more </TD>
831
* <TD> <code>Polygon</code> </TD>
835
*@return the minimum-area convex polygon containing this <code>Geometry</code>'
838
public Geometry convexHull() {
839
return (new ConvexHull(this)).getConvexHull();
843
* Returns a <code>Geometry</code> representing the points shared by this
844
* <code>Geometry</code> and <code>other</code>.
846
*@param other the <code>Geometry</code> with which to compute the
848
*@return the points common to the two <code>Geometry</code>s
850
public Geometry intersection(Geometry other) {
851
checkNotGeometryCollection(this);
852
checkNotGeometryCollection(other);
853
return OverlayOp.overlayOp(this, other, OverlayOp.INTERSECTION);
857
* Returns a <code>Geometry</code> representing all the points in this <code>Geometry</code>
858
* and <code>other</code>.
860
*@param other the <code>Geometry</code> with which to compute the union
861
*@return a set combining the points of this <code>Geometry</code> and
862
* the points of <code>other</code>
864
public Geometry union(Geometry other) {
865
checkNotGeometryCollection(this);
866
checkNotGeometryCollection(other);
867
return OverlayOp.overlayOp(this, other, OverlayOp.UNION);
871
* Returns a <code>Geometry</code> representing the points making up this
872
* <code>Geometry</code> that do not make up <code>other</code>. This method
873
* returns the closure of the resultant <code>Geometry</code>.
875
*@param other the <code>Geometry</code> with which to compute the
877
*@return the point set difference of this <code>Geometry</code> with
880
public Geometry difference(Geometry other) {
881
checkNotGeometryCollection(this);
882
checkNotGeometryCollection(other);
883
return OverlayOp.overlayOp(this, other, OverlayOp.DIFFERENCE);
887
* Returns a set combining the points in this <code>Geometry</code> not in
888
* <code>other</code>, and the points in <code>other</code> not in this
889
* <code>Geometry</code>. This method returns the closure of the resultant
890
* <code>Geometry</code>.
892
*@param other the <code>Geometry</code> with which to compute the symmetric
894
*@return the point set symmetric difference of this <code>Geometry</code>
895
* with <code>other</code>
897
public Geometry symDifference(Geometry other) {
898
checkNotGeometryCollection(this);
899
checkNotGeometryCollection(other);
900
return OverlayOp.overlayOp(this, other, OverlayOp.SYMDIFFERENCE);
904
* Returns true if the two <code>Geometry</code>s are exactly equal,
905
* up to a specified tolerance.
906
* Two Geometries are exactly within a tolerance equal iff:
908
* <li>they have the same class
909
* <li>they have the same values of Coordinates,
910
* within the given tolerance distance, in their internal
911
* Coordinate lists, in exactly the same order.
913
* If this and the other <code>Geometry</code>s are
914
* composites and any children are not <code>Geometry</code>s, returns
917
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
918
*@parm tolerance distance at or below which two Coordinates will be considered
920
*@return <code>true</code> if this and the other <code>Geometry</code>
921
* are of the same class and have equal internal data.
923
public abstract boolean equalsExact(Geometry other, double tolerance);
926
* Returns true if the two <code>Geometry</code>s are exactly equal.
927
* Two Geometries are exactly equal iff:
929
* <li>they have the same class
930
* <li>they have the same values of Coordinates in their internal
931
* Coordinate lists, in exactly the same order.
933
* If this and the other <code>Geometry</code>s are
934
* composites and any children are not <code>Geometry</code>s, returns
937
* This provides a stricter test of equality than
938
* <code>equals</code>.
940
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
941
*@return <code>true</code> if this and the other <code>Geometry</code>
942
* are of the same class and have equal internal data.
944
public boolean equalsExact(Geometry other) { return equalsExact(other, 0); }
947
* Performs an operation with or on this <code>Geometry</code>'s
948
* coordinates. If you are using this method to modify the geometry, be sure
949
* to call #geometryChanged() afterwards. Note that you cannot use this
951
* modify this Geometry if its underlying CoordinateSequence's #get method
952
* returns a copy of the Coordinate, rather than the actual Coordinate stored
953
* (if it even stores Coordinates at all).
955
*@param filter the filter to apply to this <code>Geometry</code>'s
958
public abstract void apply(CoordinateFilter filter);
961
* Performs an operation with or on this <code>Geometry</code> and its
962
* subelement <code>Geometry</code>s (if any).
963
* Only GeometryCollections and subclasses
964
* have subelement Geometry's.
966
*@param filter the filter to apply to this <code>Geometry</code> (and
967
* its children, if it is a <code>GeometryCollection</code>).
969
public abstract void apply(GeometryFilter filter);
972
* Performs an operation with or on this Geometry and its
973
* component Geometry's. Only GeometryCollections and
974
* Polygons have component Geometry's; for Polygons they are the LinearRings
975
* of the shell and holes.
977
*@param filter the filter to apply to this <code>Geometry</code>.
979
public abstract void apply(GeometryComponentFilter filter);
981
public Object clone() {
983
Geometry clone = (Geometry) super.clone();
984
if (clone.envelope != null) { clone.envelope = new Envelope(clone.envelope); }
987
catch (CloneNotSupportedException e) {
988
Assert.shouldNeverReachHere();
994
* Converts this <code>Geometry</code> to <b>normal form</b> (or <b>
995
* canonical form</b> ). Normal form is a unique representation for <code>Geometry</code>
996
* s. It can be used to test whether two <code>Geometry</code>s are equal
997
* in a way that is independent of the ordering of the coordinates within
998
* them. Normal form equality is a stronger condition than topological
999
* equality, but weaker than pointwise equality. The definitions for normal
1000
* form use the standard lexicographical ordering for coordinates. "Sorted in
1001
* order of coordinates" means the obvious extension of this ordering to
1002
* sequences of coordinates.
1004
public abstract void normalize();
1007
* Returns whether this <code>Geometry</code> is greater than, equal to,
1008
* or less than another <code>Geometry</code>. <P>
1010
* If their classes are different, they are compared using the following
1013
* <LI> Point (lowest)
1017
* <LI> MultiLineString
1020
* <LI> GeometryCollection (highest)
1022
* If the two <code>Geometry</code>s have the same class, their first
1023
* elements are compared. If those are the same, the second elements are
1026
*@param o a <code>Geometry</code> with which to compare this <code>Geometry</code>
1027
*@return a positive number, 0, or a negative number, depending on whether
1028
* this object is greater than, equal to, or less than <code>o</code>, as
1029
* defined in "Normal Form For Geometry" in the JTS Technical
1032
public int compareTo(Object o) {
1033
Geometry other = (Geometry) o;
1034
if (getClassSortIndex() != other.getClassSortIndex()) {
1035
return getClassSortIndex() - other.getClassSortIndex();
1037
if (isEmpty() && other.isEmpty()) {
1043
if (other.isEmpty()) {
1046
return compareToSameClass(o);
1050
* Returns whether the two <code>Geometry</code>s are equal, from the point
1051
* of view of the <code>equalsExact</code> method. Called by <code>equalsExact</code>
1052
* . In general, two <code>Geometry</code> classes are considered to be
1053
* "equivalent" only if they are the same class. An exception is <code>LineString</code>
1054
* , which is considered to be equivalent to its subclasses.
1056
*@param other the <code>Geometry</code> with which to compare this <code>Geometry</code>
1058
*@return <code>true</code> if the classes of the two <code>Geometry</code>
1059
* s are considered to be equal by the <code>equalsExact</code> method.
1061
protected boolean isEquivalentClass(Geometry other) {
1062
return this.getClass().getName().equals(other.getClass().getName());
1066
* Throws an exception if <code>g</code>'s class is <code>GeometryCollection</code>
1067
* . (Its subclasses do not trigger an exception).
1069
*@param g the <code>Geometry</code> to check
1070
*@throws IllegalArgumentException if <code>g</code> is a <code>GeometryCollection</code>
1071
* but not one of its subclasses
1073
protected void checkNotGeometryCollection(Geometry g) {
1074
//Don't use instanceof because we want to allow subclasses
1075
if (g.getClass().getName().equals("com.vividsolutions.jts.geom.GeometryCollection")) {
1076
throw new IllegalArgumentException("This method does not support GeometryCollection arguments");
1082
* Returns the minimum and maximum x and y values in this <code>Geometry</code>
1083
* , or a null <code>Envelope</code> if this <code>Geometry</code> is empty.
1084
* Unlike <code>getEnvelopeInternal</code>, this method calculates the <code>Envelope</code>
1085
* each time it is called; <code>getEnvelopeInternal</code> caches the result
1088
*@return this <code>Geometry</code>s bounding box; if the <code>Geometry</code>
1089
* is empty, <code>Envelope#isNull</code> will return <code>true</code>
1091
protected abstract Envelope computeEnvelopeInternal();
1094
* Returns whether this <code>Geometry</code> is greater than, equal to,
1095
* or less than another <code>Geometry</code> having the same class.
1097
*@param o a <code>Geometry</code> having the same class as this <code>Geometry</code>
1098
*@return a positive number, 0, or a negative number, depending on whether
1099
* this object is greater than, equal to, or less than <code>o</code>, as
1100
* defined in "Normal Form For Geometry" in the JTS Technical
1103
protected abstract int compareToSameClass(Object o);
1106
* Returns the first non-zero result of <code>compareTo</code> encountered as
1107
* the two <code>Collection</code>s are iterated over. If, by the time one of
1108
* the iterations is complete, no non-zero result has been encountered,
1109
* returns 0 if the other iteration is also complete. If <code>b</code>
1110
* completes before <code>a</code>, a positive number is returned; if a
1111
* before b, a negative number.
1113
*@param a a <code>Collection</code> of <code>Comparable</code>s
1114
*@param b a <code>Collection</code> of <code>Comparable</code>s
1115
*@return the first non-zero <code>compareTo</code> result, if any;
1118
protected int compare(Collection a, Collection b) {
1119
Iterator i = a.iterator();
1120
Iterator j = b.iterator();
1121
while (i.hasNext() && j.hasNext()) {
1122
Comparable aElement = (Comparable) i.next();
1123
Comparable bElement = (Comparable) j.next();
1124
int comparison = aElement.compareTo(bElement);
1125
if (comparison != 0) {
1138
protected boolean equal(Coordinate a, Coordinate b, double tolerance) {
1139
if (tolerance == 0) { return a.equals(b); }
1140
return a.distance(b) <= tolerance;
1143
private int getClassSortIndex() {
1144
for (int i = 0; i < sortedClasses.length; i++) {
1145
if (sortedClasses[i].isInstance(this)) {
1149
Assert.shouldNeverReachHere("Class not supported: " + this.getClass());
1153
private Point createPointFromInternalCoord(Coordinate coord, Geometry exemplar)
1155
exemplar.getPrecisionModel().makePrecise(coord);
1156
return exemplar.getFactory().createPoint(coord);