Statistics
| Revision:

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

History | View | Annotate | Download (15.1 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.handler.Handler;
15
import org.gvsig.fmap.geom.operation.GeometryOperation;
16
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
17
import org.gvsig.fmap.geom.operation.GeometryOperationException;
18
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
19
import org.gvsig.fmap.geom.operation.relationship.DefaultRelationshipGeometryOperationContext;
20
import org.gvsig.fmap.geom.primitive.Envelope;
21
import org.gvsig.fmap.geom.primitive.FShape;
22
import org.gvsig.fmap.geom.primitive.GeneralPathX;
23
import org.gvsig.fmap.geom.primitive.Primitive;
24
import org.gvsig.fmap.geom.type.GeometryType;
25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
27

    
28

    
29
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
30
 *
31
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
32
 *
33
 * This program is free software; you can redistribute it and/or
34
 * modify it under the terms of the GNU General Public License
35
 * as published by the Free Software Foundation; either version 2
36
 * of the License, or (at your option) any later version.
37
 *
38
 * This program is distributed in the hope that it will be useful,
39
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
41
 * GNU General Public License for more details.
42
 *
43
 * You should have received a copy of the GNU General Public License
44
 * along with this program; if not, write to the Free Software
45
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
46
 *
47
 * For more information, contact:
48
 *
49
 *  Generalitat Valenciana
50
 *   Conselleria d'Infraestructures i Transport
51
 *   Av. Blasco Ib??ez, 50
52
 *   46010 VALENCIA
53
 *   SPAIN
54
 *
55
 *      +34 963862235
56
 *   gvsig@gva.es
57
 *      www.gvsig.gva.es
58
 *
59
 *    or
60
 *
61
 *   IVER T.I. S.A
62
 *   Salamanca 50
63
 *   46005 Valencia
64
 *   Spain
65
 *
66
 *   +34 963163400
67
 *   dac@iver.es
68
 */
69
/* CVS MESSAGES:
70
 *
71
 * $Id: AbstractGeometry.java,v 1.2 2008/03/25 08:47:41 cvs Exp $
72
 * $Log: AbstractGeometry.java,v $
73
 * Revision 1.2  2008/03/25 08:47:41  cvs
74
 * Visitors removed
75
 *
76
 * Revision 1.1  2008/03/12 08:46:20  cvs
77
 * *** empty log message ***
78
 *
79
 *
80
 */
81
/**
82
 * @author Jorge Piera Llodr? (jorge.piera@iver.es)
83
 */
84
public abstract class AbstractPrimitive implements Primitive, FShape, Serializable {
85
        
86
        private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
87

    
88
        private static final long serialVersionUID = -4334977368955260872L;
89
        protected String id = null;
90
        protected IProjection projection = null;
91
        protected GeometryType geometryType = null;
92
        private static GeometryManager geomManager = GeometryLocator.getGeometryManager();
93

    
94
        /**
95
         * The constructor with the GeometryType like and argument 
96
         * is used by the {@link GeometryType}{@link #create()}
97
         * to create the geometry
98
         * @param type
99
         * The geometry type
100
         */
101
        public AbstractPrimitive(GeometryType geometryType) {
102
                this(geometryType, null, null);                
103
        }
104
        
105
        AbstractPrimitive(int type, int subtype) {
106
                try {
107
                        geometryType = geomManager.getGeometryType(type, subtype);
108
                } catch (Exception e) {
109
                        //TODO Not registered geometry
110
                        geometryType = null;
111
                }
112
        }        
113
        
114
        public AbstractPrimitive(GeometryType geometryType, String id, IProjection projection) {
115
                super();
116
                this.id = id;
117
                this.projection = projection;
118
                this.geometryType = geometryType;
119
        }
120

    
121
        public AbstractPrimitive(GeometryType geometryType, IProjection projection) {
122
                this(geometryType, null, projection);
123
        }
124

    
125
        /* (non-Javadoc)
126
         * @see org.gvsig.fmap.geom.Geometry#getGeometryType()
127
         */
128
        public GeometryType getGeometryType() {
129
                return geometryType;
130
        }
131

    
132
        /* (non-Javadoc)
133
         * @see org.gvsig.fmap.geom.Geometry#getType()
134
         */
135
        public int getType() {
136
                return geometryType.getType();
137
        }
138

    
139
        /**
140
         * (non-Javadoc)
141
         * @see com.iver.cit.gvsig.fmap.core.Geometry#getInternalShape()
142
         * @deprecated this Geometry is a Shape.
143
         */
144
        public Shape getInternalShape() {
145
                return this;
146
        }
147

    
148
        /* (non-Javadoc)
149
         * @see org.gvsig.geometries.iso.AbstractGeometry#getId()
150
         */
151
        public String getId() {
152
                return id;
153
        }
154

    
155
        /* (non-Javadoc)
156
         * @see org.gvsig.geometries.iso.AbstractGeometry#getSRS()
157
         */
158
        public IProjection getSRS() {
159
                return projection;
160
        }
161

    
162
        /* (non-Javadoc)
163
         * @see org.gvsig.geometries.iso.AbstractGeometry#transform(org.cresques.cts.IProjection)
164
         */
165
        public AbstractPrimitive transform(IProjection newProjection) {
166
                Geometry newGeom = cloneGeometry();
167
                ICoordTrans coordTrans = projection.getCT(newProjection);
168
                newGeom.reProject(coordTrans);
169
                return (AbstractPrimitive)newGeom;
170
        }
171

    
172

    
173
        /*
174
         * TODO adaptar metodo procedente de UtilFunctions
175
         */
176
        public static void rotateGeom(Geometry geometry, double radAngle, double basex, double basey) {
177
                AffineTransform at = new AffineTransform();
178
                at.rotate(radAngle,basex,basey);
179
                geometry.transform(at);
180

    
181
        }
182

    
183
        /*
184
         * TODO adaptar metodo procedente de UtilFunctions
185
         */
186
        public static void moveGeom(Geometry geometry, double dx, double dy) {
187
        AffineTransform at = new AffineTransform();
188
        at.translate(dx, dy);
189
        geometry.transform(at);
190
        }
191

    
192
        /*
193
         * TODO adaptar metodo procedente de UtilFunctions
194
         */
195
        public static void scaleGeom(Geometry geometry, Point2D basePoint, double sx, double sy) {
196
                AffineTransform at = new AffineTransform();
197
                at.setToTranslation(basePoint.getX(),basePoint.getY());
198
                at.scale(sx,sy);
199
                at.translate(-basePoint.getX(),-basePoint.getY());
200
                geometry.transform(at);
201
        }
202

    
203
        /*
204
         * (non-Javadoc)
205
         * @see org.gvsig.fmap.geom.Geometry#fastIntersects(double, double, double, double)
206
         */
207
        public boolean fastIntersects(double x, double y, double w, double h) {
208

    
209
                boolean resp = true;
210
                
211
                try {
212
                        resp = intersectsRectangle(this, x, y, w, h);
213
                } catch (GeometryOperationException e) {
214
                        logger.error("While doing fastintersects: " + e.getMessage(), e);
215
                }
216
                
217
                return resp;
218
        }
219

    
220
        /*
221
         * (non-Javadoc)
222
         * @see org.gvsig.fmap.geom.Geometry#cloneGeometry()
223
         */
224
        public Geometry cloneGeometry() {
225
                return (Geometry)cloneFShape();
226
        }
227

    
228
        /*
229
         * (non-Javadoc)
230
         * @see org.gvsig.fmap.geom.Geometry#getHandlers(int)
231
         */
232
        public Handler[] getHandlers(int type) {
233
                if (type==STRETCHINGHANDLER){
234
                        return getStretchingHandlers();
235
                }else if (type==SELECTHANDLER){
236
                        return getSelectHandlers();
237
                }
238
                return null;
239
        }
240

    
241
        /*
242
         * (non-Javadoc)
243
         * @see org.gvsig.fmap.geom.Geometry#isSimple()
244
         */
245
        public boolean isSimple() {
246
                return true;
247
        }
248

    
249
        /*
250
         * (non-Javadoc)
251
         * @see org.gvsig.fmap.geom.Geometry#invokeOperation(int, org.gvsig.fmap.geom.operation.GeometryOperationContext)
252
         */
253
        public Object invokeOperation(int index, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
254
                return geomManager.invokeOperation(index, this, ctx);
255
        }
256

    
257
        /*
258
         * (non-Javadoc)
259
         * @see org.gvsig.fmap.geom.Geometry#invokeOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperationContext)
260
         */
261
        public Object invokeOperation(String oppName, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
262
                return geomManager.invokeOperation(oppName, this, ctx);
263
        }
264

    
265
        /*
266
         * (non-Javadoc)
267
         * @see java.lang.Comparable#compareTo(T)
268
         */
269
        public int compareTo(Object arg0) {
270
                // TODO Auto-generated method stub
271
                return -1;
272
        }
273

    
274
        /*
275
         * (non-Javadoc)
276
         * @see java.lang.Object#toString()
277
         */
278
        public String toString() {
279
                String name=getGeometryType().getName();
280
                return name.substring(name.lastIndexOf(".")+1);
281
        }
282

    
283
        /*
284
         * (non-Javadoc)
285
         * @see java.lang.Object#equals(java.lang.Object)
286
         */
287
        public boolean equals(Object obj) {
288
                if (obj == null) {
289
                        return false;
290
                }
291
                if (this.getClass() != obj.getClass()) {
292
                        return false;
293
                }
294

    
295
                AbstractPrimitive other = (AbstractPrimitive) obj;
296
                if (this.getGeometryType().getType() != other.getGeometryType()
297
                                .getType()) {
298
                        return false;
299

    
300
                }
301
                if (this.getGeometryType().getSubType() != other.getGeometryType()
302
                                .getSubType()) {
303
                        return false;
304

    
305
                }
306
                if (this.projection != other.projection) {
307
                        if (this.projection == null) {
308
                                return false;
309
                        }
310
                        if (this.projection.getAbrev() != other.projection.getAbrev()) { //FIXME this must be false
311
                                return false;
312
                        }
313
                }
314
                if (!this.getBounds().equals(other.getBounds())) {
315
                        return false;
316
                }
317

    
318

    
319
                GeneralPathX myPath = this.getGeneralPath();
320
                GeneralPathX otherPath = other.getGeneralPath();
321
                if (myPath == null) {
322
                        if (otherPath != null) {
323
                                return false;
324
                        } else {
325
                                // TODO checkThis
326
                                return true;
327
                        }
328

    
329
                }
330
                if (myPath.getNumTypes() != otherPath.getNumTypes()) {
331
                        return false;
332
                }
333
                if (Math.abs(myPath.getNumCoords() - otherPath.getNumCoords()) > this
334
                                .getDimension()) {
335
                        return false;
336
                }
337
                PathIterator myIter = myPath.getPathIterator(null);
338
                PathIterator otherIter = otherPath.getPathIterator(null);
339
                int myType,otherType;
340
                // FIXME when 3D, 2DM and 3DM
341
                double[] myData = new double[6];
342
                double[] otherData = new double[6];
343
                double[] myFirst = new double[] { myPath.getPointCoords()[0],myPath.getPointCoords()[1]};
344
                double[] otherFirst = new double[] { otherPath.getPointCoords()[0],otherPath.getPointCoords()[1]};
345

    
346
                while (!myIter.isDone()) {
347
                        if (otherIter.isDone()) {
348
                                return false;
349
                        }
350
                        for (int i = 0; i < myData.length; i++) {
351
                                myData[i] = 0.0;
352
                                otherData[i] = 0.0;
353
                        }
354

    
355
                        myType = myIter.currentSegment(myData);
356
                        otherType = otherIter.currentSegment(otherData);
357

    
358
                        switch (myType) {
359
                        case PathIterator.SEG_LINETO:
360
                                if (otherType != myType) {
361
                                        if (otherType == PathIterator.SEG_CLOSE){
362
                                                if (!comparePathIteratorData(otherFirst, myData)) {
363
                                                        return false;
364
                                                }
365
                                        } else {
366
                                                return false;
367
                                        }
368
                                } else {
369
                                        if (!comparePathIteratorData(myData, otherData)) {
370
                                                return false;
371
                                        }
372
                                }
373
                                break;
374

    
375

    
376
                        case PathIterator.SEG_CLOSE:
377
                                if (otherType != myType) {
378
                                        if (otherType == PathIterator.SEG_LINETO) {
379
                                                if (!comparePathIteratorData(myFirst, otherData)) {
380
                                                        return false;
381
                                                }
382
                                        } else {
383
                                                return false;
384
                                        }
385
                                } else {
386
                                        if (!comparePathIteratorData(myData, otherData)) {
387
                                                return false;
388
                                        }
389
                                }
390
                                break;
391

    
392

    
393

    
394
                        case PathIterator.SEG_MOVETO:
395
                        case PathIterator.SEG_QUADTO:
396
                        case PathIterator.SEG_CUBICTO:
397
                                if (otherType != myType) {
398
                                        return false;
399
                                }
400
                                if (!comparePathIteratorData(myData, otherData)) {
401
                                        return false;
402
                                }
403
                                break;
404

    
405
                        } // end switch
406

    
407

    
408
                        myIter.next();
409
                        otherIter.next();
410
                }
411
                if (!otherIter.isDone()) {
412
                        return false;
413
                }
414
                return true;
415
        }
416

    
417
        private boolean comparePathIteratorData(double[] org, double[] other) {
418
                for (int i = 0; i < org.length; i++) {
419
                        if (Math.abs(org[i] - other[i]) > 0.0000001) {
420
                                return false;
421
                        }
422
                }
423
                return true;
424
        }
425

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

    
478
                return respboolean;
479
        }
480

    
481
        /**
482
         * 
483
         * @param geometry
484
         * @param x
485
         * @param y
486
         * @param w
487
         * @param h
488
         * @return
489
         */
490
        protected boolean containsRectangle(Geometry geom, double x, double y,
491
                        double w, double h) throws GeometryOperationException {
492
                
493
                
494
                // exclude disjoint boxes
495
                Envelope env = geom.getEnvelope();
496
                if (x > env.getMaximum(0)) return false; 
497
                if ((x+w) < env.getMinimum(0)) return false; 
498
                if (y > env.getMaximum(1)) return false; 
499
                if ((y+h) < env.getMinimum(1)) return false; 
500
                
501
                if (w == 0 && h == 0) {
502
                        return  containsPoint(geom, x, y); 
503
                }
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_CONTAINS_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_CONTAINS_CODE, drgoc);
527
                        respboolean = ((Boolean) resp).booleanValue();
528
                } catch (Exception e) {
529
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_CONTAINS_CODE, e);
530
                }
531

    
532
                return respboolean;
533
        }
534
        
535

    
536
        /**
537
         * 
538
         * @param geom
539
         * @param x
540
         * @param y
541
         * @param w
542
         * @param h
543
         * @return
544
         */
545
        protected boolean intersectsRectangle(Geometry geom, double x, double y,
546
                        double w, double h) throws GeometryOperationException {
547
                
548
                // exclude disjoint boxes
549
                Envelope env = geom.getEnvelope();
550
                if (x > env.getMaximum(0)) return false; 
551
                if ((x+w) < env.getMinimum(0)) return false; 
552
                if (y > env.getMaximum(1)) return false; 
553
                if ((y+h) < env.getMinimum(1)) return false; 
554
                
555
                // boxes overlap, need long version
556
                Geometry rectgeom = null;
557
                GeneralPathX gpx = new GeneralPathX();
558
                gpx.moveTo(x, y);
559
                gpx.lineTo(x+w, y);
560
                gpx.lineTo(x+w, y+h);
561
                gpx.lineTo(x, y+h);
562
                gpx.lineTo(x, y);
563
                
564
                try {
565
                        rectgeom = GeometryLocator.getGeometryManager().createSurface(gpx, SUBTYPES.GEOM2D);
566
                } catch (Exception e1) {
567
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_INTERSECTS_CODE, e1);
568
                }
569
                
570
                DefaultRelationshipGeometryOperationContext drgoc =
571
                        new DefaultRelationshipGeometryOperationContext(rectgeom);
572
                
573
                Object resp = null;
574
                boolean respboolean = true;
575
                try {
576
                        resp = geom.invokeOperation(GeometryOperation.OPERATION_INTERSECTS_CODE, drgoc);
577
                        respboolean = ((Boolean) resp).booleanValue();
578
                } catch (Exception e) {
579
                        throw new GeometryOperationException(geom.getType(), GeometryOperation.OPERATION_INTERSECTS_CODE, e);
580
                }
581

    
582
                return respboolean;
583

    
584

    
585
        }
586

    
587
        
588
        
589
}