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

History | View | Annotate | Download (32.2 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.aggregate.Aggregate;
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.Envelope;
61
import org.gvsig.fmap.geom.primitive.OrientableCurve;
62
import org.gvsig.fmap.geom.primitive.OrientableSurface;
63
import org.gvsig.fmap.geom.primitive.Point;
64
import org.gvsig.fmap.geom.type.GeometryType;
65
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
67

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

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

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

    
82
    private GeometryType geometryType;
83

    
84
    private IProjection projection;
85

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
256
    }
257

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
411
    }
412

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

    
424
    }
425

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

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

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

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

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

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

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

    
554
    }
555

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

    
564
    }
565

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

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

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

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

    
598
    }
599

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

    
604
        EWKTWriter writer; // = null;
605

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
909
    }
910

    
911

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

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

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

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

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

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

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

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

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

    
972
    @Override
973
    public Geometry boundary() {
974
        return JTSUtils.createGeometry(this.getProjection(), getJTS().getBoundary(), null);
975
    }
976

    
977
    
978
}