Statistics
| Revision:

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
}