Source Code Cross Referenced for Geometry.java in  » GIS » jts » com » vividsolutions » jts » geom » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » jts » com.vividsolutions.jts.geom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * The JTS Topology Suite is a collection of Java classes that
0003:         * implement the fundamental operations required to validate a given
0004:         * geo-spatial data set to a known topological specification.
0005:         *
0006:         * Copyright (C) 2001 Vivid Solutions
0007:         *
0008:         * This library is free software; you can redistribute it and/or
0009:         * modify it under the terms of the GNU Lesser General Public
0010:         * License as published by the Free Software Foundation; either
0011:         * version 2.1 of the License, or (at your option) any later version.
0012:         *
0013:         * This library is distributed in the hope that it will be useful,
0014:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016:         * Lesser General Public License for more details.
0017:         *
0018:         * You should have received a copy of the GNU Lesser General Public
0019:         * License along with this library; if not, write to the Free Software
0020:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0021:         *
0022:         * For more information, contact:
0023:         *
0024:         *     Vivid Solutions
0025:         *     Suite #1A
0026:         *     2328 Government Street
0027:         *     Victoria BC  V8T 5G5
0028:         *     Canada
0029:         *
0030:         *     (250)385-6040
0031:         *     www.vividsolutions.com
0032:         */
0033:        package com.vividsolutions.jts.geom;
0034:
0035:        import java.io.Serializable;
0036:        import java.util.Collection;
0037:        import java.util.Iterator;
0038:
0039:        import com.vividsolutions.jts.algorithm.*;
0040:        import com.vividsolutions.jts.io.WKTWriter;
0041:        import com.vividsolutions.jts.operation.*;
0042:        import com.vividsolutions.jts.operation.buffer.BufferOp;
0043:        import com.vividsolutions.jts.operation.distance.DistanceOp;
0044:        import com.vividsolutions.jts.operation.overlay.OverlayOp;
0045:        import com.vividsolutions.jts.operation.overlay.snap.SnapIfNeededOverlayOp;
0046:        import com.vividsolutions.jts.operation.predicate.RectangleIntersects;
0047:        import com.vividsolutions.jts.operation.predicate.RectangleContains;
0048:        import com.vividsolutions.jts.operation.relate.RelateOp;
0049:        import com.vividsolutions.jts.operation.valid.IsValidOp;
0050:        import com.vividsolutions.jts.util.Assert;
0051:
0052:        /**
0053:         * The base class for all geometric objects.
0054:         * <P>
0055:         *
0056:         *  <H3>Binary Predicates</H3>
0057:         * Because it is not clear at this time
0058:         * what semantics for spatial
0059:         *  analysis methods involving <code>GeometryCollection</code>s would be useful,
0060:         *  <code>GeometryCollection</code>s are not supported as arguments to binary
0061:         *  predicates (other than <code>convexHull</code>) or the <code>relate</code>
0062:         *  method.
0063:         *
0064:         *  <H3>Set-Theoretic Methods</H3>
0065:         *
0066:         *  The spatial analysis methods will
0067:         *  return the most specific class possible to represent the result. If the
0068:         *  result is homogeneous, a <code>Point</code>, <code>LineString</code>, or
0069:         *  <code>Polygon</code> will be returned if the result contains a single
0070:         *  element; otherwise, a <code>MultiPoint</code>, <code>MultiLineString</code>,
0071:         *  or <code>MultiPolygon</code> will be returned. If the result is
0072:         *  heterogeneous a <code>GeometryCollection</code> will be returned. <P>
0073:         *
0074:         *  Because it is not clear at this time what semantics for set-theoretic
0075:         *  methods involving <code>GeometryCollection</code>s would be useful,
0076:         * <code>GeometryCollections</code>
0077:         *  are not supported as arguments to the set-theoretic methods.
0078:         *
0079:         *  <H4>Representation of Computed Geometries </H4>
0080:         *
0081:         *  The SFS states that the result
0082:         *  of a set-theoretic method is the "point-set" result of the usual
0083:         *  set-theoretic definition of the operation (SFS 3.2.21.1). However, there are
0084:         *  sometimes many ways of representing a point set as a <code>Geometry</code>.
0085:         *  <P>
0086:         *
0087:         *  The SFS does not specify an unambiguous representation of a given point set
0088:         *  returned from a spatial analysis method. One goal of JTS is to make this
0089:         *  specification precise and unambiguous. JTS will use a canonical form for
0090:         *  <code>Geometry</code>s returned from spatial analysis methods. The canonical
0091:         *  form is a <code>Geometry</code> which is simple and noded:
0092:         *  <UL>
0093:         *    <LI> Simple means that the Geometry returned will be simple according to
0094:         *    the JTS definition of <code>isSimple</code>.
0095:         *    <LI> Noded applies only to overlays involving <code>LineString</code>s. It
0096:         *    means that all intersection points on <code>LineString</code>s will be
0097:         *    present as endpoints of <code>LineString</code>s in the result.
0098:         *  </UL>
0099:         *  This definition implies that non-simple geometries which are arguments to
0100:         *  spatial analysis methods must be subjected to a line-dissolve process to
0101:         *  ensure that the results are simple.
0102:         *
0103:         *  <H4> Constructed Points And The Precision Model </H4>
0104:         *
0105:         *  The results computed by the set-theoretic methods may
0106:         *  contain constructed points which are not present in the input <code>Geometry</code>
0107:         *  s. These new points arise from intersections between line segments in the
0108:         *  edges of the input <code>Geometry</code>s. In the general case it is not
0109:         *  possible to represent constructed points exactly. This is due to the fact
0110:         *  that the coordinates of an intersection point may contain twice as many bits
0111:         *  of precision as the coordinates of the input line segments. In order to
0112:         *  represent these constructed points explicitly, JTS must truncate them to fit
0113:         *  the <code>PrecisionModel</code>. <P>
0114:         *
0115:         *  Unfortunately, truncating coordinates moves them slightly. Line segments
0116:         *  which would not be coincident in the exact result may become coincident in
0117:         *  the truncated representation. This in turn leads to "topology collapses" --
0118:         *  situations where a computed element has a lower dimension than it would in
0119:         *  the exact result. <P>
0120:         *
0121:         *  When JTS detects topology collapses during the computation of spatial
0122:         *  analysis methods, it will throw an exception. If possible the exception will
0123:         *  report the location of the collapse. <P>
0124:         *
0125:         *  #equals(Object) and #hashCode are not overridden, so that when two
0126:         *  topologically equal Geometries are added to HashMaps and HashSets, they
0127:         *  remain distinct. This behaviour is desired in many cases.
0128:         *
0129:         *@version 1.7
0130:         */
0131:        public abstract class Geometry implements  Cloneable, Comparable,
0132:                Serializable {
0133:            private static final long serialVersionUID = 8763622679187376702L;
0134:
0135:            private final static Class[] sortedClasses = new Class[] {
0136:                    Point.class, MultiPoint.class, LineString.class,
0137:                    LinearRing.class, MultiLineString.class, Polygon.class,
0138:                    MultiPolygon.class, GeometryCollection.class };
0139:
0140:            private final static GeometryComponentFilter geometryChangedFilter = new GeometryComponentFilter() {
0141:                public void filter(Geometry geom) {
0142:                    geom.geometryChangedAction();
0143:                }
0144:            };
0145:
0146:            /**
0147:             *  The bounding box of this <code>Geometry</code>.
0148:             */
0149:            protected Envelope envelope;
0150:
0151:            /**
0152:             * The {@link GeometryFactory} used to create this Geometry
0153:             */
0154:            protected final GeometryFactory factory;
0155:
0156:            /**
0157:             *  The ID of the Spatial Reference System used by this <code>Geometry</code>
0158:             */
0159:            protected int SRID;
0160:
0161:            /**
0162:             * Creates a new <tt>Geometry</tt> via the specified GeometryFactory.
0163:             *
0164:             * @param factory
0165:             */
0166:            public Geometry(GeometryFactory factory) {
0167:                this .factory = factory;
0168:                this .SRID = factory.getSRID();
0169:            }
0170:
0171:            /**
0172:             *  Returns the name of this object's <code>com.vivid.jts.geom</code>
0173:             *  interface.
0174:             *
0175:             *@return    the name of this <code>Geometry</code>s most specific <code>com.vividsolutions.jts.geom</code>
0176:             *      interface
0177:             */
0178:            public abstract String getGeometryType();
0179:
0180:            /**
0181:             *  Returns true if the array contains any non-empty <code>Geometry</code>s.
0182:             *
0183:             *@param  geometries  an array of <code>Geometry</code>s; no elements may be
0184:             *      <code>null</code>
0185:             *@return             <code>true</code> if any of the <code>Geometry</code>s
0186:             *      <code>isEmpty</code> methods return <code>false</code>
0187:             */
0188:            protected static boolean hasNonEmptyElements(Geometry[] geometries) {
0189:                for (int i = 0; i < geometries.length; i++) {
0190:                    if (!geometries[i].isEmpty()) {
0191:                        return true;
0192:                    }
0193:                }
0194:                return false;
0195:            }
0196:
0197:            /**
0198:             *  Returns true if the array contains any <code>null</code> elements.
0199:             *
0200:             *@param  array  an array to validate
0201:             *@return        <code>true</code> if any of <code>array</code>s elements are
0202:             *      <code>null</code>
0203:             */
0204:            protected static boolean hasNullElements(Object[] array) {
0205:                for (int i = 0; i < array.length; i++) {
0206:                    if (array[i] == null) {
0207:                        return true;
0208:                    }
0209:                }
0210:                return false;
0211:            }
0212:
0213:            /**
0214:             *  Returns the ID of the Spatial Reference System used by the <code>Geometry</code>.
0215:             *  <P>
0216:             *
0217:             *  JTS supports Spatial Reference System information in the simple way
0218:             *  defined in the SFS. A Spatial Reference System ID (SRID) is present in
0219:             *  each <code>Geometry</code> object. <code>Geometry</code> provides basic
0220:             *  accessor operations for this field, but no others. The SRID is represented
0221:             *  as an integer.
0222:             *
0223:             *@return    the ID of the coordinate space in which the <code>Geometry</code>
0224:             *      is defined.
0225:             *
0226:             */
0227:            public int getSRID() {
0228:                return SRID;
0229:            }
0230:
0231:            /**
0232:             *  Sets the ID of the Spatial Reference System used by the <code>Geometry</code>.
0233:             */
0234:            public void setSRID(int SRID) {
0235:                this .SRID = SRID;
0236:            }
0237:
0238:            private Object userData = null;
0239:
0240:            /**
0241:             * Gets the factory which contains the context in which this geometry was created.
0242:             *
0243:             * @return the factory for this geometry
0244:             */
0245:            public GeometryFactory getFactory() {
0246:                return factory;
0247:            }
0248:
0249:            /**
0250:             * Gets the user data object for this geometry, if any.
0251:             *
0252:             * @return the user data object, or <code>null</code> if none set
0253:             */
0254:            public Object getUserData() {
0255:                return userData;
0256:            }
0257:
0258:            /**
0259:             * Returns the number of {@link Geometry}s in a {@link GeometryCollection}
0260:             * (or 1, if the geometry is not a collection).
0261:             *
0262:             * @return the number of geometries contained in this geometry
0263:             */
0264:            public int getNumGeometries() {
0265:                return 1;
0266:            }
0267:
0268:            /**
0269:             * Returns an element {@link Geometry} from a {@link GeometryCollection}
0270:             * (or <code>this</code>, if the geometry is not a collection).
0271:             *
0272:             * @param n the index of the geometry element
0273:             * @return the n'th geometry contained in this geometry
0274:             */
0275:            public Geometry getGeometryN(int n) {
0276:                return this ;
0277:            }
0278:
0279:            /**
0280:             * A simple scheme for applications to add their own custom data to a Geometry.
0281:             * An example use might be to add an object representing a Coordinate Reference System.
0282:             * <p>
0283:             * Note that user data objects are not present in geometries created by
0284:             * construction methods.
0285:             *
0286:             * @param userData an object, the semantics for which are defined by the
0287:             * application using this Geometry
0288:             */
0289:            public void setUserData(Object userData) {
0290:                this .userData = userData;
0291:            }
0292:
0293:            /**
0294:             *  Returns the <code>PrecisionModel</code> used by the <code>Geometry</code>.
0295:             *
0296:             *@return    the specification of the grid of allowable points, for this
0297:             *      <code>Geometry</code> and all other <code>Geometry</code>s
0298:             */
0299:            public PrecisionModel getPrecisionModel() {
0300:                return factory.getPrecisionModel();
0301:            }
0302:
0303:            /**
0304:             *  Returns a vertex of this <code>Geometry</code>.
0305:             *
0306:             *@return    a {@link Coordinate} which is a vertex of this <code>Geometry</code>.
0307:             *          Returns <code>null</code> if this Geometry is empty
0308:             */
0309:            public abstract Coordinate getCoordinate();
0310:
0311:            /**
0312:             *  Returns this <code>Geometry</code> s vertices. If you modify the coordinates
0313:             *  in this array, be sure to call #geometryChanged afterwards.
0314:             *  The <code>Geometry</code>s contained by composite <code>Geometry</code>s
0315:             *  must be Geometry's; that is, they must implement <code>getCoordinates</code>.
0316:             *
0317:             *@return    the vertices of this <code>Geometry</code>
0318:             */
0319:            public abstract Coordinate[] getCoordinates();
0320:
0321:            /**
0322:             *  Returns the count of this <code>Geometry</code>s vertices. The <code>Geometry</code>
0323:             *  s contained by composite <code>Geometry</code>s must be
0324:             *  Geometry's; that is, they must implement <code>getNumPoints</code>
0325:             *
0326:             *@return    the number of vertices in this <code>Geometry</code>
0327:             */
0328:            public abstract int getNumPoints();
0329:
0330:            /**
0331:             * Tests whether this {@link Geometry} is simple.
0332:             * In general, the SFS specification of simplicity
0333:             * follows the rule:
0334:             *  <UL>
0335:             *    <LI> A Geometry is simple iff the only self-intersections are at
0336:             *    boundary points.
0337:             *  </UL>
0338:             * Simplicity is defined for each {@link Geometry} subclass as follows:
0339:             * <ul>
0340:             * <li>Valid polygonal geometries are simple by definition, so
0341:             * <code>isSimple</code> trivially returns true.
0342:             * <li>Linear geometries are simple iff they do not self-intersect at points
0343:             * other than boundary points.
0344:             * <li>Zero-dimensional geometries (points) are simple iff they have no
0345:             * repeated points.
0346:             * <li>Empty <code>Geometry</code>s are always simple
0347:             * <ul>
0348:             *
0349:             * @return    <code>true</code> if this <code>Geometry</code> has any points of
0350:             *      self-tangency, self-intersection or other anomalous points
0351:             * @see #isValid
0352:             */
0353:            public boolean isSimple() {
0354:                checkNotGeometryCollection(this );
0355:                IsSimpleOp op = new IsSimpleOp(this );
0356:                return op.isSimple();
0357:            }
0358:
0359:            /**
0360:             *  Tests the validity of this <code>Geometry</code>.
0361:             *  Subclasses provide their own definition of "valid".
0362:             *
0363:             *@return    <code>true</code> if this <code>Geometry</code> is valid
0364:             *
0365:             * @see IsValidOp
0366:             */
0367:            public boolean isValid() {
0368:                IsValidOp isValidOp = new IsValidOp(this );
0369:                return isValidOp.isValid();
0370:            }
0371:
0372:            /**
0373:             *  Returns whether or not the set of points in this <code>Geometry</code> is
0374:             *  empty.
0375:             *
0376:             *@return    <code>true</code> if this <code>Geometry</code> equals the empty
0377:             *      geometry
0378:             */
0379:            public abstract boolean isEmpty();
0380:
0381:            /**
0382:             *  Returns the minimum distance between this <code>Geometry</code>
0383:             *  and the <code>Geometry</code> g
0384:             *
0385:             *@param  g  the <code>Geometry</code> from which to compute the distance
0386:             */
0387:            public double distance(Geometry g) {
0388:                return DistanceOp.distance(this , g);
0389:            }
0390:
0391:            /**
0392:             * Tests whether the distance from this <code>Geometry</code>
0393:             * to another is less than or equal to a specified value.
0394:             *
0395:             * @param geom the Geometry to check the distance to
0396:             * @param distance the distance value to compare
0397:             * @return <code>true</code> if the geometries are less than <code>distance</code> apart.
0398:             */
0399:            public boolean isWithinDistance(Geometry geom, double distance) {
0400:                double envDist = getEnvelopeInternal().distance(
0401:                        geom.getEnvelopeInternal());
0402:                if (envDist > distance)
0403:                    return false;
0404:                return DistanceOp.isWithinDistance(this , geom, distance);
0405:                /*
0406:                double geomDist = this.distance(geom);
0407:                if (geomDist > distance)
0408:                  return false;
0409:                return true;
0410:                 */
0411:            }
0412:
0413:            public boolean isRectangle() {
0414:                // Polygon overrides to check for actual rectangle
0415:                return false;
0416:            }
0417:
0418:            /**
0419:             *  Returns the area of this <code>Geometry</code>.
0420:             *  Areal Geometries have a non-zero area.
0421:             *  They override this function to compute the area.
0422:             *  Others return 0.0
0423:             *
0424:             *@return the area of the Geometry
0425:             */
0426:            public double getArea() {
0427:                return 0.0;
0428:            }
0429:
0430:            /**
0431:             *  Returns the length of this <code>Geometry</code>.
0432:             *  Linear geometries return their length.
0433:             *  Areal geometries return their perimeter.
0434:             *  They override this function to compute the area.
0435:             *  Others return 0.0
0436:             *
0437:             *@return the length of the Geometry
0438:             */
0439:            public double getLength() {
0440:                return 0.0;
0441:            }
0442:
0443:            /**
0444:             * Computes the centroid of this <code>Geometry</code>.
0445:             * The centroid
0446:             * is equal to the centroid of the set of component Geometries of highest
0447:             * dimension (since the lower-dimension geometries contribute zero
0448:             * "weight" to the centroid)
0449:             *
0450:             * @return a {@link Point} which is the centroid of this Geometry
0451:             */
0452:            public Point getCentroid() {
0453:                if (isEmpty()) {
0454:                    return null;
0455:                }
0456:                Coordinate centPt = null;
0457:                int dim = getDimension();
0458:                if (dim == 0) {
0459:                    CentroidPoint cent = new CentroidPoint();
0460:                    cent.add(this );
0461:                    centPt = cent.getCentroid();
0462:                } else if (dim == 1) {
0463:                    CentroidLine cent = new CentroidLine();
0464:                    cent.add(this );
0465:                    centPt = cent.getCentroid();
0466:                } else {
0467:                    CentroidArea cent = new CentroidArea();
0468:                    cent.add(this );
0469:                    centPt = cent.getCentroid();
0470:                }
0471:                return createPointFromInternalCoord(centPt, this );
0472:
0473:            }
0474:
0475:            /**
0476:             * Computes an interior point of this <code>Geometry</code>.
0477:             * An interior point is guaranteed to lie in the interior of the Geometry,
0478:             * if it possible to calculate such a point exactly. Otherwise,
0479:             * the point may lie on the boundary of the geometry.
0480:             *
0481:             * @return a {@link Point} which is in the interior of this Geometry
0482:             */
0483:            public Point getInteriorPoint() {
0484:                Coordinate interiorPt = null;
0485:                int dim = getDimension();
0486:                if (dim == 0) {
0487:                    InteriorPointPoint intPt = new InteriorPointPoint(this );
0488:                    interiorPt = intPt.getInteriorPoint();
0489:                } else if (dim == 1) {
0490:                    InteriorPointLine intPt = new InteriorPointLine(this );
0491:                    interiorPt = intPt.getInteriorPoint();
0492:                } else {
0493:                    InteriorPointArea intPt = new InteriorPointArea(this );
0494:                    interiorPt = intPt.getInteriorPoint();
0495:                }
0496:                return createPointFromInternalCoord(interiorPt, this );
0497:            }
0498:
0499:            /**
0500:             *  Returns the dimension of this <code>Geometry</code>.
0501:             *
0502:             *@return    the dimension of the class implementing this interface, whether
0503:             *      or not this object is the empty geometry
0504:             */
0505:            public abstract int getDimension();
0506:
0507:            /**
0508:             * Returns the boundary, or an empty geometry of appropriate dimension
0509:             * if this <code>Geometry</code>  is empty.
0510:             * (In the case of zero-dimensional geometries, '
0511:             * an empty GeometryCollection is returned.)
0512:             * For a discussion of this function, see the OpenGIS Simple
0513:             * Features Specification. As stated in SFS Section 2.1.13.1, "the boundary
0514:             * of a Geometry is a set of Geometries of the next lower dimension."
0515:             *
0516:             *@return    the closure of the combinatorial boundary of this <code>Geometry</code>
0517:             */
0518:            public abstract Geometry getBoundary();
0519:
0520:            /**
0521:             *  Returns the dimension of this <code>Geometry</code>s inherent boundary.
0522:             *
0523:             *@return    the dimension of the boundary of the class implementing this
0524:             *      interface, whether or not this object is the empty geometry. Returns
0525:             *      <code>Dimension.FALSE</code> if the boundary is the empty geometry.
0526:             */
0527:            public abstract int getBoundaryDimension();
0528:
0529:            /**
0530:             *  Returns this <code>Geometry</code>s bounding box. If this <code>Geometry</code>
0531:             *  is the empty geometry, returns an empty <code>Point</code>. If the <code>Geometry</code>
0532:             *  is a point, returns a non-empty <code>Point</code>. Otherwise, returns a
0533:             *  <code>Polygon</code> whose points are (minx, miny), (maxx, miny), (maxx,
0534:             *  maxy), (minx, maxy), (minx, miny).
0535:             *
0536:             *@return    an empty <code>Point</code> (for empty <code>Geometry</code>s), a
0537:             *      <code>Point</code> (for <code>Point</code>s) or a <code>Polygon</code>
0538:             *      (in all other cases)
0539:             */
0540:            public Geometry getEnvelope() {
0541:                return getFactory().toGeometry(getEnvelopeInternal());
0542:            }
0543:
0544:            /**
0545:             *  Returns the minimum and maximum x and y values in this <code>Geometry</code>
0546:             *  , or a null <code>Envelope</code> if this <code>Geometry</code> is empty.
0547:             *
0548:             *@return    this <code>Geometry</code>s bounding box; if the <code>Geometry</code>
0549:             *      is empty, <code>Envelope#isNull</code> will return <code>true</code>
0550:             */
0551:            public Envelope getEnvelopeInternal() {
0552:                if (envelope == null) {
0553:                    envelope = computeEnvelopeInternal();
0554:                }
0555:                return envelope;
0556:            }
0557:
0558:            /**
0559:             * Notifies this Geometry that its Coordinates have been changed by an external
0560:             * party (using a CoordinateFilter, for example). The Geometry will flush
0561:             * and/or update any information it has cached (such as its {@link Envelope} ).
0562:             */
0563:            public void geometryChanged() {
0564:                apply(geometryChangedFilter);
0565:            }
0566:
0567:            /**
0568:             * Notifies this Geometry that its Coordinates have been changed by an external
0569:             * party. When #geometryChanged is called, this method will be called for
0570:             * this Geometry and its component Geometries.
0571:             * @see #apply(GeometryComponentFilter)
0572:             */
0573:            protected void geometryChangedAction() {
0574:                envelope = null;
0575:            }
0576:
0577:            /**
0578:             * Returns <code>true</code> if this geometry is disjoint to the specified geometry.
0579:             * <p>
0580:             * The <code>disjoint</code> predicate has the following equivalent definitions:
0581:             * <ul>
0582:             * <li>The two geometries have no point in common
0583:             * <li>The DE-9IM Intersection Matrix for the two geometries is FF*FF****
0584:             * <li>! <code>g.intersects(this)</code>
0585:             * (<code>disjoint</code> is the inverse of <code>intersects</code>)
0586:             * </ul>
0587:             *
0588:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0589:             *@return        <code>true</code> if the two <code>Geometry</code>s are
0590:             *      disjoint
0591:             *
0592:             * @see Geometry#intersects
0593:             */
0594:            public boolean disjoint(Geometry g) {
0595:                return !intersects(g);
0596:            }
0597:
0598:            /**
0599:             * Returns <code>true</code> if this geometry touches the
0600:             * specified geometry.
0601:             * <p>
0602:             * The <code>touches</code> predicate has the following equivalent definitions:
0603:             * <ul>
0604:             * <li>The geometries have at least one point in common, but their interiors do not intersect.
0605:             * <li>The DE-9IM Intersection Matrix for the two geometries is
0606:             *   FT*******, F**T***** or F***T****
0607:             * </ul>
0608:             * If both geometries have dimension 0, this predicate returns <code>false</code>
0609:             *
0610:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0611:             *@return        <code>true</code> if the two <code>Geometry</code>s touch;
0612:             *      Returns <code>false</code> if both <code>Geometry</code>s are points
0613:             */
0614:            public boolean touches(Geometry g) {
0615:                // short-circuit test
0616:                if (!getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
0617:                    return false;
0618:                return relate(g).isTouches(getDimension(), g.getDimension());
0619:            }
0620:
0621:            /**
0622:             * Returns <code>true</code> if this geometry intersects the specified geometry.
0623:             * <p>
0624:             * The <code>intersects</code> predicate has the following equivalent definitions:
0625:             * <ul>
0626:             * <li>The two geometries have at least one point in common
0627:             * <li>! <code>g.disjoint(this)</code>
0628:             * (<code>intersects</code> is the inverse of <code>disjoint</code>)
0629:             * </ul>
0630:             *
0631:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0632:             *@return        <code>true</code> if the two <code>Geometry</code>s intersect
0633:             *
0634:             * @see Geometry#disjoint
0635:             */
0636:            public boolean intersects(Geometry g) {
0637:
0638:                // short-circuit envelope test
0639:                if (!getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
0640:                    return false;
0641:
0642:                /**
0643:                 * TODO: (MD) Add optimizations:
0644:                 *
0645:                 * - for P-A case:
0646:                 * If P is in env(A), test for point-in-poly
0647:                 *
0648:                 * - for A-A case:
0649:                 * If env(A1).overlaps(env(A2))
0650:                 * test for overlaps via point-in-poly first (both ways)
0651:                 * Possibly optimize selection of point to test by finding point of A1
0652:                 * closest to centre of env(A2).
0653:                 * (Is there a test where we shouldn't bother - e.g. if env A
0654:                 * is much smaller than env B, maybe there's no point in testing
0655:                 * pt(B) in env(A)?
0656:                 */
0657:
0658:                // optimization for rectangle arguments
0659:                if (isRectangle()) {
0660:                    return RectangleIntersects.intersects((Polygon) this , g);
0661:                }
0662:                if (g.isRectangle()) {
0663:                    return RectangleIntersects.intersects((Polygon) g, this );
0664:                }
0665:                // general case
0666:                return relate(g).isIntersects();
0667:            }
0668:
0669:            /**
0670:             * Returns <code>true</code> if this geometry crosses the
0671:             * specified geometry.
0672:             * <p>
0673:             * The <code>crosses</code> predicate has the following equivalent definitions:
0674:             * <ul>
0675:             * <li>The geometries have some but not all interior points in common.
0676:             * <li>The DE-9IM Intersection Matrix for the two geometries is
0677:             *   <ul>
0678:             *    <li>T*T****** (for P/L, P/A, and L/A situations)
0679:             *    <li>T*****T** (for L/P, L/A, and A/L situations)
0680:             *    <li>0******** (for L/L situations)
0681:             *   </ul>
0682:             * </ul>
0683:             * For any other combination of dimensions this predicate returns <code>false</code>.
0684:             * <p>
0685:             * The SFS defined this predicate only for P/L, P/A, L/L, and L/A situations.
0686:             * JTS extends the definition to apply to L/P, A/P and A/L situations as well.
0687:             * This makes the relation symmetric.
0688:             *
0689:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0690:             *@return        <code>true</code> if the two <code>Geometry</code>s cross.
0691:             */
0692:            public boolean crosses(Geometry g) {
0693:                // short-circuit test
0694:                if (!getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
0695:                    return false;
0696:                return relate(g).isCrosses(getDimension(), g.getDimension());
0697:            }
0698:
0699:            /**
0700:             * Returns <code>true</code> if this geometry is within the
0701:             * specified geometry.
0702:             * <p>
0703:             * The <code>within</code> predicate has the following equivalent definitions:
0704:             * <ul>
0705:             * <li>Every point of this geometry is a point of the other geometry,
0706:             * and the interiors of the two geometries have at least one point in common.
0707:             * <li>The DE-9IM Intersection Matrix for the two geometries is T*F**F***
0708:             * <li><code>g.contains(this)</code>
0709:             * (<code>within</code> is the inverse of <code>contains</code>)
0710:             * </ul>
0711:             * An implication of the definition is that
0712:             * "The boundary of a Polygon is not within the Polygon".
0713:             * In other words, if a geometry G is a subset of
0714:             * the points in the boundary of a polygon P, <code>G.within(P) = false</code>
0715:             *
0716:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0717:             *@return        <code>true</code> if this <code>Geometry</code> is within
0718:             *      <code>other</code>
0719:             *
0720:             * @see Geometry#contains
0721:             */
0722:            public boolean within(Geometry g) {
0723:                return g.contains(this );
0724:            }
0725:
0726:            /**
0727:             * Returns <code>true</code> if this geometry contains the
0728:             * specified geometry.
0729:             * <p>
0730:             * The <code>contains</code> predicate has the following equivalent definitions:
0731:             * <ul>
0732:             * <li>Every point of the other geometry is a point of this geometry,
0733:             * and the interiors of the two geometries have at least one point in common.
0734:             * <li>The DE-9IM Intersection Matrix for the two geometries is <code>T*****FF*</code>
0735:             * <li><code>g.within(this)</code>
0736:             * (<code>contains</code> is the inverse of <code>within</code>)
0737:             * </ul>
0738:             * An implication of the definition is that "Polygons do not
0739:             * contain their boundary".  In other words, if a geometry G is a subset of
0740:             * the points in the boundary of a polygon P, <code>P.contains(G) = false</code>
0741:             *
0742:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0743:             *@return        <code>true</code> if this <code>Geometry</code> contains <code>g</code>
0744:             *
0745:             * @see Geometry#within
0746:             */
0747:            public boolean contains(Geometry g) {
0748:                // short-circuit test
0749:                if (!getEnvelopeInternal().contains(g.getEnvelopeInternal()))
0750:                    return false;
0751:                // optimization for rectangle arguments
0752:                if (isRectangle()) {
0753:                    return RectangleContains.contains((Polygon) this , g);
0754:                }
0755:                // general case
0756:                return relate(g).isContains();
0757:            }
0758:
0759:            /**
0760:             * Returns <code>true</code> if this geometry overlaps the
0761:             * specified geometry.
0762:             * <p>
0763:             * The <code>overlaps</code> predicate has the following equivalent definitions:
0764:             * <ul>
0765:             * <li>The geometries have some but not all points in common,
0766:             * they have the same dimension,
0767:             * and the intersection of the interiors of the two geometries has
0768:             * the same dimension as the geometries themselves.
0769:             * <li>The DE-9IM Intersection Matrix for the two geometries is
0770:             *   <code>T*T***T**</code> (for two points or two surfaces)
0771:             *   or <code>1*T***T**</code> (for two curves)
0772:             * </ul>
0773:             * If the geometries are of different dimension this predicate returns <code>false</code>.
0774:             *
0775:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0776:             *@return        <code>true</code> if the two <code>Geometry</code>s overlap.
0777:             */
0778:            public boolean overlaps(Geometry g) {
0779:                // short-circuit test
0780:                if (!getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
0781:                    return false;
0782:                return relate(g).isOverlaps(getDimension(), g.getDimension());
0783:            }
0784:
0785:            /**
0786:             * Returns <code>true</code> if this geometry covers the
0787:             * specified geometry.
0788:             * <p>
0789:             * The <code>covers</code> predicate has the following equivalent definitions:
0790:             * <ul>
0791:             * <li>Every point of the other geometry is a point of this geometry.
0792:             * <li>The DE-9IM Intersection Matrix for the two geometries is
0793:             *    <code>T*****FF*</code>
0794:             * or <code>*T****FF*</code>
0795:             * or <code>***T**FF*</code>
0796:             * or <code>****T*FF*</code>
0797:             * <li><code>g.coveredBy(this)</code>
0798:             * (<code>covers</code> is the inverse of <code>coverdBy</code>)
0799:             * </ul>
0800:             * Note the difference between <code>covers</code> and <code>contains</code>
0801:             * - <code>covers</code> is a more inclusive relation.
0802:             * In particular, unlike <code>contains</code> it does not distinguish between
0803:             * points in the boundary and in the interior of geometries.
0804:             * For most situations, <code>covers</code> should be used in preference to <code>contains</code>.
0805:             * As an added benefit, <code>covers</code> is more amenable to optimization,
0806:             * and hence should be more performant.
0807:             *
0808:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0809:             *@return        <code>true</code> if this <code>Geometry</code> covers <code>g</code>
0810:             *
0811:             * @see Geometry#contains
0812:             * @see Geometry#coveredBy
0813:             */
0814:            public boolean covers(Geometry g) {
0815:                // short-circuit test
0816:                if (!getEnvelopeInternal().contains(g.getEnvelopeInternal()))
0817:                    return false;
0818:                // optimization for rectangle arguments
0819:                if (isRectangle()) {
0820:                    return getEnvelopeInternal().contains(
0821:                            g.getEnvelopeInternal());
0822:                }
0823:                return relate(g).isCovers();
0824:            }
0825:
0826:            /**
0827:             * Returns <code>true</code> if this geometry is covered by the
0828:             * specified geometry.
0829:             * <p>
0830:             * The <code>coveredBy</code> predicate has the following equivalent definitions:
0831:             * <ul>
0832:             * <li>Every point of this geometry is a point of the other geometry.
0833:             * <li>The DE-9IM Intersection Matrix for the two geometries is
0834:             *    <code>T*F**F***</code>
0835:             * or <code>*TF**F***</code>
0836:             * or <code>**FT*F***</code>
0837:             * or <code>**F*TF***</code>
0838:             * <li><code>g.covers(this)</code>
0839:             * (<code>coveredBy</code> is the inverse of <code>covers</code>)
0840:             * </ul>
0841:             * Note the difference between <code>coveredBy</code> and <code>within</code>
0842:             * - <code>coveredBy</code> is a more inclusive relation.
0843:             *
0844:             *@param  g  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0845:             *@return        <code>true</code> if this <code>Geometry</code> is covered by <code>g</code>
0846:             *
0847:             * @see Geometry#within
0848:             * @see Geometry#covers
0849:             */
0850:            public boolean coveredBy(Geometry g) {
0851:                return g.covers(this );
0852:            }
0853:
0854:            /**
0855:             *  Returns <code>true</code> if the elements in the DE-9IM
0856:             * {@link IntersectionMatrix} for the two <code>Geometry</code>s match the elements in <code>intersectionPattern</code>.
0857:             * The pattern is a 9-character string, with symbols drawn from the following set:
0858:             *  <UL>
0859:             *    <LI> 0 (dimension 0)
0860:             *    <LI> 1 (dimension 1)
0861:             *    <LI> 2 (dimension 2)
0862:             *    <LI> T ( matches 0, 1 or 2)
0863:             *    <LI> F ( matches FALSE)
0864:             *    <LI> * ( matches any value)
0865:             *  </UL>
0866:             *  For more information on the DE-9IM, see the <i>OpenGIS Simple Features
0867:             *  Specification</i>.
0868:             *
0869:             *@param  other                the <code>Geometry</code> with which to compare
0870:             *      this <code>Geometry</code>
0871:             *@param  intersectionPattern  the pattern against which to check the
0872:             *      intersection matrix for the two <code>Geometry</code>s
0873:             *@return                      <code>true</code> if the DE-9IM intersection
0874:             *      matrix for the two <code>Geometry</code>s match <code>intersectionPattern</code>
0875:             * @see IntersectionMatrix
0876:             */
0877:            public boolean relate(Geometry g, String intersectionPattern) {
0878:                return relate(g).matches(intersectionPattern);
0879:            }
0880:
0881:            /**
0882:             *  Returns the DE-9IM {@link IntersectionMatrix} for the two <code>Geometry</code>s.
0883:             *
0884:             *@param  other  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0885:             *@return        an {@link IntersectionMatrix} describing the intersections of the interiors,
0886:             *      boundaries and exteriors of the two <code>Geometry</code>s
0887:             */
0888:            public IntersectionMatrix relate(Geometry g) {
0889:                checkNotGeometryCollection(this );
0890:                checkNotGeometryCollection(g);
0891:                return RelateOp.relate(this , g);
0892:            }
0893:
0894:            /**
0895:             * Returns <code>true</code> if this geometry is equal to the
0896:             * specified geometry.
0897:             * <p>
0898:             * The <code>equals</code> predicate has the following equivalent definitions:
0899:             * <ul>
0900:             * <li>The two geometries have at least one point in common,
0901:             * and no point of either geometry lies in the exterior of the other geometry.
0902:             * <li>The DE-9IM Intersection Matrix for the two geometries is T*F**FFF*
0903:             * </ul>
0904:             *
0905:             *@param  other  the <code>Geometry</code> with which to compare this <code>Geometry</code>
0906:             *@return        <code>true</code> if the two <code>Geometry</code>s are equal
0907:             */
0908:            public boolean equals(Geometry g) {
0909:                // short-circuit test
0910:                if (!getEnvelopeInternal().equals(g.getEnvelopeInternal()))
0911:                    return false;
0912:                return relate(g).isEquals(getDimension(), g.getDimension());
0913:            }
0914:
0915:            //<<PERHAPS:DESIGN>> Override Object#equals [Jon Aquino]
0916:
0917:            public String toString() {
0918:                return toText();
0919:            }
0920:
0921:            /**
0922:             *  Returns the Well-known Text representation of this <code>Geometry</code>.
0923:             *  For a definition of the Well-known Text format, see the OpenGIS Simple
0924:             *  Features Specification.
0925:             *
0926:             *@return    the Well-known Text representation of this <code>Geometry</code>
0927:             */
0928:            public String toText() {
0929:                WKTWriter writer = new WKTWriter();
0930:                return writer.write(this );
0931:            }
0932:
0933:            /**
0934:             * Computes a buffer area around this geometry having the given
0935:             * width.
0936:             * The buffer of a Geometry is the Minkowski sum or difference
0937:             * of the geometry with a disc of radius <code>abs(distance)</code>.
0938:             * The buffer is constructed using 8 segments per quadrant to represent curves.
0939:             * The end cap style is <tt>CAP_ROUND</tt>.
0940:             *
0941:             *@param  distance  the width of the buffer (may be positive, negative or 0)
0942:             *@return an area geometry representing the buffer region
0943:             *
0944:             * @throws TopologyException if a robustness error occurs
0945:             *
0946:             * @see #buffer(double, int)
0947:             * @see #buffer(double, int, int)
0948:             */
0949:            public Geometry buffer(double distance) {
0950:                return BufferOp.bufferOp(this , distance);
0951:            }
0952:
0953:            /**
0954:             * Computes a buffer area around this geometry having the given
0955:             * width and with a specified accuracy of approximation for circular arcs.
0956:             * <p>
0957:             * Buffer area boundaries can contain circular arcs.
0958:             * To represent these arcs using linear geometry they must be approximated with line segments.
0959:             * The <code>quadrantSegments</code> argument allows controlling the
0960:             * accuracy of the approximation
0961:             * by specifying the number of line segments used to represent a quadrant of a circle
0962:             *
0963:             *@param  distance  the width of the buffer (may be positive, negative or 0)
0964:             *@param quadrantSegments the number of line segments used to represent a quadrant of a circle
0965:             *@return an area geometry representing the buffer region
0966:             *
0967:             * @throws TopologyException if a robustness error occurs
0968:             *
0969:             * @see #buffer(double)
0970:             * @see #buffer(double, int, int)
0971:             */
0972:            public Geometry buffer(double distance, int quadrantSegments) {
0973:                return BufferOp.bufferOp(this , distance, quadrantSegments);
0974:            }
0975:
0976:            /**
0977:             * Computes a buffer area around this geometry having the given
0978:             * width and with a specified accuracy of approximation for circular arcs,
0979:             * and using a specified end cap style.
0980:             * <p>
0981:             * Buffer area boundaries can contain circular arcs.
0982:             * To represent these arcs using linear geometry they must be approximated with line segments.
0983:             * The <code>quadrantSegments</code> argument allows controlling the
0984:             * accuracy of the approximation
0985:             * by specifying the number of line segments used to represent a quadrant of a circle
0986:             * <p>
0987:             * The end cap style specifies the buffer geometry that will be
0988:             * created at the ends of linestrings.  The styles provided are:
0989:             * <ul>
0990:             * <li><tt>BufferOp.CAP_ROUND</tt> - (default) a semi-circle
0991:             * <li><tt>BufferOp.CAP_BUTT</tt> - a straight line perpendicular to the end segment
0992:             * <li><tt>BufferOp.CAP_SQUARE</tt> - a half-square
0993:             * </ul>
0994:             *
0995:             *@param  distance  the width of the buffer (may be positive, negative or 0)
0996:             *@param quadrantSegments the number of line segments used to represent a quadrant of a circle
0997:             *@param endCapStyle the end cap style to use
0998:             *@return an area geometry representing the buffer region
0999:             *
1000:             * @throws TopologyException if a robustness error occurs
1001:             *
1002:             * @see #buffer(double)
1003:             * @see #buffer(double, int)
1004:             * @see BufferOp
1005:             */
1006:            public Geometry buffer(double distance, int quadrantSegments,
1007:                    int endCapStyle) {
1008:                return BufferOp.bufferOp(this , distance, quadrantSegments,
1009:                        endCapStyle);
1010:            }
1011:
1012:            /**
1013:             *  Computes the smallest convex <code>Polygon</code> that contains all the
1014:             *  points in the <code>Geometry</code>. This obviously applies only to <code>Geometry</code>
1015:             *  s which contain 3 or more points; the results for degenerate cases are
1016:             *  specified as follows:
1017:             *  <TABLE>
1018:             *    <TR>
1019:             *      <TH>    Number of <code>Point</code>s in argument <code>Geometry</code>   </TH>
1020:             *      <TH>    <code>Geometry</code> class of result     </TH>
1021:             *    </TR>
1022:             *    <TR>
1023:             *      <TD>        0      </TD>
1024:             *      <TD>        empty <code>GeometryCollection</code>      </TD>
1025:             *    </TR>
1026:             *    <TR>  <TD>      1     </TD>
1027:             *      <TD>     <code>Point</code>     </TD>
1028:             *    </TR>
1029:             *    <TR>
1030:             *      <TD>      2     </TD>
1031:             *      <TD>     <code>LineString</code>     </TD>
1032:             *    </TR>
1033:             *    <TR>
1034:             *      <TD>       3 or more     </TD>
1035:             *      <TD>      <code>Polygon</code>     </TD>
1036:             *    </TR>
1037:             *  </TABLE>
1038:             *
1039:             *@return    the minimum-area convex polygon containing this <code>Geometry</code>'
1040:             *      s points
1041:             */
1042:            public Geometry convexHull() {
1043:                return (new ConvexHull(this )).getConvexHull();
1044:            }
1045:
1046:            /**
1047:             *  Computes a <code>Geometry</code> representing the points shared by this
1048:             *  <code>Geometry</code> and <code>other</code>.
1049:             *
1050:             * @param  other  the <code>Geometry</code> with which to compute the
1051:             *      intersection
1052:             * @return        the points common to the two <code>Geometry</code>s
1053:             * @throws TopologyException if a robustness error occurs
1054:             * @throws IllegalArgumentException if either input is a non-empty GeometryCollection
1055:             */
1056:            public Geometry intersection(Geometry other) {
1057:                /**
1058:                 * TODO: MD - add optimization for P-A case using Point-In-Polygon
1059:                 */
1060:                // special case: if one input is empty ==> empty
1061:                if (this .isEmpty())
1062:                    return this .getFactory().createGeometryCollection(null);
1063:                if (other.isEmpty())
1064:                    return this .getFactory().createGeometryCollection(null);
1065:
1066:                checkNotGeometryCollection(this );
1067:                checkNotGeometryCollection(other);
1068:                return SnapIfNeededOverlayOp.overlayOp(this , other,
1069:                        OverlayOp.INTERSECTION);
1070:            }
1071:
1072:            /**
1073:             *  Computes a <code>Geometry</code> representing all the points in this <code>Geometry</code>
1074:             *  and <code>other</code>.
1075:             *
1076:             *@param  other  the <code>Geometry</code> with which to compute the union
1077:             *@return        a set combining the points of this <code>Geometry</code> and
1078:             *      the points of <code>other</code>
1079:             * @throws TopologyException if a robustness error occurs
1080:             * @throws IllegalArgumentException if either input is a non-empty GeometryCollection
1081:             */
1082:            public Geometry union(Geometry other) {
1083:                // special case: if either input is empty ==> other input
1084:                if (this .isEmpty())
1085:                    return (Geometry) other.clone();
1086:                if (other.isEmpty())
1087:                    return (Geometry) clone();
1088:
1089:                checkNotGeometryCollection(this );
1090:                checkNotGeometryCollection(other);
1091:                return SnapIfNeededOverlayOp.overlayOp(this , other,
1092:                        OverlayOp.UNION);
1093:            }
1094:
1095:            /**
1096:             *  Computes a <code>Geometry</code> representing the points making up this
1097:             *  <code>Geometry</code> that do not make up <code>other</code>. This method
1098:             *  returns the closure of the resultant <code>Geometry</code>.
1099:             *
1100:             *@param  other  the <code>Geometry</code> with which to compute the
1101:             *      difference
1102:             *@return        the point set difference of this <code>Geometry</code> with
1103:             *      <code>other</code>
1104:             * @throws TopologyException if a robustness error occurs
1105:             * @throws IllegalArgumentException if either input is a non-empty GeometryCollection
1106:             */
1107:            public Geometry difference(Geometry other) {
1108:                // special case: if A.isEmpty ==> empty; if B.isEmpty ==> A
1109:                if (this .isEmpty())
1110:                    return this .getFactory().createGeometryCollection(null);
1111:                if (other.isEmpty())
1112:                    return (Geometry) clone();
1113:
1114:                checkNotGeometryCollection(this );
1115:                checkNotGeometryCollection(other);
1116:                return SnapIfNeededOverlayOp.overlayOp(this , other,
1117:                        OverlayOp.DIFFERENCE);
1118:            }
1119:
1120:            /**
1121:             *  Returns a set combining the points in this <code>Geometry</code> not in
1122:             *  <code>other</code>, and the points in <code>other</code> not in this
1123:             *  <code>Geometry</code>. This method returns the closure of the resultant
1124:             *  <code>Geometry</code>.
1125:             *
1126:             *@param  other  the <code>Geometry</code> with which to compute the symmetric
1127:             *      difference
1128:             *@return        the point set symmetric difference of this <code>Geometry</code>
1129:             *      with <code>other</code>
1130:             * @throws TopologyException if a robustness error occurs
1131:             * @throws IllegalArgumentException if either input is a non-empty GeometryCollection
1132:             */
1133:            public Geometry symDifference(Geometry other) {
1134:                // special case: if either input is empty ==> other input
1135:                if (this .isEmpty())
1136:                    return (Geometry) other.clone();
1137:                if (other.isEmpty())
1138:                    return (Geometry) clone();
1139:
1140:                checkNotGeometryCollection(this );
1141:                checkNotGeometryCollection(other);
1142:                return SnapIfNeededOverlayOp.overlayOp(this , other,
1143:                        OverlayOp.SYMDIFFERENCE);
1144:            }
1145:
1146:            /**
1147:             * Returns true if the two <code>Geometry</code>s are exactly equal,
1148:             * up to a specified distance tolerance.
1149:             * Two Geometries are exactly equal within a distance tolerance
1150:             * if and only if:
1151:             * <ul>
1152:             * <li>they have the same class
1153:             * <li>they have the same values for their vertices,
1154:             * within the given tolerance distance, in exactly the same order.
1155:             * </ul>
1156:             * If this and the other <code>Geometry</code>s are
1157:             * composites and any children are not <code>Geometry</code>s, returns
1158:             * <code>false</code>.
1159:             *
1160:             * @param  other  the <code>Geometry</code> with which to compare this <code>Geometry</code>
1161:             * @parm tolerance distance at or below which two <code>Coordinate</code>s
1162:             *   are considered equal
1163:             * @return <code>true</code> if this and the other <code>Geometry</code>
1164:             *   are of the same class and have equal internal data.
1165:             */
1166:            public abstract boolean equalsExact(Geometry other, double tolerance);
1167:
1168:            /**
1169:             *  Returns true if the two <code>Geometry</code>s are exactly equal.
1170:             * Two Geometries are exactly equal iff:
1171:             * <ul>
1172:             * <li>they have the same class
1173:             * <li>they have the same values of Coordinates in their internal
1174:             * Coordinate lists, in exactly the same order.
1175:             * </ul>
1176:             * If this and the other <code>Geometry</code>s are
1177:             *  composites and any children are not <code>Geometry</code>s, returns
1178:             *  false.
1179:             * <p>
1180:             *  This provides a stricter test of equality than
1181:             *  <code>equals</code>.
1182:             *
1183:             *@param  other  the <code>Geometry</code> with which to compare this <code>Geometry</code>
1184:             *@return        <code>true</code> if this and the other <code>Geometry</code>
1185:             *      are of the same class and have equal internal data.
1186:             */
1187:            public boolean equalsExact(Geometry other) {
1188:                return equalsExact(other, 0);
1189:            }
1190:
1191:            /**
1192:             *  Performs an operation with or on this <code>Geometry</code>'s
1193:             *  coordinates. 
1194:             *  If this method modifies any coordinate values,
1195:             *  #geometryChanged() must be called to update the geometry state. 
1196:             *  Note that you cannot use this
1197:             *  method to
1198:             *  modify this Geometry if its underlying CoordinateSequence's #get method
1199:             *  returns a copy of the Coordinate, rather than the actual Coordinate stored
1200:             *  (if it even stores Coordinates at all).
1201:             *
1202:             *@param  filter  the filter to apply to this <code>Geometry</code>'s
1203:             *      coordinates
1204:             */
1205:            public abstract void apply(CoordinateFilter filter);
1206:
1207:            /**
1208:             *  Performs an operation on the coordinates in this <code>Geometry</code>'s
1209:             *  {@link CoordinateSequence}s. 
1210:             *  If this method modifies any coordinate values,
1211:             *  #geometryChanged() must be called to update the geometry state. 
1212:             *
1213:             *@param  filter  the filter to apply
1214:             */
1215:            public abstract void apply(CoordinateSequenceFilter filter);
1216:
1217:            /**
1218:             *  Performs an operation with or on this <code>Geometry</code> and its
1219:             *  subelement <code>Geometry</code>s (if any).
1220:             *  Only GeometryCollections and subclasses
1221:             *  have subelement Geometry's.
1222:             *
1223:             *@param  filter  the filter to apply to this <code>Geometry</code> (and
1224:             *      its children, if it is a <code>GeometryCollection</code>).
1225:             */
1226:            public abstract void apply(GeometryFilter filter);
1227:
1228:            /**
1229:             *  Performs an operation with or on this Geometry and its
1230:             *  component Geometry's.  Only GeometryCollections and
1231:             *  Polygons have component Geometry's; for Polygons they are the LinearRings
1232:             *  of the shell and holes.
1233:             *
1234:             *@param  filter  the filter to apply to this <code>Geometry</code>.
1235:             */
1236:            public abstract void apply(GeometryComponentFilter filter);
1237:
1238:            /**
1239:             * Creates and returns a full copy of this {@link Geometry} object
1240:             * (including all coordinates contained by it).
1241:             * Subclasses are responsible for overriding this method and copying
1242:             * their internal data.  Overrides should call this method first.
1243:             *
1244:             * @return a clone of this instance
1245:             */
1246:            public Object clone() {
1247:                try {
1248:                    Geometry clone = (Geometry) super .clone();
1249:                    if (clone.envelope != null) {
1250:                        clone.envelope = new Envelope(clone.envelope);
1251:                    }
1252:                    return clone;
1253:                } catch (CloneNotSupportedException e) {
1254:                    Assert.shouldNeverReachHere();
1255:                    return null;
1256:                }
1257:            }
1258:
1259:            /**
1260:             *  Converts this <code>Geometry</code> to <b>normal form</b> (or <b>
1261:             *  canonical form</b> ). Normal form is a unique representation for <code>Geometry</code>
1262:             *  s. It can be used to test whether two <code>Geometry</code>s are equal
1263:             *  in a way that is independent of the ordering of the coordinates within
1264:             *  them. Normal form equality is a stronger condition than topological
1265:             *  equality, but weaker than pointwise equality. The definitions for normal
1266:             *  form use the standard lexicographical ordering for coordinates. "Sorted in
1267:             *  order of coordinates" means the obvious extension of this ordering to
1268:             *  sequences of coordinates.
1269:             */
1270:            public abstract void normalize();
1271:
1272:            /**
1273:             *  Returns whether this <code>Geometry</code> is greater than, equal to,
1274:             *  or less than another <code>Geometry</code>. <P>
1275:             *
1276:             *  If their classes are different, they are compared using the following
1277:             *  ordering:
1278:             *  <UL>
1279:             *    <LI> Point (lowest)
1280:             *    <LI> MultiPoint
1281:             *    <LI> LineString
1282:             *    <LI> LinearRing
1283:             *    <LI> MultiLineString
1284:             *    <LI> Polygon
1285:             *    <LI> MultiPolygon
1286:             *    <LI> GeometryCollection (highest)
1287:             *  </UL>
1288:             *  If the two <code>Geometry</code>s have the same class, their first
1289:             *  elements are compared. If those are the same, the second elements are
1290:             *  compared, etc.
1291:             *
1292:             *@param  o  a <code>Geometry</code> with which to compare this <code>Geometry</code>
1293:             *@return    a positive number, 0, or a negative number, depending on whether
1294:             *      this object is greater than, equal to, or less than <code>o</code>, as
1295:             *      defined in "Normal Form For Geometry" in the JTS Technical
1296:             *      Specifications
1297:             */
1298:            public int compareTo(Object o) {
1299:                Geometry other = (Geometry) o;
1300:                if (getClassSortIndex() != other.getClassSortIndex()) {
1301:                    return getClassSortIndex() - other.getClassSortIndex();
1302:                }
1303:                if (isEmpty() && other.isEmpty()) {
1304:                    return 0;
1305:                }
1306:                if (isEmpty()) {
1307:                    return -1;
1308:                }
1309:                if (other.isEmpty()) {
1310:                    return 1;
1311:                }
1312:                return compareToSameClass(o);
1313:            }
1314:
1315:            /**
1316:             *  Returns whether this <code>Geometry</code> is greater than, equal to,
1317:             *  or less than another <code>Geometry</code>,
1318:             * using the given {@link CoordinateSequenceComparator}.
1319:             * <P>
1320:             *
1321:             *  If their classes are different, they are compared using the following
1322:             *  ordering:
1323:             *  <UL>
1324:             *    <LI> Point (lowest)
1325:             *    <LI> MultiPoint
1326:             *    <LI> LineString
1327:             *    <LI> LinearRing
1328:             *    <LI> MultiLineString
1329:             *    <LI> Polygon
1330:             *    <LI> MultiPolygon
1331:             *    <LI> GeometryCollection (highest)
1332:             *  </UL>
1333:             *  If the two <code>Geometry</code>s have the same class, their first
1334:             *  elements are compared. If those are the same, the second elements are
1335:             *  compared, etc.
1336:             *
1337:             *@param  o  a <code>Geometry</code> with which to compare this <code>Geometry</code>
1338:             *@param comp a <code>CoordinateSequenceComparator</code>
1339:             *
1340:             *@return    a positive number, 0, or a negative number, depending on whether
1341:             *      this object is greater than, equal to, or less than <code>o</code>, as
1342:             *      defined in "Normal Form For Geometry" in the JTS Technical
1343:             *      Specifications
1344:             */
1345:            public int compareTo(Object o, CoordinateSequenceComparator comp) {
1346:                Geometry other = (Geometry) o;
1347:                if (getClassSortIndex() != other.getClassSortIndex()) {
1348:                    return getClassSortIndex() - other.getClassSortIndex();
1349:                }
1350:                if (isEmpty() && other.isEmpty()) {
1351:                    return 0;
1352:                }
1353:                if (isEmpty()) {
1354:                    return -1;
1355:                }
1356:                if (other.isEmpty()) {
1357:                    return 1;
1358:                }
1359:                return compareToSameClass(o, comp);
1360:            }
1361:
1362:            /**
1363:             *  Returns whether the two <code>Geometry</code>s are equal, from the point
1364:             *  of view of the <code>equalsExact</code> method. Called by <code>equalsExact</code>
1365:             *  . In general, two <code>Geometry</code> classes are considered to be
1366:             *  "equivalent" only if they are the same class. An exception is <code>LineString</code>
1367:             *  , which is considered to be equivalent to its subclasses.
1368:             *
1369:             *@param  other  the <code>Geometry</code> with which to compare this <code>Geometry</code>
1370:             *      for equality
1371:             *@return        <code>true</code> if the classes of the two <code>Geometry</code>
1372:             *      s are considered to be equal by the <code>equalsExact</code> method.
1373:             */
1374:            protected boolean isEquivalentClass(Geometry other) {
1375:                return this .getClass().getName().equals(
1376:                        other.getClass().getName());
1377:            }
1378:
1379:            /**
1380:             *  Throws an exception if <code>g</code>'s class is <code>GeometryCollection</code>
1381:             *  . (Its subclasses do not trigger an exception).
1382:             *
1383:             *@param  g                          the <code>Geometry</code> to check
1384:             *@throws  IllegalArgumentException  if <code>g</code> is a <code>GeometryCollection</code>
1385:             *      but not one of its subclasses
1386:             */
1387:            protected void checkNotGeometryCollection(Geometry g) {
1388:                //Don't use instanceof because we want to allow subclasses
1389:                if (g.getClass().getName().equals(
1390:                        "com.vividsolutions.jts.geom.GeometryCollection")) {
1391:                    throw new IllegalArgumentException(
1392:                            "This method does not support GeometryCollection arguments");
1393:                }
1394:            }
1395:
1396:            /**
1397:             *  Returns the minimum and maximum x and y values in this <code>Geometry</code>
1398:             *  , or a null <code>Envelope</code> if this <code>Geometry</code> is empty.
1399:             *  Unlike <code>getEnvelopeInternal</code>, this method calculates the <code>Envelope</code>
1400:             *  each time it is called; <code>getEnvelopeInternal</code> caches the result
1401:             *  of this method.
1402:             *
1403:             *@return    this <code>Geometry</code>s bounding box; if the <code>Geometry</code>
1404:             *      is empty, <code>Envelope#isNull</code> will return <code>true</code>
1405:             */
1406:            protected abstract Envelope computeEnvelopeInternal();
1407:
1408:            /**
1409:             *  Returns whether this <code>Geometry</code> is greater than, equal to,
1410:             *  or less than another <code>Geometry</code> having the same class.
1411:             *
1412:             *@param  o  a <code>Geometry</code> having the same class as this <code>Geometry</code>
1413:             *@return    a positive number, 0, or a negative number, depending on whether
1414:             *      this object is greater than, equal to, or less than <code>o</code>, as
1415:             *      defined in "Normal Form For Geometry" in the JTS Technical
1416:             *      Specifications
1417:             */
1418:            protected abstract int compareToSameClass(Object o);
1419:
1420:            /**
1421:             *  Returns whether this <code>Geometry</code> is greater than, equal to,
1422:             *  or less than another <code>Geometry</code> of the same class.
1423:             * using the given {@link CoordinateSequenceComparator}.
1424:             *
1425:             *@param  o  a <code>Geometry</code> having the same class as this <code>Geometry</code>
1426:             *@param comp a <code>CoordinateSequenceComparator</code>
1427:             *@return    a positive number, 0, or a negative number, depending on whether
1428:             *      this object is greater than, equal to, or less than <code>o</code>, as
1429:             *      defined in "Normal Form For Geometry" in the JTS Technical
1430:             *      Specifications
1431:             */
1432:            protected abstract int compareToSameClass(Object o,
1433:                    CoordinateSequenceComparator comp);
1434:
1435:            /**
1436:             *  Returns the first non-zero result of <code>compareTo</code> encountered as
1437:             *  the two <code>Collection</code>s are iterated over. If, by the time one of
1438:             *  the iterations is complete, no non-zero result has been encountered,
1439:             *  returns 0 if the other iteration is also complete. If <code>b</code>
1440:             *  completes before <code>a</code>, a positive number is returned; if a
1441:             *  before b, a negative number.
1442:             *
1443:             *@param  a  a <code>Collection</code> of <code>Comparable</code>s
1444:             *@param  b  a <code>Collection</code> of <code>Comparable</code>s
1445:             *@return    the first non-zero <code>compareTo</code> result, if any;
1446:             *      otherwise, zero
1447:             */
1448:            protected int compare(Collection a, Collection b) {
1449:                Iterator i = a.iterator();
1450:                Iterator j = b.iterator();
1451:                while (i.hasNext() && j.hasNext()) {
1452:                    Comparable aElement = (Comparable) i.next();
1453:                    Comparable bElement = (Comparable) j.next();
1454:                    int comparison = aElement.compareTo(bElement);
1455:                    if (comparison != 0) {
1456:                        return comparison;
1457:                    }
1458:                }
1459:                if (i.hasNext()) {
1460:                    return 1;
1461:                }
1462:                if (j.hasNext()) {
1463:                    return -1;
1464:                }
1465:                return 0;
1466:            }
1467:
1468:            protected boolean equal(Coordinate a, Coordinate b, double tolerance) {
1469:                if (tolerance == 0) {
1470:                    return a.equals(b);
1471:                }
1472:                return a.distance(b) <= tolerance;
1473:            }
1474:
1475:            private int getClassSortIndex() {
1476:                for (int i = 0; i < sortedClasses.length; i++) {
1477:                    if (sortedClasses[i].isInstance(this )) {
1478:                        return i;
1479:                    }
1480:                }
1481:                Assert.shouldNeverReachHere("Class not supported: "
1482:                        + this .getClass());
1483:                return -1;
1484:            }
1485:
1486:            private Point createPointFromInternalCoord(Coordinate coord,
1487:                    Geometry exemplar) {
1488:                exemplar.getPrecisionModel().makePrecise(coord);
1489:                return exemplar.getFactory().createPoint(coord);
1490:            }
1491:
1492:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.