root/platform/orbisgis-core/src/main/java/org/orbisgis/renderer/liteShape/GeomCollectionIterator.java @ 4753

Revision 4753, 8.8 KB (checked in by fernando, 2 years ago)

BUG 4204: Wrong (I think) winding rule for geometry collections.

Line 
1/*
2 * OrbisGIS is a GIS application dedicated to scientific spatial simulation.
3 * This cross-platform GIS is developed at French IRSTV institute and is able
4 * to manipulate and create vector and raster spatial information. OrbisGIS
5 * is distributed under GPL 3 license. It is produced  by the geo-informatic team of
6 * the IRSTV Institute <http://www.irstv.cnrs.fr/>, CNRS FR 2488:
7 *    Erwan BOCHER, scientific researcher,
8 *    Thomas LEDUC, scientific researcher,
9 *    Fernando GONZALEZ CORTES, computer engineer.
10 *
11 * Copyright (C) 2007 Erwan BOCHER, Fernando GONZALEZ CORTES, Thomas LEDUC
12 *
13 * This file is part of OrbisGIS.
14 *
15 * OrbisGIS is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation, either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * OrbisGIS is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with OrbisGIS. If not, see <http://www.gnu.org/licenses/>.
27 *
28 * For more information, please consult:
29 *    <http://orbisgis.cerma.archi.fr/>
30 *    <http://sourcesup.cru.fr/projects/orbisgis/>
31 *
32 * or contact directly:
33 *    erwan.bocher _at_ ec-nantes.fr
34 *    fergonco _at_ gmail.com
35 *    thomas.leduc _at_ cerma.archi.fr
36 */
37/*
38 *    GeoTools - OpenSource mapping toolkit
39 *    http://geotools.org
40 *    (C) 2004-2006, Geotools Project Managment Committee (PMC)
41 *
42 *    This library is free software; you can redistribute it and/or
43 *    modify it under the terms of the GNU Lesser General Public
44 *    License as published by the Free Software Foundation; either
45 *    version 2.1 of the License, or (at your option) any later version.
46 *
47 *    This library is distributed in the hope that it will be useful,
48 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
49 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
50 *    Lesser General Public License for more details.
51 */
52
53package org.orbisgis.renderer.liteShape;
54
55import java.awt.geom.AffineTransform;
56import java.awt.geom.PathIterator;
57
58import com.vividsolutions.jts.geom.Geometry;
59import com.vividsolutions.jts.geom.GeometryCollection;
60import com.vividsolutions.jts.geom.LineString;
61import com.vividsolutions.jts.geom.LinearRing;
62import com.vividsolutions.jts.geom.Point;
63import com.vividsolutions.jts.geom.Polygon;
64
65/**
66 * A path iterator for the LiteShape class, specialized to iterate over a
67 * geometry collection. It can be seen as a composite, since uses in fact other,
68 * simpler iterator to carry on its duties.
69 *
70 * @author Andrea Aime
71 * @source $URL:
72 *         http://svn.geotools.org/geotools/tags/2.3.1/module/render/src/org/geotools/renderer/lite/GeomCollectionIterator.java $
73 * @version $Id: GeomCollectionIterator.java 20874 2006-08-07 10:00:01Z jgarnett $
74 */
75public final class GeomCollectionIterator extends AbstractLiteIterator {
76        /** Transform applied on the coordinates during iteration */
77        private AffineTransform at;
78
79        /** The set of geometries that we will iterate over */
80        private GeometryCollection gc;
81
82        /** The current geometry */
83        private int currentGeom;
84
85        /** The current sub-iterator */
86        private PathIterator currentIterator;
87
88        /** True when the iterator is terminate */
89        private boolean done = false;
90
91        /** If true, apply simple distance based generalization */
92        private boolean generalize = false;
93
94        /** Maximum distance for point elision when generalizing */
95        private double maxDistance = 1.0;
96
97        private LineIterator lineIterator = new LineIterator();
98
99        public GeomCollectionIterator() {
100
101        }
102
103        /**
104         * @param gc
105         * @param at
106         */
107        public void init(GeometryCollection gc, AffineTransform at,
108                        boolean generalize, double maxDistance) {
109                this.gc = gc;
110                this.at = at == null ? new AffineTransform() : at;
111                this.generalize = generalize;
112                this.maxDistance = maxDistance;
113                currentGeom = 0;
114                done = false;
115                currentIterator = getIterator(gc.getGeometryN(0));
116        }
117
118        /**
119         * Creates a new instance of GeomCollectionIterator
120         *
121         * @param gc
122         *            The geometry collection the iterator will use
123         * @param at
124         *            The affine transform applied to coordinates during iteration
125         * @param generalize
126         *            if true apply simple distance based generalization
127         * @param maxDistance
128         *            during iteration, a point will be skipped if it's distance
129         *            from the previous is less than maxDistance
130         */
131        public GeomCollectionIterator(GeometryCollection gc, AffineTransform at,
132                        boolean generalize, double maxDistance) {
133                init(gc, at, generalize, maxDistance);
134        }
135
136        /**
137         * Sets the distance limit for point skipping during distance based
138         * generalization
139         *
140         * @param distance
141         *            the maximum distance for point skipping
142         */
143        public void setMaxDistance(double distance) {
144                maxDistance = distance;
145        }
146
147        /**
148         * Returns the distance limit for point skipping during distance based
149         * generalization
150         *
151         * @return the maximum distance for distance based generalization
152         */
153        public double getMaxDistance() {
154                return maxDistance;
155        }
156
157        /**
158         * Returns the specific iterator for the geometry passed.
159         *
160         * @param g
161         *            The geometry whole iterator is requested
162         *
163         * @return the specific iterator for the geometry passed.
164         */
165        private AbstractLiteIterator getIterator(Geometry g) {
166                AbstractLiteIterator pi = null;
167
168                if (g instanceof Polygon) {
169                        Polygon p = (Polygon) g;
170                        pi = new PolygonIterator(p, at, generalize, maxDistance);
171                } else if (g instanceof GeometryCollection) {
172                        GeometryCollection gc = (GeometryCollection) g;
173                        pi = new GeomCollectionIterator(gc, at, generalize, maxDistance);
174                } else if (g instanceof LineString) {
175                        LineString ls = (LineString) g;
176                        lineIterator.init(ls, at, generalize, (float) maxDistance);
177                        pi = lineIterator;
178                } else if (g instanceof LinearRing) {
179                        LinearRing lr = (LinearRing) g;
180                        lineIterator.init(lr, at, generalize, (float) maxDistance);
181                        pi = lineIterator;
182                } else if (g instanceof Point) {
183                        Point p = (Point) g;
184                        pi = new PointIterator(p, at);
185                }
186
187                return pi;
188        }
189
190        /**
191         * Returns the coordinates and type of the current path segment in the
192         * iteration. The return value is the path-segment type: SEG_MOVETO,
193         * SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. A double array of
194         * length 6 must be passed in and can be used to store the coordinates of
195         * the point(s). Each point is stored as a pair of double x,y coordinates.
196         * SEG_MOVETO and SEG_LINETO types returns one point, SEG_QUADTO returns two
197         * points, SEG_CUBICTO returns 3 points and SEG_CLOSE does not return any
198         * points.
199         *
200         * @param coords
201         *            an array that holds the data returned from this method
202         *
203         * @return the path-segment type of the current path segment.
204         *
205         * @see #SEG_MOVETO
206         * @see #SEG_LINETO
207         * @see #SEG_QUADTO
208         * @see #SEG_CUBICTO
209         * @see #SEG_CLOSE
210         */
211        public int currentSegment(double[] coords) {
212                return currentIterator.currentSegment(coords);
213        }
214
215        /**
216         * Returns the coordinates and type of the current path segment in the
217         * iteration. The return value is the path-segment type: SEG_MOVETO,
218         * SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. A float array of
219         * length 6 must be passed in and can be used to store the coordinates of
220         * the point(s). Each point is stored as a pair of float x,y coordinates.
221         * SEG_MOVETO and SEG_LINETO types returns one point, SEG_QUADTO returns two
222         * points, SEG_CUBICTO returns 3 points and SEG_CLOSE does not return any
223         * points.
224         *
225         * @param coords
226         *            an array that holds the data returned from this method
227         *
228         * @return the path-segment type of the current path segment.
229         *
230         * @see #SEG_MOVETO
231         * @see #SEG_LINETO
232         * @see #SEG_QUADTO
233         * @see #SEG_CUBICTO
234         * @see #SEG_CLOSE
235         */
236        public int currentSegment(float[] coords) {
237                return currentIterator.currentSegment(coords);
238        }
239
240        /**
241         * Returns the winding rule for determining the interior of the path.
242         *
243         * @return the winding rule.
244         *
245         * @see #WIND_EVEN_ODD
246         * @see #WIND_NON_ZERO
247         */
248        public int getWindingRule() {
249                return WIND_EVEN_ODD;
250        }
251
252        /**
253         * Tests if the iteration is complete.
254         *
255         * @return <code>true</code> if all the segments have been read;
256         *         <code>false</code> otherwise.
257         */
258        public boolean isDone() {
259                return done;
260        }
261
262        /**
263         * Moves the iterator to the next segment of the path forwards along the
264         * primary direction of traversal as long as there are more points in that
265         * direction.
266         */
267        public void next() {
268                if (currentIterator.isDone()) {
269                        if (currentGeom < (gc.getNumGeometries() - 1)) {
270                                currentGeom++;
271                                currentIterator = getIterator(gc.getGeometryN(currentGeom));
272                        } else {
273                                done = true;
274                        }
275                } else {
276                        currentIterator.next();
277                }
278        }
279
280}
Note: See TracBrowser for help on using the browser.