Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.jts / src / main / java / org / gvsig / fmap / geom / jts / primitive / curve / line / AbstractLine.java @ 42980

History | View | Annotate | Download (16.5 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2015 gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.geom.jts.primitive.curve.line;
24

    
25
import java.awt.Shape;
26
import java.awt.geom.AffineTransform;
27
import java.awt.geom.GeneralPath;
28
import java.awt.geom.PathIterator;
29
import java.util.Collections;
30
import java.util.Iterator;
31

    
32
import com.vividsolutions.jts.geom.Coordinate;
33

    
34
import org.apache.commons.lang3.StringUtils;
35
import org.cresques.cts.ICoordTrans;
36
import org.slf4j.Logger;
37
import org.slf4j.LoggerFactory;
38

    
39
import org.gvsig.fmap.geom.Geometry;
40
import org.gvsig.fmap.geom.exception.ReprojectionRuntimeException;
41
import org.gvsig.fmap.geom.jts.gputils.DefaultGeneralPathX;
42
import org.gvsig.fmap.geom.jts.gputils.GeneralPathXIterator;
43
import org.gvsig.fmap.geom.jts.primitive.curve.AbstractCurve;
44
import org.gvsig.fmap.geom.jts.primitive.point.Point2D;
45
import org.gvsig.fmap.geom.jts.primitive.point.PointJTS;
46
import org.gvsig.fmap.geom.jts.util.ArrayListCoordinateSequence;
47
import org.gvsig.fmap.geom.jts.util.JTSUtils;
48
import org.gvsig.fmap.geom.operation.GeometryOperationException;
49
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
50
import org.gvsig.fmap.geom.primitive.GeneralPathX;
51
import org.gvsig.fmap.geom.primitive.IGeneralPathX;
52
import org.gvsig.fmap.geom.primitive.Point;
53

    
54
/**
55
 * @author fdiaz
56
 *
57
 */
58
public abstract class AbstractLine extends AbstractCurve {
59

    
60
    /**
61
     *
62
     */
63
    private static final long serialVersionUID = 5034197096871344597L;
64
    private static final Logger logger = LoggerFactory.getLogger(AbstractLine.class);
65

    
66
    protected ArrayListCoordinateSequence coordinates;
67

    
68
    public class VertexIterator implements Iterator<Point> {
69

    
70
        private PointJTS vertex;
71
        private int current;
72

    
73
        public VertexIterator() {
74
            this.current = 0;
75
            if( getNumVertices()>0 ) {
76
                this.vertex = (PointJTS) getVertex(0).cloneGeometry();
77
            } else {
78
                this.vertex = null;
79
            }
80
        }
81

    
82
        @Override
83
        public boolean hasNext() {
84
            return this.current < getNumVertices() ;
85
        }
86

    
87
        @Override
88
        public Point next() {
89
            this.vertex.setJTSCoordinate(coordinates.get(current) );
90
            this.current++;
91
            return this.vertex;
92
        }
93

    
94
        @Override
95
        public void remove() {
96
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
97
        }
98

    
99
    }
100
    /**
101
    *
102
    */
103
    protected AbstractLine(int subtype) {
104
        super(Geometry.TYPES.LINE, subtype);
105
    }
106

    
107
    /**
108
     * @param type
109
     * @param subtype
110
     */
111
    public AbstractLine(int type, int subtype) {
112
        super(type, subtype);
113
    }
114

    
115
    abstract public Point getVertex(int index);
116

    
117
    public Iterator<Point> iterator() {
118
        return new VertexIterator();
119
    }
120

    
121
    /*
122
     * (non-Javadoc)
123
     *
124
     * @see org.gvsig.fmap.geom.jts.GeometryJTS#getJTS()
125
     */
126
    public com.vividsolutions.jts.geom.Geometry getJTS() {
127
        return JTSUtils.createJTSLineString(coordinates);
128
    }
129

    
130
    /*
131
     * (non-Javadoc)
132
     *
133
     * @see
134
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#addVertex(org.gvsig
135
     * .fmap.geom.primitive.Point)
136
     */
137
    public void addVertex(Point point) {
138
        point = fixPoint(point);
139
        coordinates.add(((PointJTS) point).getJTSCoordinate());
140
    }
141

    
142
    /*
143
     * (non-Javadoc)
144
     *
145
     * @see
146
     * org.gvsig.fmap.geom.primitive.Curve#setPoints(org.gvsig.fmap.geom.primitive
147
     * .Point, org.gvsig.fmap.geom.primitive.Point)
148
     */
149
    public void setPoints(Point initialPoint, Point endPoint) {
150
        initialPoint = fixPoint(initialPoint);
151
        endPoint = fixPoint(endPoint);
152
        coordinates.clear();
153
        addVertex(initialPoint);
154
        addVertex(endPoint);
155
    }
156

    
157
    /**
158
     * @param point
159
     * @return
160
     */
161
    protected abstract Point fixPoint(Point point);
162

    
163
    /*
164
     * (non-Javadoc)
165
     *
166
     * @see
167
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#getCoordinateAt(int,
168
     * int)
169
     */
170
    public double getCoordinateAt(int index, int dimension) {
171
        return coordinates.getOrdinate(index, dimension);
172
    }
173

    
174
    /*
175
     * (non-Javadoc)
176
     *
177
     * @see
178
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#setCoordinateAt(int,
179
     * int, double)
180
     */
181
    public void setCoordinateAt(int index, int dimension, double value) {
182
        coordinates.setOrdinate(index, dimension, value);
183
    }
184

    
185
    /*
186
     * (non-Javadoc)
187
     *
188
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#removeVertex(int)
189
     */
190
    public void removeVertex(int index) {
191
        coordinates.remove(index);
192
    }
193

    
194
    /*
195
     * (non-Javadoc)
196
     *
197
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#getNumVertices()
198
     */
199
    public int getNumVertices() {
200
        return coordinates.size();
201
    }
202

    
203
    /*
204
     * (non-Javadoc)
205
     *
206
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#insertVertex(int,
207
     * org.gvsig.fmap.geom.primitive.Point)
208
     */
209
    public void insertVertex(int index, Point p) {
210
        p = fixPoint(p);
211
        coordinates.add(index, ((PointJTS) p).getJTSCoordinate());
212
    }
213

    
214
    /*
215
     * (non-Javadoc)
216
     *
217
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#setVertex(int,
218
     * org.gvsig.fmap.geom.primitive.Point)
219
     */
220
    public void setVertex(int index, Point p) {
221
        p = fixPoint(p);
222
        coordinates.set(index, ((PointJTS) p).getJTSCoordinate());
223
    }
224

    
225
    /*
226
     * (non-Javadoc)
227
     *
228
     * @see
229
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#setGeneralPath(org.
230
     * gvsig.fmap.geom.primitive.GeneralPathX)
231
     */
232
    public void setGeneralPath(GeneralPathX generalPathX) {
233
        PathIterator it = generalPathX.getPathIterator(null);
234
        double[] segment = new double[6];
235
        int i = 0;
236
        while(!it.isDone()){
237
            int type = it.currentSegment(segment);
238
            if(i==0){
239
                switch (type) {
240
                case IGeneralPathX.SEG_MOVETO:
241
                    Point p = new Point2D(segment[0], segment[1]);
242
                    p = fixPoint(p);
243
                    coordinates.add(((PointJTS)p).getJTSCoordinate());
244
                    break;
245
                default:
246
                    String message = StringUtils.replace("Type of segment %(segment)s isn't SEG_MOVETO.","%(segment)s",String.valueOf(i));
247
                    logger.warn(message);
248
                    throw new RuntimeException(message);
249
                }
250
            } else {
251
                //Dudo de que los casos SEG_QUADTO y SEG_CUBICTO est?n bien pero se hac?a lo mismo en la librer?a de geometr?as vieja.
252
                Point p;
253
                switch (type) {
254
                case IGeneralPathX.SEG_LINETO:
255
                    p = new Point2D(segment[0], segment[1]);
256
                    p = fixPoint(p);
257
                    coordinates.add(((PointJTS)p).getJTSCoordinate());
258
                    break;
259
                case IGeneralPathX.SEG_QUADTO:
260
                    for (int j = 0; j <= 1; j++) {
261
                        p = new Point2D(segment[i], segment[i+1]);
262
                        p = fixPoint(p);
263
                        coordinates.add(((PointJTS) p).getJTSCoordinate());
264
                    }
265
                    break;
266
                case IGeneralPathX.SEG_CUBICTO:
267
                    for (int j = 0; j <= 2; j++) {
268
                        p = new Point2D(segment[i], segment[i+1]);
269
                        p = fixPoint(p);
270
                        coordinates.add(((PointJTS) p).getJTSCoordinate());
271
                    }
272
                    break;
273
                case IGeneralPathX.SEG_CLOSE:
274
                    if(!coordinates.get(0).equals(coordinates.get(coordinates.size()-1))){
275
                        coordinates.add(coordinates.get(0));
276
                    }
277
                    break;
278
                default:
279
                    String message = StringUtils.replace("The general path has a gap in segment %(segment)s.","%(segment)s",String.valueOf(i));
280
                    logger.warn(message);
281
                    throw new RuntimeException(message);
282
                }
283
            }
284
            it.next();
285
            i++;
286
        }
287
    }
288

    
289
    /*
290
     * (non-Javadoc)
291
     *
292
     * @see
293
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#addMoveToVertex(org
294
     * .gvsig.fmap.geom.primitive.Point)
295
     */
296
    public void addMoveToVertex(Point point) {
297
        notifyDeprecated("Calling deprecated metohd addMoveToVertex in Line");
298
        throw new UnsupportedOperationException();
299
    }
300

    
301
    /*
302
     * (non-Javadoc)
303
     *
304
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#closePrimitive()
305
     */
306
    public void closePrimitive() {
307
        if (!coordinates.isEmpty() && !isClosed()) {
308
            coordinates.add((Coordinate)coordinates.get(0).clone());
309
        }
310
    }
311

    
312
    /*
313
     * (non-Javadoc)
314
     *
315
     * @see
316
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#ensureCapacity(int)
317
     */
318
    public void ensureCapacity(int capacity) {
319
        this.coordinates.ensureCapacity(capacity);
320
    }
321

    
322
    /*
323
     * (non-Javadoc)
324
     *
325
     * @see org.gvsig.fmap.geom.Geometry#reProject(org.cresques.cts.ICoordTrans)
326
     */
327
    public void reProject(ICoordTrans ct) {
328
        if (ct == null) {
329
            return;
330
        }
331
        ArrayListCoordinateSequence tmpCoordinates = new ArrayListCoordinateSequence();
332
        tmpCoordinates.ensureCapacity(coordinates.size());
333
        for (Iterator<Coordinate> iterator = coordinates.iterator(); iterator.hasNext();) {
334
            Coordinate coordinate = (Coordinate) iterator.next();
335

    
336
            java.awt.geom.Point2D p = new java.awt.geom.Point2D.Double(coordinate.x, coordinate.y);
337
            try {
338
                p = ct.convert(p, p);
339
                coordinate.x = p.getX();
340
                coordinate.y = p.getY();
341
                tmpCoordinates.add(coordinate);
342
            } catch (Exception exc) {
343
                /*
344
                 * This can happen when the reprojection lib is unable
345
                 * to reproject (for example the source point
346
                 * is out of the valid range and some computing
347
                 * problem happens)
348
                 */
349
            }
350
        }
351
        coordinates=tmpCoordinates;
352
    }
353

    
354
    /*
355
     * (non-Javadoc)
356
     *
357
     * @see
358
     * org.gvsig.fmap.geom.Geometry#transform(java.awt.geom.AffineTransform)
359
     */
360
    public void transform(AffineTransform at) {
361
        if (at == null) {
362
            return;
363
        }
364

    
365
        for (int i = 0; i < coordinates.size(); i++) {
366
            Coordinate coordinate = coordinates.get(i);
367
            java.awt.geom.Point2D p = new java.awt.geom.Point2D.Double(coordinate.x, coordinate.y);
368

    
369
            at.transform(p, p);
370
            coordinate.x = p.getX();
371
            coordinate.y = p.getY();
372

    
373
        }
374
    }
375

    
376
    /*
377
     * (non-Javadoc)
378
     *
379
     * @see org.gvsig.fmap.geom.Geometry#getDimension()
380
     */
381
    public int getDimension() {
382
        return this.getGeometryType().getDimension();
383
    }
384

    
385
    /*
386
     * (non-Javadoc)
387
     *
388
     * @see org.gvsig.fmap.geom.Geometry#getShape(java.awt.geom.AffineTransform)
389
     */
390
    public Shape getShape(AffineTransform affineTransform) {
391
        if( this.coordinates.isEmpty() ) {
392
            // Esto no deberia de pasar, se trataria de una geometria
393
            // corrupta.
394
            return new GeneralPath();
395
        }
396
        return new DefaultGeneralPathX(getPathIterator(affineTransform),false,0);
397
    }
398

    
399
    /*
400
     * (non-Javadoc)
401
     *
402
     * @see org.gvsig.fmap.geom.Geometry#getShape()
403
     */
404
    public Shape getShape() {
405
        return new DefaultGeneralPathX(getPathIterator(null),false,0);
406
    }
407

    
408

    
409
    /*
410
     * (non-Javadoc)
411
     *
412
     * @see
413
     * org.gvsig.fmap.geom.Geometry#getPathIterator(java.awt.geom.AffineTransform
414
     * )
415
     */
416
    public PathIterator getPathIterator(AffineTransform at) {
417
        LineIterator pi = new LineIterator(at);
418
        return pi;
419
    }
420

    
421
    /*
422
     * (non-Javadoc)
423
     *
424
     * @see
425
     * org.gvsig.fmap.geom.Geometry#getPathIterator(java.awt.geom.AffineTransform
426
     * , double)
427
     */
428
    public PathIterator getPathIterator(AffineTransform at, double flatness) {
429
        return getPathIterator(at);
430
    }
431

    
432
    /*
433
     * (non-Javadoc)
434
     *
435
     * @see org.gvsig.fmap.geom.Geometry#getGeneralPath()
436
     */
437
    public GeneralPathX getGeneralPath() {
438
        return new DefaultGeneralPathX(getPathIterator(null), false, 0);
439
    }
440

    
441
    protected class LineIterator extends GeneralPathXIterator {
442

    
443
        /** Transform applied on the coordinates during iteration */
444
        private AffineTransform at;
445

    
446
        /** True when the point has been read once */
447
        private boolean done;
448
        private int index = 0;
449

    
450
        /**
451
         * Creates a new PointIterator object.
452
         *
453
         * @param p
454
         *            The polygon
455
         * @param at
456
         *            The affine transform applied to coordinates during
457
         *            iteration
458
         */
459
        public LineIterator(AffineTransform at) {
460
            super(new GeneralPathX());
461
            if (at == null) {
462
                at = new AffineTransform();
463
            }
464

    
465
            this.at = at;
466
            done = false;
467
        }
468

    
469
        /**
470
         * Return the winding rule for determining the interior of the path.
471
         *
472
         * @return <code>WIND_EVEN_ODD</code> by default.
473
         */
474
        public int getWindingRule() {
475
            return PathIterator.WIND_EVEN_ODD;
476
        }
477

    
478
        /**
479
         * @see java.awt.geom.PathIterator#next()
480
         */
481
        public void next() {
482
            done = (coordinates.size() == ++index);
483
        }
484

    
485
        /**
486
         * @see java.awt.geom.PathIterator#isDone()
487
         */
488
        public boolean isDone() {
489
            return done;
490
        }
491

    
492
        /**
493
         * @see java.awt.geom.PathIterator#currentSegment(double[])
494
         */
495
        public int currentSegment(double[] coords) {
496
            coords[0] = coordinates.getX(index);
497
            coords[1] = coordinates.getY(index);
498
            at.transform(coords, 0, coords, 0, 1);
499

    
500
            if (index == 0) {
501
                return PathIterator.SEG_MOVETO;
502
            } else {
503
                return PathIterator.SEG_LINETO;
504
            }
505
        }
506

    
507
        /*
508
         * (non-Javadoc)
509
         *
510
         * @see java.awt.geom.PathIterator#currentSegment(float[])
511
         */
512
        public int currentSegment(float[] coords) {
513
            coords[0] = (float) coordinates.getX(index);
514
            coords[1] = (float) coordinates.getY(index);
515
            at.transform(coords, 0, coords, 0, 1);
516

    
517
            if (index == 0) {
518
                return PathIterator.SEG_MOVETO;
519
            } else {
520
                return PathIterator.SEG_LINETO;
521
            }
522
        }
523
    }
524

    
525
    /*
526
     * (non-Javadoc)
527
     *
528
     * @see org.gvsig.fmap.geom.jts.GeometryJTS#is3D()
529
     */
530
    public boolean is3D() {
531
        int subtype = this.getGeometryType().getType();
532
        return subtype == Geometry.SUBTYPES.GEOM3D || subtype == Geometry.SUBTYPES.GEOM3DM;
533
    }
534

    
535
    protected boolean isClosed(){
536
        return coordinates.get(0).equals(coordinates.get(coordinates.size()-1));
537
    }
538

    
539
    /* (non-Javadoc)
540
     * @see org.gvsig.fmap.geom.jts.GeometryJTS#flip()
541
     */
542
    public void flip() throws GeometryOperationNotSupportedException, GeometryOperationException {
543
        Collections.reverse(coordinates);
544
    }
545

    
546
    protected ArrayListCoordinateSequence cloneCoordinates() {
547
        ArrayListCoordinateSequence cloned = new ArrayListCoordinateSequence();
548
        cloned.ensureCapacity(coordinates.size());
549
        for (Iterator iterator = coordinates.iterator(); iterator.hasNext();) {
550
            Coordinate coordinate = (Coordinate) iterator.next();
551
            cloned.add((Coordinate)coordinate.clone());
552
        }
553
        return cloned;
554
    }
555

    
556
}