svn-gvsig-desktop / tags / J2ME_compat_v1_2_Build_1209 / libraries / libFMap / src / com / iver / cit / gvsig / fmap / core / gt2 / LineIterator.java @ 19509
History | View | Annotate | Download (10.9 KB)
1 |
package com.iver.cit.gvsig.fmap.core.gt2; |
---|---|
2 |
|
3 |
|
4 |
import java.awt.geom.AffineTransform; |
5 |
|
6 |
import com.vividsolutions.jts.geom.CoordinateSequence; |
7 |
import com.vividsolutions.jts.geom.LineString; |
8 |
import com.vividsolutions.jts.geom.LinearRing; |
9 |
|
10 |
|
11 |
/**
|
12 |
* A path iterator for the LiteShape class, specialized to iterate over
|
13 |
* LineString object.
|
14 |
*
|
15 |
* @author Andrea Aime
|
16 |
* @version $Id: LineIterator.java 2943 2005-09-22 11:27:52Z fjp $
|
17 |
*/
|
18 |
class LineIterator extends AbstractLiteIterator { |
19 |
/** Transform applied on the coordinates during iteration */
|
20 |
private AffineTransform at; |
21 |
|
22 |
/** The array of coordinates that represents the line geometry */
|
23 |
private CoordinateSequence coordinates = null; |
24 |
|
25 |
/** Current line coordinate */
|
26 |
private int currentCoord = 0; |
27 |
|
28 |
/** The previous coordinate (during iteration) */
|
29 |
private float oldX = Float.NaN; |
30 |
private float oldY = Float.NaN; |
31 |
|
32 |
/** True when the iteration is terminated */
|
33 |
private boolean done = false; |
34 |
|
35 |
/** True if the line is a ring */
|
36 |
private boolean isClosed; |
37 |
|
38 |
/** If true, apply simple distance based generalization */
|
39 |
private boolean generalize = false; |
40 |
|
41 |
/** Maximum distance for point elision when generalizing */
|
42 |
private float maxDistance = 1.0f; |
43 |
|
44 |
/** Horizontal scale, got from the affine transform and cached */
|
45 |
private float xScale; |
46 |
|
47 |
/** Vertical scale, got from the affine transform and cached */
|
48 |
private float yScale; |
49 |
|
50 |
private int coordinateCount; |
51 |
|
52 |
private static final AffineTransform NO_TRANSFORM = new AffineTransform(); |
53 |
|
54 |
/**
|
55 |
*
|
56 |
*/
|
57 |
public LineIterator() {
|
58 |
} |
59 |
|
60 |
/**
|
61 |
* Creates a new instance of LineIterator
|
62 |
*
|
63 |
* @param ls The line string the iterator will use
|
64 |
* @param at The affine transform applied to coordinates during iteration
|
65 |
*/
|
66 |
public LineIterator(LineString ls, AffineTransform at, boolean generalize, |
67 |
float maxDistance) {
|
68 |
init(ls, at, generalize, maxDistance); |
69 |
} |
70 |
|
71 |
/**
|
72 |
* Creates a new instance of LineIterator
|
73 |
*
|
74 |
* @param ls The line string the iterator will use
|
75 |
* @param at The affine transform applied to coordinates during iteration
|
76 |
* @param generalize if true apply simple distance based generalization
|
77 |
*/
|
78 |
// public LineIterator(LineString ls, AffineTransform at, boolean generalize) {
|
79 |
// this(ls, at);
|
80 |
//
|
81 |
// }
|
82 |
|
83 |
/**
|
84 |
* Creates a new instance of LineIterator
|
85 |
*
|
86 |
* @param ls The line string the iterator will use
|
87 |
* @param at The affine transform applied to coordinates during iteration
|
88 |
* @param generalize if true apply simple distance based generalization
|
89 |
* @param maxDistance during iteration, a point will be skipped if it's
|
90 |
* distance from the previous is less than maxDistance
|
91 |
*/
|
92 |
// public LineIterator(
|
93 |
// LineString ls, AffineTransform at, boolean generalize,
|
94 |
// double maxDistance) {
|
95 |
// this(ls, at, generalize);
|
96 |
//
|
97 |
// }
|
98 |
|
99 |
/**
|
100 |
* @param string
|
101 |
* @param combined
|
102 |
* @param generalize2
|
103 |
* @param f
|
104 |
* @param scale
|
105 |
* @param scale2
|
106 |
*/
|
107 |
public void init(LineString ls, AffineTransform at, boolean generalize, float maxDistance, float xScale, float yScale) { |
108 |
this.xScale = xScale;
|
109 |
this.yScale = yScale;
|
110 |
|
111 |
_init(ls, at, generalize, maxDistance); |
112 |
} |
113 |
|
114 |
/**
|
115 |
* @param ls
|
116 |
* @param at
|
117 |
* @param generalize
|
118 |
* @param maxDistance
|
119 |
*/
|
120 |
public void init(LineString ls, AffineTransform at, boolean generalize, float maxDistance) { |
121 |
_init(ls, at, generalize, maxDistance); |
122 |
|
123 |
xScale = (float) Math.sqrt( |
124 |
(at.getScaleX() * at.getScaleX()) |
125 |
+ (at.getShearX() * at.getShearX())); |
126 |
yScale = (float) Math.sqrt( |
127 |
(at.getScaleY() * at.getScaleY()) |
128 |
+ (at.getShearY() * at.getShearY())); |
129 |
|
130 |
|
131 |
} |
132 |
|
133 |
/**
|
134 |
* @param ls
|
135 |
* @param at
|
136 |
* @param generalize
|
137 |
* @param maxDistance
|
138 |
* @return
|
139 |
*/
|
140 |
private void _init(LineString ls, AffineTransform at, boolean generalize, float maxDistance) { |
141 |
if (at == null) { |
142 |
at = NO_TRANSFORM; |
143 |
} |
144 |
|
145 |
this.at = at;
|
146 |
coordinates = ls.getCoordinateSequence(); |
147 |
coordinateCount = coordinates.size(); |
148 |
isClosed = ls instanceof LinearRing;
|
149 |
|
150 |
this.generalize = generalize;
|
151 |
this.maxDistance = maxDistance;
|
152 |
done = false;
|
153 |
currentCoord = 0;
|
154 |
|
155 |
oldX = Float.NaN;
|
156 |
oldY = Float.NaN;
|
157 |
} |
158 |
|
159 |
/**
|
160 |
* Sets the distance limit for point skipping during distance based
|
161 |
* generalization
|
162 |
*
|
163 |
* @param distance the maximum distance for point skipping
|
164 |
*/
|
165 |
public void setMaxDistance(float distance) { |
166 |
maxDistance = distance; |
167 |
} |
168 |
|
169 |
/**
|
170 |
* Returns the distance limit for point skipping during distance based
|
171 |
* generalization
|
172 |
*
|
173 |
* @return the maximum distance for distance based generalization
|
174 |
*/
|
175 |
public double getMaxDistance() { |
176 |
return maxDistance;
|
177 |
} |
178 |
|
179 |
// /**
|
180 |
// * Returns the coordinates and type of the current path segment in the
|
181 |
// * iteration. The return value is the path-segment type: SEG_MOVETO,
|
182 |
// * SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. A double array of
|
183 |
// * length 6 must be passed in and can be used to store the coordinates of
|
184 |
// * the point(s). Each point is stored as a pair of double x,y coordinates.
|
185 |
// * SEG_MOVETO and SEG_LINETO types returns one point, SEG_QUADTO returns
|
186 |
// * two points, SEG_CUBICTO returns 3 points and SEG_CLOSE does not return
|
187 |
// * any points.
|
188 |
// *
|
189 |
// * @param coords an array that holds the data returned from this method
|
190 |
// *
|
191 |
// * @return the path-segment type of the current path segment.
|
192 |
// *
|
193 |
// * @see #SEG_MOVETO
|
194 |
// * @see #SEG_LINETO
|
195 |
// * @see #SEG_QUADTO
|
196 |
// * @see #SEG_CUBICTO
|
197 |
// * @see #SEG_CLOSE
|
198 |
// */
|
199 |
// public int currentSegment(float[] coords) {
|
200 |
// if (currentCoord == 0) {
|
201 |
// coords[0] = (float) coordinates.getX(0);
|
202 |
// coords[1] = (float) coordinates.getY(0);
|
203 |
// at.transform(coords, 0, coords, 0, 1);
|
204 |
//
|
205 |
// return SEG_MOVETO;
|
206 |
// } else if ((currentCoord == coordinateCount) && isClosed) {
|
207 |
// return SEG_CLOSE;
|
208 |
// } else {
|
209 |
// coords[0] = oldX; // (float) coordinates.getX(currentCoord);
|
210 |
// coords[1] = oldY; // (float) coordinates.getY(currentCoord);
|
211 |
// at.transform(coords, 0, coords, 0, 1);
|
212 |
//
|
213 |
// return SEG_LINETO;
|
214 |
// }
|
215 |
// }
|
216 |
|
217 |
// /**
|
218 |
// * Returns the coordinates and type of the current path segment in the
|
219 |
// * iteration. The return value is the path-segment type: SEG_MOVETO,
|
220 |
// * SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. A float array of
|
221 |
// * length 6 must be passed in and can be used to store the coordinates of
|
222 |
// * the point(s). Each point is stored as a pair of float x,y coordinates.
|
223 |
// * SEG_MOVETO and SEG_LINETO types returns one point, SEG_QUADTO returns
|
224 |
// * two points, SEG_CUBICTO returns 3 points and SEG_CLOSE does not return
|
225 |
// * any points.
|
226 |
// *
|
227 |
// * @param coords an array that holds the data returned from this method
|
228 |
// *
|
229 |
// * @return the path-segment type of the current path segment.
|
230 |
// *
|
231 |
// * @see #SEG_MOVETO
|
232 |
// * @see #SEG_LINETO
|
233 |
// * @see #SEG_QUADTO
|
234 |
// * @see #SEG_CUBICTO
|
235 |
// * @see #SEG_CLOSE
|
236 |
// */
|
237 |
// public int currentSegment(float[] coords) {
|
238 |
// double[] dcoords = new double[2];
|
239 |
// int result = currentSegment(dcoords);
|
240 |
// coords[0] = (float) dcoords[0];
|
241 |
// coords[1] = (float) dcoords[1];
|
242 |
//
|
243 |
// return result;
|
244 |
// }
|
245 |
|
246 |
/**
|
247 |
* Returns the winding rule for determining the interior of the path.
|
248 |
*
|
249 |
* @return the winding rule.
|
250 |
*
|
251 |
* @see #WIND_EVEN_ODD
|
252 |
* @see #WIND_NON_ZERO
|
253 |
*/
|
254 |
public int getWindingRule() { |
255 |
return WIND_NON_ZERO;
|
256 |
} |
257 |
|
258 |
/**
|
259 |
* Tests if the iteration is complete.
|
260 |
*
|
261 |
* @return <code>true</code> if all the segments have been read;
|
262 |
* <code>false</code> otherwise.
|
263 |
*/
|
264 |
public boolean isDone() { |
265 |
return done;
|
266 |
} |
267 |
|
268 |
/**
|
269 |
* Moves the iterator to the next segment of the path forwards along the
|
270 |
* primary direction of traversal as long as there are more points in that
|
271 |
* direction.
|
272 |
*/
|
273 |
public void next() { |
274 |
if (
|
275 |
((currentCoord == (coordinateCount - 1)) && !isClosed)
|
276 |
|| ((currentCoord == coordinateCount) && isClosed)) { |
277 |
done = true;
|
278 |
} else {
|
279 |
if (generalize) {
|
280 |
if (Float.isNaN(oldX)) { |
281 |
currentCoord++; |
282 |
oldX = (float) coordinates.getX(currentCoord);
|
283 |
oldY = (float) coordinates.getY(currentCoord);
|
284 |
} else {
|
285 |
float distx = 0; |
286 |
float disty = 0; |
287 |
float x = 0; |
288 |
float y = 0; |
289 |
|
290 |
do {
|
291 |
currentCoord++; |
292 |
x = (float) coordinates.getX(currentCoord);
|
293 |
y = (float) coordinates.getY(currentCoord);
|
294 |
|
295 |
if (currentCoord < coordinateCount) {
|
296 |
distx = Math.abs(
|
297 |
x - oldX); |
298 |
disty = Math.abs(
|
299 |
y - oldY); |
300 |
} |
301 |
} while (
|
302 |
((distx * xScale) < maxDistance) |
303 |
&& ((disty * yScale) < maxDistance) |
304 |
&& ((!isClosed |
305 |
&& (currentCoord < (coordinateCount - 1)))
|
306 |
|| (isClosed && (currentCoord < coordinateCount)))); |
307 |
|
308 |
oldX = x; |
309 |
oldY = y; |
310 |
} |
311 |
} else {
|
312 |
currentCoord++; |
313 |
} |
314 |
} |
315 |
} |
316 |
|
317 |
/**
|
318 |
* @see java.awt.geom.PathIterator#currentSegment(double[])
|
319 |
*/
|
320 |
public int currentSegment(double[] coords) { |
321 |
if (currentCoord == 0) { |
322 |
coords[0] = (double) coordinates.getX(0); |
323 |
coords[1] = (double) coordinates.getY(0); |
324 |
at.transform(coords, 0, coords, 0, 1); |
325 |
return SEG_MOVETO;
|
326 |
} else if ((currentCoord == coordinateCount) && isClosed) { |
327 |
return SEG_CLOSE;
|
328 |
} else {
|
329 |
coords[0] = coordinates.getX(currentCoord);
|
330 |
coords[1] = coordinates.getY(currentCoord);
|
331 |
at.transform(coords, 0, coords, 0, 1); |
332 |
|
333 |
return SEG_LINETO;
|
334 |
} |
335 |
} |
336 |
|
337 |
|
338 |
} |