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

History | View | Annotate | Download (35.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 com.vividsolutions.jts.io.gml2.GMLReader;
28
import java.awt.geom.PathIterator;
29
import java.util.ArrayList;
30
import java.util.HashMap;
31
import java.util.Iterator;
32
import java.util.List;
33
import java.util.Map;
34
import org.cresques.cts.IProjection;
35

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

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

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

    
93
public class DefaultGeometryManager implements GeometryManager {
94

    
95
    private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
96
    private double flatness = 0.8;
97

    
98
    private Map spatialIndexFactories = new HashMap();
99

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

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

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

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

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

    
135
    public DefaultGeometryManager() throws GeometryException {
136
        this(DEFAULT_TYPES_SIZE, DEFAULT_SUBTYPES_SIZE);
137
    }
138

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

    
145
    @Override
146
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, GeometryType geomType) {
147
        if (geomOp == null) {
148
            throw new IllegalArgumentException("geomOp cannot be null.");
149
        }
150
        if (geomType == null) {
151
            throw new IllegalArgumentException("geomType cannot be null.");
152
        }
153

    
154
        int index = getGeometryOperationCode(geomOpName);
155

    
156
        geomType.setGeometryOperation(index, geomOp);
157

    
158
        return index;
159
    }
160

    
161
    @Override
162
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp) {
163
        if (geomOpName == null) {
164
            throw new IllegalArgumentException("geomOpName cannot be null.");
165
        }
166
        if (geomOp == null) {
167
            throw new IllegalArgumentException("geomOp cannot be null.");
168
        }
169

    
170
        int index = getGeometryOperationCode(geomOpName);
171

    
172
        Iterator it = geometryTypeName.values().iterator();
173
        while (it.hasNext()) {
174
            GeometryType geometryType = (GeometryType) it.next();
175
            registerGeometryOperation(geomOpName, geomOp, geometryType);
176
        }
177

    
178
        return index;
179

    
180
    }
181

    
182
    @SuppressWarnings("override")
183
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, int type, int subType)
184
        throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
185
        GeometryType geometryType = getGeometryType(type, subType);
186
        return registerGeometryOperation(geomOpName, geomOp, geometryType);
187
    }
188

    
189
    @Override
190
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, int type) {
191
        int code = -1;
192
        Iterator it = geometryTypeName.values().iterator();
193
        while (it.hasNext()) {
194
            GeometryType geometryType = (GeometryType) it.next();
195
            if ((type == geometryType.getType())) {
196
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
197
            }
198
        }
199
        return code;
200
    }
201

    
202
    @Override
203
    public int registerGeometryOperationBySubtype(String geomOpName, GeometryOperation geomOp, int subType) {
204
        int code = -1;
205
        Iterator it = geometryTypeName.values().iterator();
206
        while (it.hasNext()) {
207
            GeometryType geometryType = (GeometryType) it.next();
208
            if ((subType == geometryType.getSubType())) {
209
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
210
            }
211
        }
212
        return code;
213
    }
214

    
215
    @Override
216
    public int registerGeometryOperationBySuperType(String geomOpName, GeometryOperation geomOp, int superType) {
217
        int code = -1;
218
        Iterator it = geometryTypeName.values().iterator();
219
        while (it.hasNext()) {
220
            GeometryType geometryType = (GeometryType) it.next();
221
            if (geometryType.isTypeOf(superType)) {
222
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
223
            }
224
        }
225
        return code;
226
    }
227

    
228
    @Override
229
    public int registerGeometryOperationBySuperSubType(String geomOpName, GeometryOperation geomOp, int superSubType) {
230
        int code = -1;
231
        Iterator it = geometryTypeName.values().iterator();
232
        while (it.hasNext()) {
233
            GeometryType geometryType = (GeometryType) it.next();
234
            if (geometryType.isSubTypeOf(superSubType)) {
235
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
236
            }
237
        }
238
        return code;
239
    }
240

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

    
246
    @Override
247
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int superType,
248
        int superSubType) {
249
        return registerGeometryType(geomClass, name, type, subType, new int[] { superType }, new int[] { superSubType });
250
    }
251

    
252
    @Override
253
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int superType) {
254
        return registerGeometryType(geomClass, name, type, subType, new int[] { superType }, new int[0]);
255
    }
256

    
257
    @Override
258
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int[] superTypes) {
259
        return registerGeometryType(geomClass, name, type, subType, superTypes, new int[0]);
260
    }
261

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

    
313
        if (!Geometry.class.isAssignableFrom(geomClass)) {
314
            throw new IllegalArgumentException(geomClass.getName() + " must implement the Geometry interface");
315
        }
316

    
317
        // Check if it is registered
318
        GeometryType geomType = null;
319
        if (type >= geometryTypes.length || subType >= geometryTypes[0].length
320
            || (geomType = geometryTypes[type][subType]) == null) {
321
            geomType = new DefaultGeometryType(geomClass, name, type, subType, superTypes, superSubTypes);
322
            registerGeometryType(geomType);
323
        }
324

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

    
327
        return geomType;
328
    }
329

    
330
    @Override
331
    public void registerGeometryType(GeometryType geometryType) {
332
        if (geometryType.getType() >= geometryTypes.length || geometryType.getSubType() >= geometryTypes[0].length) {
333

    
334
            // Recreate the geometry type matrix if the types
335
            // or subtypes don't fit
336
            int newTypesSize =
337
                geometryType.getType() < geometryTypes.length ? geometryTypes.length : geometryType.getType() + 1;
338
            int newSubTypesSize =
339
                geometryType.getSubType() < geometryTypes[0].length ? geometryTypes[0].length : geometryType
340
                    .getSubType() + 1;
341
            GeometryType[][] newMatrix = new GeometryType[newTypesSize][newSubTypesSize];
342

    
343
            for (int i = 0; i < geometryTypes.length; i++) {
344
                System.arraycopy(geometryTypes[i], 0, newMatrix[i], 0, geometryTypes[i].length);
345
            }
346
            geometryTypes = newMatrix;
347
        }
348

    
349
        geometryTypes[geometryType.getType()][geometryType.getSubType()] = geometryType;
350
        geometryTypeName.put(geometryType.getName(), geometryType);
351
    }
352

    
353
    @Override
354
    public GeometryType registerGeometryType(Class geomClass, int type, int subType) {
355
        return registerGeometryType(geomClass, null, type, subType);
356
    }
357

    
358
    @Override
359
    public GeometryType getGeometryType(int type, int subType) throws GeometryTypeNotSupportedException,
360
        GeometryTypeNotValidException {
361
        GeometryType gType = null;
362
        if (type >= geometryTypes.length || subType >= geometryTypes[0].length) {
363
            throw new GeometryTypeNotValidException(type, subType);
364
        }
365

    
366
        gType = geometryTypes[type][subType];
367

    
368
        if (gType == null) {
369
            throw new GeometryTypeNotSupportedException(type, subType);
370
        }
371

    
372
        return gType;
373
    }
374

    
375
    @Override
376
    public Geometry create(GeometryType geomType) throws CreateGeometryException {
377
        return geomType.create();
378
    }
379

    
380
    @Override
381
    public Geometry create(String name) throws CreateGeometryException {
382
        if (!geometryTypeName.containsKey(name)) {
383
            throw new IllegalArgumentException(name + " has not been registered yet.");
384
        }
385
        return ((GeometryType) geometryTypeName.get(name)).create();
386
    }
387

    
388
    @Override
389
    public Geometry create(int type, int subType) throws CreateGeometryException {
390
        try {
391
            return getGeometryType(type, subType).create();
392
        } catch (GeometryException e) {
393
            throw new CreateGeometryException(type, subType, e);
394
        }
395
    }
396

    
397
    @Override
398
    public Curve createCurve(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
399
        Curve curve = (Curve) create(TYPES.CURVE, subType);
400
        curve.setGeneralPath(generalPathX);
401
        return curve;
402
    }
403

    
404
    @Override
405
    public NullGeometry createNullGeometry(int subType) throws CreateGeometryException {
406
        NullGeometry nullGeom = (NullGeometry) create(TYPES.NULL, subType);
407
        return nullGeom;
408
    }
409

    
410
    @Override
411
    public Point createPoint(double x, double y, int subType) throws CreateGeometryException {
412
        Point point = (Point) create(TYPES.POINT, subType);
413
        point.setX(x);
414
        point.setY(y);
415
        return point;
416
    }
417

    
418
    @Override
419
    public Surface createSurface(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
420
        Surface surface = (Surface) create(TYPES.SURFACE, subType);
421
        surface.setGeneralPath(generalPathX);
422
        return surface;
423
    }
424

    
425
    @Override
426
    public GeometryOperation getGeometryOperation(int opCode, int type, int subType)
427
        throws GeometryTypeNotSupportedException, GeometryOperationNotSupportedException, GeometryTypeNotValidException {
428
        GeometryType geometryType = getGeometryType(type, subType);
429
        return geometryType.getGeometryOperation(opCode);
430
    }
431

    
432
    @Override
433
    public GeometryOperation getGeometryOperation(int opCode) throws GeometryOperationNotSupportedException {
434
        if (opCode < 0) {
435
            throw new GeometryOperationNotSupportedException(opCode);
436
        }
437
        GeometryType type = (GeometryType) geometryTypeName.get(DefaultNullGeometry.class.getName());
438
        if (type == null) {
439
            throw new GeometryOperationNotSupportedException(opCode);
440
        }
441
        return type.getGeometryOperation(opCode);
442
    }
443

    
444
    @Override
445
    public Object invokeOperation(int opCode, Geometry geom, GeometryOperationContext ctx)
446
        throws GeometryOperationNotSupportedException, GeometryOperationException {
447
        GeometryOperation geomOp = geom.getGeometryType().getGeometryOperation(opCode);
448

    
449
        if (geomOp != null) {
450
            return geomOp.invoke(geom, ctx);
451
        }
452

    
453
        throw new GeometryOperationNotSupportedException(opCode, geom.getGeometryType());
454
    }
455

    
456
    @Override
457
    public Object invokeOperation(String geomOpName, Geometry geom, GeometryOperationContext ctx)
458
        throws GeometryOperationNotSupportedException, GeometryOperationException {
459
        int index = geometryOperations.indexOf(geomOpName);
460
        if (index == -1) {
461
            throw new GeometryOperationNotSupportedException(-1);
462
        }
463
        return invokeOperation(index, geom, ctx);
464
    }
465

    
466
    @Override
467
    public Object invokeOperation(String geomOpName, GeometryOperationContext ctx)
468
        throws GeometryOperationNotSupportedException, GeometryOperationException {
469
        int index = geometryOperations.indexOf(geomOpName);
470
        GeometryOperation geomOp = getGeometryOperation(index);
471
        return geomOp.invoke(null, ctx);
472
    }
473

    
474
    @Override
475
    public Envelope createEnvelope(int subType) {
476
        // TODO: register the envelopes!!!
477
        switch (subType) {
478
        case SUBTYPES.GEOM3D:
479
            return new Envelope3D();
480
        default:
481
            return new Envelope2D();
482
        }
483
    }
484

    
485
    @Override
486
    public Envelope createEnvelope(double minX, double minY, double maxX, double maxY, int subType)
487
        throws CreateEnvelopeException {
488
        org.gvsig.fmap.geom.primitive.Point min = null;
489
        org.gvsig.fmap.geom.primitive.Point max = null;
490
        try {
491
            min = createPoint(minX, minY, subType);
492
            max = createPoint(maxX, maxY, subType);
493
        } catch (CreateGeometryException e) {
494
            throw new CreateEnvelopeException(subType, e);
495
        }
496
        switch (subType) {
497
        case SUBTYPES.GEOM2D:
498
        case SUBTYPES.GEOM2DM:
499
            // Small optimization to directly create an Envelope2D
500
            // return new Envelope2D(minX, minY, maxX, maxY);
501
            return new Envelope2D(min, max);
502
        default:
503
            Envelope envelope = createEnvelope(subType);
504
            envelope.setLowerCorner(min);
505
            envelope.setUpperCorner(max);
506
            return envelope;
507
        }
508
    }
509

    
510
    @Override
511
    public MultiCurve createMultiCurve(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
512
        if (subType != SUBTYPES.GEOM2D) {
513
            // FIXME Exception
514
            throw new UnsupportedOperationException();
515
        }
516
        MultiCurve multiCurve = (MultiCurve) create(TYPES.MULTICURVE, subType);
517
        PathIterator piter = generalPathX.getPathIterator(null);
518
        GeneralPathX tmpPath = null;
519
        Curve tmpCurve = null;
520
        double[] coords = new double[6];
521
        double[] first = new double[6];
522
        int type;
523
        while (!piter.isDone()) {
524
            type = piter.currentSegment(coords);
525
            switch (type) {
526
            case PathIterator.SEG_MOVETO:
527
                if (tmpPath != null) {
528
                    tmpCurve = createCurve(tmpPath, subType);
529
                    multiCurve.addCurve(tmpCurve);
530
                }
531
                System.arraycopy(coords, 0, first, 0, 2);
532
                tmpPath = new GeneralPathX(piter.getWindingRule());
533
                tmpPath.moveTo(coords[0], coords[1]);
534
                break;
535

    
536
            case PathIterator.SEG_LINETO:
537
                if (tmpPath == null) {
538
                    System.arraycopy(coords, 0, first, 0, 2);
539
                    tmpPath = new GeneralPathX(piter.getWindingRule());
540
                }
541
                tmpPath.lineTo(coords[0], coords[1]);
542
                break;
543

    
544
            case PathIterator.SEG_QUADTO:
545
                if (tmpPath == null) {
546
                    System.arraycopy(coords, 0, first, 0, 2);
547
                    tmpPath = new GeneralPathX(piter.getWindingRule());
548
                }
549
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
550
                break;
551

    
552
            case PathIterator.SEG_CUBICTO:
553
                if (tmpPath == null) {
554
                    System.arraycopy(coords, 0, first, 0, 2);
555
                    tmpPath = new GeneralPathX(piter.getWindingRule());
556
                }
557
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
558
                break;
559

    
560
            case PathIterator.SEG_CLOSE:
561
                tmpPath.lineTo(first[0], first[1]);
562
                break;
563

    
564
            } // end switch
565

    
566
            piter.next();
567

    
568
        }
569
        if (tmpPath != null) {
570
            tmpCurve = createCurve(tmpPath, subType);
571
            multiCurve.addCurve(tmpCurve);
572
        }
573

    
574
        return multiCurve;
575

    
576
    }
577

    
578
    @Override
579
    public MultiSurface createMultiSurface(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
580
        if (subType != SUBTYPES.GEOM2D) {
581
            // FIXME Exception
582
            throw new UnsupportedOperationException();
583
        }
584
        MultiSurface multiSurface = (MultiSurface) create(TYPES.MULTISURFACE, subType);
585
        PathIterator piter = generalPathX.getPathIterator(null);
586
        GeneralPathX tmpPath = null;
587
        Surface tmpSurface = null;
588
        double[] coords = new double[6];
589
        double[] first = new double[6];
590
        int type;
591
        while (!piter.isDone()) {
592
            type = piter.currentSegment(coords);
593
            switch (type) {
594
            case PathIterator.SEG_MOVETO:
595
                if (tmpPath != null) {
596
                    tmpSurface = createSurface(tmpPath, subType);
597
                    multiSurface.addSurface(tmpSurface);
598
                }
599
                System.arraycopy(coords, 0, first, 0, 2);
600
                tmpPath = new GeneralPathX(piter.getWindingRule());
601
                tmpPath.moveTo(coords[0], coords[1]);
602

    
603
            case PathIterator.SEG_LINETO:
604
                if (tmpPath == null) {
605
                    System.arraycopy(coords, 0, first, 0, 2);
606
                    tmpPath = new GeneralPathX(piter.getWindingRule());
607
                }
608
                tmpPath.lineTo(coords[0], coords[1]);
609
                break;
610

    
611
            case PathIterator.SEG_QUADTO:
612
                if (tmpPath == null) {
613
                    System.arraycopy(coords, 0, first, 0, 2);
614
                    tmpPath = new GeneralPathX(piter.getWindingRule());
615
                }
616
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
617
                break;
618

    
619
            case PathIterator.SEG_CUBICTO:
620
                if (tmpPath == null) {
621
                    System.arraycopy(coords, 0, first, 0, 2);
622
                    tmpPath = new GeneralPathX(piter.getWindingRule());
623
                }
624
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
625
                break;
626

    
627
            case PathIterator.SEG_CLOSE:
628
                tmpPath.lineTo(first[0], first[1]);
629
                break;
630
            } // end switch
631

    
632
            piter.next();
633

    
634
        }
635
        if (tmpPath != null) {
636
            tmpSurface = createSurface(tmpPath, subType);
637
            multiSurface.addSurface(tmpSurface);
638
        }
639

    
640
        return multiSurface;
641

    
642
    }
643

    
644
    @Override
645
    public MultiPoint createMultiPoint(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
646
        if (subType != SUBTYPES.GEOM2D) {
647
            // FIXME Exception
648
            throw new UnsupportedOperationException();
649
        }
650
        MultiPoint multiPoint = (MultiPoint) create(TYPES.MULTIPOINT, subType);
651
        PathIterator piter = generalPathX.getPathIterator(null);
652
        Point tmpPoint = null;
653
        double[] coords = new double[6];
654
        int type;
655
        while (!piter.isDone()) {
656
            type = piter.currentSegment(coords);
657
            switch (type) {
658
            case PathIterator.SEG_MOVETO:
659
                tmpPoint = createPoint(coords[0], coords[1], subType);
660
                multiPoint.addPoint(tmpPoint);
661

    
662
            case PathIterator.SEG_LINETO:
663
                throw new IllegalArgumentException("The general have a SEG_LINETO.");
664

    
665
            case PathIterator.SEG_QUADTO:
666
                throw new IllegalArgumentException("The general have a SEG_QUADTO.");
667

    
668
            case PathIterator.SEG_CUBICTO:
669
                throw new IllegalArgumentException("The general have a SEG_CUBICTO.");
670

    
671
            case PathIterator.SEG_CLOSE:
672
                throw new IllegalArgumentException("The general have a SEG_CLOSE.");
673
            } // end switch
674

    
675
            piter.next();
676

    
677
        }
678
        return multiPoint;
679

    
680
    }
681

    
682
    @Override
683
    public int getGeometryOperationCode(String geomOpName) {
684
        if (geomOpName == null) {
685
            throw new IllegalArgumentException("geomOpName cannot be null.");
686
        }
687

    
688
        int index = geometryOperations.indexOf(geomOpName);
689
        if (index == -1) {
690
            geometryOperations.add(geomOpName);
691
            index = geometryOperations.indexOf(geomOpName);
692
        }
693
        return index;
694
    }
695

    
696
    @Override
697
    public List getGeometryOperationNames() {
698
        List operations = new ArrayList();
699
        for (int i = 0; i < operations.size(); i++) {
700
            operations.add(geometryOperations.get(i));
701
        }
702
        return operations;
703
    }
704

    
705
    @Override
706
    public double getFlatness() {
707
        return flatness;
708
    }
709

    
710
    @Override
711
    public void setFlatness(double flatness) {
712
        this.flatness = flatness;
713
    }
714

    
715
    @Override
716
    public Geometry createFrom(Object data) throws CreateGeometryException, GeometryException {
717
        if( data == null ) {
718
            throw new IllegalArgumentException("null data is not allowed");
719
        }
720
        if( data instanceof String ) {
721
            Geometry geom = GMLUtils.GML2Geometry((String) data);
722
            if( geom != null ) {
723
                return geom;
724
            }
725
            return this.createFrom((String)data);
726
        }
727
        if( data instanceof byte[] ) {
728
            return this.createFrom((byte[])data);
729
        }
730
        if( data instanceof com.vividsolutions.jts.geom.Geometry ) {
731
            return this.createFrom((com.vividsolutions.jts.geom.Geometry)data);
732
        }
733
        if( data instanceof Geometry ) {
734
            return ((Geometry)data).cloneGeometry();
735
        }
736
        throw new IllegalArgumentException("Type of data ("+data.getClass().getName()+") not supported.");
737
    }
738

    
739
    @Override
740
    public Geometry createFrom(String wkt, String srs) throws GeometryException {
741
        GeometryOperationContext context = new GeometryOperationContext();
742
        context.setAttribute("text", wkt);
743
        context.setAttribute("srs", srs);
744

    
745
        try {
746
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
747
        } catch (GeometryOperationNotSupportedException e) {
748
            throw new GeometryException(e);
749
        } catch (GeometryOperationException e) {
750
            throw new GeometryException(e);
751
        }
752
    }
753

    
754
    @Override
755
    public Geometry createFrom(String wkt, IProjection srs) throws GeometryException {
756
        GeometryOperationContext context = new GeometryOperationContext();
757
        context.setAttribute("text", wkt);
758
        context.setAttribute("srs", srs);
759

    
760
        try {
761
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
762
        } catch (GeometryOperationNotSupportedException e) {
763
            throw new GeometryException(e);
764
        } catch (GeometryOperationException e) {
765
            throw new GeometryException(e);
766
        }
767
    }
768

    
769
    public Geometry createFrom(IProjection proj, com.vividsolutions.jts.geom.Geometry geom) throws GeometryException {
770
        return JTSUtils.createGeometry(proj, geom);
771
    }
772

    
773
    @Override
774
    public Geometry createFrom(String wkt) throws GeometryException {
775
        try {
776
            char ch = wkt.charAt(0);
777
            if( (ch == '0' || ch =='1') && (wkt.length() % 2) == 0  ) {
778
                return createFrom(Hex.decodeHex(wkt.toCharArray()));
779
            }
780

    
781
            GeometryOperationContext context = new GeometryOperationContext();
782
            context.setAttribute("text", wkt);
783
            context.setAttribute("srs", null);
784

    
785
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
786
        } catch (Exception e) {
787
            throw new GeometryException(e);
788
        }
789
    }
790

    
791
    @Override
792
    public Geometry createFrom(byte[] wkb) throws GeometryException {
793
        GeometryOperationContext context = new GeometryOperationContext();
794
        context.setAttribute("data", wkb);
795
        try {
796
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
797
        } catch (GeometryOperationNotSupportedException e) {
798
            throw new GeometryException(e);
799
        } catch (GeometryOperationException e) {
800
            throw new GeometryException(e);
801
        }
802
    }
803

    
804
    @Override
805
    public Geometry createFrom(byte[] wkb, IProjection srs) throws GeometryException {
806
        GeometryOperationContext context = new GeometryOperationContext();
807
        context.setAttribute("data", wkb);
808
        context.setAttribute("srs", srs);
809
        try {
810
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
811
        } catch (GeometryOperationNotSupportedException e) {
812
            throw new GeometryException(e);
813
        } catch (GeometryOperationException e) {
814
            throw new GeometryException(e);
815
        }
816
    }
817

    
818
    @Override
819
    public IGeneralPathX createGeneralPath(int rule, PathIterator pathIterator) {
820
        if (pathIterator == null) {
821
            return new DefaultGeneralPathX(rule);
822
        }
823
        return new DefaultGeneralPathX(pathIterator, false, 0);
824
    }
825

    
826
    @Override
827
    public MultiPoint createMultiPoint(int subType) throws CreateGeometryException {
828
        return (MultiPoint) create(TYPES.MULTIPOINT, subType);
829
    }
830

    
831
    @Override
832
    public Line createLine(int subType) throws CreateGeometryException {
833
        return (Line) create(TYPES.CURVE, subType);
834
    }
835

    
836
    @Override
837
    public Curve createCurve(int subType) throws CreateGeometryException {
838
        return (Curve) create(TYPES.CURVE, subType);
839
    }
840

    
841
    @Override
842
    public MultiCurve createMultiCurve(int subType) throws CreateGeometryException {
843
        return (MultiCurve) create(TYPES.MULTICURVE, subType);
844
    }
845

    
846
    @Override
847
    public MultiLine createMultiLine(int subType) throws CreateGeometryException {
848
        return (MultiLine) create(TYPES.MULTILINE, subType);
849
    }
850

    
851
    @Override
852
    public MultiSurface createMultiSurface(int subType) throws CreateGeometryException {
853
        return (MultiSurface) create(TYPES.MULTISURFACE, subType);
854
    }
855

    
856
    @Override
857
    public MultiPolygon createMultiPolygon(int subType) throws CreateGeometryException {
858
        return (MultiPolygon) create(TYPES.MULTIPOLYGON, subType);
859
    }
860

    
861
    @Override
862
    public Polygon createPolygon(int subType) throws CreateGeometryException {
863
        return (Polygon) create(TYPES.SURFACE, subType);
864
    }
865

    
866
    @Override
867
    public Surface createSurface(int subType) throws CreateGeometryException {
868
        return (Surface) create(TYPES.SURFACE, subType);
869
    }
870

    
871
    @Override
872
    public SpatialIndex createDefaultMemorySpatialIndex() throws ServiceException {
873
        return this.createSpatialIndex(SpatialIndexFactoryJTSQuadtree.NAME, null);
874
    }
875

    
876
    @Override
877
    public SpatialIndex createSpatialIndex(String name, DynObject parameters) throws ServiceException {
878
        SpatialIndexFactory factory = this.getSpatialIndexFactory(name);
879
        if (factory == null) {
880
            throw new CantExistsService(name);
881
        }
882
        return (SpatialIndex) factory.create(parameters, this);
883
    }
884

    
885
    @Override
886
    public SpatialIndexFactory getSpatialIndexFactory(String name) {
887
        return (SpatialIndexFactory) this.spatialIndexFactories.get(name);
888
    }
889

    
890
    @Override
891
    public void addServiceFactory(ServiceFactory serviceFactory) {
892
        serviceFactory.initialize();
893
        this.spatialIndexFactories.put(serviceFactory.getName(), serviceFactory);
894
    }
895

    
896
    @Override
897
    public Service createService(DynObject serviceParameters) throws ServiceException {
898
        throw new UnsupportedOperationException("Not supported yet.");
899
    }
900

    
901
    @Override
902
    public DynObject createServiceParameters(String serviceName) throws ServiceException {
903
        SpatialIndexFactory factory = this.getSpatialIndexFactory(serviceName);
904
        if (factory == null) {
905
            throw new CantExistsService(serviceName);
906
        }
907
        return factory.createParameters();
908
    }
909

    
910
    @Override
911
    public Service getService(DynObject parameters) throws ServiceException {
912
        return this.createSpatialIndex((String) parameters.getDynValue("serviceName"), parameters);
913
    }
914

    
915
    public class CantExistsService extends ServiceException {
916

    
917
        public CantExistsService(String serviceName) {
918
            super("Can't existe service %(service).", "_Cant_existe_service_XserviceX", 100001);
919
            setValue("service", serviceName);
920
        }
921

    
922
    }
923

    
924
    @Override
925
    public InformationbuilderWithGeometrySupport createInformacionBuilder() {
926
        return new BaseInformationBuilderWithGeometrySupport();
927
    }
928

    
929
    @Override
930
    public boolean isSubtype(int geomTypeParent, int geomTypeChild) {
931
        // Esto es un implementacion patatera que habria que mejorar,
932
        // pero mejor aqui que esparcida por todas partes en donde se
933
        // necesite.
934
        if( geomTypeParent == geomTypeChild ) {
935
            return true;
936
        }
937
        if( geomTypeParent == Geometry.TYPES.GEOMETRY ) {
938
            return true;
939
        }
940
        switch(geomTypeParent) {
941
        case Geometry.TYPES.MULTICURVE:
942
            return geomTypeChild==Geometry.TYPES.MULTILINE ;
943
        case Geometry.TYPES.MULTISURFACE:
944
            return geomTypeChild==Geometry.TYPES.MULTIPOLYGON ;
945
        case Geometry.TYPES.MULTIPOINT:
946
            return geomTypeChild==Geometry.TYPES.MULTIPOINT ;
947

    
948
        case Geometry.TYPES.CURVE:
949
            return
950
                geomTypeChild == Geometry.TYPES.CURVE ||
951
                geomTypeChild == Geometry.TYPES.LINE ||
952
                geomTypeChild == Geometry.TYPES.ARC ||
953
                geomTypeChild == Geometry.TYPES.SPLINE ||
954
                geomTypeChild == Geometry.TYPES.CIRCUMFERENCE ||
955
                geomTypeChild == Geometry.TYPES.PERIELLIPSE
956
                ;
957
        case Geometry.TYPES.SURFACE:
958
            return
959
            geomTypeChild==Geometry.TYPES.SURFACE ||
960
            geomTypeChild==Geometry.TYPES.POLYGON ||
961
            geomTypeChild == Geometry.TYPES.CIRCLE ||
962
            geomTypeChild == Geometry.TYPES.ELLIPSE ||
963
            geomTypeChild == Geometry.TYPES.RING ||
964
            geomTypeChild == Geometry.TYPES.FILLEDSPLINE ||
965
            geomTypeChild == Geometry.TYPES.ELLIPTICARC
966
            ;
967
        case Geometry.TYPES.POINT:
968
            return geomTypeChild==Geometry.TYPES.POINT ;
969
        }
970
        return false;
971
    }
972
}