Statistics
| Revision:

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

History | View | Annotate | Download (29.3 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2009 {Iver T.I.}   {Task}
26
 */
27

    
28
package org.gvsig.fmap.geom.impl;
29

    
30
import java.awt.geom.PathIterator;
31
import java.util.ArrayList;
32
import java.util.HashMap;
33
import java.util.Iterator;
34
import java.util.List;
35
import java.util.Map;
36

    
37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.GeometryException;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.GeometryManager;
41
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
42
import org.gvsig.fmap.geom.Geometry.TYPES;
43
import org.gvsig.fmap.geom.aggregate.MultiCurve;
44
import org.gvsig.fmap.geom.aggregate.MultiSurface;
45
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
46
import org.gvsig.fmap.geom.exception.CreateGeometryException;
47
import org.gvsig.fmap.geom.operation.GeometryOperation;
48
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
49
import org.gvsig.fmap.geom.operation.GeometryOperationException;
50
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
51
import org.gvsig.fmap.geom.operation.fromwkb.FromWKBGeometryOperationContext;
52
import org.gvsig.fmap.geom.operation.fromwkt.FromWKTGeometryOperationContext;
53
import org.gvsig.fmap.geom.primitive.Curve;
54
import org.gvsig.fmap.geom.primitive.Envelope;
55
import org.gvsig.fmap.geom.primitive.GeneralPathX;
56
import org.gvsig.fmap.geom.primitive.NullGeometry;
57
import org.gvsig.fmap.geom.primitive.Point;
58
import org.gvsig.fmap.geom.primitive.Surface;
59
import org.gvsig.fmap.geom.primitive.impl.DefaultNullGeometry;
60
import org.gvsig.fmap.geom.primitive.impl.Envelope2D;
61
import org.gvsig.fmap.geom.primitive.impl.Envelope3D;
62
import org.gvsig.fmap.geom.type.GeometryType;
63
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
64
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
65
import org.gvsig.fmap.geom.type.impl.DefaultGeometryType;
66
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
68

    
69
/**
70
 * Default implementation for the {@link GeometryManager}. When the
71
 * application starts, this class is registered in the
72
 * {@link GeometryLocator} using the {@link DefaultGeometryLibrary}.
73
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
74
 */
75

    
76
public class DefaultGeometryManager implements GeometryManager {
77
        private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
78
        private double flatness = 0.8;
79

    
80
        /** This list holds the unique name of all registered geometry operations.
81
         * The index in which they are stored is also the operation code used to invoke each one of them */
82
        private List geometryOperations = new ArrayList();
83

    
84
        /** Common operations are registered here. Type specific operations are registered in the corresponding GeometryType instance */
85
        //private List commonOperations = new ArrayList();
86

    
87
        /** This map holds the instances of all registered GeometryType. The key is the name of the specific Geometry subclass.
88
         * In other words, the string "org.gvsig.fmap.geom.primitive.Point2D" is the hash key to obtain an instance of GeometryType holding the
89
         * operations associated to the class org.gvsig.fmap.geom.primitive.Point2D.
90
         */
91
        private Map geometryTypeName = new HashMap();
92

    
93
        /**
94
         * Matrix of geometry types by type (row) and subtype (column). This matrix
95
         * will contain null values in the cells where a GeometryType hasn't been
96
         * registered.
97
         */
98
        private GeometryType[][] geometryTypes;
99

    
100
        /** GeometryType index counter. Each time a new geometry type (not predefined) is registered it is assigned this counter's value as index and after that
101
         * it is incremented by 1 */
102
        private int geometryTypeIndex = 0;//Geometry.EXTENDED_GEOMTYPE_OFFSET; //65536;//2^16
103

    
104
        // Initially create a matrix of 17 x 6, which are the current default
105
        // types and subtypes. If another type or subtype is registered, the
106
        // matrix will grow as needed
107
        private static final int DEFAULT_TYPES_SIZE = 17;
108
        private static final int DEFAULT_SUBTYPES_SIZE = 6;
109

    
110
        public DefaultGeometryManager() {
111
                this(DEFAULT_TYPES_SIZE, DEFAULT_SUBTYPES_SIZE);
112
        }
113

    
114
        public DefaultGeometryManager(int initialTypesSize, int initialSubtypesSize) {
115
                geometryTypes = new GeometryType[initialTypesSize][initialSubtypesSize];
116
        }
117

    
118
        /*
119
         * (non-Javadoc)
120
         * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperation, org.gvsig.fmap.geom.type.GeometryType)
121
         */
122
        public int registerGeometryOperation(String geomOpName,
123
                        GeometryOperation geomOp, GeometryType geomType) {
124
                if (geomOp == null) {
125
                        throw new IllegalArgumentException("geomOp cannot be null.");
126
                }
127
                if (geomType == null) {
128
                        throw new IllegalArgumentException("geomType cannot be null.");
129
                }
130

    
131
                int index = getGeometryOperationCode(geomOpName);
132

    
133
                geomType.setGeometryOperation(index, geomOp);
134

    
135
                return index;
136
        }
137

    
138
        /*
139
         * (non-Javadoc)
140
         * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperation)
141
         */
142
        public int registerGeometryOperation(String geomOpName,
143
                        GeometryOperation geomOp) {
144
                if (geomOpName == null) {
145
                        throw new IllegalArgumentException("geomOpName cannot be null.");
146
                }
147
                if (geomOp == null) {
148
                        throw new IllegalArgumentException("geomOp cannot be null.");
149
                }
150

    
151
                int index = getGeometryOperationCode(geomOpName);
152

    
153
                Iterator it = geometryTypeName.keySet().iterator();
154
                while (it.hasNext()){
155
                        String className = (String)it.next();
156
                        GeometryType geometryType = (GeometryType) geometryTypeName.get(className);
157
                        registerGeometryOperation(geomOpName, geomOp, geometryType);
158
                }
159

    
160
                return index;
161

    
162
        }
163

    
164
        // /**
165
        // * Registers a GeometryOperation associated to a GeometryType.
166
        // * Returns an unique index that is used later to identify and invoke the
167
        // operation.<br>
168
        // *
169
        // * By convention, the return value should be stored in a public constant
170
        // within the class implementing
171
        // * the operation:<BR>
172
        // * <pre>
173
        // * public class MyOperation extends GeometryOperation {
174
        // * public static final int CODE =
175
        // * GeometryManager.getInstance()
176
        // * .registerGeometryOperation("MyOperation", new MyOperation(),
177
        // MyGeometry.class);
178
        // * }
179
        // * </pre>
180
        // *
181
        // * This method is only used if you have not a reference to the
182
        // GeometryType associated to the
183
        // * geometry class. If you have such reference then it is slightly faster
184
        // to use the method that receives
185
        // * the GeometryType.<br>
186
        // *
187
        // * @param geomOpName Operation's unique name
188
        // * @param geomOp Specific GeometryOperation's instance implementing this
189
        // operation
190
        // * @param geomClass Geometry implementation class
191
        // * @return Index assigned to this operation. This index is used later to
192
        // access the operation.
193
        // */
194
        // private int registerGeometryOperation(String geomOpName,
195
        // GeometryOperation geomOp, Class geomClass) {
196
        //
197
        // GeometryType geomType = getGeometryType(geomClass);
198
        // return registerGeometryOperation(geomOpName, geomOp, geomType);
199
        // }
200

    
201
        // /**
202
        // * Registers a GeometryOperation associated to a GeometryType.
203
        // * Returns an unique index that is used later to identify and invoke the
204
        // operation.<br>
205
        // *
206
        // * By convention, the return value should be stored in a public constant
207
        // within the class implementing
208
        // * the operation:<BR>
209
        // * <pre>
210
        // * public class MyOperation extends GeometryOperation {
211
        // * public static final int CODE =
212
        // * GeometryManager.getInstance()
213
        // * .registerGeometryOperation("MyOperation", MyOperation.class,
214
        // myGeomType);
215
        // * }
216
        // * </pre>
217
        // *
218
        // * @param geomOpName Operation's unique name
219
        // * @param geomOpClass GeometryOperation class
220
        // * @param geomType GeometryType instance to which this operation should be
221
        // associated
222
        // * @return Index assigned to this operation. This index is used later to
223
        // access the operation.
224
        // * @throws IllegalAccessException, {@link InstantiationException} Either
225
        // exception maybe thrown when
226
        // * trying to instance the geometry operation class.
227
        // */
228
        // private int registerGeometryOperation(String geomOpName, Class
229
        // geomOpClass,
230
        // GeometryType geomType)
231
        // throws IllegalAccessException, InstantiationException {
232
        //
233
        // GeometryOperation geomOp = (GeometryOperation) geomOpClass.newInstance();
234
        // return registerGeometryOperation(geomOpName, geomOp, geomType);
235
        // }
236

    
237
        /* (non-Javadoc)
238
         * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperation, int, int)
239
         */
240
        public int registerGeometryOperation(String geomOpName,
241
                        GeometryOperation geomOp, int type, int subType) throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
242
                GeometryType geometryType = getGeometryType(type, subType);
243
                return registerGeometryOperation(geomOpName, geomOp, geometryType);
244
        }
245

    
246
        /* (non-Javadoc)
247
         * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperation, int)
248
         */
249
        public int registerGeometryOperation(String geomOpName,
250
                        GeometryOperation geomOp, int type) {
251
                Iterator it = geometryTypeName.keySet().iterator();
252
                int code = -1;
253
                while (it.hasNext()){
254
                        String className = (String)it.next();
255
                        GeometryType geometryType = (GeometryType) geometryTypeName.get(className);
256
                        if ((type == geometryType.getType())) {
257
                                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
258
                        }
259
                }
260
                return code;
261
        }
262

    
263
        /* (non-Javadoc)
264
         * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryOperationBySubtype(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperation, int)
265
         */
266
        public int registerGeometryOperationBySubtype(String geomOpName,
267
                        GeometryOperation geomOp, int subType) {
268
                Iterator it = geometryTypeName.keySet().iterator();
269
                int code = -1;
270
                while (it.hasNext()){
271
                        String className = (String)it.next();
272
                        GeometryType geometryType = (GeometryType) geometryTypeName.get(className);
273
                        if ((subType == geometryType.getSubType())) {
274
                                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
275
                        }
276
                }
277
                return code;
278
        }
279

    
280
        /*
281
         * (non-Javadoc)
282
         * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryType(java.lang.Class, java.lang.String, int)
283
         */
284
        public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType) {
285
                return registerGeometryType(geomClass, name, geometryTypeIndex++, type, subType);
286
        }
287

    
288
        /**
289
         * Registers a Geometry implementation class with a predefined geometry type and returns the
290
         * associated GeometryType instance. Available predefined types are defined in {@link Geometry.TYPES}
291
         * If the class is already registered then this method throws an IllegalArgumentException.<br>
292
         *
293
         * How to register a geometry class with a predefined type:
294
         * <pre>
295
         *
296
         * public class Point2D implements Point {
297
         *   private static final GeometryType geomType = GeometryManager.getInstance()
298
         *           .registerBasicGeometryType(Point2D.class, "Point2D", Geometry.TYPES.POINT);
299
         *
300
         *   public static final int CODE = geomType.getId();
301
         * ...
302
         *   public int getType() {
303
         *      return geomType.getType();
304
         *   }
305
         * }
306
         * </pre>
307
         *
308
         * @param geomClass
309
         *            Geometry subclass. It must not be null and must implement Geometry, otherwise an exception
310
         *            is raised.
311
         * @param name
312
         *                           Symbolic name for the geometry type, it can be null. If it is null then the symbolic name
313
         *                       will be the simple class name.
314
         * @param id
315
         *                           Geometry identifier.
316
         * @param type
317
         *                           Type of geometry. Must be a value defined in {@link Geometry.TYPES}
318
         * @param subType
319
         * SubType of geometry. Must be a value defined in {@link Geometry.SUBTYPES}
320
         * @return Instance of GeometryType associated to the Geometry implementation class
321
         *         geomClass
322
         * @throws IllegalArgumentException
323
         *             If geomClass is null or does not implement Geometry
324
         */
325
        private GeometryType registerGeometryType(Class geomClass, String name, int id,
326
                        int type, int subType){
327
                if (geomClass == null) {
328
                        throw new IllegalArgumentException("geomClass cannot be null.");
329
                }
330

    
331
                if (!Geometry.class.isAssignableFrom(geomClass)) {
332
                        throw new IllegalArgumentException(geomClass.getName()
333
                                        + " must implement the Geometry interface");
334
                }
335

    
336
                // Check if it is registered
337
                GeometryType geomType = null;
338
                if (type >= geometryTypes.length || subType >= geometryTypes[0].length
339
                                || (geomType = geometryTypes[type][subType]) == null) {
340
                        geomType =
341
                                        new DefaultGeometryType(geomClass, name, id, type, subType);
342
                        registerGeometryType(geomType);
343
                        geometryTypeName.put(geomClass.getName(), geomType);
344
                }
345

    
346
                logger.debug("Class {} registered with name {}", geomClass,
347
                                geomType.getName());
348

    
349
                return geomType;
350
        }
351

    
352
        private void registerGeometryType(GeometryType geometryType) {
353
                if (geometryType.getType() >= geometryTypes.length
354
                                || geometryType.getSubType() >= geometryTypes[0].length) {
355

    
356
                        // Recreate the geometry type matrix if the types
357
                        // or subtypes don't fit
358
                        int newTypesSize =
359
                                        geometryType.getType() < geometryTypes.length ? geometryTypes.length
360
                                                        : geometryType.getType() + 1;
361
                        int newSubTypesSize =
362
                                        geometryType.getSubType() < geometryTypes[0].length ? geometryTypes[0].length
363
                                                        : geometryType.getSubType() + 1;
364
                        GeometryType[][] newMatrix =
365
                                        new GeometryType[newTypesSize][newSubTypesSize];
366

    
367
                        for (int i = 0; i < geometryTypes.length; i++) {
368
                                System.arraycopy(geometryTypes[i], 0, newMatrix[i], 0,
369
                                                geometryTypes[i].length);
370
                        }
371
                        geometryTypes = newMatrix;
372
                }
373

    
374
                geometryTypes[geometryType.getType()][geometryType.getSubType()] =
375
                                geometryType;
376
        }
377

    
378
        /*
379
         * (non-Javadoc)
380
         * @see org.gvsig.fmap.geom.GeometryManager#registerGeometryType(java.lang.Class, int)
381
         */
382
        public GeometryType registerGeometryType(Class geomClass, int type, int subType) {
383
                return registerGeometryType(geomClass, null, type, subType);
384
        }
385

    
386
        // /**
387
        // * Returns an instance of GeometryType given the associated Geometry
388
        // implementation
389
        // * class.
390
        // *
391
        // * @param geomClass
392
        // * @return Instance of GeometryType associated to the Geometry
393
        // implementation class
394
        // */
395
        // private GeometryType getGeometryType(Class geomClass) {
396
        // logger.debug("getting " + geomClass.getName());
397
        // return (GeometryType) geometryTypeName.get(geomClass.getName());
398
        // }
399

    
400
        /*
401
         * (non-Javadoc)
402
         * @see org.gvsig.fmap.geom.GeometryManager#getGeometryType(java.lang.String)
403
         */
404
        public GeometryType getGeometryType(String className) throws GeometryTypeNotSupportedException {
405
                if (!geometryTypeName.containsKey(className)){
406
                        throw new GeometryTypeNotSupportedException(className);
407
                }
408
                return (GeometryType) geometryTypeName.get(className);
409
        }
410

    
411
        /* (non-Javadoc)
412
         * @see org.gvsig.fmap.geom.GeometryManager#getGeometryType(int, int)
413
         */
414
        public GeometryType getGeometryType(int type, int subType) throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
415
                GeometryType gType = null;
416
                if (type >= geometryTypes.length || subType >= geometryTypes[0].length) {
417
                        throw new GeometryTypeNotValidException(type, subType);
418
                }
419

    
420
                gType = geometryTypes[type][subType];
421

    
422
                if (gType == null) {
423
                        throw new GeometryTypeNotSupportedException(type, subType);
424
                }
425

    
426
                return gType;
427

    
428
                // Iterator it = geometryTypeName.keySet().iterator();
429
                // while (it.hasNext()){
430
                // String className = (String)it.next();
431
                // GeometryType geometryType = getGeometryType(className);
432
                // if ((type == geometryType.getType()) &&
433
                // (subType == geometryType.getSubType())){
434
                // return geometryType;
435
                // }
436
                // if (subType == SUBTYPES.UNKNOWN){
437
                // throw new GeometryTypeNotValidException(type, subType);
438
                // }
439
                // }
440
                // throw new GeometryTypeNotSupportedException(type, subType);
441
        }
442

    
443
        /*
444
         * (non-Javadoc)
445
         * @see org.gvsig.fmap.geom.GeometryManager#create(org.gvsig.fmap.geom.type.GeometryType)
446
         */
447
        public Geometry create(GeometryType geomType) throws CreateGeometryException{
448
                return geomType.create();
449
        }
450

    
451
        /*
452
         * (non-Javadoc)
453
         * @see org.gvsig.fmap.geom.GeometryManager#create(java.lang.String)
454
         */
455
        public Geometry create(String name) throws CreateGeometryException{
456
                if (!geometryTypeName.containsKey(name)){
457
                        throw new IllegalArgumentException(name + " has not been registered yet.");
458
                }
459
                return ((GeometryType)geometryTypeName.get(name)).create();
460
        }
461

    
462
        /*
463
         * (non-Javadoc)
464
         * @see org.gvsig.fmap.geom.GeometryManager#create(int)
465
         */
466
        public Geometry create(int type, int subType)
467
                        throws CreateGeometryException {
468
                try {
469
                        return getGeometryType(type, subType).create();
470
                } catch (GeometryException e) {
471
                        throw new CreateGeometryException(type, subType, e);
472
                }
473
        }
474

    
475

    
476
        /* (non-Javadoc)
477
         * @see org.gvsig.fmap.geom.GeometryManager#createCurve(org.gvsig.fmap.geom.primitive.GeneralPathX, int)
478
         */
479
        public Curve createCurve(GeneralPathX generalPathX, int subType)
480
                        throws CreateGeometryException {
481
                Curve curve = (Curve)create(TYPES.CURVE, subType);
482
                curve.setGeneralPath(generalPathX);
483
                return curve;
484
        }
485

    
486
        /* (non-Javadoc)
487
         * @see org.gvsig.fmap.geom.GeometryManager#createNullGeometry(int)
488
         */
489
        public NullGeometry createNullGeometry(int subType)
490
                        throws CreateGeometryException {
491
                NullGeometry nullGeom = (NullGeometry)create(TYPES.NULL, subType);
492
                return nullGeom;
493
        }
494

    
495
        /* (non-Javadoc)
496
         * @see org.gvsig.fmap.geom.GeometryManager#createPoint(double, double, int)
497
         */
498
        public Point createPoint(double x, double y, int subType)
499
                        throws CreateGeometryException {
500
                Point point = (Point)create(TYPES.POINT, subType);
501
                point.setX(x);
502
                point.setY(y);
503
                return point;
504
        }
505

    
506
        /* (non-Javadoc)
507
         * @see org.gvsig.fmap.geom.GeometryManager#createSurface(org.gvsig.fmap.geom.primitive.GeneralPathX, int)
508
         */
509
        public Surface createSurface(GeneralPathX generalPathX, int subType)
510
                        throws CreateGeometryException {
511
                Surface surface = (Surface)create(TYPES.SURFACE, subType);
512
                surface.setGeneralPath(generalPathX);
513
                return surface;
514
        }
515

    
516
        /* (non-Javadoc)
517
         * @see org.gvsig.fmap.geom.GeometryManager#getGeometryOperation(int, int, int)
518
         */
519
        public GeometryOperation getGeometryOperation(int opCode, int type,
520
                        int subType) throws GeometryTypeNotSupportedException,
521
                        GeometryOperationNotSupportedException, GeometryTypeNotValidException {
522
                GeometryType geometryType = getGeometryType(type, subType);
523
                return geometryType.getGeometryOperation(opCode);
524
        }
525

    
526
        //        /*
527
        //         * (non-Javadoc)
528
        //         * @see org.gvsig.fmap.geom.GeometryManager#getGeometryOperation(java.lang.Class, int)
529
        //         */
530
        //        private GeometryOperation getGeometryOperation(Class geomClass, int opCode) throws GeometryTypeNotSupportedException, GeometryOperationNotSupportedException {
531
        //
532
        //                GeometryOperation geomOp = null;
533
        //
534
        //                // Check if it is a common operation, and if so, get it from the common registry
535
        //                if (opCode >= COMMON_OPS_OFFSET) {
536
        //                        geomOp = ((GeometryOperation)commonOperations.get(opCode - COMMON_OPS_OFFSET));
537
        //
538
        //                        if (geomOp == null) {
539
        //                                throw new GeometryOperationNotSupportedException(opCode);
540
        //                        }
541
        //                } else {
542
        //                        // If it is type specific, get it from its type        registry
543
        //                        if (geomClass != null) {
544
        //                                GeometryType geomType = getGeometryType(geomClass);
545
        //
546
        //                                // If the geometry type is not registered, throw an exception
547
        //                                if (geomType == null) {
548
        //                                        throw new GeometryTypeNotSupportedException(geomClass);
549
        //                                }
550
        //
551
        //                                // Get the operation
552
        //                                geomOp = geomType.getGeometryOperation(opCode);
553
        //
554
        //                                // If the operation is not registered throw an exception
555
        //                                if (geomOp == null) {
556
        //                                        throw new GeometryOperationNotSupportedException(opCode, geomType);
557
        //                                }
558
        //                        }
559
        //                }
560
        //                return geomOp;
561
        //        }
562

    
563
        /*
564
         * (non-Javadoc)
565
         * @see org.gvsig.fmap.geom.GeometryManager#invokeOperation(int, org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.geom.operation.GeometryOperationContext)
566
         */
567
        public Object invokeOperation(int opCode, Geometry geom, GeometryOperationContext ctx) throws GeometryOperationNotSupportedException, GeometryOperationException {
568
                GeometryOperation geomOp = geom.getGeometryType().getGeometryOperation(opCode);
569

    
570
                if (geomOp != null) {
571
                        return geomOp.invoke(geom, ctx);
572
                }
573

    
574
                throw new GeometryOperationNotSupportedException(opCode, geom.getGeometryType());
575
        }
576

    
577
        /* (non-Javadoc)
578
         * @see org.gvsig.fmap.geom.GeometryManager#invokeOperation(java.lang.String, org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.geom.operation.GeometryOperationContext)
579
         */
580
        public Object invokeOperation(String geomOpName, Geometry geom,
581
                        GeometryOperationContext ctx)
582
        throws GeometryOperationNotSupportedException,
583
        GeometryOperationException {
584
                int index = geometryOperations.indexOf(geomOpName);
585
                if (index == -1){
586
                        throw new GeometryOperationNotSupportedException(-1);
587
                }
588
                return invokeOperation(index, geom, ctx);
589
        }
590
        
591
        /*
592
         * (non-Javadoc)
593
         * @see org.gvsig.fmap.geom.GeometryManager#invokeOperation(java.lang.String, org.gvsig.fmap.geom.operation.GeometryOperationContext)
594
         */
595
        public Object invokeOperation(String geomOpName, GeometryOperationContext ctx) 
596
                throws GeometryOperationNotSupportedException, GeometryOperationException {
597
                int index = geometryOperations.indexOf(geomOpName);
598
                if (index == -1) 
599
                        throw new GeometryOperationNotSupportedException(-1);
600
                DefaultGeometryType type = (DefaultGeometryType)geometryTypeName.get(DefaultNullGeometry.class.getName());
601
                if(type != null) {
602
                        GeometryOperation geomOp = type.getGeometryOperation(index);
603
                        return geomOp.invoke(null, ctx);
604
                }
605
                return null;
606
        }
607

    
608
        /*
609
         * (non-Javadoc)
610
         * @see org.gvsig.fmap.geom.GeometryManager#unregisterGeometryType(java.lang.Class)
611
         */
612
        public GeometryType unregisterGeometryType(Class geomClass) {
613
                return (GeometryType) geometryTypeName.remove(geomClass.getName());
614
        }
615

    
616
        /* (non-Javadoc)
617
         * @see org.gvsig.fmap.geom.GeometryManager#createEnvelope(int)
618
         */
619
        public Envelope createEnvelope(int subType) {
620
                //TODO: register the envelopes!!!
621
                switch (subType){
622
                case SUBTYPES.GEOM2DZ:
623
                case SUBTYPES.GEOM3D:
624
                        return new Envelope3D();
625
                default:
626
                        return new Envelope2D();
627
                }
628
        }
629

    
630

    
631
        /* (non-Javadoc)
632
         * @see org.gvsig.fmap.geom.GeometryManager#createEnvelope(double, double, double, double)
633
         */
634
        public Envelope createEnvelope(double minX, double minY, double maxX,
635
                        double maxY, int subType) throws CreateEnvelopeException {
636
                org.gvsig.fmap.geom.primitive.Point min = null;
637
                org.gvsig.fmap.geom.primitive.Point max = null;
638
                try {
639
                        GeometryType gType = getGeometryType(TYPES.POINT, subType);
640
                        min = (Point) gType.create();
641
                        min.setX(minX);
642
                        min.setY(minY);
643
                        max = (Point) gType.create();
644
                        max.setX(maxX);
645
                        max.setY(maxY);
646
                        // min = createPoint(minX, minY, subType);
647
                        // max = createPoint(maxX, maxY, subType);
648
                } catch (CreateGeometryException e) {
649
                        throw new CreateEnvelopeException(subType, e);
650
                } catch (GeometryTypeNotSupportedException e) {
651
                        throw new CreateEnvelopeException(subType, e);
652
                } catch (GeometryTypeNotValidException e) {
653
                        throw new CreateEnvelopeException(subType, e);
654
                }
655
                switch (subType) {
656
                case SUBTYPES.GEOM2D:
657
                case SUBTYPES.GEOM2DM:
658
                        // Small optimization to directly create an Envelope2D
659
                        // return new Envelope2D(minX, minY, maxX, maxY);
660
                        return new Envelope2D(min, max);
661
                default:
662
                        Envelope envelope = createEnvelope(subType);
663
                        envelope.setLowerCorner(min);
664
                        envelope.setUpperCorner(max);
665
                        return envelope;
666
                }
667
        }
668

    
669
        public MultiCurve createMultiCurve(GeneralPathX generalPathX, int subType)
670
                        throws CreateGeometryException {
671
                if (subType != SUBTYPES.GEOM2D){
672
                        // FIXME Exception
673
                        throw new UnsupportedOperationException();
674
                }
675
                MultiCurve multiCurve = (MultiCurve) create(TYPES.MULTICURVE, subType);
676
                PathIterator piter = generalPathX.getPathIterator(null);
677
                GeneralPathX tmpPath = null;
678
                Curve tmpCurve = null;
679
                double[] coords = new double[6];
680
                double[] first = new double[6];
681
                int type;
682
                while (!piter.isDone()) {
683
                        type = piter.currentSegment(coords);
684
                        switch (type) {
685
                        case PathIterator.SEG_MOVETO:
686
                                if (tmpPath != null){
687
                                        tmpCurve = createCurve(tmpPath, subType);
688
                                        multiCurve.addCurve(tmpCurve);
689
                                }
690
                                System.arraycopy(coords, 0, first, 0, 2);
691
                                tmpPath =  new GeneralPathX(piter.getWindingRule());
692
                                tmpPath.moveTo(coords[0], coords[1]);
693
                                break;
694

    
695

    
696
                        case PathIterator.SEG_LINETO:
697
                                if (tmpPath == null) {
698
                                        System.arraycopy(coords, 0, first, 0, 2);
699
                                        tmpPath = new GeneralPathX(piter.getWindingRule());
700
                                }
701
                                tmpPath.lineTo(coords[0], coords[1]);
702
                                break;
703

    
704

    
705
                        case PathIterator.SEG_QUADTO:
706
                                if (tmpPath == null) {
707
                                        System.arraycopy(coords, 0, first, 0, 2);
708
                                        tmpPath = new GeneralPathX(piter.getWindingRule());
709
                                }
710
                                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
711
                                break;
712

    
713
                        case PathIterator.SEG_CUBICTO:
714
                                if (tmpPath == null) {
715
                                        System.arraycopy(coords, 0, first, 0, 2);
716
                                        tmpPath = new GeneralPathX(piter.getWindingRule());
717
                                }
718
                                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3],
719
                                                coords[4], coords[5]);
720
                                 break;
721

    
722
                        case PathIterator.SEG_CLOSE:
723
                                tmpPath.lineTo(first[0], first[1]);
724
                                 break;
725

    
726
                        } // end switch
727

    
728
                        piter.next();
729

    
730
                }
731
                if (tmpPath != null) {
732
                        tmpCurve = createCurve(tmpPath, subType);
733
                        multiCurve.addCurve(tmpCurve);
734
                }
735

    
736
                return multiCurve;
737

    
738
        }
739

    
740
        public MultiSurface createMultiSurface(GeneralPathX generalPathX,
741
                        int subType) throws CreateGeometryException {
742
                if (subType != SUBTYPES.GEOM2D) {
743
                        // FIXME Exception
744
                        throw new UnsupportedOperationException();
745
                }
746
                MultiSurface multiSurface = (MultiSurface) create(TYPES.MULTISURFACE,
747
                                subType);
748
                PathIterator piter = generalPathX.getPathIterator(null);
749
                GeneralPathX tmpPath = null;
750
                Surface tmpSurface = null;
751
                double[] coords = new double[6];
752
                double[] first = new double[6];
753
                int type;
754
                while (!piter.isDone()) {
755
                        type = piter.currentSegment(coords);
756
                        switch (type) {
757
                        case PathIterator.SEG_MOVETO:
758
                                if (tmpPath != null) {
759
                                        tmpSurface = createSurface(tmpPath, subType);
760
                                        multiSurface.addSurface(tmpSurface);
761
                                }
762
                                System.arraycopy(coords, 0, first, 0, 2);
763
                                tmpPath = new GeneralPathX(piter.getWindingRule());
764
                                tmpPath.moveTo(coords[0], coords[1]);
765

    
766
                        case PathIterator.SEG_LINETO:
767
                                if (tmpPath == null) {
768
                                        System.arraycopy(coords, 0, first, 0, 2);
769
                                        tmpPath = new GeneralPathX(piter.getWindingRule());
770
                                }
771
                                tmpPath.lineTo(coords[0], coords[1]);
772
                                break;
773

    
774

    
775
                        case PathIterator.SEG_QUADTO:
776
                                if (tmpPath == null) {
777
                                        System.arraycopy(coords, 0, first, 0, 2);
778
                                        tmpPath = new GeneralPathX(piter.getWindingRule());
779
                                }
780
                                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
781
                                break;
782

    
783
                        case PathIterator.SEG_CUBICTO:
784
                                if (tmpPath == null) {
785
                                        System.arraycopy(coords, 0, first, 0, 2);
786
                                        tmpPath = new GeneralPathX(piter.getWindingRule());
787
                                }
788
                                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3],
789
                                                coords[4], coords[5]);
790
                                break;
791

    
792
                        case PathIterator.SEG_CLOSE:
793
                                tmpPath.lineTo(first[0], first[1]);
794
                                break;
795
                        } // end switch
796

    
797
                        piter.next();
798

    
799
                }
800
                if (tmpPath != null) {
801
                        tmpSurface = createSurface(tmpPath, subType);
802
                        multiSurface.addSurface(tmpSurface);
803
                }
804

    
805
                return multiSurface;
806

    
807
        }
808

    
809
        /* (non-Javadoc)
810
         * @see org.gvsig.fmap.geom.GeometryManager#getGeometryOperationCode(java.lang.String)
811
         */
812
        public int getGeometryOperationCode(String geomOpName) {
813
                if (geomOpName == null) {
814
                        throw new IllegalArgumentException("geomOpName cannot be null.");
815
                }
816

    
817
                int index = geometryOperations.indexOf(geomOpName);
818
                if (index == -1) {
819
                        geometryOperations.add(geomOpName);
820
                        index = geometryOperations.indexOf(geomOpName);
821
                }
822
                return index;
823
        }
824

    
825
        /* (non-Javadoc)
826
         * @see org.gvsig.fmap.geom.GeometryManager#getGeometryOperationNames()
827
         */
828
        public List getGeometryOperationNames() {
829
                List operations = new ArrayList();
830
                for (int i=0 ; i<operations.size() ; i++){
831
                        operations.add(geometryOperations.get(i));
832
                }
833
                return operations;
834
        }
835

    
836
        /*
837
         * (non-Javadoc)
838
         * @see org.gvsig.fmap.geom.GeometryManager#getFlatness()
839
         */
840
        public double getFlatness() {
841
                return flatness;
842
        }
843

    
844
        /*
845
         * (non-Javadoc)
846
         * @see org.gvsig.fmap.geom.GeometryManager#setFlatness(double)
847
         */
848
        public void setFlatness(double flatness) {
849
                this.flatness = flatness;
850
        }
851

    
852
        public Geometry createFrom(String wkt, String srs) throws GeometryException {
853
                FromWKTGeometryOperationContext context = new FromWKTGeometryOperationContext(wkt,srs);
854
                try {
855
                        return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
856
                } catch (GeometryOperationNotSupportedException e) {
857
                        throw new  GeometryException(e);
858
                } catch (GeometryOperationException e) {
859
                        throw new  GeometryException(e);
860
                }
861
        }
862

    
863
        public Geometry createFrom(byte[] wkb) throws GeometryException {
864
                FromWKBGeometryOperationContext context = new FromWKBGeometryOperationContext();
865
                context.setData(wkb);
866
                try {
867
                        return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
868
                } catch (GeometryOperationNotSupportedException e) {
869
                        throw new  GeometryException(e);
870
                } catch (GeometryOperationException e) {
871
                        throw new  GeometryException(e);
872
                }
873
        }        
874
}