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 / AbstractGeometry.java @ 47685

History | View | Annotate | Download (36 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;
24

    
25
import com.vividsolutions.jts.algorithm.CGAlgorithms;
26
import com.vividsolutions.jts.geom.Coordinate;
27
import com.vividsolutions.jts.io.geojson.GeoJsonWriter;
28
import com.vividsolutions.jts.operation.buffer.BufferParameters;
29
import com.vividsolutions.jts.operation.distance.DistanceOp;
30
import com.vividsolutions.jts.operation.overlay.snap.GeometrySnapper;
31
import com.vividsolutions.jts.operation.valid.IsValidOp;
32
import com.vividsolutions.jts.operation.valid.TopologyValidationError;
33
import java.awt.Rectangle;
34
import java.awt.Shape;
35
import java.awt.geom.AffineTransform;
36
import java.awt.geom.Rectangle2D;
37
import org.apache.commons.codec.binary.Hex;
38
import org.apache.commons.lang3.StringUtils;
39
import org.cresques.cts.IProjection;
40
import org.gvsig.fmap.crs.CRSFactory;
41
import org.gvsig.fmap.geom.Geometry;
42
import org.gvsig.fmap.geom.GeometryLocator;
43
import org.gvsig.fmap.geom.GeometryManager;
44
import org.gvsig.fmap.geom.aggregate.Aggregate;
45
import org.gvsig.fmap.geom.aggregate.MultiLine;
46
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
47
import org.gvsig.fmap.geom.complex.Complex;
48
import org.gvsig.fmap.geom.exception.CreateGeometryException;
49
import org.gvsig.fmap.geom.jts.operation.towkb.OGCWKBEncoder;
50
import org.gvsig.fmap.geom.jts.operation.towkb.PostGISEWKBEncoder;
51
import org.gvsig.fmap.geom.jts.operation.towkt.EWKTWriter;
52
import org.gvsig.fmap.geom.jts.primitive.Envelope2D;
53
import org.gvsig.fmap.geom.jts.primitive.Envelope3D;
54
import org.gvsig.fmap.geom.jts.primitive.point.Point3D;
55
import org.gvsig.fmap.geom.jts.util.GMLUtils;
56
import org.gvsig.fmap.geom.jts.util.JTSUtils;
57
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
58
import org.gvsig.fmap.geom.operation.GeometryOperationException;
59
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
60
import org.gvsig.fmap.geom.primitive.Curve;
61
import org.gvsig.fmap.geom.primitive.Envelope;
62
import org.gvsig.fmap.geom.primitive.OrientableCurve;
63
import org.gvsig.fmap.geom.primitive.OrientablePrimitive;
64
import org.gvsig.fmap.geom.primitive.OrientableSurface;
65
import org.gvsig.fmap.geom.primitive.Point;
66
import org.gvsig.fmap.geom.type.GeometryType;
67
import org.gvsig.tools.util.IsEmpty;
68
import org.slf4j.Logger;
69
import org.slf4j.LoggerFactory;
70

    
71
/**
72
 * @author gvSIG Team
73
 *
74
 */
75
@SuppressWarnings("UseSpecificCatch")
76
public abstract class AbstractGeometry implements GeometryJTS {
77

    
78
    protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractGeometry.class);
79

    
80
    /**
81
     *
82
     */
83
    private static final long serialVersionUID = 4999326772576222293L;
84

    
85
    private GeometryType geometryType;
86

    
87
    private IProjection projection;
88

    
89
    /**
90
     *
91
     * @param type
92
     * @param subtype
93
     */
94
    public AbstractGeometry(int type, int subtype) {
95
        try {
96
            this.geometryType = GeometryLocator.getGeometryManager().getGeometryType(type, subtype);
97
        } catch (Exception e) {
98
            // TODO: Ver de crear una excepcion para esto o si hay alguna en el API.
99
            throw new RuntimeException(e);
100
        }
101
    }
102
    
103
    public void setGeometryType(GeometryType geometryType) {
104
        this.geometryType = geometryType;
105
    }
106

    
107
    @Override
108
    public GeometryType getGeometryType() {
109
        return geometryType;
110
    }
111

    
112
    protected GeometryManager getManager() {
113
        return GeometryLocator.getGeometryManager();
114
    }
115

    
116
    /*
117
     * (non-Javadoc)
118
     *
119
     * @see org.gvsig.fmap.geom.Geometry#contains(org.gvsig.fmap.geom.Geometry)
120
     */
121
    @Override
122
    public boolean contains(Geometry geometry) throws GeometryOperationNotSupportedException,
123
            GeometryOperationException {
124
        if (!(geometry instanceof GeometryJTS)) {
125
            return false;
126
        }
127
        com.vividsolutions.jts.geom.Geometry theJTS = this.getJTS();
128
        if(this instanceof Aggregate){
129
            theJTS = theJTS.union();
130
        }
131
        
132
        com.vividsolutions.jts.geom.Geometry otherJTS = ((GeometryJTS)geometry).getJTS();
133
        if(geometry instanceof Aggregate){
134
            otherJTS = otherJTS.union();
135
        }
136
        return theJTS.contains(otherJTS);
137
    }
138

    
139
    /*
140
     * (non-Javadoc)
141
     *
142
     * @see java.lang.Comparable#compareTo(java.lang.Object)
143
     */
144
    @Override
145
    public int compareTo(Object o) {
146
        return getJTS().compareTo(((GeometryJTS) o).getJTS());
147
    }
148

    
149
    /*
150
     * (non-Javadoc)
151
     *
152
     * @see java.awt.Shape#contains(double, double)
153
     */
154
    @Override
155
    public boolean contains(double x, double y) {
156
        notifyDeprecated("Calling deprecated method of geometry contains from shape interface");
157
        Shape shp = getShape();
158
        return shp.contains(x, y);
159
    }
160

    
161
    /*
162
     * (non-Javadoc)
163
     *
164
     * @see java.awt.Shape#intersects(double, double, double, double)
165
     */
166
    @Override
167
    public boolean intersects(double x, double y, double w, double h) {
168

    
169
        notifyDeprecated("Calling deprecated method of geometry intersects from shape interface");
170
        Shape shp = this.getShape();
171
        return shp.intersects(x, y, w, h);
172
    }
173

    
174
    /*
175
     * (non-Javadoc)
176
     *
177
     * @see java.awt.Shape#contains(double, double, double, double)
178
     */
179
    @Override
180
    public boolean contains(double x, double y, double w, double h) {
181
        notifyDeprecated("Calling deprecated method of geometry contains from shape interface");
182
        Shape shp = this.getShape();
183
        return shp.contains(x, y, w, h);
184
    }
185

    
186
    /*
187
     * (non-Javadoc)
188
     *
189
     * @see java.awt.Shape#contains(java.awt.geom.Point2D)
190
     */
191
    @Override
192
    public boolean contains(java.awt.geom.Point2D p) {
193
        notifyDeprecated("Calling deprecated method of geometry contains from shape interface");
194
        Shape shp = this.getShape();
195
        return shp.contains(p);
196
    }
197

    
198
    /*
199
     * (non-Javadoc)
200
     *
201
     * @see java.awt.Shape#contains(java.awt.geom.Rectangle2D)
202
     */
203
    @Override
204
    public boolean contains(Rectangle2D r) {
205
        notifyDeprecated("Calling deprecated method of geometry contains from shape interface");
206
        Shape shp = this.getShape();
207
        return shp.contains(r);
208
    }
209

    
210
    /*
211
     * (non-Javadoc)
212
     *
213
     * @see org.gvsig.fmap.geom.Geometry#distance(org.gvsig.fmap.geom.Geometry)
214
     */
215
    @Override
216
    public double distance(org.gvsig.fmap.geom.Geometry other) throws GeometryOperationNotSupportedException,
217
            GeometryOperationException {
218
        return getJTS().distance(((GeometryJTS) other).getJTS());
219
    }
220

    
221
    /*
222
     * (non-Javadoc)
223
     *
224
     * @see
225
     * org.gvsig.fmap.geom.Geometry#isWithinDistance(org.gvsig.fmap.geom.Geometry
226
     * , double)
227
     */
228
    @Override
229
    public boolean isWithinDistance(org.gvsig.fmap.geom.Geometry other, double distance)
230
            throws GeometryOperationNotSupportedException, GeometryOperationException {
231
        return com.vividsolutions.jts.operation.distance.DistanceOp.isWithinDistance(this.getJTS(),
232
                ((GeometryJTS) other).getJTS(), distance);
233
    }
234

    
235
    /*
236
     * (non-Javadoc)
237
     *
238
     * @see org.gvsig.fmap.geom.Geometry#overlaps(org.gvsig.fmap.geom.Geometry)
239
     */
240
    @Override
241
    public boolean overlaps(org.gvsig.fmap.geom.Geometry geometry) throws GeometryOperationNotSupportedException,
242
            GeometryOperationException {
243
        // TODO: this method can be implemented throw invokeOperation
244
        return getJTS().overlaps(((GeometryJTS) geometry).getJTS());
245
    }
246

    
247
    @Override
248
    public boolean coveredBy(Geometry geometry) throws GeometryOperationNotSupportedException,
249
            GeometryOperationException {
250

    
251
        return getJTS().coveredBy(((GeometryJTS) geometry).getJTS());
252
    }
253

    
254
    @Override
255
    public boolean covers(Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException {
256
        // TODO: this method can be implemented throw invokeOperation
257
        return getJTS().covers(((GeometryJTS) geometry).getJTS());
258

    
259
    }
260

    
261
    @Override
262
    public boolean crosses(Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException {
263
        // TODO: this method can be implemented throw invokeOperation
264
        return getJTS().crosses(((GeometryJTS) geometry).getJTS());
265
    }
266

    
267
    @Override
268
    public boolean intersects(Geometry geometry) throws GeometryOperationNotSupportedException,
269
            GeometryOperationException {
270
        return getJTS().intersects(((GeometryJTS) geometry).getJTS());
271
    }
272

    
273
    @Override
274
    public boolean touches(Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException {
275
        // TODO: this method can be implemented throw invokeOperation
276
        return getJTS().touches(((GeometryJTS) geometry).getJTS());
277
    }
278

    
279
    @Override
280
    public boolean disjoint(Geometry geometry) throws GeometryOperationNotSupportedException,
281
            GeometryOperationException {
282
        // TODO: this method can be implemented throw invokeOperation
283
        return getJTS().disjoint(((GeometryJTS) geometry).getJTS());
284
    }
285

    
286
    @Override
287
    public boolean within(Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException {
288
        // TODO: this method can be implemented throw invokeOperation
289
        return getJTS().within(((GeometryJTS) geometry).getJTS());
290
    }
291

    
292
    @Override
293
    public double area() throws GeometryOperationNotSupportedException, GeometryOperationException {
294
        return getJTS().getArea();
295
    }
296

    
297
    @Override
298
    public double perimeter() throws GeometryOperationNotSupportedException, GeometryOperationException {
299
        return getJTS().getLength();
300
    }
301

    
302
    /*
303
     * (non-Javadoc)
304
     *
305
     * @see org.gvsig.fmap.geom.Geometry#intersects(java.awt.geom.Rectangle2D)
306
     */
307
    @Override
308
    public boolean intersects(Rectangle2D r) {
309
        double x = r.getMinX();
310
        double y = r.getMinY();
311
        double w = r.getWidth();
312
        double h = r.getHeight();
313

    
314
        return fastIntersects(x, y, w, h);
315
    }
316

    
317
    /*
318
     * (non-Javadoc)
319
     *
320
     * @see org.gvsig.fmap.geom.Geometry#fastIntersects(double, double, double,
321
     * double)
322
     */
323
    @Override
324
    public boolean fastIntersects(double x, double y, double w, double h) {
325
        com.vividsolutions.jts.geom.Geometry rect; 
326
        com.vividsolutions.jts.geom.Coordinate[] coord = new com.vividsolutions.jts.geom.Coordinate[5];
327
        coord[0] = new com.vividsolutions.jts.geom.Coordinate(x, y);
328
        coord[1] = new com.vividsolutions.jts.geom.Coordinate(x + w, y);
329
        coord[2] = new com.vividsolutions.jts.geom.Coordinate(x + w, y + w);
330
        coord[3] = new com.vividsolutions.jts.geom.Coordinate(x, y + w);
331
        coord[4] = new com.vividsolutions.jts.geom.Coordinate(x, y);
332
        rect = JTSUtils.createJTSPolygon(coord);
333

    
334
        return getJTS().intersects(rect);
335
    }
336

    
337
    /*
338
     * (non-Javadoc)
339
     *
340
     * @see org.gvsig.fmap.geom.Geometry#getEnvelope()
341
     */
342
    @Override
343
    public Envelope getEnvelope() {
344
        if (is3D()) {
345
            if(this.isEmpty()){
346
                return new Envelope3D(getProjection());
347
            }
348
            Coordinate[] coordinates = getJTS().getCoordinates();
349

    
350
            double minx = Double.POSITIVE_INFINITY;
351
            double miny = Double.POSITIVE_INFINITY;
352
            double minz = Double.POSITIVE_INFINITY;
353

    
354
            double maxx = Double.NEGATIVE_INFINITY;
355
            double maxy = Double.NEGATIVE_INFINITY;
356
            double maxz = Double.NEGATIVE_INFINITY;
357

    
358
            double x;
359
            double y;
360
            double z;
361

    
362
            for (Coordinate coordinate : coordinates) {
363
                x = coordinate.x;
364
                y = coordinate.y;
365
                z = coordinate.z;
366
                minx = Math.min(x, minx);
367
                miny = Math.min(y, miny);
368
                minz = Math.min(z, minz);
369
                maxx = Math.max(x, maxx);
370
                maxy = Math.max(y, maxy);
371
                maxz = Math.max(z, maxz);
372
            }
373

    
374
            if (minx <= maxx && miny <= maxy && (minz <= maxz || (Double.isNaN(minz) && Double.isNaN(maxz)) ) ) {
375
                Point min = new Point3D(minx, miny, minz);
376
                Point max = new Point3D(maxx, maxy, maxz);
377
                return new Envelope3D(min, max, this.getProjection());
378
            }
379
            return new Envelope3D(this.getProjection());
380
        } else {
381
            if(this.isEmpty()){
382
                return new Envelope2D(getProjection());
383
            }
384
            try {
385
                com.vividsolutions.jts.geom.Envelope envelope = getJTS().getEnvelopeInternal();
386
                return new Envelope2D(envelope, this.getProjection());
387
            } catch (Exception ex){
388
                try {
389
                    MultiLine lines = this.toLines();
390
                    return lines.getEnvelope();
391
                } catch (Exception ex2) {
392
                    throw ex;
393
                }
394
                
395
            }
396
        }
397
    }
398

    
399
    /*
400
     * (non-Javadoc)
401
     *
402
     * @see org.gvsig.fmap.geom.Geometry#isSimple()
403
     */
404
    @Override
405
    public boolean isSimple() {
406
        return this.getJTS().isSimple();
407
    }
408

    
409
    /*
410
     * (non-Javadoc)
411
     *
412
     * @see org.gvsig.fmap.geom.Geometry#isCCW()
413
     */
414
    @Override
415
    public boolean isCCW() throws GeometryOperationNotSupportedException, GeometryOperationException {
416
        return CGAlgorithms.isCCW(this.getJTS().getCoordinates());
417
    }
418

    
419
    /*
420
     * (non-Javadoc)
421
     *
422
     * @see org.gvsig.fmap.geom.Geometry#invokeOperation(int,
423
     * org.gvsig.fmap.geom.operation.GeometryOperationContext)
424
     */
425
    @Override
426
    public Object invokeOperation(int index, GeometryOperationContext ctx)
427
            throws GeometryOperationNotSupportedException, GeometryOperationException {
428
        return getManager().invokeOperation(index, this, ctx);
429

    
430
    }
431

    
432
    /*
433
     * (non-Javadoc)
434
     *
435
     * @see org.gvsig.fmap.geom.Geometry#invokeOperation(java.lang.String,
436
     * org.gvsig.fmap.geom.operation.GeometryOperationContext)
437
     */
438
    @Override
439
    public Object invokeOperation(String opName, GeometryOperationContext ctx)
440
            throws GeometryOperationNotSupportedException, GeometryOperationException {
441
        return getManager().invokeOperation(opName, this, ctx);
442

    
443
    }
444

    
445
    /*
446
     * (non-Javadoc)
447
     *
448
     * @see org.gvsig.fmap.geom.Geometry#getType()
449
     */
450
    @Override
451
    public int getType() {
452
        return this.getGeometryType().getType();
453
    }
454

    
455
    @Override
456
    public Object convertTo(String format) throws GeometryOperationNotSupportedException, GeometryOperationException {
457
        if( StringUtils.isEmpty(format) ) {
458
            throw new IllegalArgumentException("Can't accept null as format name.");
459
        }
460
        format = format.trim().toLowerCase();
461
        switch(format) {
462
            case "jts":
463
                return this.getJTS();
464
            case "wkb":
465
                return this.convertToWKB();
466
            case "hexwkb":
467
                return this.convertToHexWKB();
468
            case "ewkb":
469
                return this.convertToEWKB();
470
            case "wkt":
471
                return this.convertToWKT();
472
            case "gml":
473
                return GMLUtils.geometry2GML(this);
474
            case "json":
475
            case "geojson":
476
                return this.convertToGeoJson();
477
            default:
478
                throw new IllegalArgumentException("Format '"+format+"' not supported");
479
        }
480
        
481
    }
482
    
483
    @Override
484
    public byte[] convertToWKB() throws GeometryOperationNotSupportedException, GeometryOperationException {
485
        try {
486
            return new OGCWKBEncoder().encode(this);
487
        } catch (Exception e) {
488
            throw new GeometryOperationException(e);
489
        }
490
    }
491

    
492
    @Override
493
    public String convertToHexWKB() throws GeometryOperationNotSupportedException, GeometryOperationException {
494
        try {
495
            byte[] bytes = new OGCWKBEncoder().encode(this);
496
            return Hex.encodeHexString(bytes);
497
        } catch (Exception e) {
498
            throw new GeometryOperationException(e);
499
        }
500
    }
501
    
502
    public String convertToGeoJson() throws GeometryOperationNotSupportedException, GeometryOperationException {
503
        try {
504
            GeoJsonWriter writer = new GeoJsonWriter();
505
            writer.setEncodeCRS(true);
506
            return writer.write(this.getJTS());
507
        } catch (Exception e) {
508
            throw new GeometryOperationException(e);
509
        }
510
    }
511
    
512
    @Override
513
    public String convertToHexEWKB() throws GeometryOperationNotSupportedException, GeometryOperationException {
514
        try {
515
            byte[] bytes = new PostGISEWKBEncoder().encode(this);
516
            return Hex.encodeHexString(bytes);
517
        } catch (Exception e) {
518
            throw new GeometryOperationException(e);
519
        }
520
    }
521

    
522
    @Override
523
    public byte[] convertToWKBQuietly() {
524
        try {
525
            return new OGCWKBEncoder().encode(this);
526
        } catch (Exception e) {
527
            return null;
528
        }
529
    }
530
    
531
    @Override
532
    public String convertToHexWKBQuietly() {
533
        try {
534
            byte[] bytes = new OGCWKBEncoder().encode(this);
535
            return Hex.encodeHexString(bytes);
536
        } catch (Exception e) {
537
            return null;
538
        }
539
    }
540
    
541
    @Override
542
    public String convertToHexEWKBQuietly() {
543
        try {
544
            byte[] bytes = new PostGISEWKBEncoder().encode(this);
545
            return Hex.encodeHexString(bytes);
546
        } catch (Exception e) {
547
            return null;
548
        }
549
    }
550
    
551
    @Override
552
    public byte[] convertToWKB(int srs) throws GeometryOperationNotSupportedException, GeometryOperationException {
553
        /*
554
             * No se sabe si la especificaci?n de OGC soporta SRS. OGCWKBEncoder no.
555
         */
556

    
557
        try {
558
            return new OGCWKBEncoder().encode(this);
559
        } catch (Exception e) {
560
            throw new GeometryOperationException(e);
561
        }
562
    }
563

    
564
    @Override
565
    public byte[] convertToWKBForcingType(int srs, int type) throws GeometryOperationNotSupportedException,
566
            GeometryOperationException {
567
        /*
568
             * No se sabe si la especificaci?n de OGC soporta SRS. OGCWKBEncoder no.
569
         */
570
        Geometry geom = this;
571
        if (this.getType() != type) {
572
            com.vividsolutions.jts.geom.Geometry jts = getJTS();
573
            jts = JTSUtils.convertTypes(jts, this.getType(), type);
574

    
575
            geom = JTSUtils.createGeometry(this.getProjection(), jts);
576
        }
577
        try {
578
            return new OGCWKBEncoder().encode(geom);
579
        } catch (Exception e) {
580
            throw new GeometryOperationException(e);
581
        }
582

    
583
    }
584

    
585
    @Override
586
    public byte[] convertToEWKB() throws GeometryOperationNotSupportedException, GeometryOperationException {
587
        try {
588
            return new PostGISEWKBEncoder().encode(this);
589
        } catch (Exception e) {
590
            throw new GeometryOperationException(e);
591
        }
592

    
593
    }
594

    
595
    @Override
596
    public byte[] convertToEWKB(int srs) throws GeometryOperationNotSupportedException, GeometryOperationException {
597
        /*
598
             * No se sabe si la especificaci?n de OGC soporta SRS. OGCWKBEncoder no.
599
         */
600

    
601
        try {
602
            return new PostGISEWKBEncoder().encode(this);
603
        } catch (Exception e) {
604
            throw new GeometryOperationException(e);
605
        }
606
    }
607

    
608
    @Override
609
    public byte[] convertToEWKBForcingType(int srs, int type) throws GeometryOperationNotSupportedException,
610
            GeometryOperationException {
611
        /*
612
             * No se sabe si la especificaci?n de OGC soporta SRS. OGCWKBEncoder no.
613
         */
614
        Geometry geom = this;
615
        if (this.getType() != type) {
616
            com.vividsolutions.jts.geom.Geometry jts = getJTS();
617
            jts = JTSUtils.convertTypes(jts, this.getType(), type);
618

    
619
            geom = JTSUtils.createGeometry(this.getProjection(), jts);
620
        }
621
        try {
622
            return new PostGISEWKBEncoder().encode(geom);
623
        } catch (Exception e) {
624
            throw new GeometryOperationException(e);
625
        }
626

    
627
    }
628

    
629
    @Override
630
    public String convertToWKT() throws GeometryOperationNotSupportedException, GeometryOperationException {
631
        int subType = getGeometryType().getSubType();
632

    
633
        EWKTWriter writer; // = null;
634

    
635
        switch (subType) {
636
            case Geometry.SUBTYPES.GEOM3D:
637
                writer = new EWKTWriter(3, false);
638
                break;
639
            case Geometry.SUBTYPES.GEOM2DM:
640
                writer = new EWKTWriter(3, true);
641
                break;
642
            case Geometry.SUBTYPES.GEOM3DM:
643
                writer = new EWKTWriter(4, true);
644
                break;
645

    
646
            default:
647
                writer = new EWKTWriter(2, false);
648
                break;
649
        }
650
        com.vividsolutions.jts.geom.Geometry jts = getJTS();
651
        return writer.write(jts);
652
    }
653

    
654
    @Override
655
    public String convertToWKTQuietly() {
656
        try {
657
            return this.convertToWKT();
658
        } catch(Exception ex) {
659
            return null;
660
        }
661
    }
662

    
663
    @Override
664
    public org.gvsig.fmap.geom.Geometry buffer(double distance) throws GeometryOperationNotSupportedException,
665
        GeometryOperationException {
666
        if( distance==0 ) {
667
          return this;
668
        }
669
        return JTSUtils.createGeometry(this.getProjection(), getJTS().buffer(distance));
670
    }
671
    
672
    
673
    @Override
674
    public org.gvsig.fmap.geom.Geometry buffer(double distance, int joinStyle, boolean capButt) throws GeometryOperationNotSupportedException,
675
        GeometryOperationException {
676
        if( distance==0 ) {
677
          return this;
678
        }
679
        
680
        int quadrantSegments = JTSUtils.calculateQuadrantSegments(joinStyle);
681
        
682
        return JTSUtils.createGeometry(this.getProjection(), getJTS().buffer(
683
                distance, 
684
                quadrantSegments, 
685
                capButt ? BufferParameters.CAP_FLAT : BufferParameters.CAP_ROUND
686
        ));
687
    }
688

    
689
    /*
690
     * (non-Javadoc)
691
     *
692
     * @see org.gvsig.fmap.geom.Geometry#snapTo(org.gvsig.fmap.geom.Geometry,
693
     * double)
694
     */
695
    @Override
696
    public org.gvsig.fmap.geom.Geometry snapTo(org.gvsig.fmap.geom.Geometry other, double snapTolerance)
697
            throws GeometryOperationNotSupportedException, GeometryOperationException {
698
        Geometry result; // = null;
699
        GeometrySnapper snapper = new GeometrySnapper(getJTS());
700
        com.vividsolutions.jts.geom.Geometry jts_result = snapper.snapTo(((GeometryJTS) other).getJTS(), snapTolerance);
701
        result = JTSUtils.createGeometry(this.getProjection(), jts_result);
702
        return result;
703
    }
704

    
705
    /*
706
     * (non-Javadoc)
707
     *
708
     * @see org.gvsig.fmap.geom.Geometry#getInteriorPoint()
709
     */
710
    @Override
711
    public Point getInteriorPoint() throws GeometryOperationNotSupportedException, GeometryOperationException {
712

    
713
        com.vividsolutions.jts.geom.Geometry geometry = getJTS();
714
        com.vividsolutions.jts.geom.Point point = geometry.getInteriorPoint();
715
        Geometry result = JTSUtils.createGeometry(this.getProjection(), point);
716
        return (Point) result;
717
    }
718

    
719
    /*
720
     * (non-Javadoc)
721
     *
722
     * @see org.gvsig.fmap.geom.Geometry#isValid()
723
     */
724
    @Override
725
    public boolean isValid() {
726
        return getJTS().isValid();
727
    }
728

    
729
    @Override
730
    public ValidationStatus getValidationStatus() {
731
        DefaultValidationStatus status = new DefaultValidationStatus(ValidationStatus.VALID, null);
732
        com.vividsolutions.jts.geom.Geometry jtsgeom; // = null;
733
        try {
734
            jtsgeom = this.getJTS();
735
            IsValidOp validOp = new IsValidOp(jtsgeom);
736
            if (!validOp.isValid() ) {
737
                status.setValidationError(validOp.getValidationError());
738
            }
739
        } catch (Throwable ex) {
740
            status.setStatusCode(ValidationStatus.CURRUPTED);
741
            status.setMesage("The geometry is corrupted.");
742
            if (this instanceof OrientableSurface) {
743
                int vertices = ((OrientableSurface) this).getNumVertices();
744
                if (vertices < 3) {
745
                    status.setStatusCode(ValidationStatus.TOO_FEW_POINTS);
746
                    status.setMesage(TopologyValidationError.errMsg[TopologyValidationError.TOO_FEW_POINTS]);
747
                }
748
            } else if (this instanceof OrientableCurve) {
749
                int vertices = ((OrientableCurve) this).getNumVertices();
750
                if (vertices < 2) {
751
                    status.setStatusCode(ValidationStatus.TOO_FEW_POINTS);
752
                    status.setMesage(TopologyValidationError.errMsg[TopologyValidationError.TOO_FEW_POINTS]);
753
                }
754
            }
755
        }
756
        return status;
757
    }
758

    
759
    /*
760
     * (non-Javadoc)
761
     *
762
     * @see org.gvsig.fmap.geom.Geometry#makeValid()
763
     */
764
    @Override
765
    public org.gvsig.fmap.geom.Geometry makeValid() {
766
        try {
767
            ValidationStatus vs = this.getValidationStatus();
768
            if (vs.isValid()) {
769
                return this;
770
            }
771
            Geometry g; // = null;
772
            switch (vs.getStatusCode()) {
773
                case Geometry.ValidationStatus.RING_SELF_INTERSECTION:
774
                case Geometry.ValidationStatus.SELF_INTERSECTION:
775
                    g = this.buffer(0);
776
                    if (g.isValid()) {
777
                        return g;
778
                    }
779
                    break;
780

    
781
                case Geometry.ValidationStatus.TOO_FEW_POINTS:
782
                    if (this instanceof OrientableCurve) {
783
                        int vertices = ((OrientableCurve) this).getNumVertices();
784
                        if (vertices < 2) {
785
                            return null; // new
786
                            // DefaultNullGeometry(this.getGeometryType());
787
                        }
788
                    }
789
                    if (this instanceof OrientableSurface) {
790
                        int vertices = ((OrientableSurface) this).getNumVertices();
791
                        if (vertices < 3) {
792
                            return null; // new
793
                            // DefaultNullGeometry(this.getGeometryType());
794
                        }
795
                    }
796
            }
797
        } catch (Exception ex) {
798
            return null;
799
        }
800
        return null;
801
    }
802

    
803
    /*
804
     * (non-Javadoc)
805
     *
806
     * @see org.gvsig.fmap.geom.Geometry#getBounds2D()
807
     */
808
    @Override
809
    public Rectangle2D getBounds2D() {
810
        com.vividsolutions.jts.geom.Envelope envInternal = getJTS().getEnvelopeInternal();
811
        return new Rectangle2D.Double(envInternal.getMinX(), envInternal.getMinY(), envInternal.getWidth(),
812
                envInternal.getHeight());
813
    }
814

    
815
    /*
816
     * (non-Javadoc)
817
     *
818
     * @see java.awt.Shape#getBounds()
819
     */
820
    @Override
821
    public Rectangle getBounds() {
822
        return this.getShape().getBounds();
823
    }
824

    
825
    /*
826
     * (non-Javadoc)
827
     *
828
     * @see org.gvsig.fmap.geom.Geometry#getInternalShape()
829
     */
830
    @Override
831
    public Shape getInternalShape() {
832
        return getShape();
833
    }
834

    
835
    @Override
836
    public void rotate(double radAngle, double basex, double basey) {
837

    
838
        AffineTransform at = new AffineTransform();
839
        at.rotate(radAngle, basex, basey);
840
        this.transform(at);
841
    }
842

    
843
    @Override
844
    public void move(double dx, double dy) {
845

    
846
        AffineTransform at = new AffineTransform();
847
        at.translate(dx, dy);
848
        this.transform(at);
849
    }
850

    
851
    @Override
852
    public void scale(Point basePoint, double sx, double sy) {
853

    
854
        AffineTransform at = new AffineTransform();
855
        at.setToTranslation(basePoint.getX(), basePoint.getY());
856
        at.scale(sx, sy);
857
        at.translate(-basePoint.getX(), -basePoint.getY());
858
        this.transform(at);
859
    }
860

    
861
    @Override
862
    public Geometry[] closestPoints(Geometry other) throws GeometryOperationNotSupportedException,
863
            GeometryOperationException {
864
        Point[] points;
865

    
866
        Coordinate[] jts_points = DistanceOp.nearestPoints(getJTS(), ((GeometryJTS) other).getJTS());
867
        points = new Point[jts_points.length];
868
        for (int i = 0; i < jts_points.length; i++) {
869
            try {
870
                points[i] = JTSUtils.createPoint(this.getGeometryType(), this.getProjection(), jts_points[i]);
871
            } catch (CreateGeometryException e) {
872
                throw new GeometryOperationException(e);
873
            }
874
        }
875

    
876
        return (Geometry[]) points;
877
    }
878

    
879
    @Override
880
    public Geometry convexHull() throws GeometryOperationNotSupportedException, GeometryOperationException {
881
        return JTSUtils.createGeometry(this.getProjection(), getJTS().convexHull(), null);
882
    }
883

    
884
    @Override
885
    public Geometry difference(Geometry other) throws GeometryOperationNotSupportedException,
886
            GeometryOperationException {
887
        com.vividsolutions.jts.geom.Geometry otherJTS = ((GeometryJTS) other).getJTS();
888
        if(other instanceof Aggregate){
889
            otherJTS = otherJTS.union();
890
        }
891
            return JTSUtils.createGeometry(this.getProjection(), getJTS().difference(otherJTS), null);
892
        }
893

    
894
    @Override
895
    public Geometry intersection(Geometry other) throws GeometryOperationNotSupportedException,
896
            GeometryOperationException {
897
        com.vividsolutions.jts.geom.Geometry otherJTS = ((GeometryJTS) other).getJTS();
898
        if(other instanceof Aggregate){
899
            otherJTS = otherJTS.union();
900
        }
901
        return JTSUtils.createGeometry(this.getProjection(), getJTS().intersection(otherJTS), null);
902
    }
903

    
904
    @Override
905
    public Geometry union(Geometry other) throws GeometryOperationNotSupportedException, GeometryOperationException {
906
        try {
907
            com.vividsolutions.jts.geom.Geometry jts = getJTS();
908
            com.vividsolutions.jts.geom.Geometry otherJts = ((GeometryJTS)other).getJTS();
909
            
910
            if(jts.isValid() && otherJts.isValid()){
911
                return JTSUtils.createGeometry(this.getProjection(), jts.union(otherJts), this.getGeometryType());
912
            }
913
            MultiPrimitive geom = this.getManager().createMultiPrimitive(geometryType);
914
            geom.addPrimitives(this);
915
            geom.addPrimitives(other);
916
            return geom;
917
        } catch (CreateGeometryException ex) {
918
            throw new GeometryOperationException(
919
                    this.getGeometryType().getType(), 
920
                    this.getManager().getGeometryOperationCode(Geometry.OPERATIONS.UNION), 
921
                    ex);
922
        }
923
    }
924

    
925
    @Override
926
    public org.gvsig.fmap.geom.primitive.Point centroid() throws GeometryOperationNotSupportedException,
927
            GeometryOperationException {
928
        try {
929
            return JTSUtils.createPoint(this.getGeometryType(), this.getProjection(), getJTS().getCentroid().getCoordinate());
930
        } catch (CreateGeometryException e) {
931
            throw new GeometryOperationException(e);
932
        }
933
    }
934

    
935
    protected void notifyDeprecated(String message) {
936
        LOGGER.info(message);
937

    
938
    }
939

    
940

    
941
    @Override
942
    public boolean ensureOrientation(boolean ccw) throws GeometryOperationNotSupportedException, GeometryOperationException {
943
        if (ccw != isCCW()) {
944
            flip();
945
            return true;
946
        }
947
        return false;
948
    }
949

    
950
    /* (non-Javadoc)
951
     * @see org.gvsig.fmap.geom.jts.GeometryJTS#out(org.gvsig.fmap.geom.Geometry)
952
     */
953
    @Override
954
    public boolean out(Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException {
955
        GeometryJTS otherJtsGeom = (GeometryJTS) geometry;
956
        return (!contains(otherJtsGeom) && !intersects(otherJtsGeom));
957
    }
958

    
959
    @Override
960
    public boolean equals(Object obj) {
961
        if (obj instanceof GeometryJTS) {
962
            return this.getJTS().equals(((GeometryJTS) obj).getJTS());
963
        }
964
        return false;
965
    }
966

    
967
    @Override
968
    public String toString() {
969
        return this.getGeometryType().getFullName();
970
    }
971

    
972
    @Override
973
    public IProjection getProjection() {
974
        return this.projection;
975
    }
976

    
977
    @Override
978
    public void setProjectionIffNull(IProjection projection) {
979
        if (this.projection == null) {
980
            this.projection = projection;
981
        }
982
    }
983

    
984
    @Override
985
    public void setProjection(IProjection projection) {
986
        this.projection = projection;
987
    }
988

    
989
    @Override
990
    public void setProjection(String projection) {
991
        IProjection proj = CRSFactory.getCRS("EPSG:4326");
992
        this.setProjection(proj);
993
    }
994

    
995
    @Override
996
    @SuppressWarnings("CloneDoesntCallSuperClone")
997
    public Geometry clone() throws CloneNotSupportedException {
998
        return this.cloneGeometry();
999
    }
1000

    
1001
    @Override
1002
    public Geometry boundary() {
1003
        return JTSUtils.createGeometry(this.getProjection(), getJTS().getBoundary(), null);
1004
    }
1005
    
1006
    @Override
1007
    public Geometry fix() {
1008
        try {
1009
            ValidationStatus status = this.getValidationStatus();
1010
            if(status.isValid()) {
1011
                return this.cloneGeometry();
1012
            }
1013
            int statusCode = status.getStatusCode();
1014
            Geometry fixed;
1015
            switch (statusCode) {
1016
                case ValidationStatus.VALID:
1017
                    return this.cloneGeometry();
1018
                case ValidationStatus.SELF_INTERSECTION:
1019
                case ValidationStatus.RING_SELF_INTERSECTION:
1020
                    fixed = this.buffer(Double.MIN_VALUE);
1021
                    break;
1022
                case ValidationStatus.CURRUPTED:
1023
                case ValidationStatus.UNKNOW:
1024
                case ValidationStatus.DISCONNECTED_INTERIOR:
1025
                case ValidationStatus.DUPLICATE_RINGS:
1026
                case ValidationStatus.HOLE_OUTSIDE_SHELL:
1027
                case ValidationStatus.INVALID_COORDINATE:
1028
                case ValidationStatus.NESTED_HOLES:
1029
                case ValidationStatus.NESTED_SHELLS:
1030
                case ValidationStatus.RING_NOT_CLOSED:
1031
                case ValidationStatus.TOO_FEW_POINTS:
1032
                default:
1033
                    return null;
1034
            }
1035
            if(!fixed.isValid()){
1036
                return null;
1037
            }
1038
            if(this.getGeometryType().getType() != fixed.getGeometryType().getType()){
1039
                return null;
1040
            }
1041
            return fixed;
1042
        } catch (Exception ex) {
1043
            return null;
1044
        }
1045
    }
1046

    
1047
    @Override
1048
    public Geometry forceSubtype(int subtype) throws GeometryOperationNotSupportedException, GeometryOperationException {
1049
        switch(subtype){
1050
            case Geometry.SUBTYPES.GEOM2D:
1051
                return force2D();
1052
            case Geometry.SUBTYPES.GEOM2DM:
1053
                return force2DM();
1054
            case Geometry.SUBTYPES.GEOM3D:
1055
                return force3D();
1056
            case Geometry.SUBTYPES.GEOM3DM:
1057
                return force3DM();
1058
        }
1059
        return this;
1060
    }
1061
    
1062
    protected abstract Geometry force2DM() throws GeometryOperationNotSupportedException, GeometryOperationException;
1063
    
1064
    protected abstract Geometry force3D() throws GeometryOperationNotSupportedException, GeometryOperationException;
1065
    
1066
    protected abstract Geometry force3DM() throws GeometryOperationNotSupportedException, GeometryOperationException;
1067

    
1068
    @Override
1069
    public boolean isEmpty() {
1070
        if(this instanceof Aggregate) {
1071
            if(((Aggregate)this).getPrimitivesNumber()<1){
1072
                return true;
1073
            }
1074
        } else if(this instanceof Complex) {
1075
            if(((Complex)this).getPrimitivesNumber()<1){
1076
                return true;
1077
            }
1078
        } else if(this instanceof OrientablePrimitive) {
1079
            return ((OrientablePrimitive)this).isEmpty();
1080
        }
1081
        return false;
1082
    }
1083
    
1084
    
1085
    
1086
}