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

History | View | Annotate | Download (33.7 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 java.util.logging.Level;
38
import org.apache.commons.codec.binary.Hex;
39
import org.apache.commons.lang3.StringUtils;
40
import org.cresques.cts.IProjection;
41
import org.gvsig.fmap.crs.CRSFactory;
42
import org.gvsig.fmap.geom.Geometry;
43
import org.gvsig.fmap.geom.GeometryLocator;
44
import org.gvsig.fmap.geom.GeometryManager;
45
import org.gvsig.fmap.geom.GeometryUtils;
46
import org.gvsig.fmap.geom.aggregate.Aggregate;
47
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
48
import org.gvsig.fmap.geom.complex.Complex;
49
import org.gvsig.fmap.geom.exception.CreateGeometryException;
50
import org.gvsig.fmap.geom.jts.operation.towkb.OGCWKBEncoder;
51
import org.gvsig.fmap.geom.jts.operation.towkb.PostGISEWKBEncoder;
52
import org.gvsig.fmap.geom.jts.operation.towkt.EWKTWriter;
53
import org.gvsig.fmap.geom.jts.primitive.Envelope2D;
54
import org.gvsig.fmap.geom.jts.primitive.Envelope3D;
55
import org.gvsig.fmap.geom.jts.primitive.point.Point3D;
56
import org.gvsig.fmap.geom.jts.util.GMLUtils;
57
import org.gvsig.fmap.geom.jts.util.JTSUtils;
58
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
59
import org.gvsig.fmap.geom.operation.GeometryOperationException;
60
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
61
import org.gvsig.fmap.geom.primitive.Envelope;
62
import org.gvsig.fmap.geom.primitive.OrientableCurve;
63
import org.gvsig.fmap.geom.primitive.OrientableSurface;
64
import org.gvsig.fmap.geom.primitive.Point;
65
import org.gvsig.fmap.geom.type.GeometryType;
66
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
68

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

    
76
    protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractGeometry.class);
77

    
78
    /**
79
     *
80
     */
81
    private static final long serialVersionUID = 4999326772576222293L;
82

    
83
    private GeometryType geometryType;
84

    
85
    private IProjection projection;
86

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

    
105
    @Override
106
    public GeometryType getGeometryType() {
107
        return geometryType;
108
    }
109

    
110
    protected GeometryManager getManager() {
111
        return GeometryLocator.getGeometryManager();
112
    }
113

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

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

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

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

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

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

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

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

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

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

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

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

    
249
        return getJTS().coveredBy(((GeometryJTS) geometry).getJTS());
250
    }
251

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

    
257
    }
258

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

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

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

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

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

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

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

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

    
312
        return fastIntersects(x, y, w, h);
313
    }
314

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

    
332
        return getJTS().intersects(rect);
333
    }
334

    
335
    /*
336
     * (non-Javadoc)
337
     *
338
     * @see org.gvsig.fmap.geom.Geometry#getEnvelope()
339
     */
340
    @Override
341
    public Envelope getEnvelope() {
342
        if (is3D()) {
343
            Coordinate[] coordinates = getJTS().getCoordinates();
344

    
345
            double minx = Double.POSITIVE_INFINITY;
346
            double miny = Double.POSITIVE_INFINITY;
347
            double minz = Double.POSITIVE_INFINITY;
348

    
349
            double maxx = Double.NEGATIVE_INFINITY;
350
            double maxy = Double.NEGATIVE_INFINITY;
351
            double maxz = Double.NEGATIVE_INFINITY;
352

    
353
            double x;
354
            double y;
355
            double z;
356

    
357
            for (Coordinate coordinate : coordinates) {
358
                x = coordinate.x;
359
                y = coordinate.y;
360
                z = coordinate.z;
361
                minx = Math.min(x, minx);
362
                miny = Math.min(y, miny);
363
                minz = Math.min(z, minz);
364
                maxx = Math.max(x, maxx);
365
                maxy = Math.max(y, maxy);
366
                maxz = Math.max(z, maxz);
367
            }
368

    
369
            if (minx <= maxx && miny <= maxy && minz <= maxz) {
370
                Point min = new Point3D(minx, miny, minz);
371
                Point max = new Point3D(maxx, maxy, maxz);
372
                return new Envelope3D(min, max, this.getProjection());
373
            }
374
            return new Envelope3D(this.getProjection());
375
        } else {
376
            com.vividsolutions.jts.geom.Envelope envelope = getJTS().getEnvelopeInternal();
377
            return new Envelope2D(envelope, this.getProjection());
378
        }
379
    }
380

    
381
    /*
382
     * (non-Javadoc)
383
     *
384
     * @see org.gvsig.fmap.geom.Geometry#isSimple()
385
     */
386
    @Override
387
    public boolean isSimple() {
388
        return this.getJTS().isSimple();
389
    }
390

    
391
    /*
392
     * (non-Javadoc)
393
     *
394
     * @see org.gvsig.fmap.geom.Geometry#isCCW()
395
     */
396
    @Override
397
    public boolean isCCW() throws GeometryOperationNotSupportedException, GeometryOperationException {
398
        return CGAlgorithms.isCCW(this.getJTS().getCoordinates());
399
    }
400

    
401
    /*
402
     * (non-Javadoc)
403
     *
404
     * @see org.gvsig.fmap.geom.Geometry#invokeOperation(int,
405
     * org.gvsig.fmap.geom.operation.GeometryOperationContext)
406
     */
407
    @Override
408
    public Object invokeOperation(int index, GeometryOperationContext ctx)
409
            throws GeometryOperationNotSupportedException, GeometryOperationException {
410
        return getManager().invokeOperation(index, this, ctx);
411

    
412
    }
413

    
414
    /*
415
     * (non-Javadoc)
416
     *
417
     * @see org.gvsig.fmap.geom.Geometry#invokeOperation(java.lang.String,
418
     * org.gvsig.fmap.geom.operation.GeometryOperationContext)
419
     */
420
    @Override
421
    public Object invokeOperation(String opName, GeometryOperationContext ctx)
422
            throws GeometryOperationNotSupportedException, GeometryOperationException {
423
        return getManager().invokeOperation(opName, this, ctx);
424

    
425
    }
426

    
427
    /*
428
     * (non-Javadoc)
429
     *
430
     * @see org.gvsig.fmap.geom.Geometry#getType()
431
     */
432
    @Override
433
    public int getType() {
434
        return this.getGeometryType().getType();
435
    }
436

    
437
    @Override
438
    public Object convertTo(String format) throws GeometryOperationNotSupportedException, GeometryOperationException {
439
        if( StringUtils.isEmpty(format) ) {
440
            throw new IllegalArgumentException("Can't accept null as format name.");
441
        }
442
        format = format.trim().toLowerCase();
443
        switch(format) {
444
            case "jts":
445
                return this.getJTS();
446
            case "wkb":
447
                return this.convertToWKB();
448
            case "hexwkb":
449
                return this.convertToHexWKB();
450
            case "ewkb":
451
                return this.convertToEWKB();
452
            case "wkt":
453
                return this.convertToWKT();
454
            case "gml":
455
                return GMLUtils.geometry2GML(this);
456
            case "json":
457
            case "geojson":
458
                return this.convertToGeoJson();
459
            default:
460
                throw new IllegalArgumentException("Format '"+format+"' not supported");
461
        }
462
        
463
    }
464
    
465
    @Override
466
    public byte[] convertToWKB() throws GeometryOperationNotSupportedException, GeometryOperationException {
467
        try {
468
            return new OGCWKBEncoder().encode(this);
469
        } catch (Exception e) {
470
            throw new GeometryOperationException(e);
471
        }
472
    }
473

    
474
    @Override
475
    public String convertToHexWKB() throws GeometryOperationNotSupportedException, GeometryOperationException {
476
        try {
477
            byte[] bytes = new OGCWKBEncoder().encode(this);
478
            return Hex.encodeHexString(bytes);
479
        } catch (Exception e) {
480
            throw new GeometryOperationException(e);
481
        }
482
    }
483
    
484
    public String convertToGeoJson() throws GeometryOperationNotSupportedException, GeometryOperationException {
485
        try {
486
            GeoJsonWriter writer = new GeoJsonWriter();
487
            writer.setEncodeCRS(true);
488
            return writer.write(this.getJTS());
489
        } catch (Exception e) {
490
            throw new GeometryOperationException(e);
491
        }
492
    }
493
    
494
    @Override
495
    public String convertToHexEWKB() throws GeometryOperationNotSupportedException, GeometryOperationException {
496
        try {
497
            byte[] bytes = new PostGISEWKBEncoder().encode(this);
498
            return Hex.encodeHexString(bytes);
499
        } catch (Exception e) {
500
            throw new GeometryOperationException(e);
501
        }
502
    }
503

    
504
    @Override
505
    public byte[] convertToWKBQuietly() {
506
        try {
507
            return new OGCWKBEncoder().encode(this);
508
        } catch (Exception e) {
509
            return null;
510
        }
511
    }
512
    
513
    @Override
514
    public String convertToHexWKBQuietly() {
515
        try {
516
            byte[] bytes = new OGCWKBEncoder().encode(this);
517
            return Hex.encodeHexString(bytes);
518
        } catch (Exception e) {
519
            return null;
520
        }
521
    }
522
    
523
    @Override
524
    public byte[] convertToWKB(int srs) throws GeometryOperationNotSupportedException, GeometryOperationException {
525
        /*
526
             * No se sabe si la especificaci?n de OGC soporta SRS. OGCWKBEncoder no.
527
         */
528

    
529
        try {
530
            return new OGCWKBEncoder().encode(this);
531
        } catch (Exception e) {
532
            throw new GeometryOperationException(e);
533
        }
534
    }
535

    
536
    @Override
537
    public byte[] convertToWKBForcingType(int srs, int type) throws GeometryOperationNotSupportedException,
538
            GeometryOperationException {
539
        /*
540
             * No se sabe si la especificaci?n de OGC soporta SRS. OGCWKBEncoder no.
541
         */
542
        Geometry geom = this;
543
        if (this.getType() != type) {
544
            com.vividsolutions.jts.geom.Geometry jts = getJTS();
545
            jts = JTSUtils.convertTypes(jts, this.getType(), type);
546

    
547
            geom = JTSUtils.createGeometry(this.getProjection(), jts);
548
        }
549
        try {
550
            return new OGCWKBEncoder().encode(geom);
551
        } catch (Exception e) {
552
            throw new GeometryOperationException(e);
553
        }
554

    
555
    }
556

    
557
    @Override
558
    public byte[] convertToEWKB() throws GeometryOperationNotSupportedException, GeometryOperationException {
559
        try {
560
            return new PostGISEWKBEncoder().encode(this);
561
        } catch (Exception e) {
562
            throw new GeometryOperationException(e);
563
        }
564

    
565
    }
566

    
567
    @Override
568
    public byte[] convertToEWKB(int srs) throws GeometryOperationNotSupportedException, GeometryOperationException {
569
        /*
570
             * No se sabe si la especificaci?n de OGC soporta SRS. OGCWKBEncoder no.
571
         */
572

    
573
        try {
574
            return new PostGISEWKBEncoder().encode(this);
575
        } catch (Exception e) {
576
            throw new GeometryOperationException(e);
577
        }
578
    }
579

    
580
    @Override
581
    public byte[] convertToEWKBForcingType(int srs, int type) throws GeometryOperationNotSupportedException,
582
            GeometryOperationException {
583
        /*
584
             * No se sabe si la especificaci?n de OGC soporta SRS. OGCWKBEncoder no.
585
         */
586
        Geometry geom = this;
587
        if (this.getType() != type) {
588
            com.vividsolutions.jts.geom.Geometry jts = getJTS();
589
            jts = JTSUtils.convertTypes(jts, this.getType(), type);
590

    
591
            geom = JTSUtils.createGeometry(this.getProjection(), jts);
592
        }
593
        try {
594
            return new PostGISEWKBEncoder().encode(geom);
595
        } catch (Exception e) {
596
            throw new GeometryOperationException(e);
597
        }
598

    
599
    }
600

    
601
    @Override
602
    public String convertToWKT() throws GeometryOperationNotSupportedException, GeometryOperationException {
603
        int subType = getGeometryType().getSubType();
604

    
605
        EWKTWriter writer; // = null;
606

    
607
        switch (subType) {
608
            case Geometry.SUBTYPES.GEOM3D:
609
                writer = new EWKTWriter(3, false);
610
                break;
611
            case Geometry.SUBTYPES.GEOM2DM:
612
                writer = new EWKTWriter(3, true);
613
                break;
614
            case Geometry.SUBTYPES.GEOM3DM:
615
                writer = new EWKTWriter(4, true);
616
                break;
617

    
618
            default:
619
                writer = new EWKTWriter(2, false);
620
                break;
621
        }
622
        com.vividsolutions.jts.geom.Geometry jts = getJTS();
623
        return writer.write(jts);
624
    }
625

    
626
    @Override
627
    public String convertToWKTQuietly() {
628
        try {
629
            return this.convertToWKT();
630
        } catch(Exception ex) {
631
            return null;
632
        }
633
    }
634

    
635
    @Override
636
    public org.gvsig.fmap.geom.Geometry buffer(double distance) throws GeometryOperationNotSupportedException,
637
        GeometryOperationException {
638
        if( distance==0 ) {
639
          return this;
640
        }
641
        return JTSUtils.createGeometry(this.getProjection(), getJTS().buffer(distance));
642
    }
643
    
644
    
645
    @Override
646
    public org.gvsig.fmap.geom.Geometry buffer(double distance, int joinStyle, boolean capButt) throws GeometryOperationNotSupportedException,
647
        GeometryOperationException {
648
        if( distance==0 ) {
649
          return this;
650
        }
651
        
652
        int quadrantSegments = JTSUtils.calculateQuadrantSegments(joinStyle);
653
        
654
        return JTSUtils.createGeometry(this.getProjection(), getJTS().buffer(
655
                distance, 
656
                quadrantSegments, 
657
                capButt ? BufferParameters.CAP_FLAT : BufferParameters.CAP_ROUND
658
        ));
659
    }
660

    
661
    /*
662
     * (non-Javadoc)
663
     *
664
     * @see org.gvsig.fmap.geom.Geometry#snapTo(org.gvsig.fmap.geom.Geometry,
665
     * double)
666
     */
667
    @Override
668
    public org.gvsig.fmap.geom.Geometry snapTo(org.gvsig.fmap.geom.Geometry other, double snapTolerance)
669
            throws GeometryOperationNotSupportedException, GeometryOperationException {
670
        Geometry result; // = null;
671
        GeometrySnapper snapper = new GeometrySnapper(getJTS());
672
        com.vividsolutions.jts.geom.Geometry jts_result = snapper.snapTo(((GeometryJTS) other).getJTS(), snapTolerance);
673
        result = JTSUtils.createGeometry(this.getProjection(), jts_result);
674
        return result;
675
    }
676

    
677
    /*
678
     * (non-Javadoc)
679
     *
680
     * @see org.gvsig.fmap.geom.Geometry#getInteriorPoint()
681
     */
682
    @Override
683
    public Point getInteriorPoint() throws GeometryOperationNotSupportedException, GeometryOperationException {
684

    
685
        com.vividsolutions.jts.geom.Geometry geometry = getJTS();
686
        com.vividsolutions.jts.geom.Point point = geometry.getInteriorPoint();
687
        Geometry result = JTSUtils.createGeometry(this.getProjection(), point);
688
        return (Point) result;
689
    }
690

    
691
    /*
692
     * (non-Javadoc)
693
     *
694
     * @see org.gvsig.fmap.geom.Geometry#isValid()
695
     */
696
    @Override
697
    public boolean isValid() {
698
        return getJTS().isValid();
699
    }
700

    
701
    @Override
702
    public ValidationStatus getValidationStatus() {
703
        DefaultValidationStatus status = new DefaultValidationStatus(ValidationStatus.VALID, null);
704
        com.vividsolutions.jts.geom.Geometry jtsgeom; // = null;
705
        try {
706
            jtsgeom = this.getJTS();
707
            IsValidOp validOp = new IsValidOp(jtsgeom);
708
            if (!validOp.isValid() ) {
709
                status.setValidationError(validOp.getValidationError());
710
            }
711
        } catch (Throwable ex) {
712
            status.setStatusCode(ValidationStatus.CURRUPTED);
713
            status.setMesage("The geometry is corrupted.");
714
            if (this instanceof OrientableSurface) {
715
                int vertices = ((OrientableSurface) this).getNumVertices();
716
                if (vertices < 3) {
717
                    status.setStatusCode(ValidationStatus.TOO_FEW_POINTS);
718
                    status.setMesage(TopologyValidationError.errMsg[TopologyValidationError.TOO_FEW_POINTS]);
719
                }
720
            } else if (this instanceof OrientableCurve) {
721
                int vertices = ((OrientableCurve) this).getNumVertices();
722
                if (vertices < 2) {
723
                    status.setStatusCode(ValidationStatus.TOO_FEW_POINTS);
724
                    status.setMesage(TopologyValidationError.errMsg[TopologyValidationError.TOO_FEW_POINTS]);
725
                }
726
            }
727
        }
728
        return status;
729
    }
730

    
731
    /*
732
     * (non-Javadoc)
733
     *
734
     * @see org.gvsig.fmap.geom.Geometry#makeValid()
735
     */
736
    @Override
737
    public org.gvsig.fmap.geom.Geometry makeValid() {
738
        try {
739
            ValidationStatus vs = this.getValidationStatus();
740
            if (vs.isValid()) {
741
                return this;
742
            }
743
            Geometry g; // = null;
744
            switch (vs.getStatusCode()) {
745
                case Geometry.ValidationStatus.RING_SELF_INTERSECTION:
746
                case Geometry.ValidationStatus.SELF_INTERSECTION:
747
                    g = this.buffer(0);
748
                    if (g.isValid()) {
749
                        return g;
750
                    }
751
                    break;
752

    
753
                case Geometry.ValidationStatus.TOO_FEW_POINTS:
754
                    if (this instanceof OrientableCurve) {
755
                        int vertices = ((OrientableCurve) this).getNumVertices();
756
                        if (vertices < 2) {
757
                            return null; // new
758
                            // DefaultNullGeometry(this.getGeometryType());
759
                        }
760
                    }
761
                    if (this instanceof OrientableSurface) {
762
                        int vertices = ((OrientableSurface) this).getNumVertices();
763
                        if (vertices < 3) {
764
                            return null; // new
765
                            // DefaultNullGeometry(this.getGeometryType());
766
                        }
767
                    }
768
            }
769
        } catch (Exception ex) {
770
            return null;
771
        }
772
        return null;
773
    }
774

    
775
    /*
776
     * (non-Javadoc)
777
     *
778
     * @see org.gvsig.fmap.geom.Geometry#getBounds2D()
779
     */
780
    @Override
781
    public Rectangle2D getBounds2D() {
782
        com.vividsolutions.jts.geom.Envelope envInternal = getJTS().getEnvelopeInternal();
783
        return new Rectangle2D.Double(envInternal.getMinX(), envInternal.getMinY(), envInternal.getWidth(),
784
                envInternal.getHeight());
785
    }
786

    
787
    /*
788
     * (non-Javadoc)
789
     *
790
     * @see java.awt.Shape#getBounds()
791
     */
792
    @Override
793
    public Rectangle getBounds() {
794
        return this.getShape().getBounds();
795
    }
796

    
797
    /*
798
     * (non-Javadoc)
799
     *
800
     * @see org.gvsig.fmap.geom.Geometry#getInternalShape()
801
     */
802
    @Override
803
    public Shape getInternalShape() {
804
        return getShape();
805
    }
806

    
807
    @Override
808
    public void rotate(double radAngle, double basex, double basey) {
809

    
810
        AffineTransform at = new AffineTransform();
811
        at.rotate(radAngle, basex, basey);
812
        this.transform(at);
813
    }
814

    
815
    @Override
816
    public void move(double dx, double dy) {
817

    
818
        AffineTransform at = new AffineTransform();
819
        at.translate(dx, dy);
820
        this.transform(at);
821
    }
822

    
823
    @Override
824
    public void scale(Point basePoint, double sx, double sy) {
825

    
826
        AffineTransform at = new AffineTransform();
827
        at.setToTranslation(basePoint.getX(), basePoint.getY());
828
        at.scale(sx, sy);
829
        at.translate(-basePoint.getX(), -basePoint.getY());
830
        this.transform(at);
831
    }
832

    
833
    @Override
834
    public Geometry[] closestPoints(Geometry other) throws GeometryOperationNotSupportedException,
835
            GeometryOperationException {
836
        Point[] points;
837

    
838
        Coordinate[] jts_points = DistanceOp.nearestPoints(getJTS(), ((GeometryJTS) other).getJTS());
839
        points = new Point[jts_points.length];
840
        for (int i = 0; i < jts_points.length; i++) {
841
            try {
842
                points[i] = JTSUtils.createPoint(this.getGeometryType(), this.getProjection(), jts_points[i]);
843
            } catch (CreateGeometryException e) {
844
                throw new GeometryOperationException(e);
845
            }
846
        }
847

    
848
        return (Geometry[]) points;
849
    }
850

    
851
    @Override
852
    public Geometry convexHull() throws GeometryOperationNotSupportedException, GeometryOperationException {
853
        return JTSUtils.createGeometry(this.getProjection(), getJTS().convexHull(), null);
854
    }
855

    
856
    @Override
857
    public Geometry difference(Geometry other) throws GeometryOperationNotSupportedException,
858
            GeometryOperationException {
859
        com.vividsolutions.jts.geom.Geometry otherJTS = ((GeometryJTS) other).getJTS();
860
        if(other instanceof Aggregate){
861
            otherJTS = otherJTS.union();
862
        }
863
            return JTSUtils.createGeometry(this.getProjection(), getJTS().difference(otherJTS), null);
864
        }
865

    
866
    @Override
867
    public Geometry intersection(Geometry other) throws GeometryOperationNotSupportedException,
868
            GeometryOperationException {
869
        com.vividsolutions.jts.geom.Geometry otherJTS = ((GeometryJTS) other).getJTS();
870
        if(other instanceof Aggregate){
871
            otherJTS = otherJTS.union();
872
        }
873
        return JTSUtils.createGeometry(this.getProjection(), getJTS().intersection(otherJTS), null);
874
    }
875

    
876
    @Override
877
    public Geometry union(Geometry other) throws GeometryOperationNotSupportedException, GeometryOperationException {
878
        try {
879
            com.vividsolutions.jts.geom.Geometry jts = getJTS();
880
            com.vividsolutions.jts.geom.Geometry otherJts = ((GeometryJTS)other).getJTS();
881
            
882
            if(jts.isValid() && otherJts.isValid()){
883
                return JTSUtils.createGeometry(this.getProjection(), jts.union(otherJts), this.getGeometryType());
884
            }
885
            MultiPrimitive geom = this.getManager().createMultiPrimitive(geometryType);
886
            geom.addPrimitives(this);
887
            geom.addPrimitives(other);
888
            return geom;
889
        } catch (CreateGeometryException ex) {
890
            throw new GeometryOperationException(
891
                    this.getGeometryType().getType(), 
892
                    this.getManager().getGeometryOperationCode(Geometry.OPERATIONS.UNION), 
893
                    ex);
894
        }
895
    }
896

    
897
    @Override
898
    public org.gvsig.fmap.geom.primitive.Point centroid() throws GeometryOperationNotSupportedException,
899
            GeometryOperationException {
900
        try {
901
            return JTSUtils.createPoint(this.getGeometryType(), this.getProjection(), getJTS().getCentroid().getCoordinate());
902
        } catch (CreateGeometryException e) {
903
            throw new GeometryOperationException(e);
904
        }
905
    }
906

    
907
    protected void notifyDeprecated(String message) {
908
        LOGGER.info(message);
909

    
910
    }
911

    
912

    
913
    @Override
914
    public boolean ensureOrientation(boolean ccw) throws GeometryOperationNotSupportedException, GeometryOperationException {
915
        if (ccw != isCCW()) {
916
            flip();
917
            return true;
918
        }
919
        return false;
920
    }
921

    
922
    /* (non-Javadoc)
923
     * @see org.gvsig.fmap.geom.jts.GeometryJTS#out(org.gvsig.fmap.geom.Geometry)
924
     */
925
    @Override
926
    public boolean out(Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException {
927
        GeometryJTS otherJtsGeom = (GeometryJTS) geometry;
928
        return (!contains(otherJtsGeom) && !intersects(otherJtsGeom));
929
    }
930

    
931
    @Override
932
    public boolean equals(Object obj) {
933
        if (obj instanceof GeometryJTS) {
934
            return this.getJTS().equals(((GeometryJTS) obj).getJTS());
935
        }
936
        return false;
937
    }
938

    
939
    @Override
940
    public String toString() {
941
        return this.getGeometryType().getFullName();
942
    }
943

    
944
    @Override
945
    public IProjection getProjection() {
946
        return this.projection;
947
    }
948

    
949
    @Override
950
    public void setProjectionIffNull(IProjection projection) {
951
        if (this.projection == null) {
952
            this.projection = projection;
953
        }
954
    }
955

    
956
    @Override
957
    public void setProjection(IProjection projection) {
958
        this.projection = projection;
959
    }
960

    
961
    @Override
962
    public void setProjection(String projection) {
963
        IProjection proj = CRSFactory.getCRS("EPSG:4326");
964
        this.setProjection(proj);
965
    }
966

    
967
    @Override
968
    @SuppressWarnings("CloneDoesntCallSuperClone")
969
    public Geometry clone() throws CloneNotSupportedException {
970
        return this.cloneGeometry();
971
    }
972

    
973
    @Override
974
    public Geometry boundary() {
975
        return JTSUtils.createGeometry(this.getProjection(), getJTS().getBoundary(), null);
976
    }
977
    
978
    @Override
979
    public Geometry fix() {
980
        try {
981
            ValidationStatus status = this.getValidationStatus();
982
            if(status.isValid()) {
983
                return this.cloneGeometry();
984
            }
985
            int statusCode = status.getStatusCode();
986
            Geometry fixed;
987
            switch (statusCode) {
988
                case ValidationStatus.VALID:
989
                    return this.cloneGeometry();
990
                case ValidationStatus.SELF_INTERSECTION:
991
                case ValidationStatus.RING_SELF_INTERSECTION:
992
                    fixed = this.buffer(Double.MIN_VALUE);
993
                    break;
994
                case ValidationStatus.CURRUPTED:
995
                case ValidationStatus.UNKNOW:
996
                case ValidationStatus.DISCONNECTED_INTERIOR:
997
                case ValidationStatus.DUPLICATE_RINGS:
998
                case ValidationStatus.HOLE_OUTSIDE_SHELL:
999
                case ValidationStatus.INVALID_COORDINATE:
1000
                case ValidationStatus.NESTED_HOLES:
1001
                case ValidationStatus.NESTED_SHELLS:
1002
                case ValidationStatus.RING_NOT_CLOSED:
1003
                case ValidationStatus.TOO_FEW_POINTS:
1004
                default:
1005
                    return null;
1006
            }
1007
            if(!fixed.isValid()){
1008
                return null;
1009
            }
1010
            if(this.getGeometryType().getType() != fixed.getGeometryType().getType()){
1011
                return null;
1012
            }
1013
            return fixed;
1014
        } catch (Exception ex) {
1015
            return null;
1016
        }
1017
    }
1018

    
1019
    
1020
}