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

History | View | Annotate | Download (26.3 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
                    ValidationStatus.VALID,
210
                    null
211
            );
212
            com.vividsolutions.jts.geom.Geometry jtsgeom = null;
213
            try {
214
                jtsgeom = this.getJTS();
215
                IsValidOp validOp = new IsValidOp(jtsgeom);
216
                if( validOp != null ) {
217
                    status.setValidationError(validOp.getValidationError());
218
                }
219
            } catch(Exception ex) {
220
                status.setStatusCode(ValidationStatus.CURRUPTED);
221
                status.setMesage("The geometry is corrupted.");
222
            }
223
            return status;
224
        }
225
        
226
        /*
227
         * (non-Javadoc)
228
         * @see org.gvsig.fmap.geom.Geometry#invokeOperation(int, org.gvsig.fmap.geom.operation.GeometryOperationContext)
229
         */
230
        public Object invokeOperation(int index, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
231
                return geomManager.invokeOperation(index, this, ctx);
232
        }
233

    
234
        /*
235
         * (non-Javadoc)
236
         * @see org.gvsig.fmap.geom.Geometry#invokeOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperationContext)
237
         */
238
        public Object invokeOperation(String oppName, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
239
                return geomManager.invokeOperation(oppName, this, ctx);
240
        }
241

    
242
        /*
243
         * (non-Javadoc)
244
         * @see java.lang.Comparable#compareTo(T)
245
         */
246
        public int compareTo(Object arg0) {
247
                // TODO Auto-generated method stub
248
                return -1;
249
        }
250

    
251
        /*
252
         * (non-Javadoc)
253
         * @see java.lang.Object#toString()
254
         */
255
        public String toString() {
256
                String name=getGeometryType().getName();
257
                return name.substring(name.lastIndexOf(".")+1);
258
        }
259

    
260
        /*
261
         * (non-Javadoc)
262
         * @see java.lang.Object#equals(java.lang.Object)
263
         */
264
        public boolean equals(Object obj) {
265
                if (obj == null) {
266
                        return false;
267
                }
268
                if (this.getClass() != obj.getClass()) {
269
                        return false;
270
                }
271

    
272
                AbstractPrimitive other = (AbstractPrimitive) obj;
273
                if (this.getGeometryType().getType() != other.getGeometryType()
274
                                .getType()) {
275
                        return false;
276

    
277
                }
278
                
279
                if (this.getGeometryType().getSubType() != other.getGeometryType()
280
                                .getSubType()) {
281
                        return false;
282

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

    
311

    
312
                GeneralPathX myPath = this.getGeneralPath();
313
                GeneralPathX otherPath = other.getGeneralPath();
314
                if (myPath == null) {
315
                        if (otherPath != null) {
316
                                return false;
317
                        } else {
318
                                // TODO checkThis
319
                                return true;
320
                        }
321

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

    
339
                while (!myIter.isDone()) {
340
                        if (otherIter.isDone()) {
341
                                return false;
342
                        }
343
                        for (int i = 0; i < myData.length; i++) {
344
                                myData[i] = 0.0;
345
                                otherData[i] = 0.0;
346
                        }
347

    
348
                        myType = myIter.currentSegment(myData);
349
                        otherType = otherIter.currentSegment(otherData);
350

    
351
                        switch (myType) {
352
                        case PathIterator.SEG_LINETO:
353
                                if (otherType != myType) {
354
                                        if (otherType == PathIterator.SEG_CLOSE){
355
                                                if (!comparePathIteratorData(otherFirst, myData)) {
356
                                                        return false;
357
                                                }
358
                                        } else {
359
                                                return false;
360
                                        }
361
                                } else {
362
                                        if (!comparePathIteratorData(myData, otherData)) {
363
                                                return false;
364
                                        }
365
                                }
366
                                break;
367

    
368

    
369
                        case PathIterator.SEG_CLOSE:
370
                                if (otherType != myType) {
371
                                        if (otherType == PathIterator.SEG_LINETO) {
372
                                                if (!comparePathIteratorData(myFirst, otherData)) {
373
                                                        return false;
374
                                                }
375
                                        } else {
376
                                                return false;
377
                                        }
378
                                } else {
379
                                        if (!comparePathIteratorData(myData, otherData)) {
380
                                                return false;
381
                                        }
382
                                }
383
                                break;
384

    
385

    
386

    
387
                        case PathIterator.SEG_MOVETO:
388
                        case PathIterator.SEG_QUADTO:
389
                        case PathIterator.SEG_CUBICTO:
390
                                if (otherType != myType) {
391
                                        return false;
392
                                }
393
                                if (!comparePathIteratorData(myData, otherData)) {
394
                                        return false;
395
                                }
396
                                break;
397

    
398
                        } // end switch
399

    
400

    
401
                        myIter.next();
402
                        otherIter.next();
403
                }
404
                if (!otherIter.isDone()) {
405
                        return false;
406
                }
407
                return true;
408
        }
409

    
410
        private boolean comparePathIteratorData(double[] org, double[] other) {
411
                for (int i = 0; i < org.length; i++) {
412
                        if (Math.abs(org[i] - other[i]) > 0.0000001) {
413
                                return false;
414
                        }
415
                }
416
                return true;
417
        }
418

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

    
471
                return respboolean;
472
        }
473

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

    
516
                Object resp = null;
517
                boolean respboolean = true;
518
                try {
519
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_CONTAINS_CODE, drgoc);
520
                        respboolean = ((Boolean) resp).booleanValue();
521
                } catch (Exception e) {
522
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e);
523
                }
524

    
525
                return respboolean;
526
        }
527
        
528

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

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

    
575
                return respboolean;
576

    
577

    
578
        }
579

    
580
        private com.vividsolutions.jts.geom.Geometry getJTS() {
581
                return Converter.geometryToJts(this);
582
        }
583
        
584
        public byte[] convertToWKB() throws GeometryOperationNotSupportedException,
585
                        GeometryOperationException {
586
                return (byte[]) this.invokeOperation(OPERATIONS.CONVERTTOWKB, null);
587
        }
588

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

    
607
                WKBWriter write = null;
608
                if(is3D)
609
                        write = new WKBWriter(3);
610
                else
611
                        write = new WKBWriter(2);
612
                return write.write(Converter.geometryToJtsWithSRIDForcingType(this, srs, type));
613
        }
614

    
615
        public String convertToWKT() throws GeometryOperationNotSupportedException,
616
                        GeometryOperationException {
617
                return (String) this.invokeOperation(OPERATIONS.CONVERTTOWKT, null);
618
        }
619

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

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

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

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

    
878
    public Geometry makeValid() {
879
        try {
880
            ValidationStatus vs = this.getValidationStatus();
881
            if (vs.isValid()) {
882
                return this;
883
            }
884
            Geometry g = null;
885
            switch (vs.getStatusCode()) {
886
                case Geometry.ValidationStatus.RING_SELF_INTERSECTION:
887
                case Geometry.ValidationStatus.SELF_INTERSECTION:
888
                    g = this.buffer(0.0001);
889
                    if (g.isValid()) {
890
                        return g;
891
                    }
892
            }
893
        } catch (Exception ex) {
894
            return null;
895
        }
896
        return null;
897
    }
898

    
899
}