Class ShapeCollectionPathIterator

  1 /*
  2  * Copyright (c) 2016 Vivid Solutions.
  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.awt;
 13  
 14 import java.awt.Shape;
 15 import java.awt.geom.AffineTransform;
 16 import java.awt.geom.PathIterator;
 17 import java.util.Collection;
 18 import java.util.Iterator;
 19  
 20 /**
 21  * A {@link PathIterator} which provides paths for a collection of {@link Shape}s. 
 22  * 
 23  * @author Martin Davis
 24  */
 25 public class ShapeCollectionPathIterator implements PathIterator {
 26     private Iterator shapeIterator;
 27     
 28     // initialize with a no-op iterator
 29     private PathIterator currentPathIterator = new PathIterator() {
 30             public int getWindingRule() {
 31                 throw new UnsupportedOperationException();
 32             }
 33  
 34             public boolean isDone() {
 35                 return true;
 36             }
 37  
 38             public void next() {
 39             }
 40  
 41             public int currentSegment(float[] coords) {
 42                 throw new UnsupportedOperationException();
 43             }
 44  
 45             public int currentSegment(double[] coords) {
 46                 throw new UnsupportedOperationException();
 47             }
 48         };
 49  
 50     private AffineTransform affineTransform;
 51     private boolean done = false;
 52  
 53     /**
 54      * Creates a new path iterator for a collection of {@link Shape}s.
 55      * 
 56      * @param shapes the Shapes in the collection
 57      * @param affineTransform a optional transformation to be applied to the coordinates in the path (may be null)
 58      */
 59     public ShapeCollectionPathIterator(Collection shapes,
 60         AffineTransform affineTransform) {
 61         shapeIterator = shapes.iterator();
 62         this.affineTransform = affineTransform;
 63         next();
 64     }
 65  
 66     public int getWindingRule() {
 67         /**
 68        * WIND_NON_ZERO is more accurate than WIND_EVEN_ODD, and can be comparable
 69        * in speed. (See http://www.geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm#Winding%20Number)
 70        * However, WIND_NON_ZERO requires that the
 71        * shell and holes be oriented in a certain way.
 72        * So use WIND_EVEN_ODD. 
 73           */
 74       return PathIterator.WIND_EVEN_ODD;
 75     }
 76  
 77     public boolean isDone() {
 78         return done;
 79     }
 80  
 81     public void next() {
 82         currentPathIterator.next();
 83  
 84         if (currentPathIterator.isDone() && !shapeIterator.hasNext()) {
 85             done = true;
 86             return;
 87         }
 88         if (currentPathIterator.isDone()) {
 89             currentPathIterator = ((Shape) shapeIterator.next()).getPathIterator(affineTransform);
 90         }
 91     }
 92  
 93     public int currentSegment(float[] coords) {
 94         return currentPathIterator.currentSegment(coords);
 95     }
 96  
 97     public int currentSegment(double[] coords) {
 98         return currentPathIterator.currentSegment(coords);
 99     }
100 }
101