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

History | View | Annotate | Download (15.3 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.PathIterator;
28
import java.util.Collections;
29
import java.util.Iterator;
30

    
31
import com.vividsolutions.jts.geom.Coordinate;
32
import java.awt.geom.GeneralPath;
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
    protected PointJTS anyVertex;
68

    
69
    /**
70
    *
71
    */
72
    protected AbstractLine(int subtype) {
73
        super(Geometry.TYPES.LINE, subtype);
74
    }
75

    
76
    /**
77
     * @param type
78
     * @param subtype
79
     */
80
    public AbstractLine(int type, int subtype) {
81
        super(type, subtype);
82
    }
83

    
84
    /*
85
     * (non-Javadoc)
86
     *
87
     * @see org.gvsig.fmap.geom.jts.GeometryJTS#getJTS()
88
     */
89
    public com.vividsolutions.jts.geom.Geometry getJTS() {
90
        return JTSUtils.createJTSLineString(coordinates);
91
    }
92

    
93
    /*
94
     * (non-Javadoc)
95
     *
96
     * @see
97
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#addVertex(org.gvsig
98
     * .fmap.geom.primitive.Point)
99
     */
100
    public void addVertex(Point point) {
101
        point = fixPoint(point);
102
        coordinates.add(((PointJTS) point).getJTSCoordinate());
103
        anyVertex = (PointJTS) point;
104
    }
105

    
106
    /*
107
     * (non-Javadoc)
108
     *
109
     * @see
110
     * org.gvsig.fmap.geom.primitive.Curve#setPoints(org.gvsig.fmap.geom.primitive
111
     * .Point, org.gvsig.fmap.geom.primitive.Point)
112
     */
113
    public void setPoints(Point initialPoint, Point endPoint) {
114
        initialPoint = fixPoint(initialPoint);
115
        endPoint = fixPoint(endPoint);
116
        coordinates.clear();
117
        addVertex(initialPoint);
118
        addVertex(endPoint);
119
    }
120

    
121
    /**
122
     * @param initialPoint
123
     * @return
124
     */
125
    protected abstract Point fixPoint(Point point);
126

    
127
    /*
128
     * (non-Javadoc)
129
     *
130
     * @see
131
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#getCoordinateAt(int,
132
     * int)
133
     */
134
    public double getCoordinateAt(int index, int dimension) {
135
        return coordinates.getOrdinate(index, dimension);
136
    }
137

    
138
    /*
139
     * (non-Javadoc)
140
     *
141
     * @see
142
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#setCoordinateAt(int,
143
     * int, double)
144
     */
145
    public void setCoordinateAt(int index, int dimension, double value) {
146
        coordinates.setOrdinate(index, dimension, value);
147
    }
148

    
149
    /*
150
     * (non-Javadoc)
151
     *
152
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#removeVertex(int)
153
     */
154
    public void removeVertex(int index) {
155
        coordinates.remove(index);
156
    }
157

    
158
    /*
159
     * (non-Javadoc)
160
     *
161
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#getNumVertices()
162
     */
163
    public int getNumVertices() {
164
        return coordinates.size();
165
    }
166

    
167
    /*
168
     * (non-Javadoc)
169
     *
170
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#insertVertex(int,
171
     * org.gvsig.fmap.geom.primitive.Point)
172
     */
173
    public void insertVertex(int index, Point p) {
174
        p = fixPoint(p);
175
        coordinates.add(index, ((PointJTS) p).getJTSCoordinate());
176
    }
177

    
178
    /*
179
     * (non-Javadoc)
180
     *
181
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#setVertex(int,
182
     * org.gvsig.fmap.geom.primitive.Point)
183
     */
184
    public void setVertex(int index, Point p) {
185
        p = fixPoint(p);
186
        coordinates.set(index, ((PointJTS) p).getJTSCoordinate());
187
    }
188

    
189
    /*
190
     * (non-Javadoc)
191
     *
192
     * @see
193
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#setGeneralPath(org.
194
     * gvsig.fmap.geom.primitive.GeneralPathX)
195
     */
196
    public void setGeneralPath(GeneralPathX generalPathX) {
197
        PathIterator it = generalPathX.getPathIterator(null);
198
        double[] segment = new double[6];
199
        int i = 0;
200
        while(!it.isDone()){
201
            int type = it.currentSegment(segment);
202
            if(i==0){
203
                switch (type) {
204
                case IGeneralPathX.SEG_MOVETO:
205
                    Point p = new Point2D(segment[0], segment[1]);
206
                    p = fixPoint(p);
207
                    coordinates.add(((PointJTS)p).getJTSCoordinate());
208
                    break;
209
                default:
210
                    String message = StringUtils.replace("Type of segment %(segment)s isn't SEG_MOVETO.","%(segment)s",String.valueOf(i));
211
                    logger.warn(message);
212
                    throw new RuntimeException(message);
213
                }
214
            } else {
215
                //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.
216
                Point p;
217
                switch (type) {
218
                case IGeneralPathX.SEG_LINETO:
219
                    p = new Point2D(segment[0], segment[1]);
220
                    p = fixPoint(p);
221
                    coordinates.add(((PointJTS)p).getJTSCoordinate());
222
                    break;
223
                case IGeneralPathX.SEG_QUADTO:
224
                    for (int j = 0; j <= 1; j++) {
225
                        p = new Point2D(segment[i], segment[i+1]);
226
                        p = fixPoint(p);
227
                        coordinates.add(((PointJTS) p).getJTSCoordinate());
228
                    }
229
                    break;
230
                case IGeneralPathX.SEG_CUBICTO:
231
                    for (int j = 0; j <= 2; j++) {
232
                        p = new Point2D(segment[i], segment[i+1]);
233
                        p = fixPoint(p);
234
                        coordinates.add(((PointJTS) p).getJTSCoordinate());
235
                    }
236
                    break;
237
                case IGeneralPathX.SEG_CLOSE:
238
                    coordinates.add(coordinates.get(0));
239
                    break;
240
                default:
241
                    String message = StringUtils.replace("The general path has a gap in segment %(segment)s.","%(segment)s",String.valueOf(i));
242
                    logger.warn(message);
243
                    throw new RuntimeException(message);
244
                }
245
            }
246
            it.next();
247
            i++;
248
        }
249
    }
250

    
251
    /*
252
     * (non-Javadoc)
253
     *
254
     * @see
255
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#addMoveToVertex(org
256
     * .gvsig.fmap.geom.primitive.Point)
257
     */
258
    public void addMoveToVertex(Point point) {
259
        notifyDeprecated("Calling deprecated metohd addMoveToVertex in Line");
260
        throw new UnsupportedOperationException();
261
    }
262

    
263
    /*
264
     * (non-Javadoc)
265
     *
266
     * @see org.gvsig.fmap.geom.primitive.OrientablePrimitive#closePrimitive()
267
     */
268
    public void closePrimitive() {
269
        if (!coordinates.isEmpty() && !coordinates.get(0).equals(coordinates.get(coordinates.size()-1))) {
270
            coordinates.add((Coordinate)coordinates.get(0).clone());
271
        }
272
    }
273

    
274
    /*
275
     * (non-Javadoc)
276
     *
277
     * @see
278
     * org.gvsig.fmap.geom.primitive.OrientablePrimitive#ensureCapacity(int)
279
     */
280
    public void ensureCapacity(int capacity) {
281
        this.coordinates.ensureCapacity(capacity);
282
    }
283

    
284
    /*
285
     * (non-Javadoc)
286
     *
287
     * @see org.gvsig.fmap.geom.Geometry#reProject(org.cresques.cts.ICoordTrans)
288
     */
289
    public void reProject(ICoordTrans ct) {
290
        if (ct == null) {
291
            return;
292
        }
293
        for (Iterator<Coordinate> iterator = coordinates.iterator(); iterator.hasNext();) {
294
            Coordinate coordinate = (Coordinate) iterator.next();
295

    
296
            java.awt.geom.Point2D p = new java.awt.geom.Point2D.Double(coordinate.x, coordinate.y);
297
            try {
298
                p = ct.convert(p, p);
299
                coordinate.x = p.getX();
300
                coordinate.y = p.getY();
301
            } catch (Exception exc) {
302
                /*
303
                 * This can happen when the reprojection lib is unable
304
                 * to reproject (for example the source point
305
                 * is out of the valid range and some computing
306
                 * problem happens)
307
                 */
308
                throw new ReprojectionRuntimeException(ct.getPOrig(), ct.getPDest(), p, exc);
309
            }
310
        }
311
    }
312

    
313
    /*
314
     * (non-Javadoc)
315
     *
316
     * @see
317
     * org.gvsig.fmap.geom.Geometry#transform(java.awt.geom.AffineTransform)
318
     */
319
    public void transform(AffineTransform at) {
320
        if (at == null) {
321
            return;
322
        }
323

    
324
        for (int i = 0; i < coordinates.size(); i++) {
325
            Coordinate coordinate = coordinates.get(i);
326
            java.awt.geom.Point2D p = new java.awt.geom.Point2D.Double(coordinate.x, coordinate.y);
327

    
328
            at.transform(p, p);
329
            coordinate.x = p.getX();
330
            coordinate.y = p.getY();
331

    
332
        }
333
    }
334

    
335
    /*
336
     * (non-Javadoc)
337
     *
338
     * @see org.gvsig.fmap.geom.Geometry#getDimension()
339
     */
340
    public int getDimension() {
341
        return anyVertex.getDimension();
342
    }
343

    
344
    /*
345
     * (non-Javadoc)
346
     *
347
     * @see org.gvsig.fmap.geom.Geometry#getShape(java.awt.geom.AffineTransform)
348
     */
349
    public Shape getShape(AffineTransform affineTransform) {
350
        if( this.coordinates.isEmpty() ) {
351
            // Esto no deberia de pasar, se trataria de una geometria
352
            // corrupta.
353
            return new GeneralPath();
354
        }
355
        return new DefaultGeneralPathX(getPathIterator(affineTransform),false,0);
356
    }
357

    
358
    /*
359
     * (non-Javadoc)
360
     *
361
     * @see org.gvsig.fmap.geom.Geometry#getShape()
362
     */
363
    public Shape getShape() {
364
        return new DefaultGeneralPathX(getPathIterator(null),false,0);
365
    }
366

    
367

    
368
    /*
369
     * (non-Javadoc)
370
     *
371
     * @see
372
     * org.gvsig.fmap.geom.Geometry#getPathIterator(java.awt.geom.AffineTransform
373
     * )
374
     */
375
    public PathIterator getPathIterator(AffineTransform at) {
376
        LineIterator pi = new LineIterator(at);
377
        return pi;
378
    }
379

    
380
    /*
381
     * (non-Javadoc)
382
     *
383
     * @see
384
     * org.gvsig.fmap.geom.Geometry#getPathIterator(java.awt.geom.AffineTransform
385
     * , double)
386
     */
387
    public PathIterator getPathIterator(AffineTransform at, double flatness) {
388
        return getPathIterator(at);
389
    }
390

    
391
    /*
392
     * (non-Javadoc)
393
     *
394
     * @see org.gvsig.fmap.geom.Geometry#getGeneralPath()
395
     */
396
    public GeneralPathX getGeneralPath() {
397
        return new DefaultGeneralPathX(getPathIterator(null), false, 0);
398
    }
399

    
400
    protected class LineIterator extends GeneralPathXIterator {
401

    
402
        /** Transform applied on the coordinates during iteration */
403
        private AffineTransform at;
404

    
405
        /** True when the point has been read once */
406
        private boolean done;
407
        private int index = 0;
408

    
409
        /**
410
         * Creates a new PointIterator object.
411
         *
412
         * @param p
413
         *            The polygon
414
         * @param at
415
         *            The affine transform applied to coordinates during
416
         *            iteration
417
         */
418
        public LineIterator(AffineTransform at) {
419
            super(new GeneralPathX());
420
            if (at == null) {
421
                at = new AffineTransform();
422
            }
423

    
424
            this.at = at;
425
            done = false;
426
        }
427

    
428
        /**
429
         * Return the winding rule for determining the interior of the path.
430
         *
431
         * @return <code>WIND_EVEN_ODD</code> by default.
432
         */
433
        public int getWindingRule() {
434
            return PathIterator.WIND_EVEN_ODD;
435
        }
436

    
437
        /**
438
         * @see java.awt.geom.PathIterator#next()
439
         */
440
        public void next() {
441
            done = (coordinates.size() == ++index);
442
        }
443

    
444
        /**
445
         * @see java.awt.geom.PathIterator#isDone()
446
         */
447
        public boolean isDone() {
448
            return done;
449
        }
450

    
451
        /**
452
         * @see java.awt.geom.PathIterator#currentSegment(double[])
453
         */
454
        public int currentSegment(double[] coords) {
455
            coords[0] = coordinates.getX(index);
456
            coords[1] = coordinates.getY(index);
457
            at.transform(coords, 0, coords, 0, 1);
458

    
459
            if (index == 0) {
460
                return PathIterator.SEG_MOVETO;
461
            } else {
462
                return PathIterator.SEG_LINETO;
463
            }
464
        }
465

    
466
        /*
467
         * (non-Javadoc)
468
         *
469
         * @see java.awt.geom.PathIterator#currentSegment(float[])
470
         */
471
        public int currentSegment(float[] coords) {
472
            coords[0] = (float) coordinates.getX(index);
473
            coords[1] = (float) coordinates.getY(index);
474
            at.transform(coords, 0, coords, 0, 1);
475

    
476
            if (index == 0) {
477
                return PathIterator.SEG_MOVETO;
478
            } else {
479
                return PathIterator.SEG_LINETO;
480
            }
481
        }
482
    }
483

    
484
    /*
485
     * (non-Javadoc)
486
     *
487
     * @see org.gvsig.fmap.geom.jts.GeometryJTS#is3D()
488
     */
489
    public boolean is3D() {
490
        return anyVertex.is3D();
491
    }
492

    
493
    protected boolean isClosed(){
494
        return coordinates.get(0).equals(coordinates.get(coordinates.size()-1));
495
    }
496

    
497
    /* (non-Javadoc)
498
     * @see org.gvsig.fmap.geom.jts.GeometryJTS#flip()
499
     */
500
    public void flip() throws GeometryOperationNotSupportedException, GeometryOperationException {
501
        Collections.reverse(coordinates);
502
    }
503

    
504
    protected ArrayListCoordinateSequence cloneCoordinates() {
505
        ArrayListCoordinateSequence cloned = new ArrayListCoordinateSequence();
506
        cloned.ensureCapacity(coordinates.size());
507
        for (Iterator iterator = coordinates.iterator(); iterator.hasNext();) {
508
            Coordinate coordinate = (Coordinate) iterator.next();
509
            cloned.add((Coordinate)coordinate.clone());
510
        }
511
        return cloned;
512
    }
513

    
514
}