Class GeometryCollectionIterator

  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.Iterator;
 17 import java.util.NoSuchElementException;
 18  
 19 /**
 20  *  Iterates over all {@link Geometry}s in a {@link Geometry},
 21  *  (which may be either a collection or an atomic geometry).
 22  *  The iteration sequence follows a pre-order, depth-first traversal of the 
 23  *  structure of the <code>GeometryCollection</code>
 24  *  (which may be nested). The original <code>Geometry</code> object is
 25  *  returned as well (as the first object), as are all sub-collections and atomic elements. 
 26  *  It is  simple to ignore the intermediate <code>GeometryCollection</code> objects if they are not
 27  *  needed.
 28  *
 29  *@version 1.7
 30  */
 31 public class GeometryCollectionIterator implements Iterator {
 32  
 33   /**
 34    *  The <code>Geometry</code> being iterated over.
 35    */
 36   private Geometry parent;
 37   /**
 38    *  Indicates whether or not the first element 
 39    *  (the root <code>GeometryCollection</code>) has been returned.
 40    */
 41   private boolean atStart;
 42   /**
 43    *  The number of <code>Geometry</code>s in the the <code>GeometryCollection</code>.
 44    */
 45   private int max;
 46   /**
 47    *  The index of the <code>Geometry</code> that will be returned when <code>next</code>
 48    *  is called.
 49    */
 50   private int index;
 51   /**
 52    *  The iterator over a nested <code>Geometry</code>, or <code>null</code>
 53    *  if this <code>GeometryCollectionIterator</code> is not currently iterating
 54    *  over a nested <code>GeometryCollection</code>.
 55    */
 56   private GeometryCollectionIterator subcollectionIterator;
 57  
 58   /**
 59    *  Constructs an iterator over the given <code>Geometry</code>.
 60    *
 61    *@param  parent  the geometry over which to iterate; also, the first
 62    *      element returned by the iterator.
 63    */
 64   public GeometryCollectionIterator(Geometry parent) {
 65     this.parent = parent;
 66     atStart = true;
 67     index = 0;
 68     max = parent.getNumGeometries();
 69   }
 70  
 71   /**
 72    * Tests whether any geometry elements remain to be returned.
 73    * 
 74    * @return true if more geometry elements remain
 75    */
 76   public boolean hasNext() {
 77     if (atStart) {
 78       return true;
 79     }
 80     if (subcollectionIterator != null) {
 81       if (subcollectionIterator.hasNext()) {
 82         return true;
 83       }
 84       subcollectionIterator = null;
 85     }
 86     if (index >= max) {
 87       return false;
 88     }
 89     return true;
 90   }
 91  
 92   /**
 93    * Gets the next geometry in the iteration sequence.
 94    * 
 95    * @return the next geometry in the iteration
 96    */
 97   public Object next() {
 98     // the parent GeometryCollection is the first object returned
 99     if (atStart) {
100       atStart = false;
101       if (isAtomic(parent))
102         index++;
103       return parent;
104     }
105     if (subcollectionIterator != null) {
106       if (subcollectionIterator.hasNext()) {
107         return subcollectionIterator.next();
108       }
109       else {
110         subcollectionIterator = null;
111       }
112     }
113     if (index >= max) {
114       throw new NoSuchElementException();
115     }
116     Geometry obj = parent.getGeometryN(index++);
117     if (obj instanceof GeometryCollection) {
118       subcollectionIterator = new GeometryCollectionIterator((GeometryCollection) obj);
119       // there will always be at least one element in the sub-collection
120       return subcollectionIterator.next();
121     }
122     return obj;
123   }
124  
125   private static boolean isAtomic(Geometry geom)
126   {
127     return ! (geom instanceof GeometryCollection);
128   }
129   
130   /**
131    * Removal is not supported.
132    *
133    * @throws  UnsupportedOperationException  This method is not implemented.
134    */
135   public void remove() {
136     throw new UnsupportedOperationException(getClass().getName());
137   }
138 }
139  
140