/* * OrbisGIS is a GIS application dedicated to scientific spatial simulation. * This cross-platform GIS is developed at French IRSTV institute and is able * to manipulate and create vector and raster spatial information. OrbisGIS * is distributed under GPL 3 license. It is produced by the geo-informatic team of * the IRSTV Institute , CNRS FR 2488: * Erwan BOCHER, scientific researcher, * Thomas LEDUC, scientific researcher, * Fernando GONZALEZ CORTES, computer engineer. * * Copyright (C) 2007 Erwan BOCHER, Fernando GONZALEZ CORTES, Thomas LEDUC * * This file is part of OrbisGIS. * * OrbisGIS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OrbisGIS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OrbisGIS. If not, see . * * For more information, please consult: * * * * or contact directly: * erwan.bocher _at_ ec-nantes.fr * fergonco _at_ gmail.com * thomas.leduc _at_ cerma.archi.fr */ /* * GeoTools - OpenSource mapping toolkit * http://geotools.org * (C) 2004-2006, Geotools Project Managment Committee (PMC) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.orbisgis.renderer.liteShape; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; /** * A path iterator for the LiteShape class, specialized to iterate over a * geometry collection. It can be seen as a composite, since uses in fact other, * simpler iterator to carry on its duties. * * @author Andrea Aime * @source $URL: * http://svn.geotools.org/geotools/tags/2.3.1/module/render/src/org/geotools/renderer/lite/GeomCollectionIterator.java $ * @version $Id: GeomCollectionIterator.java 20874 2006-08-07 10:00:01Z jgarnett $ */ public final class GeomCollectionIterator extends AbstractLiteIterator { /** Transform applied on the coordinates during iteration */ private AffineTransform at; /** The set of geometries that we will iterate over */ private GeometryCollection gc; /** The current geometry */ private int currentGeom; /** The current sub-iterator */ private PathIterator currentIterator; /** True when the iterator is terminate */ private boolean done = false; /** If true, apply simple distance based generalization */ private boolean generalize = false; /** Maximum distance for point elision when generalizing */ private double maxDistance = 1.0; private LineIterator lineIterator = new LineIterator(); public GeomCollectionIterator() { } /** * @param gc * @param at */ public void init(GeometryCollection gc, AffineTransform at, boolean generalize, double maxDistance) { this.gc = gc; this.at = at == null ? new AffineTransform() : at; this.generalize = generalize; this.maxDistance = maxDistance; currentGeom = 0; done = false; currentIterator = getIterator(gc.getGeometryN(0)); } /** * Creates a new instance of GeomCollectionIterator * * @param gc * The geometry collection the iterator will use * @param at * The affine transform applied to coordinates during iteration * @param generalize * if true apply simple distance based generalization * @param maxDistance * during iteration, a point will be skipped if it's distance * from the previous is less than maxDistance */ public GeomCollectionIterator(GeometryCollection gc, AffineTransform at, boolean generalize, double maxDistance) { init(gc, at, generalize, maxDistance); } /** * Sets the distance limit for point skipping during distance based * generalization * * @param distance * the maximum distance for point skipping */ public void setMaxDistance(double distance) { maxDistance = distance; } /** * Returns the distance limit for point skipping during distance based * generalization * * @return the maximum distance for distance based generalization */ public double getMaxDistance() { return maxDistance; } /** * Returns the specific iterator for the geometry passed. * * @param g * The geometry whole iterator is requested * * @return the specific iterator for the geometry passed. */ private AbstractLiteIterator getIterator(Geometry g) { AbstractLiteIterator pi = null; if (g instanceof Polygon) { Polygon p = (Polygon) g; pi = new PolygonIterator(p, at, generalize, maxDistance); } else if (g instanceof GeometryCollection) { GeometryCollection gc = (GeometryCollection) g; pi = new GeomCollectionIterator(gc, at, generalize, maxDistance); } else if (g instanceof LineString) { LineString ls = (LineString) g; lineIterator.init(ls, at, generalize, (float) maxDistance); pi = lineIterator; } else if (g instanceof LinearRing) { LinearRing lr = (LinearRing) g; lineIterator.init(lr, at, generalize, (float) maxDistance); pi = lineIterator; } else if (g instanceof Point) { Point p = (Point) g; pi = new PointIterator(p, at); } return pi; } /** * Returns the coordinates and type of the current path segment in the * iteration. The return value is the path-segment type: SEG_MOVETO, * SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. A double array of * length 6 must be passed in and can be used to store the coordinates of * the point(s). Each point is stored as a pair of double x,y coordinates. * SEG_MOVETO and SEG_LINETO types returns one point, SEG_QUADTO returns two * points, SEG_CUBICTO returns 3 points and SEG_CLOSE does not return any * points. * * @param coords * an array that holds the data returned from this method * * @return the path-segment type of the current path segment. * * @see #SEG_MOVETO * @see #SEG_LINETO * @see #SEG_QUADTO * @see #SEG_CUBICTO * @see #SEG_CLOSE */ public int currentSegment(double[] coords) { return currentIterator.currentSegment(coords); } /** * Returns the coordinates and type of the current path segment in the * iteration. The return value is the path-segment type: SEG_MOVETO, * SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. A float array of * length 6 must be passed in and can be used to store the coordinates of * the point(s). Each point is stored as a pair of float x,y coordinates. * SEG_MOVETO and SEG_LINETO types returns one point, SEG_QUADTO returns two * points, SEG_CUBICTO returns 3 points and SEG_CLOSE does not return any * points. * * @param coords * an array that holds the data returned from this method * * @return the path-segment type of the current path segment. * * @see #SEG_MOVETO * @see #SEG_LINETO * @see #SEG_QUADTO * @see #SEG_CUBICTO * @see #SEG_CLOSE */ public int currentSegment(float[] coords) { return currentIterator.currentSegment(coords); } /** * Returns the winding rule for determining the interior of the path. * * @return the winding rule. * * @see #WIND_EVEN_ODD * @see #WIND_NON_ZERO */ public int getWindingRule() { return WIND_EVEN_ODD; } /** * Tests if the iteration is complete. * * @return true if all the segments have been read; * false otherwise. */ public boolean isDone() { return done; } /** * Moves the iterator to the next segment of the path forwards along the * primary direction of traversal as long as there are more points in that * direction. */ public void next() { if (currentIterator.isDone()) { if (currentGeom < (gc.getNumGeometries() - 1)) { currentGeom++; currentIterator = getIterator(gc.getGeometryN(currentGeom)); } else { done = true; } } else { currentIterator.next(); } } }