Class InputExtracter

  1 /*
  2  * Copyright (c) 2019 Martin Davis.
  3  *
  4  * All rights reserved. This program and the accompanying materials
  5  * are made available under the terms of the Eclipse Public License 2.0
  6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  8  * and the Eclipse Distribution License is available at
  9  *
 10  * http://www.eclipse.org/org/documents/edl-v10.php.
 11  */
 12 package org.locationtech.jts.operation.union;
 13  
 14 import java.util.ArrayList;
 15 import java.util.Collection;
 16 import java.util.List;
 17  
 18 import org.locationtech.jts.geom.Dimension;
 19 import org.locationtech.jts.geom.Geometry;
 20 import org.locationtech.jts.geom.GeometryCollection;
 21 import org.locationtech.jts.geom.GeometryFactory;
 22 import org.locationtech.jts.geom.GeometryFilter;
 23 import org.locationtech.jts.geom.LineString;
 24 import org.locationtech.jts.geom.Point;
 25 import org.locationtech.jts.geom.Polygon;
 26 import org.locationtech.jts.util.Assert;
 27  
 28  
 29 /**
 30  * Extracts atomic elements from 
 31  * input geometries or collections, 
 32  * recording the dimension found.
 33  * Empty geometries are discarded since they 
 34  * do not contribute to the result of {@link UnaryUnionOp}.
 35  * 
 36  * @author Martin Davis
 37  *
 38  */
 39 class InputExtracter implements GeometryFilter 
 40 {
 41   /**
 42    * Extracts elements from a collection of geometries.
 43    * 
 44    * @param geoms a collection of geometries
 45    * @return an extracter over the geometries
 46    */
 47   public static InputExtracter extract(Collection<Geometry> geoms) {
 48     InputExtracter extracter = new InputExtracter();
 49     extracter.add(geoms);
 50     return extracter;
 51   }
 52   
 53   /**
 54    * Extracts elements from a geometry.
 55    * 
 56    * @param geoms a geometry to extract from
 57    * @return an extracter over the geometry
 58    */
 59   public static InputExtracter extract(Geometry geom) {
 60     InputExtracter extracter = new InputExtracter();
 61     extracter.add(geom);
 62     return extracter;
 63   }
 64   
 65   private GeometryFactory geomFactory = null;
 66   private List<Polygon> polygons = new ArrayList<Polygon>();
 67   private List<LineString> lines = new ArrayList<LineString>();
 68   private List<Point> points = new ArrayList<Point>();
 69   
 70   /**
 71    * The default dimension for an empty GeometryCollection
 72    */
 73   private int dimension = Dimension.FALSE;
 74   
 75   public InputExtracter() {
 76     
 77   }
 78   
 79   /**
 80    * Tests whether there were any non-empty geometries extracted.
 81    * 
 82    * @return true if there is a non-empty geometry present
 83    */
 84   public boolean isEmpty() {
 85     return polygons.isEmpty() 
 86         && lines.isEmpty()
 87         && points.isEmpty();
 88   }
 89   
 90   /**
 91    * Gets the maximum dimension extracted.
 92    * 
 93    * @return the maximum extracted dimension
 94    */
 95   public int getDimension() {
 96     return dimension;
 97   }
 98   
 99   /**
100    * Gets the geometry factory from the extracted geometry,
101    * if there is one.
102    * If an empty collection was extracted, will return <code>null</code>.
103    * 
104    * @return a geometry factory, or null if one could not be determined
105    */
106   public GeometryFactory getFactory() {
107     return geomFactory;
108   }
109   
110   /**
111    * Gets the extracted atomic geometries of the given dimension <code>dim</code>.
112    * 
113    * @param dim the dimension of geometry to return
114    * @return a list of the extracted geometries of dimension dim.
115    */
116   public List getExtract(int dim) {
117     switch (dim) {
118     case 0return points;
119     case 1return lines;
120     case 2return polygons;
121     }
122     Assert.shouldNeverReachHere("Invalid dimension: "  + dim);
123     return null;
124   }
125   
126   private void add(Collection<Geometry> geoms) {
127     for (Geometry geom : geoms) {
128       add(geom);
129     }
130   }
131   
132   private void add(Geometry geom) {
133     if (geomFactory == null)
134       geomFactory = geom.getFactory();
135     
136     geom.apply(this);
137   }
138  
139   @Override
140   public void filter(Geometry geom) {
141     recordDimension( geom.getDimension() );
142     
143     if (geom instanceof GeometryCollection) {
144       return;
145     }
146     /**
147      * Don't keep empty geometries
148      */
149     if (geom.isEmpty()) 
150       return;
151     
152     if (geom instanceof Polygon) {
153       polygons.add((Polygon) geom);
154       return;
155     }
156     else if (geom instanceof LineString) {
157       lines.add((LineString) geom);
158       return;
159     }
160     else if (geom instanceof Point) {
161       points.add((Point) geom);
162       return;
163     }
164     Assert.shouldNeverReachHere("Unhandled geometry type: " + geom.getGeometryType());
165   }
166  
167   private void recordDimension(int dim) {
168     if (dim > dimension )
169       dimension = dim;
170   }
171 }
172