Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.impl / src / main / java / org / gvsig / fmap / geom / primitive / impl / AbstractPrimitive.java @ 40559

History | View | Annotate | Download (23.9 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.geom.primitive.impl;
25

    
26
import java.awt.Shape;
27
import java.awt.geom.AffineTransform;
28
import java.awt.geom.PathIterator;
29
import java.io.Serializable;
30

    
31
import com.vividsolutions.jts.geom.Coordinate;
32
import com.vividsolutions.jts.geom.GeometryFactory;
33
import com.vividsolutions.jts.io.WKBWriter;
34
import com.vividsolutions.jts.operation.distance.DistanceOp;
35
import com.vividsolutions.jts.operation.overlay.snap.GeometrySnapper;
36

    
37
import org.cresques.cts.ICoordTrans;
38
import org.cresques.cts.IProjection;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41

    
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.exception.CreateGeometryException;
46
import org.gvsig.fmap.geom.handler.Handler;
47
import org.gvsig.fmap.geom.operation.GeometryOperation;
48
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
49
import org.gvsig.fmap.geom.operation.GeometryOperationException;
50
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
51
import org.gvsig.fmap.geom.primitive.Envelope;
52
import org.gvsig.fmap.geom.primitive.FShape;
53
import org.gvsig.fmap.geom.primitive.GeneralPathX;
54
import org.gvsig.fmap.geom.primitive.NullGeometry;
55
import org.gvsig.fmap.geom.primitive.Point;
56
import org.gvsig.fmap.geom.primitive.Primitive;
57
import org.gvsig.fmap.geom.type.GeometryType;
58
import org.gvsig.fmap.geom.util.Converter;
59

    
60

    
61
/**
62
 * @author Jorge Piera Llodr� (jorge.piera@iver.es)
63
 */
64
public abstract class AbstractPrimitive implements Primitive, FShape, Shape, Serializable {
65
        
66
        private static final Logger logger = LoggerFactory.getLogger(AbstractPrimitive.class);
67

    
68
        private static final long serialVersionUID = -4334977368955260872L;
69
        protected String id = null;
70
        protected IProjection projection = null;
71
        protected GeometryType geometryType = null;
72
        protected static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
73

    
74
        /**
75
         * The constructor with the GeometryType like and argument 
76
         * is used by the {@link GeometryType}{@link #create()}
77
         * to create the geometry
78
         * @param type
79
         * The geometry type
80
         */
81
        public AbstractPrimitive(GeometryType geometryType) {
82
                this(geometryType, null, null);                
83
        }
84
        
85
        AbstractPrimitive(int type, int subtype) {
86
                try {
87
                        geometryType = geomManager.getGeometryType(type, subtype);
88
                } catch (Exception e) {
89
                        //TODO Not registered geometry
90
                        geometryType = null;
91
                }
92
        }        
93
        
94
        public AbstractPrimitive(GeometryType geometryType, String id, IProjection projection) {
95
                super();
96
                this.id = id;
97
                this.projection = projection;
98
                this.geometryType = geometryType;
99
        }
100

    
101
        public AbstractPrimitive(GeometryType geometryType, IProjection projection) {
102
                this(geometryType, null, projection);
103
        }
104

    
105
        /* (non-Javadoc)
106
         * @see org.gvsig.fmap.geom.Geometry#getGeometryType()
107
         */
108
        public GeometryType getGeometryType() {
109
                return geometryType;
110
        }
111

    
112
        /* (non-Javadoc)
113
         * @see org.gvsig.fmap.geom.Geometry#getType()
114
         */
115
        public int getType() {
116
                return geometryType.getType();
117
        }
118

    
119
        /**
120
         * (non-Javadoc)
121
         * @see com.iver.cit.gvsig.fmap.core.Geometry#getInternalShape()
122
         * @deprecated this Geometry is a Shape.
123
         */
124
        public Shape getInternalShape() {
125
                return this;
126
        }
127

    
128
        /* (non-Javadoc)
129
         * @see org.gvsig.geometries.iso.AbstractGeometry#getId()
130
         */
131
        public String getId() {
132
                return id;
133
        }
134

    
135
        /* (non-Javadoc)
136
         * @see org.gvsig.geometries.iso.AbstractGeometry#getSRS()
137
         */
138
        public IProjection getSRS() {
139
                return projection;
140
        }
141

    
142
        /* (non-Javadoc)
143
         * @see org.gvsig.geometries.iso.AbstractGeometry#transform(org.cresques.cts.IProjection)
144
         */
145
        public AbstractPrimitive transform(IProjection newProjection) {
146
                Geometry newGeom = cloneGeometry();
147
                ICoordTrans coordTrans = projection.getCT(newProjection);
148
                newGeom.reProject(coordTrans);
149
                return (AbstractPrimitive)newGeom;
150
        }
151

    
152

    
153

    
154
        /*
155
         * (non-Javadoc)
156
         * @see org.gvsig.fmap.geom.Geometry#fastIntersects(double, double, double, double)
157
         */
158
        public boolean fastIntersects(double x, double y, double w, double h) {
159

    
160
                boolean resp = true;
161
                
162
                try {
163
                        resp = intersectsRectangle(this, x, y, w, h);
164
                } catch (GeometryOperationException e) {
165
                        logger.error("While doing fastintersects: " + e.getMessage(), e);
166
                }
167
                
168
                return resp;
169
        }
170

    
171
        /*
172
         * (non-Javadoc)
173
         * @see org.gvsig.fmap.geom.Geometry#cloneGeometry()
174
         */
175
        public Geometry cloneGeometry() {
176
                return (Geometry)cloneFShape();
177
        }
178

    
179
        /*
180
         * (non-Javadoc)
181
         * @see org.gvsig.fmap.geom.Geometry#getHandlers(int)
182
         */
183
        public Handler[] getHandlers(int type) {
184
                if (type==STRETCHINGHANDLER){
185
                        return getStretchingHandlers();
186
                }else if (type==SELECTHANDLER){
187
                        return getSelectHandlers();
188
                }
189
                return null;
190
        }
191

    
192
        /*
193
         * (non-Javadoc)
194
         * @see org.gvsig.fmap.geom.Geometry#isSimple()
195
         */
196
        public boolean isSimple() {
197
                return true;
198
        }
199

    
200
        /*
201
         * (non-Javadoc)
202
         * @see org.gvsig.fmap.geom.Geometry#invokeOperation(int, org.gvsig.fmap.geom.operation.GeometryOperationContext)
203
         */
204
        public Object invokeOperation(int index, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
205
                return geomManager.invokeOperation(index, this, ctx);
206
        }
207

    
208
        /*
209
         * (non-Javadoc)
210
         * @see org.gvsig.fmap.geom.Geometry#invokeOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperationContext)
211
         */
212
        public Object invokeOperation(String oppName, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
213
                return geomManager.invokeOperation(oppName, this, ctx);
214
        }
215

    
216
        /*
217
         * (non-Javadoc)
218
         * @see java.lang.Comparable#compareTo(T)
219
         */
220
        public int compareTo(Object arg0) {
221
                // TODO Auto-generated method stub
222
                return -1;
223
        }
224

    
225
        /*
226
         * (non-Javadoc)
227
         * @see java.lang.Object#toString()
228
         */
229
        public String toString() {
230
                String name=getGeometryType().getName();
231
                return name.substring(name.lastIndexOf(".")+1);
232
        }
233

    
234
        /*
235
         * (non-Javadoc)
236
         * @see java.lang.Object#equals(java.lang.Object)
237
         */
238
        public boolean equals(Object obj) {
239
                if (obj == null) {
240
                        return false;
241
                }
242
                if (this.getClass() != obj.getClass()) {
243
                        return false;
244
                }
245

    
246
                AbstractPrimitive other = (AbstractPrimitive) obj;
247
                if (this.getGeometryType().getType() != other.getGeometryType()
248
                                .getType()) {
249
                        return false;
250

    
251
                }
252
                
253
                if (this.getGeometryType().getSubType() != other.getGeometryType()
254
                                .getSubType()) {
255
                        return false;
256

    
257
                }
258
                
259
                if (this instanceof NullGeometry || obj instanceof NullGeometry) {
260
                    /*
261
                     * If any of them is null geometry, they both have to be
262
                     * null geometry, or else, they are not equal.
263
                     * This prevents null pointer exception in the rest of the
264
                     * method
265
                     */
266
                if (this instanceof NullGeometry && obj instanceof NullGeometry) {
267
                    return true;
268
                } else {
269
                    return false;
270
                }
271
                }
272
                
273
                if (this.projection != other.projection) {
274
                        if (this.projection == null) {
275
                                return false;
276
                        }
277
                        if (this.projection.getAbrev() != other.projection.getAbrev()) { //FIXME this must be false
278
                                return false;
279
                        }
280
                }
281
                if (!this.getBounds().equals(other.getBounds())) {
282
                        return false;
283
                }
284

    
285

    
286
                GeneralPathX myPath = this.getGeneralPath();
287
                GeneralPathX otherPath = other.getGeneralPath();
288
                if (myPath == null) {
289
                        if (otherPath != null) {
290
                                return false;
291
                        } else {
292
                                // TODO checkThis
293
                                return true;
294
                        }
295

    
296
                }
297
                if (myPath.getNumTypes() != otherPath.getNumTypes()) {
298
                        return false;
299
                }
300
                if (Math.abs(myPath.getNumCoords() - otherPath.getNumCoords()) > this
301
                                .getDimension()) {
302
                        return false;
303
                }
304
                PathIterator myIter = myPath.getPathIterator(null);
305
                PathIterator otherIter = otherPath.getPathIterator(null);
306
                int myType,otherType;
307
                // FIXME when 3D, 2DM and 3DM
308
                double[] myData = new double[6];
309
                double[] otherData = new double[6];
310
                double[] myFirst = new double[] { myPath.getPointAt(0).getX(),myPath.getPointAt(0).getY()};
311
                double[] otherFirst = new double[] { otherPath.getPointAt(0).getX(),otherPath.getPointAt(0).getY()};
312

    
313
                while (!myIter.isDone()) {
314
                        if (otherIter.isDone()) {
315
                                return false;
316
                        }
317
                        for (int i = 0; i < myData.length; i++) {
318
                                myData[i] = 0.0;
319
                                otherData[i] = 0.0;
320
                        }
321

    
322
                        myType = myIter.currentSegment(myData);
323
                        otherType = otherIter.currentSegment(otherData);
324

    
325
                        switch (myType) {
326
                        case PathIterator.SEG_LINETO:
327
                                if (otherType != myType) {
328
                                        if (otherType == PathIterator.SEG_CLOSE){
329
                                                if (!comparePathIteratorData(otherFirst, myData)) {
330
                                                        return false;
331
                                                }
332
                                        } else {
333
                                                return false;
334
                                        }
335
                                } else {
336
                                        if (!comparePathIteratorData(myData, otherData)) {
337
                                                return false;
338
                                        }
339
                                }
340
                                break;
341

    
342

    
343
                        case PathIterator.SEG_CLOSE:
344
                                if (otherType != myType) {
345
                                        if (otherType == PathIterator.SEG_LINETO) {
346
                                                if (!comparePathIteratorData(myFirst, otherData)) {
347
                                                        return false;
348
                                                }
349
                                        } else {
350
                                                return false;
351
                                        }
352
                                } else {
353
                                        if (!comparePathIteratorData(myData, otherData)) {
354
                                                return false;
355
                                        }
356
                                }
357
                                break;
358

    
359

    
360

    
361
                        case PathIterator.SEG_MOVETO:
362
                        case PathIterator.SEG_QUADTO:
363
                        case PathIterator.SEG_CUBICTO:
364
                                if (otherType != myType) {
365
                                        return false;
366
                                }
367
                                if (!comparePathIteratorData(myData, otherData)) {
368
                                        return false;
369
                                }
370
                                break;
371

    
372
                        } // end switch
373

    
374

    
375
                        myIter.next();
376
                        otherIter.next();
377
                }
378
                if (!otherIter.isDone()) {
379
                        return false;
380
                }
381
                return true;
382
        }
383

    
384
        private boolean comparePathIteratorData(double[] org, double[] other) {
385
                for (int i = 0; i < org.length; i++) {
386
                        if (Math.abs(org[i] - other[i]) > 0.0000001) {
387
                                return false;
388
                        }
389
                }
390
                return true;
391
        }
392

    
393
        /* (non-Javadoc)
394
         * @see org.gvsig.fmap.geom.primitive.FShape#getShapeType()
395
         */
396
        public int getShapeType() {
397
                return getType();
398
        }
399
        
400
        
401
        
402
        
403
        
404
        
405
        
406
        
407
        /**
408
         * Utility method
409
         * @param geometry
410
         * @param x
411
         * @param y
412
         * @return
413
         * @throws GeometryOperationException
414
         */
415
        protected boolean containsPoint(Geometry geom, double x, double y) throws GeometryOperationException {
416
                
417
                // exclude disjoint 
418
                Envelope env = geom.getEnvelope();
419
                if (x > env.getMaximum(0)) return false; 
420
                if (y > env.getMaximum(1)) return false; 
421
                if (x < env.getMinimum(0)) return false; 
422
                if (y < env.getMinimum(1)) return false; 
423
                
424
                // boxes overlap, need long version
425
                
426
                Geometry geompoint = null;
427
                try {
428
                        geompoint = GeometryLocator.getGeometryManager().createPoint(x, y, SUBTYPES.GEOM2D);
429
                } catch (Exception e1) {
430
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e1);
431
                }
432
                
433
                GeometryOperationContext drgoc = new GeometryOperationContext();
434
                 drgoc.setAttribute("geom",geompoint);
435
                
436
                Object resp = null;
437
                boolean respboolean = true;
438
                try {
439
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_CONTAINS_CODE, drgoc);
440
                        respboolean = ((Boolean) resp).booleanValue();
441
                } catch (Exception e) {
442
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e);
443
                }
444

    
445
                return respboolean;
446
        }
447

    
448
        /**
449
         * 
450
         * @param geometry
451
         * @param x
452
         * @param y
453
         * @param w
454
         * @param h
455
         * @return
456
         */
457
        protected boolean containsRectangle(Geometry geom, double x, double y,
458
                        double w, double h) throws GeometryOperationException {
459
                
460
                
461
                // exclude disjoint boxes
462
                Envelope env = geom.getEnvelope();
463
                if (x > env.getMaximum(0)) return false; 
464
                if ((x+w) < env.getMinimum(0)) return false; 
465
                if (y > env.getMaximum(1)) return false; 
466
                if ((y+h) < env.getMinimum(1)) return false; 
467
                
468
                if (w == 0 && h == 0) {
469
                        return  containsPoint(geom, x, y); 
470
                }
471
                
472
                // boxes overlap, need long version
473
                Geometry rectgeom = null;
474
                GeneralPathX gpx = new GeneralPathX();
475
                gpx.moveTo(x, y);
476
                gpx.lineTo(x+w, y);
477
                gpx.lineTo(x+w, y+h);
478
                gpx.lineTo(x, y+h);
479
                gpx.lineTo(x, y);
480
                
481
                try {
482
                        rectgeom = GeometryLocator.getGeometryManager().createSurface(gpx, SUBTYPES.GEOM2D);
483
                } catch (Exception e1) {
484
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e1);
485
                }
486
                
487
                GeometryOperationContext drgoc = new GeometryOperationContext();
488
                drgoc.setAttribute("geom",rectgeom);
489

    
490
                Object resp = null;
491
                boolean respboolean = true;
492
                try {
493
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_CONTAINS_CODE, drgoc);
494
                        respboolean = ((Boolean) resp).booleanValue();
495
                } catch (Exception e) {
496
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e);
497
                }
498

    
499
                return respboolean;
500
        }
501
        
502

    
503
        /**
504
         * 
505
         * @param geom
506
         * @param x
507
         * @param y
508
         * @param w
509
         * @param h
510
         * @return
511
         */
512
        protected boolean intersectsRectangle(Geometry geom, double x, double y,
513
                        double w, double h) throws GeometryOperationException {
514
                
515
                // exclude disjoint boxes
516
                Envelope env = geom.getEnvelope();
517
                if (x > env.getMaximum(0)) return false; 
518
                if ((x+w) < env.getMinimum(0)) return false; 
519
                if (y > env.getMaximum(1)) return false; 
520
                if ((y+h) < env.getMinimum(1)) return false; 
521
                
522
                // boxes overlap, need long version
523
                Geometry rectgeom = null;
524
                GeneralPathX gpx = new GeneralPathX();
525
                gpx.moveTo(x, y);
526
                gpx.lineTo(x+w, y);
527
                gpx.lineTo(x+w, y+h);
528
                gpx.lineTo(x, y+h);
529
                gpx.lineTo(x, y);
530
                
531
                try {
532
                        rectgeom = GeometryLocator.getGeometryManager().createSurface(gpx, SUBTYPES.GEOM2D);
533
                } catch (Exception e1) {
534
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_INTERSECTS_CODE, e1);
535
                }
536

    
537
                GeometryOperationContext drgoc = new GeometryOperationContext();
538
                drgoc.setAttribute("geom",rectgeom);
539
                
540
                Object resp = null;
541
                boolean respboolean = true;
542
                try {
543
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_INTERSECTS_CODE, drgoc);
544
                        respboolean = ((Boolean) resp).booleanValue();
545
                } catch (Exception e) {
546
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_INTERSECTS_CODE, e);
547
                }
548

    
549
                return respboolean;
550

    
551

    
552
        }
553

    
554
        private com.vividsolutions.jts.geom.Geometry getJTS() {
555
                return Converter.geometryToJts(this);
556
        }
557
        
558
        public byte[] convertToWKB() throws GeometryOperationNotSupportedException,
559
                        GeometryOperationException {
560
                return (byte[]) this.invokeOperation(OPERATIONS.CONVERTTOWKB, null);
561
        }
562

    
563
        public byte[] convertToWKB(int srs) 
564
                throws GeometryOperationNotSupportedException, GeometryOperationException {
565
                int subType = getGeometryType().getSubType();
566
                boolean is3D = subType == 1 || subType == 3;
567
                
568
                WKBWriter write = null;
569
                if(is3D)
570
                        write = new WKBWriter(3);
571
                else
572
                        write = new WKBWriter(2);
573
                return write.write(Converter.geometryToJtsWithSRID(this, srs));
574
        }
575
        
576
        public byte[] convertToWKBForcingType(int srs, int type) 
577
                throws GeometryOperationNotSupportedException, GeometryOperationException {
578
                int subType = getGeometryType().getSubType();
579
                boolean is3D = subType == 1 || subType == 3;
580

    
581
                WKBWriter write = null;
582
                if(is3D)
583
                        write = new WKBWriter(3);
584
                else
585
                        write = new WKBWriter(2);
586
                return write.write(Converter.geometryToJtsWithSRIDForcingType(this, srs, type));
587
        }
588

    
589
        public String convertToWKT() throws GeometryOperationNotSupportedException,
590
                        GeometryOperationException {
591
                return (String) this.invokeOperation(OPERATIONS.CONVERTTOWKT, null);
592
        }
593

    
594
        public Geometry buffer(double distance)
595
                        throws GeometryOperationNotSupportedException,
596
                        GeometryOperationException {
597
                // TODO: this method can be implemented throw invokeOperation 
598
                try {
599
                        return Converter.jtsToGeometry( getJTS().buffer(distance) );
600
                } catch (CreateGeometryException e) {
601
                        throw new GeometryOperationException(e);
602
                }
603
        }
604
        
605
        public boolean contains(Geometry geometry)
606
                        throws GeometryOperationNotSupportedException,
607
                        GeometryOperationException {
608
                // TODO: this method can be implemented throw invokeOperation 
609
                return getJTS().contains(Converter.geometryToJts(geometry));
610
        }
611
        
612
        public double distance(Geometry geometry)
613
                        throws GeometryOperationNotSupportedException,
614
                        GeometryOperationException {
615
                // TODO: this method can be implemented throw invokeOperation 
616
                return getJTS().distance( Converter.geometryToJts(geometry));
617
        }
618
        
619
        public Geometry snapTo(Geometry other, double snapTolerance)
620
                        throws GeometryOperationNotSupportedException,
621
                        GeometryOperationException {
622
                Geometry result = null;
623
                GeometrySnapper snapper = new GeometrySnapper(getJTS());
624
                com.vividsolutions.jts.geom.Geometry jts_result = snapper.snapTo(Converter.geometryToJts(other), snapTolerance);
625
                try {
626
                        result = Converter.jtsToGeometry(jts_result);
627
                } catch (CreateGeometryException e) {
628
                        throw new GeometryOperationException(e);
629
                }
630
                return result;
631
        }
632
        
633
        public boolean isWithinDistance(Geometry other, double distance)
634
                        throws GeometryOperationNotSupportedException,
635
                        GeometryOperationException {
636
                return DistanceOp.isWithinDistance(this.getJTS(), Converter.geometryToJts(other), distance);
637
        }
638
        
639
        
640
        public Geometry[] closestPoints(Geometry other)
641
                        throws GeometryOperationNotSupportedException,
642
                        GeometryOperationException {
643
                Geometry[] points = null;
644

    
645
                Coordinate[] jts_points = DistanceOp.closestPoints(this.getJTS(),
646
                                Converter.geometryToJts(other));
647
                points = new Point[jts_points.length];
648
                GeometryFactory geomFactory = new GeometryFactory();
649
                for (int n = 0; n < jts_points.length; n++) {
650
                        try {
651
                                points[n] = Converter.jtsToGeometry(geomFactory.createPoint(jts_points[n]));
652
                        } catch (CreateGeometryException e) {
653
                                throw new GeometryOperationException(e);
654
                        }
655
                }
656
                return points;
657
        }
658
        
659
        public boolean overlaps(Geometry geometry)
660
                        throws GeometryOperationNotSupportedException,
661
                        GeometryOperationException {
662
                // TODO: this method can be implemented throw invokeOperation 
663
                return getJTS().overlaps(Converter.geometryToJts(geometry));
664
        }
665
        
666
        public Geometry convexHull() throws GeometryOperationNotSupportedException,
667
                        GeometryOperationException {
668
                // TODO: this method can be implemented throw invokeOperation 
669
                try {
670
                        return Converter.jtsToGeometry( getJTS().convexHull() );
671
                } catch (CreateGeometryException e) {
672
                        throw new GeometryOperationException(e);
673
                }
674
        }
675
        
676
        public boolean coveredBy(Geometry geometry)
677
                        throws GeometryOperationNotSupportedException,
678
                        GeometryOperationException {
679
                // TODO: this method can be implemented throw invokeOperation 
680
                return getJTS().coveredBy( Converter.geometryToJts(geometry));
681
        }
682
        
683
        public boolean crosses(Geometry geometry)
684
                        throws GeometryOperationNotSupportedException,
685
                        GeometryOperationException {
686
                // TODO: this method can be implemented throw invokeOperation 
687
                return getJTS().crosses(Converter.geometryToJts(geometry));
688
        }
689
        
690
        public Geometry difference(Geometry other)
691
                        throws GeometryOperationNotSupportedException,
692
                        GeometryOperationException {
693
                // TODO: this method can be implemented throw invokeOperation 
694
                try {
695
                        return Converter.jtsToGeometry( getJTS().difference( Converter.geometryToJts(other)) );
696
                } catch (CreateGeometryException e) {
697
                        throw new GeometryOperationException(e);
698
                }
699
        }
700
        
701
        public Geometry intersection(Geometry other)
702
                        throws GeometryOperationNotSupportedException,
703
                        GeometryOperationException {
704
                // TODO: this method can be implemented throw invokeOperation 
705
                try {
706
                        return Converter.jtsToGeometry( getJTS().intersection(Converter.geometryToJts(other)) );
707
                } catch (CreateGeometryException e) {
708
                        throw new GeometryOperationException(e);
709
                }
710
        }
711
        
712
        public boolean intersects(Geometry geometry)
713
                        throws GeometryOperationNotSupportedException,
714
                        GeometryOperationException {
715
                // TODO: this method can be implemented throw invokeOperation 
716
                return getJTS().intersects(Converter.geometryToJts(geometry));
717
        }
718
        
719
        public boolean touches(Geometry geometry)
720
                        throws GeometryOperationNotSupportedException,
721
                        GeometryOperationException {
722
                // TODO: this method can be implemented throw invokeOperation 
723
                return getJTS().touches(Converter.geometryToJts(geometry));
724
        }
725
        
726
        public Geometry union(Geometry other)
727
                        throws GeometryOperationNotSupportedException,
728
                        GeometryOperationException {
729
                // TODO: this method can be implemented throw invokeOperation 
730
                try {
731
                        return Converter.jtsToGeometry( getJTS().union(Converter.geometryToJts(other)) );
732
                } catch (CreateGeometryException e) {
733
                        throw new GeometryOperationException(e);
734
                }
735
        }
736
        
737
        public boolean disjoint(Geometry geometry)
738
                        throws GeometryOperationNotSupportedException,
739
                        GeometryOperationException {
740
                // TODO: this method can be implemented throw invokeOperation 
741
                return getJTS().disjoint(Converter.geometryToJts(geometry));
742
        }
743
        
744
        public boolean within(Geometry geometry)
745
                        throws GeometryOperationNotSupportedException,
746
                        GeometryOperationException {
747
                // TODO: this method can be implemented throw invokeOperation 
748
                return getJTS().within(Converter.geometryToJts(geometry));
749
        }
750
        
751
        public Point centroid() throws GeometryOperationNotSupportedException, GeometryOperationException {
752
                com.vividsolutions.jts.geom.Geometry geometry = getJTS();
753
                com.vividsolutions.jts.geom.Point point = geometry.getCentroid();
754
                GeometryOperationContext geometryOperationContext = new GeometryOperationContext();
755
                geometryOperationContext.setAttribute("JTSGeometry", point);
756
                return (Point)this.invokeOperation("fromJTS", geometryOperationContext);                
757
        }
758
        
759
           
760
        public Point getInteriorPoint() throws GeometryOperationNotSupportedException, GeometryOperationException {
761
            
762
            try {
763
                com.vividsolutions.jts.geom.Geometry geometry = getJTS();
764
                com.vividsolutions.jts.geom.Point point = geometry.getInteriorPoint();
765
                GeometryOperationContext geometryOperationContext = new GeometryOperationContext();
766
                geometryOperationContext.setAttribute("JTSGeometry", point);
767
                return (Point)this.invokeOperation("fromJTS", geometryOperationContext);
768
        } catch (GeometryOperationNotSupportedException ns_ex) {
769
            throw ns_ex;
770
        } catch (GeometryOperationException op_ex) {
771
            throw op_ex;
772
            } catch (Exception ex) {
773
                /*
774
                 * This is for unexpected null pointer exceptions or other
775
                 */
776
                throw new GeometryOperationException(ex);
777
            }
778
        }   
779

    
780
        
781
        public double area() throws GeometryOperationNotSupportedException, GeometryOperationException
782
    {
783
        //Using get getJTS method instead of use the "toJTS" operation just for performance
784
        return getJTS().getArea();
785
    }
786
    
787
    public double perimeter() throws GeometryOperationNotSupportedException, GeometryOperationException
788
    {
789
      //Using get getJTS method instead of use the "toJTS" operation just for performance
790
        return getJTS().getLength();
791
    }
792

    
793
    public Shape getShape() {
794
        return this;
795
    }  
796
    
797
    public Shape getShape(AffineTransform affineTransform) {
798
        if (affineTransform == null){
799
            return this;
800
        }
801
        return new GeneralPathAdapter(affineTransform, getGeneralPath());
802
    }     
803
    
804
    public void rotate(double radAngle, double basex, double basey) {
805
        
806
        AffineTransform at = new AffineTransform();
807
        at.rotate(radAngle,basex,basey);
808
        this.transform(at);
809
    }
810
    
811
    public void move(double dx, double dy) {
812
        
813
        AffineTransform at = new AffineTransform();
814
        at.translate(dx, dy);
815
        this.transform(at);
816
    }
817
    
818
    public void scale(Point basePoint, double sx, double sy) {
819
        
820
        AffineTransform at = new AffineTransform();
821
        at.setToTranslation(basePoint.getX(),basePoint.getY());
822
        at.scale(sx,sy);
823
        at.translate(-basePoint.getX(),-basePoint.getY());
824
        this.transform(at);
825
    }
826

    
827
}