Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_geometries / src / org / gvsig / fmap / geom / primitive / impl / AbstractPrimitive.java @ 32924

History | View | Annotate | Download (18.3 KB)

1
package org.gvsig.fmap.geom.primitive.impl;
2

    
3
import java.awt.Shape;
4
import java.awt.geom.AffineTransform;
5
import java.awt.geom.PathIterator;
6
import java.awt.geom.Point2D;
7
import java.io.Serializable;
8

    
9
import org.cresques.cts.ICoordTrans;
10
import org.cresques.cts.IProjection;
11
import org.gvsig.fmap.geom.Geometry;
12
import org.gvsig.fmap.geom.GeometryLocator;
13
import org.gvsig.fmap.geom.GeometryManager;
14
import org.gvsig.fmap.geom.exception.CreateGeometryException;
15
import org.gvsig.fmap.geom.handler.Handler;
16
import org.gvsig.fmap.geom.operation.GeometryOperation;
17
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
18
import org.gvsig.fmap.geom.operation.GeometryOperationException;
19
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
20
import org.gvsig.fmap.geom.operation.relationship.DefaultRelationshipGeometryOperationContext;
21
import org.gvsig.fmap.geom.primitive.Envelope;
22
import org.gvsig.fmap.geom.primitive.FShape;
23
import org.gvsig.fmap.geom.primitive.GeneralPathX;
24
import org.gvsig.fmap.geom.primitive.Primitive;
25
import org.gvsig.fmap.geom.type.GeometryType;
26
import org.gvsig.fmap.geom.util.Converter;
27
import org.slf4j.Logger;
28
import org.slf4j.LoggerFactory;
29

    
30

    
31
/**
32
 * @author Jorge Piera Llodr? (jorge.piera@iver.es)
33
 */
34
public abstract class AbstractPrimitive implements Primitive, FShape, Serializable {
35
        
36
        private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
37

    
38
        private static final long serialVersionUID = -4334977368955260872L;
39
        protected String id = null;
40
        protected IProjection projection = null;
41
        protected GeometryType geometryType = null;
42
        protected static GeometryManager geomManager = GeometryLocator.getGeometryManager();
43

    
44
        /**
45
         * The constructor with the GeometryType like and argument 
46
         * is used by the {@link GeometryType}{@link #create()}
47
         * to create the geometry
48
         * @param type
49
         * The geometry type
50
         */
51
        public AbstractPrimitive(GeometryType geometryType) {
52
                this(geometryType, null, null);                
53
        }
54
        
55
        AbstractPrimitive(int type, int subtype) {
56
                try {
57
                        geometryType = geomManager.getGeometryType(type, subtype);
58
                } catch (Exception e) {
59
                        //TODO Not registered geometry
60
                        geometryType = null;
61
                }
62
        }        
63
        
64
        public AbstractPrimitive(GeometryType geometryType, String id, IProjection projection) {
65
                super();
66
                this.id = id;
67
                this.projection = projection;
68
                this.geometryType = geometryType;
69
        }
70

    
71
        public AbstractPrimitive(GeometryType geometryType, IProjection projection) {
72
                this(geometryType, null, projection);
73
        }
74

    
75
        /* (non-Javadoc)
76
         * @see org.gvsig.fmap.geom.Geometry#getGeometryType()
77
         */
78
        public GeometryType getGeometryType() {
79
                return geometryType;
80
        }
81

    
82
        /* (non-Javadoc)
83
         * @see org.gvsig.fmap.geom.Geometry#getType()
84
         */
85
        public int getType() {
86
                return geometryType.getType();
87
        }
88

    
89
        /**
90
         * (non-Javadoc)
91
         * @see com.iver.cit.gvsig.fmap.core.Geometry#getInternalShape()
92
         * @deprecated this Geometry is a Shape.
93
         */
94
        public Shape getInternalShape() {
95
                return this;
96
        }
97

    
98
        /* (non-Javadoc)
99
         * @see org.gvsig.geometries.iso.AbstractGeometry#getId()
100
         */
101
        public String getId() {
102
                return id;
103
        }
104

    
105
        /* (non-Javadoc)
106
         * @see org.gvsig.geometries.iso.AbstractGeometry#getSRS()
107
         */
108
        public IProjection getSRS() {
109
                return projection;
110
        }
111

    
112
        /* (non-Javadoc)
113
         * @see org.gvsig.geometries.iso.AbstractGeometry#transform(org.cresques.cts.IProjection)
114
         */
115
        public AbstractPrimitive transform(IProjection newProjection) {
116
                Geometry newGeom = cloneGeometry();
117
                ICoordTrans coordTrans = projection.getCT(newProjection);
118
                newGeom.reProject(coordTrans);
119
                return (AbstractPrimitive)newGeom;
120
        }
121

    
122

    
123
        /*
124
         * TODO adaptar metodo procedente de UtilFunctions
125
         */
126
        public static void rotateGeom(Geometry geometry, double radAngle, double basex, double basey) {
127
                AffineTransform at = new AffineTransform();
128
                at.rotate(radAngle,basex,basey);
129
                geometry.transform(at);
130

    
131
        }
132

    
133
        /*
134
         * TODO adaptar metodo procedente de UtilFunctions
135
         */
136
        public static void moveGeom(Geometry geometry, double dx, double dy) {
137
        AffineTransform at = new AffineTransform();
138
        at.translate(dx, dy);
139
        geometry.transform(at);
140
        }
141

    
142
        /*
143
         * TODO adaptar metodo procedente de UtilFunctions
144
         */
145
        public static void scaleGeom(Geometry geometry, Point2D basePoint, double sx, double sy) {
146
                AffineTransform at = new AffineTransform();
147
                at.setToTranslation(basePoint.getX(),basePoint.getY());
148
                at.scale(sx,sy);
149
                at.translate(-basePoint.getX(),-basePoint.getY());
150
                geometry.transform(at);
151
        }
152

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

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

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

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

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

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

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

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

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

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

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

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

    
255
                }
256
                if (this.projection != other.projection) {
257
                        if (this.projection == null) {
258
                                return false;
259
                        }
260
                        if (this.projection.getAbrev() != other.projection.getAbrev()) { //FIXME this must be false
261
                                return false;
262
                        }
263
                }
264
                if (!this.getBounds().equals(other.getBounds())) {
265
                        return false;
266
                }
267

    
268

    
269
                GeneralPathX myPath = this.getGeneralPath();
270
                GeneralPathX otherPath = other.getGeneralPath();
271
                if (myPath == null) {
272
                        if (otherPath != null) {
273
                                return false;
274
                        } else {
275
                                // TODO checkThis
276
                                return true;
277
                        }
278

    
279
                }
280
                if (myPath.getNumTypes() != otherPath.getNumTypes()) {
281
                        return false;
282
                }
283
                if (Math.abs(myPath.getNumCoords() - otherPath.getNumCoords()) > this
284
                                .getDimension()) {
285
                        return false;
286
                }
287
                PathIterator myIter = myPath.getPathIterator(null);
288
                PathIterator otherIter = otherPath.getPathIterator(null);
289
                int myType,otherType;
290
                // FIXME when 3D, 2DM and 3DM
291
                double[] myData = new double[6];
292
                double[] otherData = new double[6];
293
                double[] myFirst = new double[] { myPath.getPointCoords()[0],myPath.getPointCoords()[1]};
294
                double[] otherFirst = new double[] { otherPath.getPointCoords()[0],otherPath.getPointCoords()[1]};
295

    
296
                while (!myIter.isDone()) {
297
                        if (otherIter.isDone()) {
298
                                return false;
299
                        }
300
                        for (int i = 0; i < myData.length; i++) {
301
                                myData[i] = 0.0;
302
                                otherData[i] = 0.0;
303
                        }
304

    
305
                        myType = myIter.currentSegment(myData);
306
                        otherType = otherIter.currentSegment(otherData);
307

    
308
                        switch (myType) {
309
                        case PathIterator.SEG_LINETO:
310
                                if (otherType != myType) {
311
                                        if (otherType == PathIterator.SEG_CLOSE){
312
                                                if (!comparePathIteratorData(otherFirst, myData)) {
313
                                                        return false;
314
                                                }
315
                                        } else {
316
                                                return false;
317
                                        }
318
                                } else {
319
                                        if (!comparePathIteratorData(myData, otherData)) {
320
                                                return false;
321
                                        }
322
                                }
323
                                break;
324

    
325

    
326
                        case PathIterator.SEG_CLOSE:
327
                                if (otherType != myType) {
328
                                        if (otherType == PathIterator.SEG_LINETO) {
329
                                                if (!comparePathIteratorData(myFirst, otherData)) {
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

    
344
                        case PathIterator.SEG_MOVETO:
345
                        case PathIterator.SEG_QUADTO:
346
                        case PathIterator.SEG_CUBICTO:
347
                                if (otherType != myType) {
348
                                        return false;
349
                                }
350
                                if (!comparePathIteratorData(myData, otherData)) {
351
                                        return false;
352
                                }
353
                                break;
354

    
355
                        } // end switch
356

    
357

    
358
                        myIter.next();
359
                        otherIter.next();
360
                }
361
                if (!otherIter.isDone()) {
362
                        return false;
363
                }
364
                return true;
365
        }
366

    
367
        private boolean comparePathIteratorData(double[] org, double[] other) {
368
                for (int i = 0; i < org.length; i++) {
369
                        if (Math.abs(org[i] - other[i]) > 0.0000001) {
370
                                return false;
371
                        }
372
                }
373
                return true;
374
        }
375

    
376
        /* (non-Javadoc)
377
         * @see org.gvsig.fmap.geom.primitive.FShape#getShapeType()
378
         */
379
        public int getShapeType() {
380
                return getType();
381
        }
382
        
383
        
384
        
385
        
386
        
387
        
388
        
389
        
390
        /**
391
         * Utility method
392
         * @param geometry
393
         * @param x
394
         * @param y
395
         * @return
396
         * @throws GeometryOperationException
397
         */
398
        protected boolean containsPoint(Geometry geom, double x, double y) throws GeometryOperationException {
399
                
400
                // exclude disjoint 
401
                Envelope env = geom.getEnvelope();
402
                if (x > env.getMaximum(0)) return false; 
403
                if (y > env.getMaximum(1)) return false; 
404
                if (x < env.getMinimum(0)) return false; 
405
                if (y < env.getMinimum(1)) return false; 
406
                
407
                // boxes overlap, need long version
408
                
409
                Geometry geompoint = null;
410
                try {
411
                        geompoint = GeometryLocator.getGeometryManager().createPoint(x, y, SUBTYPES.GEOM2D);
412
                } catch (Exception e1) {
413
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e1);
414
                }
415
                
416
                DefaultRelationshipGeometryOperationContext drgoc =
417
                        new DefaultRelationshipGeometryOperationContext(geompoint);
418
                
419
                Object resp = null;
420
                boolean respboolean = true;
421
                try {
422
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_CONTAINS_CODE, drgoc);
423
                        respboolean = ((Boolean) resp).booleanValue();
424
                } catch (Exception e) {
425
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e);
426
                }
427

    
428
                return respboolean;
429
        }
430

    
431
        /**
432
         * 
433
         * @param geometry
434
         * @param x
435
         * @param y
436
         * @param w
437
         * @param h
438
         * @return
439
         */
440
        protected boolean containsRectangle(Geometry geom, double x, double y,
441
                        double w, double h) throws GeometryOperationException {
442
                
443
                
444
                // exclude disjoint boxes
445
                Envelope env = geom.getEnvelope();
446
                if (x > env.getMaximum(0)) return false; 
447
                if ((x+w) < env.getMinimum(0)) return false; 
448
                if (y > env.getMaximum(1)) return false; 
449
                if ((y+h) < env.getMinimum(1)) return false; 
450
                
451
                if (w == 0 && h == 0) {
452
                        return  containsPoint(geom, x, y); 
453
                }
454
                
455
                // boxes overlap, need long version
456
                Geometry rectgeom = null;
457
                GeneralPathX gpx = new GeneralPathX();
458
                gpx.moveTo(x, y);
459
                gpx.lineTo(x+w, y);
460
                gpx.lineTo(x+w, y+h);
461
                gpx.lineTo(x, y+h);
462
                gpx.lineTo(x, y);
463
                
464
                try {
465
                        rectgeom = GeometryLocator.getGeometryManager().createSurface(gpx, SUBTYPES.GEOM2D);
466
                } catch (Exception e1) {
467
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e1);
468
                }
469
                
470
                DefaultRelationshipGeometryOperationContext drgoc =
471
                        new DefaultRelationshipGeometryOperationContext(rectgeom);
472
                
473
                Object resp = null;
474
                boolean respboolean = true;
475
                try {
476
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_CONTAINS_CODE, drgoc);
477
                        respboolean = ((Boolean) resp).booleanValue();
478
                } catch (Exception e) {
479
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e);
480
                }
481

    
482
                return respboolean;
483
        }
484
        
485

    
486
        /**
487
         * 
488
         * @param geom
489
         * @param x
490
         * @param y
491
         * @param w
492
         * @param h
493
         * @return
494
         */
495
        protected boolean intersectsRectangle(Geometry geom, double x, double y,
496
                        double w, double h) throws GeometryOperationException {
497
                
498
                // exclude disjoint boxes
499
                Envelope env = geom.getEnvelope();
500
                if (x > env.getMaximum(0)) return false; 
501
                if ((x+w) < env.getMinimum(0)) return false; 
502
                if (y > env.getMaximum(1)) return false; 
503
                if ((y+h) < env.getMinimum(1)) return false; 
504
                
505
                // boxes overlap, need long version
506
                Geometry rectgeom = null;
507
                GeneralPathX gpx = new GeneralPathX();
508
                gpx.moveTo(x, y);
509
                gpx.lineTo(x+w, y);
510
                gpx.lineTo(x+w, y+h);
511
                gpx.lineTo(x, y+h);
512
                gpx.lineTo(x, y);
513
                
514
                try {
515
                        rectgeom = GeometryLocator.getGeometryManager().createSurface(gpx, SUBTYPES.GEOM2D);
516
                } catch (Exception e1) {
517
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_INTERSECTS_CODE, e1);
518
                }
519
                
520
                DefaultRelationshipGeometryOperationContext drgoc =
521
                        new DefaultRelationshipGeometryOperationContext(rectgeom);
522
                
523
                Object resp = null;
524
                boolean respboolean = true;
525
                try {
526
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_INTERSECTS_CODE, drgoc);
527
                        respboolean = ((Boolean) resp).booleanValue();
528
                } catch (Exception e) {
529
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_INTERSECTS_CODE, e);
530
                }
531

    
532
                return respboolean;
533

    
534

    
535
        }
536

    
537
        private com.vividsolutions.jts.geom.Geometry getJTS() {
538
                return Converter.geometryToJts(this);
539
        }
540
        
541
        public byte[] convertToWKB() throws GeometryOperationNotSupportedException,
542
                        GeometryOperationException {
543
                return (byte[]) this.invokeOperation(OPERATIONS.CONVERTTOWKB, null);
544
        }
545

    
546
        public String convertToWKT() throws GeometryOperationNotSupportedException,
547
                        GeometryOperationException {
548
                return (String) this.invokeOperation(OPERATIONS.CONVERTTOWKT, null);
549
        }
550

    
551
        public Geometry buffer(double distance)
552
                        throws GeometryOperationNotSupportedException,
553
                        GeometryOperationException {
554
                // TODO: this method can be implemented throw invokeOperation 
555
                try {
556
                        return Converter.jtsToGeometry( getJTS().buffer(distance) );
557
                } catch (CreateGeometryException e) {
558
                        throw new GeometryOperationException(e);
559
                }
560
        }
561
        
562
        public boolean contains(Geometry geometry)
563
                        throws GeometryOperationNotSupportedException,
564
                        GeometryOperationException {
565
                // TODO: this method can be implemented throw invokeOperation 
566
                return getJTS().contains(Converter.geometryToJts(geometry));
567
        }
568
        
569
        public double distance(Geometry geometry)
570
                        throws GeometryOperationNotSupportedException,
571
                        GeometryOperationException {
572
                // TODO: this method can be implemented throw invokeOperation 
573
                return getJTS().distance( Converter.geometryToJts(geometry));
574
        }
575
        
576
        public boolean overlaps(Geometry geometry)
577
                        throws GeometryOperationNotSupportedException,
578
                        GeometryOperationException {
579
                // TODO: this method can be implemented throw invokeOperation 
580
                return getJTS().overlaps(Converter.geometryToJts(geometry));
581
        }
582
        
583
        public Geometry convexHull() throws GeometryOperationNotSupportedException,
584
                        GeometryOperationException {
585
                // TODO: this method can be implemented throw invokeOperation 
586
                try {
587
                        return Converter.jtsToGeometry( getJTS().convexHull() );
588
                } catch (CreateGeometryException e) {
589
                        throw new GeometryOperationException(e);
590
                }
591
        }
592
        
593
        public boolean coveredBy(Geometry geometry)
594
                        throws GeometryOperationNotSupportedException,
595
                        GeometryOperationException {
596
                // TODO: this method can be implemented throw invokeOperation 
597
                return getJTS().coveredBy( Converter.geometryToJts(geometry));
598
        }
599
        
600
        public boolean crosses(Geometry geometry)
601
                        throws GeometryOperationNotSupportedException,
602
                        GeometryOperationException {
603
                // TODO: this method can be implemented throw invokeOperation 
604
                return getJTS().crosses(Converter.geometryToJts(geometry));
605
        }
606
        
607
        public Geometry difference(Geometry other)
608
                        throws GeometryOperationNotSupportedException,
609
                        GeometryOperationException {
610
                // TODO: this method can be implemented throw invokeOperation 
611
                try {
612
                        return Converter.jtsToGeometry( getJTS().difference( Converter.geometryToJts(other)) );
613
                } catch (CreateGeometryException e) {
614
                        throw new GeometryOperationException(e);
615
                }
616
        }
617
        
618
        public Geometry intersection(Geometry other)
619
                        throws GeometryOperationNotSupportedException,
620
                        GeometryOperationException {
621
                // TODO: this method can be implemented throw invokeOperation 
622
                try {
623
                        return Converter.jtsToGeometry( getJTS().intersection(Converter.geometryToJts(other)) );
624
                } catch (CreateGeometryException e) {
625
                        throw new GeometryOperationException(e);
626
                }
627
        }
628
        
629
        public boolean intersects(Geometry geometry)
630
                        throws GeometryOperationNotSupportedException,
631
                        GeometryOperationException {
632
                // TODO: this method can be implemented throw invokeOperation 
633
                return getJTS().intersects(Converter.geometryToJts(geometry));
634
        }
635
        
636
        public boolean touches(Geometry geometry)
637
                        throws GeometryOperationNotSupportedException,
638
                        GeometryOperationException {
639
                // TODO: this method can be implemented throw invokeOperation 
640
                return getJTS().touches(Converter.geometryToJts(geometry));
641
        }
642
        
643
        public Geometry union(Geometry other)
644
                        throws GeometryOperationNotSupportedException,
645
                        GeometryOperationException {
646
                // TODO: this method can be implemented throw invokeOperation 
647
                try {
648
                        return Converter.jtsToGeometry( getJTS().union(Converter.geometryToJts(other)) );
649
                } catch (CreateGeometryException e) {
650
                        throw new GeometryOperationException(e);
651
                }
652
        }
653
        
654
        public boolean disjoint(Geometry geometry)
655
                        throws GeometryOperationNotSupportedException,
656
                        GeometryOperationException {
657
                // TODO: this method can be implemented throw invokeOperation 
658
                return getJTS().disjoint(Converter.geometryToJts(geometry));
659
        }
660
        
661
        public boolean within(Geometry geometry)
662
                        throws GeometryOperationNotSupportedException,
663
                        GeometryOperationException {
664
                // TODO: this method can be implemented throw invokeOperation 
665
                return getJTS().within(Converter.geometryToJts(geometry));
666
        }
667
        
668
        
669
}