Class GeometryCollection

  1  
  2  
  3 /*
  4  * Copyright (c) 2016 Vivid Solutions.
  5  *
  6  * All rights reserved. This program and the accompanying materials
  7  * are made available under the terms of the Eclipse Public License 2.0
  8  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  9  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
 10  * and the Eclipse Distribution License is available at
 11  *
 12  * http://www.eclipse.org/org/documents/edl-v10.php.
 13  */
 14 package org.locationtech.jts.geom;
 15  
 16 import java.util.ArrayList;
 17 import java.util.Arrays;
 18 import java.util.Collection;
 19 import java.util.TreeSet;
 20  
 21 import org.locationtech.jts.util.Assert;
 22  
 23  
 24 /**
 25  * Models a collection of {@link Geometry}s of
 26  * arbitrary type and dimension.
 27  *
 28  *
 29  *@version 1.7
 30  */
 31 public class GeometryCollection extends Geometry {
 32 //  With contributions from Markus Schaber [schabios@logi-track.com] 2004-03-26
 33   private static final long serialVersionUID = -5694727726395021467L;
 34   /**
 35    *  Internal representation of this <code>GeometryCollection</code>.
 36    */
 37   protected Geometry[] geometries;
 38  
 39   /** @deprecated Use GeometryFactory instead */
 40   public GeometryCollection(Geometry[] geometries, PrecisionModel precisionModel, int SRID) {
 41       this(geometries, new GeometryFactory(precisionModel, SRID));
 42   }
 43  
 44  
 45   /**
 46    * @param geometries
 47    *            the <code>Geometry</code>s for this <code>GeometryCollection</code>,
 48    *            or <code>null</code> or an empty array to create the empty
 49    *            geometry. Elements may be empty <code>Geometry</code>s,
 50    *            but not <code>null</code>s.
 51    */
 52   public GeometryCollection(Geometry[] geometries, GeometryFactory factory) {
 53     super(factory);
 54     if (geometries == null) {
 55       geometries = new Geometry[]{};
 56     }
 57     if (hasNullElements(geometries)) {
 58       throw new IllegalArgumentException("geometries must not contain null elements");
 59     }
 60     this.geometries = geometries;
 61   }
 62  
 63   public Coordinate getCoordinate() {
 64     if (isEmpty()) return null;
 65     return geometries[0].getCoordinate();
 66   }
 67  
 68   /**
 69    * Collects all coordinates of all subgeometries into an Array.
 70    *
 71    * Note that while changes to the coordinate objects themselves
 72    * may modify the Geometries in place, the returned Array as such
 73    * is only a temporary container which is not synchronized back.
 74    *
 75    * @return the collected coordinates
 76    *    */
 77   public Coordinate[] getCoordinates() {
 78     Coordinate[] coordinates = new Coordinate[getNumPoints()];
 79     int k = -1;
 80     for (int i = 0; i < geometries.length; i++) {
 81       Coordinate[] childCoordinates = geometries[i].getCoordinates();
 82       for (int j = 0; j < childCoordinates.length; j++) {
 83         k++;
 84         coordinates[k] = childCoordinates[j];
 85       }
 86     }
 87     return coordinates;
 88   }
 89  
 90   public boolean isEmpty() {
 91     for (int i = 0; i < geometries.length; i++) {
 92       if (!geometries[i].isEmpty()) {
 93         return false;
 94       }
 95     }
 96     return true;
 97   }
 98  
 99   public int getDimension() {
100     int dimension = Dimension.FALSE;
101     for (int i = 0; i < geometries.length; i++) {
102       dimension = Math.max(dimension, geometries[i].getDimension());
103     }
104     return dimension;
105   }
106  
107   public int getBoundaryDimension() {
108     int dimension = Dimension.FALSE;
109     for (int i = 0; i < geometries.length; i++) {
110       dimension = Math.max(dimension, ((Geometry) geometries[i]).getBoundaryDimension());
111     }
112     return dimension;
113   }
114  
115   public int getNumGeometries() {
116     return geometries.length;
117   }
118  
119   public Geometry getGeometryN(int n) {
120     return geometries[n];
121   }
122  
123   public int getNumPoints() {
124     int numPoints = 0;
125     for (int i = 0; i < geometries.length; i++) {
126       numPoints += ((Geometry) geometries[i]).getNumPoints();
127     }
128     return numPoints;
129   }
130  
131   public String getGeometryType() {
132     return Geometry.TYPENAME_GEOMETRYCOLLECTION;
133   }
134  
135   public Geometry getBoundary() {
136     checkNotGeometryCollection(this);
137     Assert.shouldNeverReachHere();
138     return null;
139   }
140  
141   /**
142    *  Returns the area of this <code>GeometryCollection</code>
143    *
144    * @return the area of the polygon
145    */
146   public double getArea()
147   {
148     double area = 0.0;
149     for (int i = 0; i < geometries.length; i++) {
150       area += geometries[i].getArea();
151     }
152     return area;
153   }
154  
155   public double getLength()
156   {
157     double sum = 0.0;
158     for (int i = 0; i < geometries.length; i++) {
159       sum += (geometries[i]).getLength();
160     }
161     return sum;
162   }
163  
164   public boolean equalsExact(Geometry other, double tolerance) {
165     if (!isEquivalentClass(other)) {
166       return false;
167     }
168     GeometryCollection otherCollection = (GeometryCollection) other;
169     if (geometries.length != otherCollection.geometries.length) {
170       return false;
171     }
172     for (int i = 0; i < geometries.length; i++) {
173       if (!((Geometry) geometries[i]).equalsExact(otherCollection.geometries[i], tolerance)) {
174         return false;
175       }
176     }
177     return true;
178   }
179  
180   public void apply(CoordinateFilter filter) {
181         for (int i = 0; i < geometries.length; i++) {
182           geometries[i].apply(filter);
183         }
184       }
185  
186   public void apply(CoordinateSequenceFilter filter) {
187     if (geometries.length == 0)
188       return;
189     for (int i = 0; i < geometries.length; i++) {
190       geometries[i].apply(filter);
191       if (filter.isDone()) {
192         break;
193       }
194     }
195     if (filter.isGeometryChanged())
196       geometryChanged();
197   }
198  
199   public void apply(GeometryFilter filter) {
200     filter.filter(this);
201     for (int i = 0; i < geometries.length; i++) {
202       geometries[i].apply(filter);
203     }
204   }
205  
206   public void apply(GeometryComponentFilter filter) {
207     filter.filter(this);
208     for (int i = 0; i < geometries.length; i++) {
209       geometries[i].apply(filter);
210     }
211   }
212  
213   /**
214    * Creates and returns a full copy of this {@link GeometryCollection} object.
215    * (including all coordinates contained by it).
216    *
217    * @return a clone of this instance
218    * @deprecated
219    */
220   public Object clone() {
221     return copy();
222   }
223  
224   protected GeometryCollection copyInternal() {
225     Geometry[] geometries = new Geometry[this.geometries.length];
226     for (int i = 0; i < geometries.length; i++) {
227       geometries[i] = this.geometries[i].copy();
228     }
229     return new GeometryCollection(geometries, factory);
230   }
231  
232   public void normalize() {
233     for (int i = 0; i < geometries.length; i++) {
234       geometries[i].normalize();
235     }
236     Arrays.sort(geometries);
237   }
238  
239   protected Envelope computeEnvelopeInternal() {
240     Envelope envelope = new Envelope();
241     for (int i = 0; i < geometries.length; i++) {
242       envelope.expandToInclude(geometries[i].getEnvelopeInternal());
243     }
244     return envelope;
245   }
246  
247   protected int compareToSameClass(Object o) {
248     TreeSet theseElements = new TreeSet(Arrays.asList(geometries));
249     TreeSet otherElements = new TreeSet(Arrays.asList(((GeometryCollection) o).geometries));
250     return compare(theseElements, otherElements);
251   }
252  
253   protected int compareToSameClass(Object o, CoordinateSequenceComparator comp) {
254     GeometryCollection gc = (GeometryCollection) o;
255  
256     int n1 = getNumGeometries();
257     int n2 = gc.getNumGeometries();
258     int i = 0;
259     while (i < n1 && i < n2) {
260       Geometry thisGeom = getGeometryN(i);
261       Geometry otherGeom = gc.getGeometryN(i);
262       int holeComp = thisGeom.compareToSameClass(otherGeom, comp);
263       if (holeComp != 0return holeComp;
264       i++;
265     }
266     if (i < n1) return 1;
267     if (i < n2) return -1;
268     return 0;
269  
270   }
271   
272   protected int getTypeCode() {
273     return Geometry.TYPECODE_GEOMETRYCOLLECTION;
274   }
275  
276   /**
277    * Creates a {@link GeometryCollection} with
278    * every component reversed.
279    * The order of the components in the collection are not reversed.
280    *
281    * @return a {@link GeometryCollection} in the reverse order
282    */
283   public GeometryCollection reverse() {
284     return (GeometryCollection) super.reverse();
285   }
286  
287   protected GeometryCollection reverseInternal()
288   {
289     int numGeometries = geometries.length;
290     Collection<Geometry> reversed = new ArrayList<>(numGeometries);
291     for (int i = 0; i < numGeometries; i++) {
292       reversed.add(geometries[i].reverse());
293     }
294     return (GeometryCollection) getFactory().buildGeometry(reversed);
295   }
296 }
297  
298