001:
002: /*
003: * The JTS Topology Suite is a collection of Java classes that
004: * implement the fundamental operations required to validate a given
005: * geo-spatial data set to a known topological specification.
006: *
007: * Copyright (C) 2001 Vivid Solutions
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: *
023: * For more information, contact:
024: *
025: * Vivid Solutions
026: * Suite #1A
027: * 2328 Government Street
028: * Victoria BC V8T 5G5
029: * Canada
030: *
031: * (250)385-6040
032: * www.vividsolutions.com
033: */
034: package com.vividsolutions.jts.geom;
035:
036: import java.util.Arrays;
037: import java.util.TreeSet;
038:
039: import com.vividsolutions.jts.util.Assert;
040:
041: /**
042: * Basic implementation of <code>GeometryCollection</code>.
043: *
044: *@version 1.7
045: */
046: public class GeometryCollection extends Geometry {
047: // With contributions from Markus Schaber [schabios@logi-track.com] 2004-03-26
048: private static final long serialVersionUID = -5694727726395021467L;
049: /**
050: * Internal representation of this <code>GeometryCollection</code>.
051: */
052: protected Geometry[] geometries;
053:
054: /** @deprecated Use GeometryFactory instead */
055: public GeometryCollection(Geometry[] geometries,
056: PrecisionModel precisionModel, int SRID) {
057: this (geometries, new GeometryFactory(precisionModel, SRID));
058: }
059:
060: /**
061: * @param geometries
062: * the <code>Geometry</code>s for this <code>GeometryCollection</code>,
063: * or <code>null</code> or an empty array to create the empty
064: * geometry. Elements may be empty <code>Geometry</code>s,
065: * but not <code>null</code>s.
066: */
067: public GeometryCollection(Geometry[] geometries,
068: GeometryFactory factory) {
069: super (factory);
070: if (geometries == null) {
071: geometries = new Geometry[] {};
072: }
073: if (hasNullElements(geometries)) {
074: throw new IllegalArgumentException(
075: "geometries must not contain null elements");
076: }
077: this .geometries = geometries;
078: }
079:
080: public Coordinate getCoordinate() {
081: if (isEmpty())
082: return null;
083: return geometries[0].getCoordinate();
084: }
085:
086: /**
087: * Collects all coordinates of all subgeometries into an Array.
088: *
089: * Note that while changes to the coordinate objects themselves
090: * may modify the Geometries in place, the returned Array as such
091: * is only a temporary container which is not synchronized back.
092: *
093: * @return the collected coordinates
094: * */
095: public Coordinate[] getCoordinates() {
096: Coordinate[] coordinates = new Coordinate[getNumPoints()];
097: int k = -1;
098: for (int i = 0; i < geometries.length; i++) {
099: Coordinate[] childCoordinates = geometries[i]
100: .getCoordinates();
101: for (int j = 0; j < childCoordinates.length; j++) {
102: k++;
103: coordinates[k] = childCoordinates[j];
104: }
105: }
106: return coordinates;
107: }
108:
109: public boolean isEmpty() {
110: for (int i = 0; i < geometries.length; i++) {
111: if (!geometries[i].isEmpty()) {
112: return false;
113: }
114: }
115: return true;
116: }
117:
118: public int getDimension() {
119: int dimension = Dimension.FALSE;
120: for (int i = 0; i < geometries.length; i++) {
121: dimension = Math.max(dimension, geometries[i]
122: .getDimension());
123: }
124: return dimension;
125: }
126:
127: public int getBoundaryDimension() {
128: int dimension = Dimension.FALSE;
129: for (int i = 0; i < geometries.length; i++) {
130: dimension = Math.max(dimension, ((Geometry) geometries[i])
131: .getBoundaryDimension());
132: }
133: return dimension;
134: }
135:
136: public int getNumGeometries() {
137: return geometries.length;
138: }
139:
140: public Geometry getGeometryN(int n) {
141: return geometries[n];
142: }
143:
144: public int getNumPoints() {
145: int numPoints = 0;
146: for (int i = 0; i < geometries.length; i++) {
147: numPoints += ((Geometry) geometries[i]).getNumPoints();
148: }
149: return numPoints;
150: }
151:
152: public String getGeometryType() {
153: return "GeometryCollection";
154: }
155:
156: public Geometry getBoundary() {
157: checkNotGeometryCollection(this );
158: Assert.shouldNeverReachHere();
159: return null;
160: }
161:
162: /**
163: * Returns the area of this <code>GeometryCollection</code>
164: *
165: * @return the area of the polygon
166: */
167: public double getArea() {
168: double area = 0.0;
169: for (int i = 0; i < geometries.length; i++) {
170: area += geometries[i].getArea();
171: }
172: return area;
173: }
174:
175: public double getLength() {
176: double sum = 0.0;
177: for (int i = 0; i < geometries.length; i++) {
178: sum += (geometries[i]).getLength();
179: }
180: return sum;
181: }
182:
183: public boolean equalsExact(Geometry other, double tolerance) {
184: if (!isEquivalentClass(other)) {
185: return false;
186: }
187: GeometryCollection otherCollection = (GeometryCollection) other;
188: if (geometries.length != otherCollection.geometries.length) {
189: return false;
190: }
191: for (int i = 0; i < geometries.length; i++) {
192: if (!((Geometry) geometries[i]).equalsExact(
193: otherCollection.geometries[i], tolerance)) {
194: return false;
195: }
196: }
197: return true;
198: }
199:
200: public void apply(CoordinateFilter filter) {
201: for (int i = 0; i < geometries.length; i++) {
202: geometries[i].apply(filter);
203: }
204: }
205:
206: public void apply(CoordinateSequenceFilter filter) {
207: if (geometries.length == 0)
208: return;
209: for (int i = 0; i < geometries.length; i++) {
210: geometries[i].apply(filter);
211: if (filter.isDone()) {
212: break;
213: }
214: }
215: if (filter.isGeometryChanged())
216: geometryChanged();
217: }
218:
219: public void apply(GeometryFilter filter) {
220: filter.filter(this );
221: for (int i = 0; i < geometries.length; i++) {
222: geometries[i].apply(filter);
223: }
224: }
225:
226: public void apply(GeometryComponentFilter filter) {
227: filter.filter(this );
228: for (int i = 0; i < geometries.length; i++) {
229: geometries[i].apply(filter);
230: }
231: }
232:
233: /**
234: * Creates and returns a full copy of this {@link GeometryCollection} object.
235: * (including all coordinates contained by it).
236: *
237: * @return a clone of this instance
238: */
239: public Object clone() {
240: GeometryCollection gc = (GeometryCollection) super .clone();
241: gc.geometries = new Geometry[geometries.length];
242: for (int i = 0; i < geometries.length; i++) {
243: gc.geometries[i] = (Geometry) geometries[i].clone();
244: }
245: return gc;// return the clone
246: }
247:
248: public void normalize() {
249: for (int i = 0; i < geometries.length; i++) {
250: geometries[i].normalize();
251: }
252: Arrays.sort(geometries);
253: }
254:
255: protected Envelope computeEnvelopeInternal() {
256: Envelope envelope = new Envelope();
257: for (int i = 0; i < geometries.length; i++) {
258: envelope.expandToInclude(geometries[i]
259: .getEnvelopeInternal());
260: }
261: return envelope;
262: }
263:
264: protected int compareToSameClass(Object o) {
265: TreeSet theseElements = new TreeSet(Arrays.asList(geometries));
266: TreeSet otherElements = new TreeSet(Arrays
267: .asList(((GeometryCollection) o).geometries));
268: return compare(theseElements, otherElements);
269: }
270:
271: protected int compareToSameClass(Object o,
272: CoordinateSequenceComparator comp) {
273: GeometryCollection gc = (GeometryCollection) o;
274:
275: int n1 = getNumGeometries();
276: int n2 = gc.getNumGeometries();
277: int i = 0;
278: while (i < n1 && i < n2) {
279: Geometry this Geom = getGeometryN(i);
280: Geometry otherGeom = gc.getGeometryN(i);
281: int holeComp = this Geom.compareToSameClass(otherGeom, comp);
282: if (holeComp != 0)
283: return holeComp;
284: i++;
285: }
286: if (i < n1)
287: return 1;
288: if (i < n2)
289: return -1;
290: return 0;
291:
292: }
293: }
|