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

History | View | Annotate | Download (25.5 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 org.cresques.cts.ICoordTrans;
32
import org.cresques.cts.IProjection;
33
import org.gvsig.fmap.geom.Geometry;
34
import org.gvsig.fmap.geom.GeometryLocator;
35
import org.gvsig.fmap.geom.GeometryManager;
36
import org.gvsig.fmap.geom.exception.CreateGeometryException;
37
import org.gvsig.fmap.geom.handler.Handler;
38
import org.gvsig.fmap.geom.operation.GeometryOperation;
39
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
40
import org.gvsig.fmap.geom.operation.GeometryOperationException;
41
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
42
import org.gvsig.fmap.geom.primitive.Envelope;
43
import org.gvsig.fmap.geom.primitive.FShape;
44
import org.gvsig.fmap.geom.primitive.GeneralPathX;
45
import org.gvsig.fmap.geom.primitive.NullGeometry;
46
import org.gvsig.fmap.geom.primitive.Point;
47
import org.gvsig.fmap.geom.primitive.Primitive;
48
import org.gvsig.fmap.geom.type.GeometryType;
49
import org.gvsig.fmap.geom.util.Converter;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52

    
53
import com.vividsolutions.jts.geom.Coordinate;
54
import com.vividsolutions.jts.geom.GeometryFactory;
55
import com.vividsolutions.jts.io.WKBWriter;
56
import com.vividsolutions.jts.operation.distance.DistanceOp;
57
import com.vividsolutions.jts.operation.overlay.snap.GeometrySnapper;
58
import com.vividsolutions.jts.operation.valid.IsValidOp;
59
import org.gvsig.fmap.geom.impl.DefaultValidationStatus;
60

    
61

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

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

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

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

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

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

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

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

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

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

    
153

    
154

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

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

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

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

    
193
        /*
194
         * (non-Javadoc)
195
         * @see org.gvsig.fmap.geom.Geometry#isSimple()
196
         */
197
        public boolean isSimple() {
198
            com.vividsolutions.jts.geom.Geometry jtsgeom = this.getJTS();
199
            return jtsgeom.isSimple();
200
        }
201

    
202
        public boolean isValid() {
203
            com.vividsolutions.jts.geom.Geometry jtsgeom = this.getJTS();
204
            return jtsgeom.isValid();
205
        }
206

    
207
        public ValidationStatus getValidationStatus() {
208
            DefaultValidationStatus status = new DefaultValidationStatus();
209
            com.vividsolutions.jts.geom.Geometry jtsgeom = null;
210
            try {
211
                jtsgeom = this.getJTS();
212
                IsValidOp validOp = new IsValidOp(jtsgeom);
213
                status.setValidationError(validOp.getValidationError());
214
            } catch(Exception ex) {
215
                status.setStatusCode(ValidationStatus.CURRUPTED);
216
                status.setMesage("The geometry is corrupted.");
217
            }
218
            return status;
219
        }
220
        
221
        /*
222
         * (non-Javadoc)
223
         * @see org.gvsig.fmap.geom.Geometry#invokeOperation(int, org.gvsig.fmap.geom.operation.GeometryOperationContext)
224
         */
225
        public Object invokeOperation(int index, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
226
                return geomManager.invokeOperation(index, this, ctx);
227
        }
228

    
229
        /*
230
         * (non-Javadoc)
231
         * @see org.gvsig.fmap.geom.Geometry#invokeOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperationContext)
232
         */
233
        public Object invokeOperation(String oppName, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
234
                return geomManager.invokeOperation(oppName, this, ctx);
235
        }
236

    
237
        /*
238
         * (non-Javadoc)
239
         * @see java.lang.Comparable#compareTo(T)
240
         */
241
        public int compareTo(Object arg0) {
242
                // TODO Auto-generated method stub
243
                return -1;
244
        }
245

    
246
        /*
247
         * (non-Javadoc)
248
         * @see java.lang.Object#toString()
249
         */
250
        public String toString() {
251
                String name=getGeometryType().getName();
252
                return name.substring(name.lastIndexOf(".")+1);
253
        }
254

    
255
        /*
256
         * (non-Javadoc)
257
         * @see java.lang.Object#equals(java.lang.Object)
258
         */
259
        public boolean equals(Object obj) {
260
                if (obj == null) {
261
                        return false;
262
                }
263
                if (this.getClass() != obj.getClass()) {
264
                        return false;
265
                }
266

    
267
                AbstractPrimitive other = (AbstractPrimitive) obj;
268
                if (this.getGeometryType().getType() != other.getGeometryType()
269
                                .getType()) {
270
                        return false;
271

    
272
                }
273
                
274
                if (this.getGeometryType().getSubType() != other.getGeometryType()
275
                                .getSubType()) {
276
                        return false;
277

    
278
                }
279
                
280
                if (this instanceof NullGeometry || obj instanceof NullGeometry) {
281
                    /*
282
                     * If any of them is null geometry, they both have to be
283
                     * null geometry, or else, they are not equal.
284
                     * This prevents null pointer exception in the rest of the
285
                     * method
286
                     */
287
                if (this instanceof NullGeometry && obj instanceof NullGeometry) {
288
                    return true;
289
                } else {
290
                    return false;
291
                }
292
                }
293
                
294
                if (this.projection != other.projection) {
295
                        if (this.projection == null) {
296
                                return false;
297
                        }
298
                        if (this.projection.getAbrev() != other.projection.getAbrev()) { //FIXME this must be false
299
                                return false;
300
                        }
301
                }
302
                if (!this.getBounds().equals(other.getBounds())) {
303
                        return false;
304
                }
305

    
306

    
307
                GeneralPathX myPath = this.getGeneralPath();
308
                GeneralPathX otherPath = other.getGeneralPath();
309
                if (myPath == null) {
310
                        if (otherPath != null) {
311
                                return false;
312
                        } else {
313
                                // TODO checkThis
314
                                return true;
315
                        }
316

    
317
                }
318
                if (myPath.getNumTypes() != otherPath.getNumTypes()) {
319
                        return false;
320
                }
321
                if (Math.abs(myPath.getNumCoords() - otherPath.getNumCoords()) > this
322
                                .getDimension()) {
323
                        return false;
324
                }
325
                PathIterator myIter = myPath.getPathIterator(null);
326
                PathIterator otherIter = otherPath.getPathIterator(null);
327
                int myType,otherType;
328
                // FIXME when 3D, 2DM and 3DM
329
                double[] myData = new double[6];
330
                double[] otherData = new double[6];
331
                double[] myFirst = new double[] { myPath.getPointAt(0).getX(),myPath.getPointAt(0).getY()};
332
                double[] otherFirst = new double[] { otherPath.getPointAt(0).getX(),otherPath.getPointAt(0).getY()};
333

    
334
                while (!myIter.isDone()) {
335
                        if (otherIter.isDone()) {
336
                                return false;
337
                        }
338
                        for (int i = 0; i < myData.length; i++) {
339
                                myData[i] = 0.0;
340
                                otherData[i] = 0.0;
341
                        }
342

    
343
                        myType = myIter.currentSegment(myData);
344
                        otherType = otherIter.currentSegment(otherData);
345

    
346
                        switch (myType) {
347
                        case PathIterator.SEG_LINETO:
348
                                if (otherType != myType) {
349
                                        if (otherType == PathIterator.SEG_CLOSE){
350
                                                if (!comparePathIteratorData(otherFirst, myData)) {
351
                                                        return false;
352
                                                }
353
                                        } else {
354
                                                return false;
355
                                        }
356
                                } else {
357
                                        if (!comparePathIteratorData(myData, otherData)) {
358
                                                return false;
359
                                        }
360
                                }
361
                                break;
362

    
363

    
364
                        case PathIterator.SEG_CLOSE:
365
                                if (otherType != myType) {
366
                                        if (otherType == PathIterator.SEG_LINETO) {
367
                                                if (!comparePathIteratorData(myFirst, otherData)) {
368
                                                        return false;
369
                                                }
370
                                        } else {
371
                                                return false;
372
                                        }
373
                                } else {
374
                                        if (!comparePathIteratorData(myData, otherData)) {
375
                                                return false;
376
                                        }
377
                                }
378
                                break;
379

    
380

    
381

    
382
                        case PathIterator.SEG_MOVETO:
383
                        case PathIterator.SEG_QUADTO:
384
                        case PathIterator.SEG_CUBICTO:
385
                                if (otherType != myType) {
386
                                        return false;
387
                                }
388
                                if (!comparePathIteratorData(myData, otherData)) {
389
                                        return false;
390
                                }
391
                                break;
392

    
393
                        } // end switch
394

    
395

    
396
                        myIter.next();
397
                        otherIter.next();
398
                }
399
                if (!otherIter.isDone()) {
400
                        return false;
401
                }
402
                return true;
403
        }
404

    
405
        private boolean comparePathIteratorData(double[] org, double[] other) {
406
                for (int i = 0; i < org.length; i++) {
407
                        if (Math.abs(org[i] - other[i]) > 0.0000001) {
408
                                return false;
409
                        }
410
                }
411
                return true;
412
        }
413

    
414
        /* (non-Javadoc)
415
         * @see org.gvsig.fmap.geom.primitive.FShape#getShapeType()
416
         */
417
        public int getShapeType() {
418
                return getType();
419
        }
420
        
421
        
422
        
423
        
424
        
425
        
426
        
427
        
428
        /**
429
         * Utility method
430
         * @param geometry
431
         * @param x
432
         * @param y
433
         * @return
434
         * @throws GeometryOperationException
435
         */
436
        protected boolean containsPoint(Geometry geom, double x, double y) throws GeometryOperationException {
437
                
438
                // exclude disjoint 
439
                Envelope env = geom.getEnvelope();
440
                if (x > env.getMaximum(0)) return false; 
441
                if (y > env.getMaximum(1)) return false; 
442
                if (x < env.getMinimum(0)) return false; 
443
                if (y < env.getMinimum(1)) return false; 
444
                
445
                // boxes overlap, need long version
446
                
447
                Geometry geompoint = null;
448
                try {
449
                        geompoint = GeometryLocator.getGeometryManager().createPoint(x, y, SUBTYPES.GEOM2D);
450
                } catch (Exception e1) {
451
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e1);
452
                }
453
                
454
                GeometryOperationContext drgoc = new GeometryOperationContext();
455
                 drgoc.setAttribute("geom",geompoint);
456
                
457
                Object resp = null;
458
                boolean respboolean = true;
459
                try {
460
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_CONTAINS_CODE, drgoc);
461
                        respboolean = ((Boolean) resp).booleanValue();
462
                } catch (Exception e) {
463
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e);
464
                }
465

    
466
                return respboolean;
467
        }
468

    
469
        /**
470
         * 
471
         * @param geometry
472
         * @param x
473
         * @param y
474
         * @param w
475
         * @param h
476
         * @return
477
         */
478
        protected boolean containsRectangle(Geometry geom, double x, double y,
479
                        double w, double h) throws GeometryOperationException {
480
                
481
                
482
                // exclude disjoint boxes
483
                Envelope env = geom.getEnvelope();
484
                if (x > env.getMaximum(0)) return false; 
485
                if ((x+w) < env.getMinimum(0)) return false; 
486
                if (y > env.getMaximum(1)) return false; 
487
                if ((y+h) < env.getMinimum(1)) return false; 
488
                
489
                if (w == 0 && h == 0) {
490
                        return  containsPoint(geom, x, y); 
491
                }
492
                
493
                // boxes overlap, need long version
494
                Geometry rectgeom = null;
495
                GeneralPathX gpx = new GeneralPathX();
496
                gpx.moveTo(x, y);
497
                gpx.lineTo(x+w, y);
498
                gpx.lineTo(x+w, y+h);
499
                gpx.lineTo(x, y+h);
500
                gpx.lineTo(x, y);
501
                
502
                try {
503
                        rectgeom = GeometryLocator.getGeometryManager().createSurface(gpx, SUBTYPES.GEOM2D);
504
                } catch (Exception e1) {
505
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e1);
506
                }
507
                
508
                GeometryOperationContext drgoc = new GeometryOperationContext();
509
                drgoc.setAttribute("geom",rectgeom);
510

    
511
                Object resp = null;
512
                boolean respboolean = true;
513
                try {
514
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_CONTAINS_CODE, drgoc);
515
                        respboolean = ((Boolean) resp).booleanValue();
516
                } catch (Exception e) {
517
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e);
518
                }
519

    
520
                return respboolean;
521
        }
522
        
523

    
524
        /**
525
         * 
526
         * @param geom
527
         * @param x
528
         * @param y
529
         * @param w
530
         * @param h
531
         * @return
532
         */
533
        protected boolean intersectsRectangle(Geometry geom, double x, double y,
534
                        double w, double h) throws GeometryOperationException {
535
                
536
                // exclude disjoint boxes
537
                Envelope env = geom.getEnvelope();
538
                if (x > env.getMaximum(0)) return false; 
539
                if ((x+w) < env.getMinimum(0)) return false; 
540
                if (y > env.getMaximum(1)) return false; 
541
                if ((y+h) < env.getMinimum(1)) return false; 
542
                
543
                // boxes overlap, need long version
544
                Geometry rectgeom = null;
545
                GeneralPathX gpx = new GeneralPathX();
546
                gpx.moveTo(x, y);
547
                gpx.lineTo(x+w, y);
548
                gpx.lineTo(x+w, y+h);
549
                gpx.lineTo(x, y+h);
550
                gpx.lineTo(x, y);
551
                
552
                try {
553
                        rectgeom = GeometryLocator.getGeometryManager().createSurface(gpx, SUBTYPES.GEOM2D);
554
                } catch (Exception e1) {
555
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_INTERSECTS_CODE, e1);
556
                }
557

    
558
                GeometryOperationContext drgoc = new GeometryOperationContext();
559
                drgoc.setAttribute("geom",rectgeom);
560
                
561
                Object resp = null;
562
                boolean respboolean = true;
563
                try {
564
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_INTERSECTS_CODE, drgoc);
565
                        respboolean = ((Boolean) resp).booleanValue();
566
                } catch (Exception e) {
567
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_INTERSECTS_CODE, e);
568
                }
569

    
570
                return respboolean;
571

    
572

    
573
        }
574

    
575
        private com.vividsolutions.jts.geom.Geometry getJTS() {
576
                return Converter.geometryToJts(this);
577
        }
578
        
579
        public byte[] convertToWKB() throws GeometryOperationNotSupportedException,
580
                        GeometryOperationException {
581
                return (byte[]) this.invokeOperation(OPERATIONS.CONVERTTOWKB, null);
582
        }
583

    
584
        public byte[] convertToWKB(int srs) 
585
                throws GeometryOperationNotSupportedException, GeometryOperationException {
586
                int subType = getGeometryType().getSubType();
587
                boolean is3D = subType == 1 || subType == 3;
588
                
589
                WKBWriter write = null;
590
                if(is3D)
591
                        write = new WKBWriter(3);
592
                else
593
                        write = new WKBWriter(2);
594
                return write.write(Converter.geometryToJtsWithSRID(this, srs));
595
        }
596
        
597
        public byte[] convertToWKBForcingType(int srs, int type) 
598
                throws GeometryOperationNotSupportedException, GeometryOperationException {
599
                int subType = getGeometryType().getSubType();
600
                boolean is3D = subType == 1 || subType == 3;
601

    
602
                WKBWriter write = null;
603
                if(is3D)
604
                        write = new WKBWriter(3);
605
                else
606
                        write = new WKBWriter(2);
607
                return write.write(Converter.geometryToJtsWithSRIDForcingType(this, srs, type));
608
        }
609

    
610
        public String convertToWKT() throws GeometryOperationNotSupportedException,
611
                        GeometryOperationException {
612
                return (String) this.invokeOperation(OPERATIONS.CONVERTTOWKT, null);
613
        }
614

    
615
        public Geometry buffer(double distance)
616
                        throws GeometryOperationNotSupportedException,
617
                        GeometryOperationException {
618
                // TODO: this method can be implemented throw invokeOperation 
619
                try {
620
                        return Converter.jtsToGeometry( getJTS().buffer(distance) );
621
                } catch (CreateGeometryException e) {
622
                        throw new GeometryOperationException(e);
623
                }
624
        }
625
        
626
        public boolean contains(Geometry geometry)
627
                        throws GeometryOperationNotSupportedException,
628
                        GeometryOperationException {
629
                // TODO: this method can be implemented throw invokeOperation 
630
                return getJTS().contains(Converter.geometryToJts(geometry));
631
        }
632
        
633
        public double distance(Geometry geometry)
634
                        throws GeometryOperationNotSupportedException,
635
                        GeometryOperationException {
636
                // TODO: this method can be implemented throw invokeOperation 
637
                return getJTS().distance( Converter.geometryToJts(geometry));
638
        }
639
        
640
        public Geometry snapTo(Geometry other, double snapTolerance)
641
                        throws GeometryOperationNotSupportedException,
642
                        GeometryOperationException {
643
                Geometry result = null;
644
                GeometrySnapper snapper = new GeometrySnapper(getJTS());
645
                com.vividsolutions.jts.geom.Geometry jts_result = snapper.snapTo(Converter.geometryToJts(other), snapTolerance);
646
                try {
647
                        result = Converter.jtsToGeometry(jts_result);
648
                } catch (CreateGeometryException e) {
649
                        throw new GeometryOperationException(e);
650
                }
651
                return result;
652
        }
653
        
654
        public boolean isWithinDistance(Geometry other, double distance)
655
                        throws GeometryOperationNotSupportedException,
656
                        GeometryOperationException {
657
                return DistanceOp.isWithinDistance(this.getJTS(), Converter.geometryToJts(other), distance);
658
        }
659
        
660
        
661
        public Geometry[] closestPoints(Geometry other)
662
                        throws GeometryOperationNotSupportedException,
663
                        GeometryOperationException {
664
                Geometry[] points = null;
665

    
666
                Coordinate[] jts_points = DistanceOp.closestPoints(this.getJTS(),
667
                                Converter.geometryToJts(other));
668
                points = new Point[jts_points.length];
669
                GeometryFactory geomFactory = new GeometryFactory();
670
                for (int n = 0; n < jts_points.length; n++) {
671
                        try {
672
                                points[n] = Converter.jtsToGeometry(geomFactory.createPoint(jts_points[n]));
673
                        } catch (CreateGeometryException e) {
674
                                throw new GeometryOperationException(e);
675
                        }
676
                }
677
                return points;
678
        }
679
        
680
        public boolean overlaps(Geometry geometry)
681
                        throws GeometryOperationNotSupportedException,
682
                        GeometryOperationException {
683
                // TODO: this method can be implemented throw invokeOperation 
684
                return getJTS().overlaps(Converter.geometryToJts(geometry));
685
        }
686
        
687
        public Geometry convexHull() throws GeometryOperationNotSupportedException,
688
                        GeometryOperationException {
689
                // TODO: this method can be implemented throw invokeOperation 
690
                try {
691
                        return Converter.jtsToGeometry( getJTS().convexHull() );
692
                } catch (CreateGeometryException e) {
693
                        throw new GeometryOperationException(e);
694
                }
695
        }
696
        
697
        public boolean coveredBy(Geometry geometry)
698
                        throws GeometryOperationNotSupportedException,
699
                        GeometryOperationException {
700
                // TODO: this method can be implemented throw invokeOperation 
701
                return getJTS().coveredBy( Converter.geometryToJts(geometry));
702
        }
703
        
704
        public boolean covers(Geometry geometry)
705
                        throws GeometryOperationNotSupportedException,
706
                        GeometryOperationException {
707
                // TODO: this method can be implemented throw invokeOperation 
708
                return getJTS().covers( Converter.geometryToJts(geometry));
709
        }
710
        
711
        public boolean crosses(Geometry geometry)
712
                        throws GeometryOperationNotSupportedException,
713
                        GeometryOperationException {
714
                // TODO: this method can be implemented throw invokeOperation 
715
                return getJTS().crosses(Converter.geometryToJts(geometry));
716
        }
717
        
718
        public Geometry difference(Geometry other)
719
                        throws GeometryOperationNotSupportedException,
720
                        GeometryOperationException {
721
                // TODO: this method can be implemented throw invokeOperation 
722
                try {
723
                        return Converter.jtsToGeometry( getJTS().difference( Converter.geometryToJts(other)) );
724
                } catch (CreateGeometryException e) {
725
                        throw new GeometryOperationException(e);
726
                }
727
        }
728
        
729
        public Geometry intersection(Geometry other)
730
                        throws GeometryOperationNotSupportedException,
731
                        GeometryOperationException {
732
                // TODO: this method can be implemented throw invokeOperation 
733
                try {
734
                        Geometry geom = null;
735
                        com.vividsolutions.jts.geom.Geometry jtsgeom = getJTS().intersection(Converter.geometryToJts(other));
736
                        if( jtsgeom == null ) {
737
                                return null;
738
                        }
739
                        if( jtsgeom.isEmpty() ) {
740
                                return null;
741
                        }
742
                        geom = Converter.jtsToGeometry( jtsgeom );
743
                        return geom;
744
                } catch (CreateGeometryException e) {
745
                        throw new GeometryOperationException(e);
746
                }
747
        }
748
        
749
        public boolean intersects(Geometry geometry)
750
                        throws GeometryOperationNotSupportedException,
751
                        GeometryOperationException {
752
                // TODO: this method can be implemented throw invokeOperation 
753
            try {
754
                return getJTS().intersects(Converter.geometryToJts(geometry));
755
            } catch (Exception exc) {
756
                /*
757
                 * The JTS library sometimes throws an exception
758
                 * (Example: "TopologyException: side location conflict")
759
                 */
760
                throw new GeometryOperationException(exc);
761
            }
762
                
763
        }
764
        
765
        public boolean touches(Geometry geometry)
766
                        throws GeometryOperationNotSupportedException,
767
                        GeometryOperationException {
768
                // TODO: this method can be implemented throw invokeOperation 
769
                return getJTS().touches(Converter.geometryToJts(geometry));
770
        }
771
        
772
        public Geometry union(Geometry other)
773
                        throws GeometryOperationNotSupportedException,
774
                        GeometryOperationException {
775
                // TODO: this method can be implemented throw invokeOperation 
776
                try {
777
                        return Converter.jtsToGeometry( getJTS().union(Converter.geometryToJts(other)) );
778
                } catch (CreateGeometryException e) {
779
                        throw new GeometryOperationException(e);
780
                }
781
        }
782
        
783
        public boolean disjoint(Geometry geometry)
784
                        throws GeometryOperationNotSupportedException,
785
                        GeometryOperationException {
786
                // TODO: this method can be implemented throw invokeOperation 
787
                return getJTS().disjoint(Converter.geometryToJts(geometry));
788
        }
789
        
790
        public boolean within(Geometry geometry)
791
                        throws GeometryOperationNotSupportedException,
792
                        GeometryOperationException {
793
                // TODO: this method can be implemented throw invokeOperation 
794
                return getJTS().within(Converter.geometryToJts(geometry));
795
        }
796
        
797
        public Point centroid() throws GeometryOperationNotSupportedException, GeometryOperationException {
798
                com.vividsolutions.jts.geom.Geometry geometry = getJTS();
799
                com.vividsolutions.jts.geom.Point point = geometry.getCentroid();
800
                GeometryOperationContext geometryOperationContext = new GeometryOperationContext();
801
                geometryOperationContext.setAttribute("JTSGeometry", point);
802
                return (Point)this.invokeOperation("fromJTS", geometryOperationContext);                
803
        }
804
        
805
           
806
        public Point getInteriorPoint() throws GeometryOperationNotSupportedException, GeometryOperationException {
807
            
808
            try {
809
                com.vividsolutions.jts.geom.Geometry geometry = getJTS();
810
                com.vividsolutions.jts.geom.Point point = geometry.getInteriorPoint();
811
                GeometryOperationContext geometryOperationContext = new GeometryOperationContext();
812
                geometryOperationContext.setAttribute("JTSGeometry", point);
813
                return (Point)this.invokeOperation("fromJTS", geometryOperationContext);
814
        } catch (GeometryOperationNotSupportedException ns_ex) {
815
            throw ns_ex;
816
        } catch (GeometryOperationException op_ex) {
817
            throw op_ex;
818
            } catch (Exception ex) {
819
                /*
820
                 * This is for unexpected null pointer exceptions or other
821
                 */
822
                throw new GeometryOperationException(ex);
823
            }
824
        }   
825

    
826
        
827
        public double area() throws GeometryOperationNotSupportedException, GeometryOperationException
828
    {
829
        //Using get getJTS method instead of use the "toJTS" operation just for performance
830
        return getJTS().getArea();
831
    }
832
    
833
    public double perimeter() throws GeometryOperationNotSupportedException, GeometryOperationException
834
    {
835
      //Using get getJTS method instead of use the "toJTS" operation just for performance
836
        return getJTS().getLength();
837
    }
838

    
839
    public Shape getShape() {
840
        return this;
841
    }  
842
    
843
    public Shape getShape(AffineTransform affineTransform) {
844
        if (affineTransform == null){
845
            return this;
846
        }
847
        return new GeneralPathAdapter(affineTransform, getGeneralPath());
848
    }     
849
    
850
    public void rotate(double radAngle, double basex, double basey) {
851
        
852
        AffineTransform at = new AffineTransform();
853
        at.rotate(radAngle,basex,basey);
854
        this.transform(at);
855
    }
856
    
857
    public void move(double dx, double dy) {
858
        
859
        AffineTransform at = new AffineTransform();
860
        at.translate(dx, dy);
861
        this.transform(at);
862
    }
863
    
864
    public void scale(Point basePoint, double sx, double sy) {
865
        
866
        AffineTransform at = new AffineTransform();
867
        at.setToTranslation(basePoint.getX(),basePoint.getY());
868
        at.scale(sx,sy);
869
        at.translate(-basePoint.getX(),-basePoint.getY());
870
        this.transform(at);
871
    }
872

    
873
}