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 @ 43785

History | View | Annotate | Download (18.1 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.jts.gputils.DefaultGeneralPathX;
41
import org.gvsig.fmap.geom.jts.gputils.GeneralPathXIterator;
42
import org.gvsig.fmap.geom.jts.primitive.curve.AbstractCurve;
43
import org.gvsig.fmap.geom.jts.primitive.point.Point2D;
44
import org.gvsig.fmap.geom.jts.primitive.point.PointJTS;
45
import org.gvsig.fmap.geom.jts.util.ArrayListCoordinateSequence;
46
import org.gvsig.fmap.geom.jts.util.JTSUtils;
47
import org.gvsig.fmap.geom.operation.GeometryOperationException;
48
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
49
import org.gvsig.fmap.geom.primitive.GeneralPathX;
50
import org.gvsig.fmap.geom.primitive.IGeneralPathX;
51
import org.gvsig.fmap.geom.primitive.Point;
52

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

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

    
65
    protected ArrayListCoordinateSequence coordinates;
66

    
67
    public class VertexIterator implements Iterator<Point> {
68

    
69
        private PointJTS vertex;
70
        private int current;
71

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

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

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

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

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

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

    
114
    abstract public Point getVertex(int index);
115

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

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

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

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

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

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

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

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

    
193

    
194
    public boolean isEmpty() {
195
        return coordinates==null || coordinates.isEmpty();
196
    }
197
    
198
    public int getNumVertices() {
199
        if( isEmpty() ) {
200
            return 0;
201
        }
202
        return coordinates.size();
203
    }
204

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

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

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

    
291
    /*
292
     * (non-Javadoc)
293
     *
294
     * @deprecated
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
        this.setProjection(ct.getPDest());
353
    }
354

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

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

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

    
374
        }
375
    }
376

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

    
386
    @Override
387
    public Shape getShape(AffineTransform affineTransform) {
388
        if( this.isEmpty() ) {
389
            // Esto no deberia de pasar, se trataria de una geometria
390
            // corrupta.
391
            return new GeneralPath();
392
        }
393
        return new DefaultGeneralPathX(getPathIterator(affineTransform),false,0);
394
    }
395

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

    
405

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

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

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

    
438
    protected class LineIterator extends GeneralPathXIterator {
439

    
440
        /** Transform applied on the coordinates during iteration */
441
        private AffineTransform at;
442

    
443
        /** True when the point has been read once */
444
        private boolean done;
445
        private int index = 0;
446

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

    
462
            this.at = at;
463
            done = false;
464
        }
465

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

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

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

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

    
497
            if (index == 0) {
498
                return PathIterator.SEG_MOVETO;
499
            } else {
500
                return PathIterator.SEG_LINETO;
501
            }
502
        }
503

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

    
514
            if (index == 0) {
515
                return PathIterator.SEG_MOVETO;
516
            } else {
517
                return PathIterator.SEG_LINETO;
518
            }
519
        }
520
    }
521

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

    
532
//    protected boolean isClosed(){
533
//        return coordinates.get(0).equals(coordinates.get(coordinates.size()-1));
534
//    }
535

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

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

    
553

    
554
    @Override
555
    public boolean canBeTransformed(AffineTransform at) {
556
        return true;
557
    }
558

    
559
    @Override
560
    public boolean canBeReprojected(ICoordTrans ct) {
561
        return true;
562
    }
563
    
564
    public boolean isClosed() {
565
        return this.isClosed(0);
566
    }
567
    
568
    public boolean isClosed(double tolerance) {
569
        int numVertices = this.getNumVertices();
570
        switch( numVertices ) {
571
            case 0:
572
            case 1:
573
            case 2:
574
                return false;
575
        }
576
            
577
        if( tolerance<0 ) {
578
            tolerance = 0.000001;
579
        }
580
        double[] first = this.getVertex(0).getCoordinates();
581
        double[] last = this.getVertex(numVertices-1).getCoordinates();
582

    
583
        for (int i = 0; i < first.length; i++) {
584
                if (Math.abs(first[i] - last[i]) > tolerance) {
585
                        return false;
586
                }
587
        }
588
        return true;
589
    }
590
    
591
    public void forceClose(double tolerance) {
592
        Point first;
593
        int numVertices = this.getNumVertices();
594
        switch( numVertices ) {
595
            case 0:
596
                return;
597
            case 1:
598
                first = this.getVertex(0);
599
                this.addVertex((Point) first.cloneGeometry());
600
                this.addVertex((Point) first.cloneGeometry());
601
                return;
602
            case 2:
603
                first = this.getVertex(0);
604
                this.addVertex((Point) first.cloneGeometry());
605
                return;
606
        }
607
        if( this.isClosed(0) ) {
608
            return;
609
        }
610
        
611
        first = this.getVertex(0);
612
        if( this.isClosed(tolerance) ) {
613
            this.setVertex(numVertices-1,(Point) first.cloneGeometry());
614
        } else {
615
            this.addVertex((Point) first.cloneGeometry());
616
        }
617
    }
618
    
619
}