Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.jts / src / main / java / org / gvsig / fmap / geom / jts / DefaultGeometryManager.java @ 43524

History | View | Annotate | Download (33.9 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.fmap.geom.jts;
26

    
27
import java.awt.geom.PathIterator;
28
import java.util.ArrayList;
29
import java.util.HashMap;
30
import java.util.Iterator;
31
import java.util.List;
32
import java.util.Map;
33
import org.cresques.cts.IProjection;
34

    
35
import org.slf4j.Logger;
36
import org.slf4j.LoggerFactory;
37

    
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
40
import org.gvsig.fmap.geom.Geometry.TYPES;
41
import org.gvsig.fmap.geom.GeometryException;
42
import org.gvsig.fmap.geom.GeometryLocator;
43
import org.gvsig.fmap.geom.GeometryManager;
44
import org.gvsig.fmap.geom.InformationbuilderWithGeometrySupport;
45
import org.gvsig.fmap.geom.SpatialIndex;
46
import org.gvsig.fmap.geom.SpatialIndexFactory;
47
import org.gvsig.fmap.geom.aggregate.MultiCurve;
48
import org.gvsig.fmap.geom.aggregate.MultiLine;
49
import org.gvsig.fmap.geom.aggregate.MultiPoint;
50
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
51
import org.gvsig.fmap.geom.aggregate.MultiSurface;
52
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
53
import org.gvsig.fmap.geom.exception.CreateGeometryException;
54
import org.gvsig.fmap.geom.jts.gputils.DefaultGeneralPathX;
55
import org.gvsig.fmap.geom.jts.primitive.DefaultNullGeometry;
56
import org.gvsig.fmap.geom.jts.primitive.Envelope2D;
57
import org.gvsig.fmap.geom.jts.primitive.Envelope3D;
58
import org.gvsig.fmap.geom.jts.spatialindex.SpatialIndexFactoryJSIRTree;
59
import org.gvsig.fmap.geom.jts.spatialindex.SpatialIndexFactoryJTSQuadtree;
60
import org.gvsig.fmap.geom.jts.util.JTSUtils;
61
import org.gvsig.fmap.geom.operation.GeometryOperation;
62
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
63
import org.gvsig.fmap.geom.operation.GeometryOperationException;
64
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
65
import org.gvsig.fmap.geom.primitive.Curve;
66
import org.gvsig.fmap.geom.primitive.Envelope;
67
import org.gvsig.fmap.geom.primitive.GeneralPathX;
68
import org.gvsig.fmap.geom.primitive.IGeneralPathX;
69
import org.gvsig.fmap.geom.primitive.Line;
70
import org.gvsig.fmap.geom.primitive.NullGeometry;
71
import org.gvsig.fmap.geom.primitive.Point;
72
import org.gvsig.fmap.geom.primitive.Polygon;
73
import org.gvsig.fmap.geom.primitive.Surface;
74
import org.gvsig.fmap.geom.type.GeometryType;
75
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
76
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
77
import org.gvsig.tools.dynobject.DynObject;
78
import org.gvsig.tools.service.Service;
79
import org.gvsig.tools.service.ServiceException;
80
import org.gvsig.tools.service.spi.ServiceFactory;
81

    
82
/**
83
 * Default implementation for the {@link GeometryManager}. When the
84
 * application starts, this class is registered in the {@link GeometryLocator}
85
 * using the {@link DefaultGeometryLibrary}.
86
 *
87
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
88
 */
89

    
90
public class DefaultGeometryManager implements GeometryManager {
91

    
92
    private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
93
    private double flatness = 0.8;
94

    
95
    private Map spatialIndexFactories = new HashMap();
96

    
97
    /**
98
     * This list holds the unique name of all registered geometry operations.
99
     * The index in which they are stored is also the operation code used to
100
     * invoke each one of them
101
     */
102
    private List geometryOperations = new ArrayList();
103

    
104
    /**
105
     * Common operations are registered here. Type specific operations are
106
     * registered in the corresponding GeometryType instance
107
     */
108
    // private List commonOperations = new ArrayList();
109

    
110
    /**
111
     * This map holds the instances of all registered GeometryType. The key is
112
     * the name of the specific Geometry subclass.
113
     * In other words, the string "org.gvsig.fmap.geom.primitive.Point2D" is the
114
     * hash key to obtain an instance of GeometryType holding the
115
     * operations associated to the class org.gvsig.fmap.geom.primitive.Point2D.
116
     */
117
    private Map geometryTypeName = new HashMap();
118

    
119
    /**
120
     * Matrix of geometry types by type (row) and subtype (column). This matrix
121
     * will contain null values in the cells where a GeometryType hasn't been
122
     * registered.
123
     */
124
    private GeometryType[][] geometryTypes;
125

    
126
    // Initially create a matrix of 26 x 6, which are the current default
127
    // types and subtypes. If another type or subtype is registered, the
128
    // matrix will grow as needed
129
    private static final int DEFAULT_TYPES_SIZE = 26;
130
    private static final int DEFAULT_SUBTYPES_SIZE = 6;
131

    
132
    public DefaultGeometryManager() throws GeometryException {
133
        this(DEFAULT_TYPES_SIZE, DEFAULT_SUBTYPES_SIZE);
134
    }
135

    
136
    public DefaultGeometryManager(int initialTypesSize, int initialSubtypesSize) throws GeometryException {
137
        geometryTypes = new GeometryType[initialTypesSize][initialSubtypesSize];
138
        this.addServiceFactory(new SpatialIndexFactoryJTSQuadtree());
139
        this.addServiceFactory(new SpatialIndexFactoryJSIRTree());
140
    }
141

    
142
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, GeometryType geomType) {
143
        if (geomOp == null) {
144
            throw new IllegalArgumentException("geomOp cannot be null.");
145
        }
146
        if (geomType == null) {
147
            throw new IllegalArgumentException("geomType cannot be null.");
148
        }
149

    
150
        int index = getGeometryOperationCode(geomOpName);
151

    
152
        geomType.setGeometryOperation(index, geomOp);
153

    
154
        return index;
155
    }
156

    
157
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp) {
158
        if (geomOpName == null) {
159
            throw new IllegalArgumentException("geomOpName cannot be null.");
160
        }
161
        if (geomOp == null) {
162
            throw new IllegalArgumentException("geomOp cannot be null.");
163
        }
164

    
165
        int index = getGeometryOperationCode(geomOpName);
166

    
167
        Iterator it = geometryTypeName.values().iterator();
168
        while (it.hasNext()) {
169
            GeometryType geometryType = (GeometryType) it.next();
170
            registerGeometryOperation(geomOpName, geomOp, geometryType);
171
        }
172

    
173
        return index;
174

    
175
    }
176

    
177
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, int type, int subType)
178
        throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
179
        GeometryType geometryType = getGeometryType(type, subType);
180
        return registerGeometryOperation(geomOpName, geomOp, geometryType);
181
    }
182

    
183
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, int type) {
184
        int code = -1;
185
        Iterator it = geometryTypeName.values().iterator();
186
        while (it.hasNext()) {
187
            GeometryType geometryType = (GeometryType) it.next();
188
            if ((type == geometryType.getType())) {
189
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
190
            }
191
        }
192
        return code;
193
    }
194

    
195
    public int registerGeometryOperationBySubtype(String geomOpName, GeometryOperation geomOp, int subType) {
196
        int code = -1;
197
        Iterator it = geometryTypeName.values().iterator();
198
        while (it.hasNext()) {
199
            GeometryType geometryType = (GeometryType) it.next();
200
            if ((subType == geometryType.getSubType())) {
201
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
202
            }
203
        }
204
        return code;
205
    }
206

    
207
    public int registerGeometryOperationBySuperType(String geomOpName, GeometryOperation geomOp, int superType) {
208
        int code = -1;
209
        Iterator it = geometryTypeName.values().iterator();
210
        while (it.hasNext()) {
211
            GeometryType geometryType = (GeometryType) it.next();
212
            if (geometryType.isTypeOf(superType)) {
213
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
214
            }
215
        }
216
        return code;
217
    }
218

    
219
    public int registerGeometryOperationBySuperSubType(String geomOpName, GeometryOperation geomOp, int superSubType) {
220
        int code = -1;
221
        Iterator it = geometryTypeName.values().iterator();
222
        while (it.hasNext()) {
223
            GeometryType geometryType = (GeometryType) it.next();
224
            if (geometryType.isSubTypeOf(superSubType)) {
225
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
226
            }
227
        }
228
        return code;
229
    }
230

    
231
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType) {
232
        return registerGeometryType(geomClass, name, type, subType, new int[0], new int[0]);
233
    }
234

    
235
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int superType,
236
        int superSubType) {
237
        return registerGeometryType(geomClass, name, type, subType, new int[] { superType }, new int[] { superSubType });
238
    }
239

    
240
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int superType) {
241
        return registerGeometryType(geomClass, name, type, subType, new int[] { superType }, new int[0]);
242
    }
243

    
244
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int[] superTypes) {
245
        return registerGeometryType(geomClass, name, type, subType, superTypes, new int[0]);
246
    }
247

    
248
    /**
249
     * Registers a Geometry implementation class with a predefined geometry type
250
     * and returns the
251
     * associated GeometryType instance. Available predefined types are defined
252
     * in {@link Geometry.TYPES} If the class is already registered then this
253
     * method throws an IllegalArgumentException.<br>
254
     *
255
     * How to register a geometry class with a predefined type:
256
     *
257
     * <pre>
258
     *
259
     * public class Point2D implements Point {
260
     *   private static final GeometryType geomType = GeometryManager.getInstance()
261
     *    .registerBasicGeometryType(Point2D.class, "Point2D", Geometry.TYPES.POINT);
262
     *
263
     * ...
264
     *   public int getType() {
265
     *      return geomType.getType();
266
     *   }
267
     * }
268
     * </pre>
269
     *
270
     * @param geomClass
271
     *            Geometry subclass. It must not be null and must implement
272
     *            Geometry, otherwise an exception
273
     *            is raised.
274
     * @param name
275
     *            Symbolic name for the geometry type, it can be null. If it is
276
     *            null then the symbolic name
277
     *            will be the simple class name.
278
     * @param id
279
     *            Geometry identifier.
280
     * @param type
281
     *            Type of geometry. Must be a value defined in
282
     *            {@link Geometry.TYPES}
283
     * @param subType
284
     *            SubType of geometry. Must be a value defined in
285
     *            {@link Geometry.SUBTYPES}
286
     * @return Instance of GeometryType associated to the Geometry
287
     *         implementation class
288
     *         geomClass
289
     * @throws IllegalArgumentException
290
     *             If geomClass is null or does not implement Geometry
291
     */
292
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int[] superTypes,
293
        int superSubTypes[]) {
294
        if (geomClass == null) {
295
            throw new IllegalArgumentException("geomClass cannot be null.");
296
        }
297

    
298
        if (!Geometry.class.isAssignableFrom(geomClass)) {
299
            throw new IllegalArgumentException(geomClass.getName() + " must implement the Geometry interface");
300
        }
301

    
302
        // Check if it is registered
303
        GeometryType geomType = null;
304
        if (type >= geometryTypes.length || subType >= geometryTypes[0].length
305
            || (geomType = geometryTypes[type][subType]) == null) {
306
            geomType = new DefaultGeometryType(geomClass, name, type, subType, superTypes, superSubTypes);
307
            registerGeometryType(geomType);
308
        }
309

    
310
        logger.debug("Class {} registered with name {}", geomClass, geomType.getName());
311

    
312
        return geomType;
313
    }
314

    
315
    public void registerGeometryType(GeometryType geometryType) {
316
        if (geometryType.getType() >= geometryTypes.length || geometryType.getSubType() >= geometryTypes[0].length) {
317

    
318
            // Recreate the geometry type matrix if the types
319
            // or subtypes don't fit
320
            int newTypesSize =
321
                geometryType.getType() < geometryTypes.length ? geometryTypes.length : geometryType.getType() + 1;
322
            int newSubTypesSize =
323
                geometryType.getSubType() < geometryTypes[0].length ? geometryTypes[0].length : geometryType
324
                    .getSubType() + 1;
325
            GeometryType[][] newMatrix = new GeometryType[newTypesSize][newSubTypesSize];
326

    
327
            for (int i = 0; i < geometryTypes.length; i++) {
328
                System.arraycopy(geometryTypes[i], 0, newMatrix[i], 0, geometryTypes[i].length);
329
            }
330
            geometryTypes = newMatrix;
331
        }
332

    
333
        geometryTypes[geometryType.getType()][geometryType.getSubType()] = geometryType;
334
        geometryTypeName.put(geometryType.getName(), geometryType);
335
    }
336

    
337
    public GeometryType registerGeometryType(Class geomClass, int type, int subType) {
338
        return registerGeometryType(geomClass, null, type, subType);
339
    }
340

    
341
    public GeometryType getGeometryType(int type, int subType) throws GeometryTypeNotSupportedException,
342
        GeometryTypeNotValidException {
343
        GeometryType gType = null;
344
        if (type >= geometryTypes.length || subType >= geometryTypes[0].length) {
345
            throw new GeometryTypeNotValidException(type, subType);
346
        }
347

    
348
        gType = geometryTypes[type][subType];
349

    
350
        if (gType == null) {
351
            throw new GeometryTypeNotSupportedException(type, subType);
352
        }
353

    
354
        return gType;
355
    }
356

    
357
    public Geometry create(GeometryType geomType) throws CreateGeometryException {
358
        return geomType.create();
359
    }
360

    
361
    public Geometry create(String name) throws CreateGeometryException {
362
        if (!geometryTypeName.containsKey(name)) {
363
            throw new IllegalArgumentException(name + " has not been registered yet.");
364
        }
365
        return ((GeometryType) geometryTypeName.get(name)).create();
366
    }
367

    
368
    public Geometry create(int type, int subType) throws CreateGeometryException {
369
        try {
370
            return getGeometryType(type, subType).create();
371
        } catch (GeometryException e) {
372
            throw new CreateGeometryException(type, subType, e);
373
        }
374
    }
375

    
376
    public Curve createCurve(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
377
        Curve curve = (Curve) create(TYPES.CURVE, subType);
378
        curve.setGeneralPath(generalPathX);
379
        return curve;
380
    }
381

    
382
    public NullGeometry createNullGeometry(int subType) throws CreateGeometryException {
383
        NullGeometry nullGeom = (NullGeometry) create(TYPES.NULL, subType);
384
        return nullGeom;
385
    }
386

    
387
    public Point createPoint(double x, double y, int subType) throws CreateGeometryException {
388
        Point point = (Point) create(TYPES.POINT, subType);
389
        point.setX(x);
390
        point.setY(y);
391
        return point;
392
    }
393

    
394
    public Surface createSurface(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
395
        Surface surface = (Surface) create(TYPES.SURFACE, subType);
396
        surface.setGeneralPath(generalPathX);
397
        return surface;
398
    }
399

    
400
    public GeometryOperation getGeometryOperation(int opCode, int type, int subType)
401
        throws GeometryTypeNotSupportedException, GeometryOperationNotSupportedException, GeometryTypeNotValidException {
402
        GeometryType geometryType = getGeometryType(type, subType);
403
        return geometryType.getGeometryOperation(opCode);
404
    }
405

    
406
    public GeometryOperation getGeometryOperation(int opCode) throws GeometryOperationNotSupportedException {
407
        if (opCode < 0) {
408
            throw new GeometryOperationNotSupportedException(opCode);
409
        }
410
        GeometryType type = (GeometryType) geometryTypeName.get(DefaultNullGeometry.class.getName());
411
        if (type == null) {
412
            throw new GeometryOperationNotSupportedException(opCode);
413
        }
414
        return type.getGeometryOperation(opCode);
415
    }
416

    
417
    public Object invokeOperation(int opCode, Geometry geom, GeometryOperationContext ctx)
418
        throws GeometryOperationNotSupportedException, GeometryOperationException {
419
        GeometryOperation geomOp = geom.getGeometryType().getGeometryOperation(opCode);
420

    
421
        if (geomOp != null) {
422
            return geomOp.invoke(geom, ctx);
423
        }
424

    
425
        throw new GeometryOperationNotSupportedException(opCode, geom.getGeometryType());
426
    }
427

    
428
    public Object invokeOperation(String geomOpName, Geometry geom, GeometryOperationContext ctx)
429
        throws GeometryOperationNotSupportedException, GeometryOperationException {
430
        int index = geometryOperations.indexOf(geomOpName);
431
        if (index == -1) {
432
            throw new GeometryOperationNotSupportedException(-1);
433
        }
434
        return invokeOperation(index, geom, ctx);
435
    }
436

    
437
    public Object invokeOperation(String geomOpName, GeometryOperationContext ctx)
438
        throws GeometryOperationNotSupportedException, GeometryOperationException {
439
        int index = geometryOperations.indexOf(geomOpName);
440
        GeometryOperation geomOp = getGeometryOperation(index);
441
        return geomOp.invoke(null, ctx);
442
    }
443

    
444
    public Envelope createEnvelope(int subType) {
445
        // TODO: register the envelopes!!!
446
        switch (subType) {
447
        case SUBTYPES.GEOM3D:
448
            return new Envelope3D();
449
        default:
450
            return new Envelope2D();
451
        }
452
    }
453

    
454
    public Envelope createEnvelope(double minX, double minY, double maxX, double maxY, int subType)
455
        throws CreateEnvelopeException {
456
        org.gvsig.fmap.geom.primitive.Point min = null;
457
        org.gvsig.fmap.geom.primitive.Point max = null;
458
        try {
459
            min = createPoint(minX, minY, subType);
460
            max = createPoint(maxX, maxY, subType);
461
        } catch (CreateGeometryException e) {
462
            throw new CreateEnvelopeException(subType, e);
463
        }
464
        switch (subType) {
465
        case SUBTYPES.GEOM2D:
466
        case SUBTYPES.GEOM2DM:
467
            // Small optimization to directly create an Envelope2D
468
            // return new Envelope2D(minX, minY, maxX, maxY);
469
            return new Envelope2D(min, max);
470
        default:
471
            Envelope envelope = createEnvelope(subType);
472
            envelope.setLowerCorner(min);
473
            envelope.setUpperCorner(max);
474
            return envelope;
475
        }
476
    }
477

    
478
    public MultiCurve createMultiCurve(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
479
        if (subType != SUBTYPES.GEOM2D) {
480
            // FIXME Exception
481
            throw new UnsupportedOperationException();
482
        }
483
        MultiCurve multiCurve = (MultiCurve) create(TYPES.MULTICURVE, subType);
484
        PathIterator piter = generalPathX.getPathIterator(null);
485
        GeneralPathX tmpPath = null;
486
        Curve tmpCurve = null;
487
        double[] coords = new double[6];
488
        double[] first = new double[6];
489
        int type;
490
        while (!piter.isDone()) {
491
            type = piter.currentSegment(coords);
492
            switch (type) {
493
            case PathIterator.SEG_MOVETO:
494
                if (tmpPath != null) {
495
                    tmpCurve = createCurve(tmpPath, subType);
496
                    multiCurve.addCurve(tmpCurve);
497
                }
498
                System.arraycopy(coords, 0, first, 0, 2);
499
                tmpPath = new GeneralPathX(piter.getWindingRule());
500
                tmpPath.moveTo(coords[0], coords[1]);
501
                break;
502

    
503
            case PathIterator.SEG_LINETO:
504
                if (tmpPath == null) {
505
                    System.arraycopy(coords, 0, first, 0, 2);
506
                    tmpPath = new GeneralPathX(piter.getWindingRule());
507
                }
508
                tmpPath.lineTo(coords[0], coords[1]);
509
                break;
510

    
511
            case PathIterator.SEG_QUADTO:
512
                if (tmpPath == null) {
513
                    System.arraycopy(coords, 0, first, 0, 2);
514
                    tmpPath = new GeneralPathX(piter.getWindingRule());
515
                }
516
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
517
                break;
518

    
519
            case PathIterator.SEG_CUBICTO:
520
                if (tmpPath == null) {
521
                    System.arraycopy(coords, 0, first, 0, 2);
522
                    tmpPath = new GeneralPathX(piter.getWindingRule());
523
                }
524
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
525
                break;
526

    
527
            case PathIterator.SEG_CLOSE:
528
                tmpPath.lineTo(first[0], first[1]);
529
                break;
530

    
531
            } // end switch
532

    
533
            piter.next();
534

    
535
        }
536
        if (tmpPath != null) {
537
            tmpCurve = createCurve(tmpPath, subType);
538
            multiCurve.addCurve(tmpCurve);
539
        }
540

    
541
        return multiCurve;
542

    
543
    }
544

    
545
    public MultiSurface createMultiSurface(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
546
        if (subType != SUBTYPES.GEOM2D) {
547
            // FIXME Exception
548
            throw new UnsupportedOperationException();
549
        }
550
        MultiSurface multiSurface = (MultiSurface) create(TYPES.MULTISURFACE, subType);
551
        PathIterator piter = generalPathX.getPathIterator(null);
552
        GeneralPathX tmpPath = null;
553
        Surface tmpSurface = null;
554
        double[] coords = new double[6];
555
        double[] first = new double[6];
556
        int type;
557
        while (!piter.isDone()) {
558
            type = piter.currentSegment(coords);
559
            switch (type) {
560
            case PathIterator.SEG_MOVETO:
561
                if (tmpPath != null) {
562
                    tmpSurface = createSurface(tmpPath, subType);
563
                    multiSurface.addSurface(tmpSurface);
564
                }
565
                System.arraycopy(coords, 0, first, 0, 2);
566
                tmpPath = new GeneralPathX(piter.getWindingRule());
567
                tmpPath.moveTo(coords[0], coords[1]);
568

    
569
            case PathIterator.SEG_LINETO:
570
                if (tmpPath == null) {
571
                    System.arraycopy(coords, 0, first, 0, 2);
572
                    tmpPath = new GeneralPathX(piter.getWindingRule());
573
                }
574
                tmpPath.lineTo(coords[0], coords[1]);
575
                break;
576

    
577
            case PathIterator.SEG_QUADTO:
578
                if (tmpPath == null) {
579
                    System.arraycopy(coords, 0, first, 0, 2);
580
                    tmpPath = new GeneralPathX(piter.getWindingRule());
581
                }
582
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
583
                break;
584

    
585
            case PathIterator.SEG_CUBICTO:
586
                if (tmpPath == null) {
587
                    System.arraycopy(coords, 0, first, 0, 2);
588
                    tmpPath = new GeneralPathX(piter.getWindingRule());
589
                }
590
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
591
                break;
592

    
593
            case PathIterator.SEG_CLOSE:
594
                tmpPath.lineTo(first[0], first[1]);
595
                break;
596
            } // end switch
597

    
598
            piter.next();
599

    
600
        }
601
        if (tmpPath != null) {
602
            tmpSurface = createSurface(tmpPath, subType);
603
            multiSurface.addSurface(tmpSurface);
604
        }
605

    
606
        return multiSurface;
607

    
608
    }
609

    
610
    public MultiPoint createMultiPoint(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
611
        if (subType != SUBTYPES.GEOM2D) {
612
            // FIXME Exception
613
            throw new UnsupportedOperationException();
614
        }
615
        MultiPoint multiPoint = (MultiPoint) create(TYPES.MULTIPOINT, subType);
616
        PathIterator piter = generalPathX.getPathIterator(null);
617
        Point tmpPoint = null;
618
        double[] coords = new double[6];
619
        int type;
620
        while (!piter.isDone()) {
621
            type = piter.currentSegment(coords);
622
            switch (type) {
623
            case PathIterator.SEG_MOVETO:
624
                tmpPoint = createPoint(coords[0], coords[1], subType);
625
                multiPoint.addPoint(tmpPoint);
626

    
627
            case PathIterator.SEG_LINETO:
628
                throw new IllegalArgumentException("The general have a SEG_LINETO.");
629

    
630
            case PathIterator.SEG_QUADTO:
631
                throw new IllegalArgumentException("The general have a SEG_QUADTO.");
632

    
633
            case PathIterator.SEG_CUBICTO:
634
                throw new IllegalArgumentException("The general have a SEG_CUBICTO.");
635

    
636
            case PathIterator.SEG_CLOSE:
637
                throw new IllegalArgumentException("The general have a SEG_CLOSE.");
638
            } // end switch
639

    
640
            piter.next();
641

    
642
        }
643
        return multiPoint;
644

    
645
    }
646

    
647
    public int getGeometryOperationCode(String geomOpName) {
648
        if (geomOpName == null) {
649
            throw new IllegalArgumentException("geomOpName cannot be null.");
650
        }
651

    
652
        int index = geometryOperations.indexOf(geomOpName);
653
        if (index == -1) {
654
            geometryOperations.add(geomOpName);
655
            index = geometryOperations.indexOf(geomOpName);
656
        }
657
        return index;
658
    }
659

    
660
    public List getGeometryOperationNames() {
661
        List operations = new ArrayList();
662
        for (int i = 0; i < operations.size(); i++) {
663
            operations.add(geometryOperations.get(i));
664
        }
665
        return operations;
666
    }
667

    
668
    public double getFlatness() {
669
        return flatness;
670
    }
671

    
672
    public void setFlatness(double flatness) {
673
        this.flatness = flatness;
674
    }
675

    
676
    public Geometry createFrom(String wkt, String srs) throws GeometryException {
677
        GeometryOperationContext context = new GeometryOperationContext();
678
        context.setAttribute("text", wkt);
679
        context.setAttribute("srs", srs);
680

    
681
        try {
682
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
683
        } catch (GeometryOperationNotSupportedException e) {
684
            throw new GeometryException(e);
685
        } catch (GeometryOperationException e) {
686
            throw new GeometryException(e);
687
        }
688
    }
689

    
690
    public Geometry createFrom(String wkt, IProjection srs) throws GeometryException {
691
        GeometryOperationContext context = new GeometryOperationContext();
692
        context.setAttribute("text", wkt);
693
        context.setAttribute("srs", srs);
694

    
695
        try {
696
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
697
        } catch (GeometryOperationNotSupportedException e) {
698
            throw new GeometryException(e);
699
        } catch (GeometryOperationException e) {
700
            throw new GeometryException(e);
701
        }
702
    }
703

    
704
    public Geometry createFrom(com.vividsolutions.jts.geom.Geometry geom) throws GeometryException {
705
        return JTSUtils.createGeometry(geom);
706
    }
707

    
708
    public Geometry createFrom(String wkt) throws GeometryException {
709
        GeometryOperationContext context = new GeometryOperationContext();
710
        context.setAttribute("text", wkt);
711
        context.setAttribute("srs", null);
712

    
713
        try {
714
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
715
        } catch (GeometryOperationNotSupportedException e) {
716
            throw new GeometryException(e);
717
        } catch (GeometryOperationException e) {
718
            throw new GeometryException(e);
719
        }
720
    }
721

    
722
    public Geometry createFrom(byte[] wkb) throws GeometryException {
723
        GeometryOperationContext context = new GeometryOperationContext();
724
        context.setAttribute("data", wkb);
725
        try {
726
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
727
        } catch (GeometryOperationNotSupportedException e) {
728
            throw new GeometryException(e);
729
        } catch (GeometryOperationException e) {
730
            throw new GeometryException(e);
731
        }
732
    }
733

    
734
    public Geometry createFrom(byte[] wkb, IProjection srs) throws GeometryException {
735
        GeometryOperationContext context = new GeometryOperationContext();
736
        context.setAttribute("data", wkb);
737
        context.setAttribute("srs", srs);
738
        try {
739
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
740
        } catch (GeometryOperationNotSupportedException e) {
741
            throw new GeometryException(e);
742
        } catch (GeometryOperationException e) {
743
            throw new GeometryException(e);
744
        }
745
    }
746

    
747
    public IGeneralPathX createGeneralPath(int rule, PathIterator pathIterator) {
748
        if (pathIterator == null) {
749
            return new DefaultGeneralPathX(rule);
750
        }
751
        return new DefaultGeneralPathX(pathIterator, false, 0);
752
    }
753

    
754
    public MultiPoint createMultiPoint(int subType) throws CreateGeometryException {
755
        return (MultiPoint) create(TYPES.MULTIPOINT, subType);
756
    }
757

    
758
    public Line createLine(int subType) throws CreateGeometryException {
759
        return (Line) create(TYPES.CURVE, subType);
760
    }
761

    
762
    public Curve createCurve(int subType) throws CreateGeometryException {
763
        return (Curve) create(TYPES.CURVE, subType);
764
    }
765

    
766
    public MultiCurve createMultiCurve(int subType) throws CreateGeometryException {
767
        return (MultiCurve) create(TYPES.MULTICURVE, subType);
768
    }
769

    
770
    public MultiLine createMultiLine(int subType) throws CreateGeometryException {
771
        return (MultiLine) create(TYPES.MULTILINE, subType);
772
    }
773

    
774
    public MultiSurface createMultiSurface(int subType) throws CreateGeometryException {
775
        return (MultiSurface) create(TYPES.MULTISURFACE, subType);
776
    }
777

    
778
    public MultiPolygon createMultiPolygon(int subType) throws CreateGeometryException {
779
        return (MultiPolygon) create(TYPES.MULTIPOLYGON, subType);
780
    }
781

    
782
    public Polygon createPolygon(int subType) throws CreateGeometryException {
783
        return (Polygon) create(TYPES.SURFACE, subType);
784
    }
785

    
786
    public Surface createSurface(int subType) throws CreateGeometryException {
787
        return (Surface) create(TYPES.SURFACE, subType);
788
    }
789

    
790
    public SpatialIndex createDefaultMemorySpatialIndex() throws ServiceException {
791
        return this.createSpatialIndex(SpatialIndexFactoryJTSQuadtree.NAME, null);
792
    }
793

    
794
    public SpatialIndex createSpatialIndex(String name, DynObject parameters) throws ServiceException {
795
        SpatialIndexFactory factory = this.getSpatialIndexFactory(name);
796
        if (factory == null) {
797
            throw new CantExistsService(name);
798
        }
799
        return (SpatialIndex) factory.create(parameters, this);
800
    }
801

    
802
    public SpatialIndexFactory getSpatialIndexFactory(String name) {
803
        return (SpatialIndexFactory) this.spatialIndexFactories.get(name);
804
    }
805

    
806
    public void addServiceFactory(ServiceFactory serviceFactory) {
807
        serviceFactory.initialize();
808
        this.spatialIndexFactories.put(serviceFactory.getName(), serviceFactory);
809
    }
810

    
811
    public Service createService(DynObject serviceParameters) throws ServiceException {
812
        throw new UnsupportedOperationException("Not supported yet.");
813
    }
814

    
815
    public DynObject createServiceParameters(String serviceName) throws ServiceException {
816
        SpatialIndexFactory factory = this.getSpatialIndexFactory(serviceName);
817
        if (factory == null) {
818
            throw new CantExistsService(serviceName);
819
        }
820
        return factory.createParameters();
821
    }
822

    
823
    public Service getService(DynObject parameters) throws ServiceException {
824
        return this.createSpatialIndex((String) parameters.getDynValue("serviceName"), parameters);
825
    }
826

    
827
    public class CantExistsService extends ServiceException {
828

    
829
        public CantExistsService(String serviceName) {
830
            super("Can't existe service %(service).", "_Cant_existe_service_XserviceX", 100001);
831
            setValue("service", serviceName);
832
        }
833

    
834
    }
835

    
836
    @Override
837
    public InformationbuilderWithGeometrySupport createInformacionBuilder() {
838
        return new BaseInformationBuilderWithGeometrySupport();
839
    }
840

    
841
    @Override
842
    public boolean isSubtype(int geomTypeParent, int geomTypeChild) {
843
        // Esto es un implementacion patatera que habria que mejorar,
844
        // pero mejor aqui que esparcida por todas partes en donde se
845
        // necesite.
846
        if( geomTypeParent == geomTypeChild ) {
847
            return true;
848
        }
849
        switch(geomTypeParent) {
850
        case Geometry.TYPES.MULTICURVE:
851
            return geomTypeChild==Geometry.TYPES.MULTILINE ;
852
        case Geometry.TYPES.MULTISURFACE:
853
            return geomTypeChild==Geometry.TYPES.MULTIPOLYGON ;
854
        case Geometry.TYPES.MULTIPOINT:
855
            return geomTypeChild==Geometry.TYPES.MULTIPOINT ;
856

    
857
        case Geometry.TYPES.CURVE:
858
            return
859
                geomTypeChild == Geometry.TYPES.CURVE ||
860
                geomTypeChild == Geometry.TYPES.LINE ||
861
                geomTypeChild == Geometry.TYPES.ARC ||
862
                geomTypeChild == Geometry.TYPES.SPLINE ||
863
                geomTypeChild == Geometry.TYPES.CIRCUMFERENCE ||
864
                geomTypeChild == Geometry.TYPES.PERIELLIPSE
865
                ;
866
        case Geometry.TYPES.SURFACE:
867
            return
868
            geomTypeChild==Geometry.TYPES.SURFACE ||
869
            geomTypeChild==Geometry.TYPES.POLYGON ||
870
            geomTypeChild == Geometry.TYPES.CIRCLE ||
871
            geomTypeChild == Geometry.TYPES.ELLIPSE ||
872
            geomTypeChild == Geometry.TYPES.RING ||
873
            geomTypeChild == Geometry.TYPES.FILLEDSPLINE ||
874
            geomTypeChild == Geometry.TYPES.ELLIPTICARC
875
            ;
876
        case Geometry.TYPES.POINT:
877
            return geomTypeChild==Geometry.TYPES.POINT ;
878
        }
879
        return false;
880
    }
881
}