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

History | View | Annotate | Download (37.1 KB)

1 42260 fdiaz
/**
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 45634 fdiaz
import org.apache.commons.codec.binary.Hex;
34
import org.apache.commons.lang3.StringUtils;
35 43078 jjdelcerro
import org.cresques.cts.IProjection;
36 42260 fdiaz
import org.gvsig.fmap.geom.Geometry;
37
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
38
import org.gvsig.fmap.geom.Geometry.TYPES;
39 45673 jjdelcerro
import org.gvsig.fmap.geom.GeometryCoercionContext;
40 42260 fdiaz
import org.gvsig.fmap.geom.GeometryException;
41
import org.gvsig.fmap.geom.GeometryLocator;
42
import org.gvsig.fmap.geom.GeometryManager;
43 43171 jjdelcerro
import org.gvsig.fmap.geom.InformationbuilderWithGeometrySupport;
44 42260 fdiaz
import org.gvsig.fmap.geom.SpatialIndex;
45
import org.gvsig.fmap.geom.SpatialIndexFactory;
46
import org.gvsig.fmap.geom.aggregate.MultiCurve;
47
import org.gvsig.fmap.geom.aggregate.MultiLine;
48
import org.gvsig.fmap.geom.aggregate.MultiPoint;
49
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
50
import org.gvsig.fmap.geom.aggregate.MultiSurface;
51
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
52
import org.gvsig.fmap.geom.exception.CreateGeometryException;
53 45673 jjdelcerro
import org.gvsig.fmap.geom.jts.coerce.DefaultGeometryCoercionContext;
54 42260 fdiaz
import org.gvsig.fmap.geom.jts.gputils.DefaultGeneralPathX;
55 42278 fdiaz
import org.gvsig.fmap.geom.jts.primitive.DefaultNullGeometry;
56 42260 fdiaz
import org.gvsig.fmap.geom.jts.primitive.Envelope2D;
57
import org.gvsig.fmap.geom.jts.primitive.Envelope3D;
58 43513 jjdelcerro
import org.gvsig.fmap.geom.jts.spatialindex.SpatialIndexFactoryJSIRTree;
59
import org.gvsig.fmap.geom.jts.spatialindex.SpatialIndexFactoryJTSQuadtree;
60 43909 jjdelcerro
import org.gvsig.fmap.geom.jts.util.GMLUtils;
61 42267 fdiaz
import org.gvsig.fmap.geom.jts.util.JTSUtils;
62 42260 fdiaz
import org.gvsig.fmap.geom.operation.GeometryOperation;
63
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
64
import org.gvsig.fmap.geom.operation.GeometryOperationException;
65
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
66
import org.gvsig.fmap.geom.primitive.Curve;
67
import org.gvsig.fmap.geom.primitive.Envelope;
68
import org.gvsig.fmap.geom.primitive.GeneralPathX;
69
import org.gvsig.fmap.geom.primitive.IGeneralPathX;
70 42268 fdiaz
import org.gvsig.fmap.geom.primitive.Line;
71 42260 fdiaz
import org.gvsig.fmap.geom.primitive.NullGeometry;
72
import org.gvsig.fmap.geom.primitive.Point;
73 42268 fdiaz
import org.gvsig.fmap.geom.primitive.Polygon;
74 42260 fdiaz
import org.gvsig.fmap.geom.primitive.Surface;
75
import org.gvsig.fmap.geom.type.GeometryType;
76
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
77
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
78
import org.gvsig.tools.dynobject.DynObject;
79
import org.gvsig.tools.service.Service;
80
import org.gvsig.tools.service.ServiceException;
81
import org.gvsig.tools.service.spi.ServiceFactory;
82 45634 fdiaz
import org.slf4j.Logger;
83
import org.slf4j.LoggerFactory;
84 42260 fdiaz
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 45425 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
94 42260 fdiaz
public class DefaultGeometryManager implements GeometryManager {
95
96 45425 jjdelcerro
    private static final Logger LOGGER = LoggerFactory.getLogger(GeometryManager.class);
97 45634 fdiaz
98
    /**
99
     * Offset for GeometryType -1 value (UNKNOWN)
100
     */
101
    private final int GEOMETRY_TYPE_OFFSET = 1;
102
103 42260 fdiaz
    private double flatness = 0.8;
104
105 45425 jjdelcerro
    private final Map spatialIndexFactories = new HashMap();
106 42260 fdiaz
107
    /**
108
     * This list holds the unique name of all registered geometry operations.
109
     * The index in which they are stored is also the operation code used to
110
     * invoke each one of them
111
     */
112 45425 jjdelcerro
    private final List geometryOperations = new ArrayList();
113 42260 fdiaz
114
    /**
115
     * Common operations are registered here. Type specific operations are
116
     * registered in the corresponding GeometryType instance
117
     */
118
    // private List commonOperations = new ArrayList();
119
120
    /**
121
     * This map holds the instances of all registered GeometryType. The key is
122
     * the name of the specific Geometry subclass.
123
     * In other words, the string "org.gvsig.fmap.geom.primitive.Point2D" is the
124
     * hash key to obtain an instance of GeometryType holding the
125
     * operations associated to the class org.gvsig.fmap.geom.primitive.Point2D.
126
     */
127 45425 jjdelcerro
    private final Map geometryTypeName = new HashMap();
128 42260 fdiaz
129
    /**
130
     * Matrix of geometry types by type (row) and subtype (column). This matrix
131
     * will contain null values in the cells where a GeometryType hasn't been
132
     * registered.
133
     */
134
    private GeometryType[][] geometryTypes;
135 45634 fdiaz
136
    // Initially create a matrix of 27 x 6, which are the current default
137 42260 fdiaz
    // types and subtypes. If another type or subtype is registered, the
138
    // matrix will grow as needed
139 45634 fdiaz
    private static final int DEFAULT_TYPES_SIZE = 27; // [-1, 25]
140 42260 fdiaz
    private static final int DEFAULT_SUBTYPES_SIZE = 6;
141
142
    public DefaultGeometryManager() throws GeometryException {
143
        this(DEFAULT_TYPES_SIZE, DEFAULT_SUBTYPES_SIZE);
144
    }
145
146
    public DefaultGeometryManager(int initialTypesSize, int initialSubtypesSize) throws GeometryException {
147
        geometryTypes = new GeometryType[initialTypesSize][initialSubtypesSize];
148 43513 jjdelcerro
        this.addServiceFactory(new SpatialIndexFactoryJTSQuadtree());
149
        this.addServiceFactory(new SpatialIndexFactoryJSIRTree());
150 42260 fdiaz
    }
151
152 44951 omartinez
    @Override
153 42260 fdiaz
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, GeometryType geomType) {
154
        if (geomOp == null) {
155
            throw new IllegalArgumentException("geomOp cannot be null.");
156
        }
157
        if (geomType == null) {
158
            throw new IllegalArgumentException("geomType cannot be null.");
159
        }
160
161
        int index = getGeometryOperationCode(geomOpName);
162
163
        geomType.setGeometryOperation(index, geomOp);
164
165
        return index;
166
    }
167
168 44951 omartinez
    @Override
169 42260 fdiaz
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp) {
170
        if (geomOpName == null) {
171
            throw new IllegalArgumentException("geomOpName cannot be null.");
172
        }
173
        if (geomOp == null) {
174
            throw new IllegalArgumentException("geomOp cannot be null.");
175
        }
176
177
        int index = getGeometryOperationCode(geomOpName);
178
179
        Iterator it = geometryTypeName.values().iterator();
180
        while (it.hasNext()) {
181
            GeometryType geometryType = (GeometryType) it.next();
182
            registerGeometryOperation(geomOpName, geomOp, geometryType);
183
        }
184
185
        return index;
186
187
    }
188
189 44951 omartinez
    @SuppressWarnings("override")
190 42260 fdiaz
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, int type, int subType)
191
        throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
192
        GeometryType geometryType = getGeometryType(type, subType);
193
        return registerGeometryOperation(geomOpName, geomOp, geometryType);
194
    }
195
196 44951 omartinez
    @Override
197 42260 fdiaz
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, int type) {
198
        int code = -1;
199
        Iterator it = geometryTypeName.values().iterator();
200
        while (it.hasNext()) {
201
            GeometryType geometryType = (GeometryType) it.next();
202
            if ((type == geometryType.getType())) {
203
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
204
            }
205
        }
206
        return code;
207
    }
208
209 44951 omartinez
    @Override
210 42260 fdiaz
    public int registerGeometryOperationBySubtype(String geomOpName, GeometryOperation geomOp, int subType) {
211
        int code = -1;
212
        Iterator it = geometryTypeName.values().iterator();
213
        while (it.hasNext()) {
214
            GeometryType geometryType = (GeometryType) it.next();
215
            if ((subType == geometryType.getSubType())) {
216
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
217
            }
218
        }
219
        return code;
220
    }
221
222 44951 omartinez
    @Override
223 42260 fdiaz
    public int registerGeometryOperationBySuperType(String geomOpName, GeometryOperation geomOp, int superType) {
224
        int code = -1;
225
        Iterator it = geometryTypeName.values().iterator();
226
        while (it.hasNext()) {
227
            GeometryType geometryType = (GeometryType) it.next();
228
            if (geometryType.isTypeOf(superType)) {
229
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
230
            }
231
        }
232
        return code;
233
    }
234
235 44951 omartinez
    @Override
236 42260 fdiaz
    public int registerGeometryOperationBySuperSubType(String geomOpName, GeometryOperation geomOp, int superSubType) {
237
        int code = -1;
238
        Iterator it = geometryTypeName.values().iterator();
239
        while (it.hasNext()) {
240
            GeometryType geometryType = (GeometryType) it.next();
241
            if (geometryType.isSubTypeOf(superSubType)) {
242
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
243
            }
244
        }
245
        return code;
246
    }
247
248 44951 omartinez
    @Override
249 42260 fdiaz
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType) {
250
        return registerGeometryType(geomClass, name, type, subType, new int[0], new int[0]);
251
    }
252
253 44951 omartinez
    @Override
254 42260 fdiaz
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int superType,
255
        int superSubType) {
256
        return registerGeometryType(geomClass, name, type, subType, new int[] { superType }, new int[] { superSubType });
257
    }
258
259 44951 omartinez
    @Override
260 42260 fdiaz
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int superType) {
261
        return registerGeometryType(geomClass, name, type, subType, new int[] { superType }, new int[0]);
262
    }
263
264 44951 omartinez
    @Override
265 42260 fdiaz
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int[] superTypes) {
266
        return registerGeometryType(geomClass, name, type, subType, superTypes, new int[0]);
267
    }
268
269
    /**
270
     * Registers a Geometry implementation class with a predefined geometry type
271
     * and returns the
272
     * associated GeometryType instance. Available predefined types are defined
273
     * in {@link Geometry.TYPES} If the class is already registered then this
274
     * method throws an IllegalArgumentException.<br>
275
     *
276
     * How to register a geometry class with a predefined type:
277
     *
278
     * <pre>
279
     *
280
     * public class Point2D implements Point {
281
     *   private static final GeometryType geomType = GeometryManager.getInstance()
282
     *    .registerBasicGeometryType(Point2D.class, "Point2D", Geometry.TYPES.POINT);
283
     *
284
     * ...
285
     *   public int getType() {
286
     *      return geomType.getType();
287
     *   }
288
     * }
289
     * </pre>
290
     *
291
     * @param geomClass
292
     *            Geometry subclass. It must not be null and must implement
293
     *            Geometry, otherwise an exception
294
     *            is raised.
295
     * @param name
296
     *            Symbolic name for the geometry type, it can be null. If it is
297
     *            null then the symbolic name
298
     *            will be the simple class name.
299
     * @param type
300
     *            Type of geometry. Must be a value defined in
301
     *            {@link Geometry.TYPES}
302
     * @param subType
303
     *            SubType of geometry. Must be a value defined in
304
     *            {@link Geometry.SUBTYPES}
305
     * @return Instance of GeometryType associated to the Geometry
306
     *         implementation class
307
     *         geomClass
308
     * @throws IllegalArgumentException
309
     *             If geomClass is null or does not implement Geometry
310
     */
311 44951 omartinez
    @Override
312 42260 fdiaz
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int[] superTypes,
313
        int superSubTypes[]) {
314
        if (geomClass == null) {
315
            throw new IllegalArgumentException("geomClass cannot be null.");
316
        }
317
318
        if (!Geometry.class.isAssignableFrom(geomClass)) {
319
            throw new IllegalArgumentException(geomClass.getName() + " must implement the Geometry interface");
320
        }
321
322 45634 fdiaz
        int offsettedType = type + GEOMETRY_TYPE_OFFSET;
323 42260 fdiaz
        // Check if it is registered
324
        GeometryType geomType = null;
325 45634 fdiaz
        if (offsettedType >= geometryTypes.length || subType >= geometryTypes[0].length
326
            || (geomType = geometryTypes[offsettedType][subType]) == null) {
327
            geomType = new DefaultGeometryType(geomClass, name, type, subType, superTypes, superSubTypes); //Attention!
328 42260 fdiaz
            registerGeometryType(geomType);
329
        }
330
331 45425 jjdelcerro
        LOGGER.debug("Class {} registered with name {}", geomClass, geomType.getName());
332 42260 fdiaz
333
        return geomType;
334
    }
335
336 44951 omartinez
    @Override
337 42260 fdiaz
    public void registerGeometryType(GeometryType geometryType) {
338 45634 fdiaz
        int offsettedType = geometryType.getType() + GEOMETRY_TYPE_OFFSET;
339
        if (offsettedType >= geometryTypes.length || geometryType.getSubType() >= geometryTypes[0].length) {
340 42260 fdiaz
341
            // Recreate the geometry type matrix if the types
342
            // or subtypes don't fit
343
            int newTypesSize =
344 45634 fdiaz
                offsettedType < geometryTypes.length ? geometryTypes.length : offsettedType + 1;
345 42260 fdiaz
            int newSubTypesSize =
346
                geometryType.getSubType() < geometryTypes[0].length ? geometryTypes[0].length : geometryType
347
                    .getSubType() + 1;
348
            GeometryType[][] newMatrix = new GeometryType[newTypesSize][newSubTypesSize];
349
350
            for (int i = 0; i < geometryTypes.length; i++) {
351
                System.arraycopy(geometryTypes[i], 0, newMatrix[i], 0, geometryTypes[i].length);
352
            }
353
            geometryTypes = newMatrix;
354
        }
355
356 45634 fdiaz
        geometryTypes[offsettedType][geometryType.getSubType()] = geometryType;
357 42260 fdiaz
        geometryTypeName.put(geometryType.getName(), geometryType);
358
    }
359
360 44951 omartinez
    @Override
361 42260 fdiaz
    public GeometryType registerGeometryType(Class geomClass, int type, int subType) {
362
        return registerGeometryType(geomClass, null, type, subType);
363
    }
364
365 44951 omartinez
    @Override
366 42260 fdiaz
    public GeometryType getGeometryType(int type, int subType) throws GeometryTypeNotSupportedException,
367
        GeometryTypeNotValidException {
368 45634 fdiaz
369
        int offsettedType = type + GEOMETRY_TYPE_OFFSET;
370
371
        if (offsettedType >= geometryTypes.length || subType >= geometryTypes[0].length) {
372 42260 fdiaz
            throw new GeometryTypeNotValidException(type, subType);
373
        }
374 45634 fdiaz
        GeometryType gType = geometryTypes[offsettedType][subType];
375 42260 fdiaz
        if (gType == null) {
376
            throw new GeometryTypeNotSupportedException(type, subType);
377
        }
378
        return gType;
379
    }
380
381 44951 omartinez
    @Override
382 42260 fdiaz
    public Geometry create(GeometryType geomType) throws CreateGeometryException {
383
        return geomType.create();
384
    }
385
386 44951 omartinez
    @Override
387 42260 fdiaz
    public Geometry create(String name) throws CreateGeometryException {
388
        if (!geometryTypeName.containsKey(name)) {
389
            throw new IllegalArgumentException(name + " has not been registered yet.");
390
        }
391
        return ((GeometryType) geometryTypeName.get(name)).create();
392
    }
393
394 44951 omartinez
    @Override
395 42260 fdiaz
    public Geometry create(int type, int subType) throws CreateGeometryException {
396
        try {
397
            return getGeometryType(type, subType).create();
398
        } catch (GeometryException e) {
399
            throw new CreateGeometryException(type, subType, e);
400
        }
401
    }
402
403 44951 omartinez
    @Override
404 42260 fdiaz
    public Curve createCurve(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
405
        Curve curve = (Curve) create(TYPES.CURVE, subType);
406
        curve.setGeneralPath(generalPathX);
407
        return curve;
408
    }
409
410 44951 omartinez
    @Override
411 42260 fdiaz
    public NullGeometry createNullGeometry(int subType) throws CreateGeometryException {
412
        NullGeometry nullGeom = (NullGeometry) create(TYPES.NULL, subType);
413
        return nullGeom;
414
    }
415
416 44951 omartinez
    @Override
417 42260 fdiaz
    public Point createPoint(double x, double y, int subType) throws CreateGeometryException {
418
        Point point = (Point) create(TYPES.POINT, subType);
419
        point.setX(x);
420
        point.setY(y);
421
        return point;
422
    }
423
424 44951 omartinez
    @Override
425 42260 fdiaz
    public Surface createSurface(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
426
        Surface surface = (Surface) create(TYPES.SURFACE, subType);
427
        surface.setGeneralPath(generalPathX);
428
        return surface;
429
    }
430
431 44951 omartinez
    @Override
432 42260 fdiaz
    public GeometryOperation getGeometryOperation(int opCode, int type, int subType)
433
        throws GeometryTypeNotSupportedException, GeometryOperationNotSupportedException, GeometryTypeNotValidException {
434
        GeometryType geometryType = getGeometryType(type, subType);
435
        return geometryType.getGeometryOperation(opCode);
436
    }
437
438 44951 omartinez
    @Override
439 42260 fdiaz
    public GeometryOperation getGeometryOperation(int opCode) throws GeometryOperationNotSupportedException {
440
        if (opCode < 0) {
441
            throw new GeometryOperationNotSupportedException(opCode);
442
        }
443
        GeometryType type = (GeometryType) geometryTypeName.get(DefaultNullGeometry.class.getName());
444
        if (type == null) {
445
            throw new GeometryOperationNotSupportedException(opCode);
446
        }
447
        return type.getGeometryOperation(opCode);
448
    }
449
450 44951 omartinez
    @Override
451 42260 fdiaz
    public Object invokeOperation(int opCode, Geometry geom, GeometryOperationContext ctx)
452
        throws GeometryOperationNotSupportedException, GeometryOperationException {
453
        GeometryOperation geomOp = geom.getGeometryType().getGeometryOperation(opCode);
454
455
        if (geomOp != null) {
456
            return geomOp.invoke(geom, ctx);
457
        }
458
459
        throw new GeometryOperationNotSupportedException(opCode, geom.getGeometryType());
460
    }
461
462 44951 omartinez
    @Override
463 42260 fdiaz
    public Object invokeOperation(String geomOpName, Geometry geom, GeometryOperationContext ctx)
464
        throws GeometryOperationNotSupportedException, GeometryOperationException {
465
        int index = geometryOperations.indexOf(geomOpName);
466
        if (index == -1) {
467
            throw new GeometryOperationNotSupportedException(-1);
468
        }
469
        return invokeOperation(index, geom, ctx);
470
    }
471
472 44951 omartinez
    @Override
473 42260 fdiaz
    public Object invokeOperation(String geomOpName, GeometryOperationContext ctx)
474
        throws GeometryOperationNotSupportedException, GeometryOperationException {
475
        int index = geometryOperations.indexOf(geomOpName);
476
        GeometryOperation geomOp = getGeometryOperation(index);
477
        return geomOp.invoke(null, ctx);
478
    }
479
480 44951 omartinez
    @Override
481 42260 fdiaz
    public Envelope createEnvelope(int subType) {
482
        // TODO: register the envelopes!!!
483
        switch (subType) {
484
        case SUBTYPES.GEOM3D:
485
            return new Envelope3D();
486
        default:
487
            return new Envelope2D();
488
        }
489
    }
490
491 44951 omartinez
    @Override
492 42260 fdiaz
    public Envelope createEnvelope(double minX, double minY, double maxX, double maxY, int subType)
493
        throws CreateEnvelopeException {
494
        org.gvsig.fmap.geom.primitive.Point min = null;
495
        org.gvsig.fmap.geom.primitive.Point max = null;
496
        try {
497 42304 fdiaz
            min = createPoint(minX, minY, subType);
498
            max = createPoint(maxX, maxY, subType);
499
        } catch (CreateGeometryException e) {
500 42260 fdiaz
            throw new CreateEnvelopeException(subType, e);
501
        }
502
        switch (subType) {
503
        case SUBTYPES.GEOM2D:
504
        case SUBTYPES.GEOM2DM:
505
            // Small optimization to directly create an Envelope2D
506
            // return new Envelope2D(minX, minY, maxX, maxY);
507
            return new Envelope2D(min, max);
508
        default:
509
            Envelope envelope = createEnvelope(subType);
510
            envelope.setLowerCorner(min);
511
            envelope.setUpperCorner(max);
512
            return envelope;
513
        }
514
    }
515
516 44951 omartinez
    @Override
517 42260 fdiaz
    public MultiCurve createMultiCurve(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
518
        if (subType != SUBTYPES.GEOM2D) {
519
            // FIXME Exception
520
            throw new UnsupportedOperationException();
521
        }
522
        MultiCurve multiCurve = (MultiCurve) create(TYPES.MULTICURVE, subType);
523
        PathIterator piter = generalPathX.getPathIterator(null);
524
        GeneralPathX tmpPath = null;
525 45425 jjdelcerro
        Curve tmpCurve;
526 42260 fdiaz
        double[] coords = new double[6];
527
        double[] first = new double[6];
528
        int type;
529
        while (!piter.isDone()) {
530
            type = piter.currentSegment(coords);
531
            switch (type) {
532
            case PathIterator.SEG_MOVETO:
533
                if (tmpPath != null) {
534
                    tmpCurve = createCurve(tmpPath, subType);
535
                    multiCurve.addCurve(tmpCurve);
536
                }
537
                System.arraycopy(coords, 0, first, 0, 2);
538
                tmpPath = new GeneralPathX(piter.getWindingRule());
539
                tmpPath.moveTo(coords[0], coords[1]);
540
                break;
541
542
            case PathIterator.SEG_LINETO:
543
                if (tmpPath == null) {
544
                    System.arraycopy(coords, 0, first, 0, 2);
545
                    tmpPath = new GeneralPathX(piter.getWindingRule());
546
                }
547
                tmpPath.lineTo(coords[0], coords[1]);
548
                break;
549
550
            case PathIterator.SEG_QUADTO:
551
                if (tmpPath == null) {
552
                    System.arraycopy(coords, 0, first, 0, 2);
553
                    tmpPath = new GeneralPathX(piter.getWindingRule());
554
                }
555
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
556
                break;
557
558
            case PathIterator.SEG_CUBICTO:
559
                if (tmpPath == null) {
560
                    System.arraycopy(coords, 0, first, 0, 2);
561
                    tmpPath = new GeneralPathX(piter.getWindingRule());
562
                }
563
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
564
                break;
565
566
            case PathIterator.SEG_CLOSE:
567
                tmpPath.lineTo(first[0], first[1]);
568
                break;
569
570
            } // end switch
571
572
            piter.next();
573
574
        }
575
        if (tmpPath != null) {
576
            tmpCurve = createCurve(tmpPath, subType);
577
            multiCurve.addCurve(tmpCurve);
578
        }
579
580
        return multiCurve;
581
582
    }
583
584 44951 omartinez
    @Override
585 42260 fdiaz
    public MultiSurface createMultiSurface(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
586
        if (subType != SUBTYPES.GEOM2D) {
587
            // FIXME Exception
588
            throw new UnsupportedOperationException();
589
        }
590
        MultiSurface multiSurface = (MultiSurface) create(TYPES.MULTISURFACE, subType);
591
        PathIterator piter = generalPathX.getPathIterator(null);
592
        GeneralPathX tmpPath = null;
593 45425 jjdelcerro
        Surface tmpSurface;
594 42260 fdiaz
        double[] coords = new double[6];
595
        double[] first = new double[6];
596
        int type;
597
        while (!piter.isDone()) {
598
            type = piter.currentSegment(coords);
599
            switch (type) {
600
            case PathIterator.SEG_MOVETO:
601
                if (tmpPath != null) {
602
                    tmpSurface = createSurface(tmpPath, subType);
603
                    multiSurface.addSurface(tmpSurface);
604
                }
605
                System.arraycopy(coords, 0, first, 0, 2);
606
                tmpPath = new GeneralPathX(piter.getWindingRule());
607
                tmpPath.moveTo(coords[0], coords[1]);
608
609
            case PathIterator.SEG_LINETO:
610
                if (tmpPath == null) {
611
                    System.arraycopy(coords, 0, first, 0, 2);
612
                    tmpPath = new GeneralPathX(piter.getWindingRule());
613
                }
614
                tmpPath.lineTo(coords[0], coords[1]);
615
                break;
616
617
            case PathIterator.SEG_QUADTO:
618
                if (tmpPath == null) {
619
                    System.arraycopy(coords, 0, first, 0, 2);
620
                    tmpPath = new GeneralPathX(piter.getWindingRule());
621
                }
622
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
623
                break;
624
625
            case PathIterator.SEG_CUBICTO:
626
                if (tmpPath == null) {
627
                    System.arraycopy(coords, 0, first, 0, 2);
628
                    tmpPath = new GeneralPathX(piter.getWindingRule());
629
                }
630
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
631
                break;
632
633
            case PathIterator.SEG_CLOSE:
634
                tmpPath.lineTo(first[0], first[1]);
635
                break;
636
            } // end switch
637
638
            piter.next();
639
640
        }
641
        if (tmpPath != null) {
642
            tmpSurface = createSurface(tmpPath, subType);
643
            multiSurface.addSurface(tmpSurface);
644
        }
645
646
        return multiSurface;
647
648
    }
649
650 44951 omartinez
    @Override
651 42982 fdiaz
    public MultiPoint createMultiPoint(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
652
        if (subType != SUBTYPES.GEOM2D) {
653
            // FIXME Exception
654
            throw new UnsupportedOperationException();
655
        }
656
        MultiPoint multiPoint = (MultiPoint) create(TYPES.MULTIPOINT, subType);
657
        PathIterator piter = generalPathX.getPathIterator(null);
658 45425 jjdelcerro
        Point tmpPoint;
659 42982 fdiaz
        double[] coords = new double[6];
660
        int type;
661
        while (!piter.isDone()) {
662
            type = piter.currentSegment(coords);
663
            switch (type) {
664
            case PathIterator.SEG_MOVETO:
665
                tmpPoint = createPoint(coords[0], coords[1], subType);
666
                multiPoint.addPoint(tmpPoint);
667
668
            case PathIterator.SEG_LINETO:
669
                throw new IllegalArgumentException("The general have a SEG_LINETO.");
670
671
            case PathIterator.SEG_QUADTO:
672
                throw new IllegalArgumentException("The general have a SEG_QUADTO.");
673
674
            case PathIterator.SEG_CUBICTO:
675
                throw new IllegalArgumentException("The general have a SEG_CUBICTO.");
676
677
            case PathIterator.SEG_CLOSE:
678
                throw new IllegalArgumentException("The general have a SEG_CLOSE.");
679
            } // end switch
680
681
            piter.next();
682
683
        }
684
        return multiPoint;
685
686
    }
687
688 44951 omartinez
    @Override
689 42260 fdiaz
    public int getGeometryOperationCode(String geomOpName) {
690
        if (geomOpName == null) {
691
            throw new IllegalArgumentException("geomOpName cannot be null.");
692
        }
693
694
        int index = geometryOperations.indexOf(geomOpName);
695
        if (index == -1) {
696
            geometryOperations.add(geomOpName);
697
            index = geometryOperations.indexOf(geomOpName);
698
        }
699
        return index;
700
    }
701
702 44951 omartinez
    @Override
703 42260 fdiaz
    public List getGeometryOperationNames() {
704
        List operations = new ArrayList();
705
        for (int i = 0; i < operations.size(); i++) {
706
            operations.add(geometryOperations.get(i));
707
        }
708
        return operations;
709
    }
710
711 44951 omartinez
    @Override
712 42260 fdiaz
    public double getFlatness() {
713
        return flatness;
714
    }
715
716 44951 omartinez
    @Override
717 42260 fdiaz
    public void setFlatness(double flatness) {
718
        this.flatness = flatness;
719
    }
720
721 43909 jjdelcerro
    @Override
722
    public Geometry createFrom(Object data) throws CreateGeometryException, GeometryException {
723
        if( data == null ) {
724
            throw new IllegalArgumentException("null data is not allowed");
725
        }
726
        if( data instanceof String ) {
727
            Geometry geom = GMLUtils.GML2Geometry((String) data);
728
            if( geom != null ) {
729
                return geom;
730
            }
731
            return this.createFrom((String)data);
732
        }
733
        if( data instanceof byte[] ) {
734
            return this.createFrom((byte[])data);
735
        }
736
        if( data instanceof com.vividsolutions.jts.geom.Geometry ) {
737
            return this.createFrom((com.vividsolutions.jts.geom.Geometry)data);
738
        }
739
        if( data instanceof Geometry ) {
740
            return ((Geometry)data).cloneGeometry();
741
        }
742
        throw new IllegalArgumentException("Type of data ("+data.getClass().getName()+") not supported.");
743
    }
744
745 44951 omartinez
    @Override
746 42260 fdiaz
    public Geometry createFrom(String wkt, String srs) throws GeometryException {
747
        GeometryOperationContext context = new GeometryOperationContext();
748
        context.setAttribute("text", wkt);
749
        context.setAttribute("srs", srs);
750
751
        try {
752
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
753 45425 jjdelcerro
        } catch (Exception e) {
754 42260 fdiaz
            throw new GeometryException(e);
755
        }
756
    }
757
758 44951 omartinez
    @Override
759 43078 jjdelcerro
    public Geometry createFrom(String wkt, IProjection srs) throws GeometryException {
760
        GeometryOperationContext context = new GeometryOperationContext();
761
        context.setAttribute("text", wkt);
762
        context.setAttribute("srs", srs);
763
764
        try {
765
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
766 45425 jjdelcerro
        } catch (Exception e) {
767 43078 jjdelcerro
            throw new GeometryException(e);
768
        }
769
    }
770
771 44099 jjdelcerro
    public Geometry createFrom(IProjection proj, com.vividsolutions.jts.geom.Geometry geom) throws GeometryException {
772
        return JTSUtils.createGeometry(proj, geom);
773 42260 fdiaz
    }
774
775 44951 omartinez
    @Override
776 45425 jjdelcerro
    public Geometry createFromQuietly(String wkt) {
777
        try {
778
            return this.createFrom(wkt);
779
        } catch(Exception ex) {
780
            return null;
781
        }
782
    }
783
784
    @Override
785 42260 fdiaz
    public Geometry createFrom(String wkt) throws GeometryException {
786 44951 omartinez
        try {
787 45425 jjdelcerro
            if( StringUtils.isBlank(wkt) ) {
788
                return null;
789
            }
790 44951 omartinez
            char ch = wkt.charAt(0);
791
            if( (ch == '0' || ch =='1') && (wkt.length() % 2) == 0  ) {
792 45425 jjdelcerro
                // it starts with 0 or 1 and the length is even. Assume it is hexwkb.
793 44964 jjdelcerro
                return createFrom(Hex.decodeHex(wkt.toCharArray()));
794 44951 omartinez
            }
795 42260 fdiaz
796 44951 omartinez
            GeometryOperationContext context = new GeometryOperationContext();
797
            context.setAttribute("text", wkt);
798
            context.setAttribute("srs", null);
799
800 42260 fdiaz
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
801 44951 omartinez
        } catch (Exception e) {
802 42260 fdiaz
            throw new GeometryException(e);
803
        }
804
    }
805
806 44951 omartinez
    @Override
807 42260 fdiaz
    public Geometry createFrom(byte[] wkb) throws GeometryException {
808
        GeometryOperationContext context = new GeometryOperationContext();
809
        context.setAttribute("data", wkb);
810
        try {
811
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
812
        } catch (GeometryOperationNotSupportedException e) {
813
            throw new GeometryException(e);
814
        } catch (GeometryOperationException e) {
815
            throw new GeometryException(e);
816
        }
817
    }
818
819 44951 omartinez
    @Override
820 43078 jjdelcerro
    public Geometry createFrom(byte[] wkb, IProjection srs) throws GeometryException {
821
        GeometryOperationContext context = new GeometryOperationContext();
822
        context.setAttribute("data", wkb);
823
        context.setAttribute("srs", srs);
824
        try {
825
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
826 45425 jjdelcerro
        } catch (Exception e) {
827 43078 jjdelcerro
            throw new GeometryException(e);
828
        }
829
    }
830
831 44951 omartinez
    @Override
832 42260 fdiaz
    public IGeneralPathX createGeneralPath(int rule, PathIterator pathIterator) {
833
        if (pathIterator == null) {
834
            return new DefaultGeneralPathX(rule);
835
        }
836 42267 fdiaz
        return new DefaultGeneralPathX(pathIterator, false, 0);
837 42260 fdiaz
    }
838
839 44951 omartinez
    @Override
840 42260 fdiaz
    public MultiPoint createMultiPoint(int subType) throws CreateGeometryException {
841
        return (MultiPoint) create(TYPES.MULTIPOINT, subType);
842
    }
843
844 44951 omartinez
    @Override
845 42260 fdiaz
    public Line createLine(int subType) throws CreateGeometryException {
846
        return (Line) create(TYPES.CURVE, subType);
847
    }
848
849 44951 omartinez
    @Override
850 42260 fdiaz
    public Curve createCurve(int subType) throws CreateGeometryException {
851
        return (Curve) create(TYPES.CURVE, subType);
852
    }
853
854 44951 omartinez
    @Override
855 42260 fdiaz
    public MultiCurve createMultiCurve(int subType) throws CreateGeometryException {
856
        return (MultiCurve) create(TYPES.MULTICURVE, subType);
857
    }
858
859 44951 omartinez
    @Override
860 42260 fdiaz
    public MultiLine createMultiLine(int subType) throws CreateGeometryException {
861 42283 fdiaz
        return (MultiLine) create(TYPES.MULTILINE, subType);
862 42260 fdiaz
    }
863
864 44951 omartinez
    @Override
865 42260 fdiaz
    public MultiSurface createMultiSurface(int subType) throws CreateGeometryException {
866
        return (MultiSurface) create(TYPES.MULTISURFACE, subType);
867
    }
868
869 44951 omartinez
    @Override
870 42260 fdiaz
    public MultiPolygon createMultiPolygon(int subType) throws CreateGeometryException {
871 42283 fdiaz
        return (MultiPolygon) create(TYPES.MULTIPOLYGON, subType);
872 42260 fdiaz
    }
873
874 44951 omartinez
    @Override
875 42260 fdiaz
    public Polygon createPolygon(int subType) throws CreateGeometryException {
876
        return (Polygon) create(TYPES.SURFACE, subType);
877
    }
878
879 44951 omartinez
    @Override
880 42260 fdiaz
    public Surface createSurface(int subType) throws CreateGeometryException {
881
        return (Surface) create(TYPES.SURFACE, subType);
882
    }
883
884 44951 omartinez
    @Override
885 42260 fdiaz
    public SpatialIndex createDefaultMemorySpatialIndex() throws ServiceException {
886 43513 jjdelcerro
        return this.createSpatialIndex(SpatialIndexFactoryJTSQuadtree.NAME, null);
887 42260 fdiaz
    }
888
889 44951 omartinez
    @Override
890 42260 fdiaz
    public SpatialIndex createSpatialIndex(String name, DynObject parameters) throws ServiceException {
891
        SpatialIndexFactory factory = this.getSpatialIndexFactory(name);
892
        if (factory == null) {
893
            throw new CantExistsService(name);
894
        }
895
        return (SpatialIndex) factory.create(parameters, this);
896
    }
897
898 44951 omartinez
    @Override
899 42260 fdiaz
    public SpatialIndexFactory getSpatialIndexFactory(String name) {
900
        return (SpatialIndexFactory) this.spatialIndexFactories.get(name);
901
    }
902
903 44951 omartinez
    @Override
904 42260 fdiaz
    public void addServiceFactory(ServiceFactory serviceFactory) {
905
        serviceFactory.initialize();
906
        this.spatialIndexFactories.put(serviceFactory.getName(), serviceFactory);
907
    }
908
909 44951 omartinez
    @Override
910 42260 fdiaz
    public Service createService(DynObject serviceParameters) throws ServiceException {
911
        throw new UnsupportedOperationException("Not supported yet.");
912
    }
913
914 44951 omartinez
    @Override
915 42260 fdiaz
    public DynObject createServiceParameters(String serviceName) throws ServiceException {
916
        SpatialIndexFactory factory = this.getSpatialIndexFactory(serviceName);
917
        if (factory == null) {
918
            throw new CantExistsService(serviceName);
919
        }
920
        return factory.createParameters();
921
    }
922
923 44951 omartinez
    @Override
924 42260 fdiaz
    public Service getService(DynObject parameters) throws ServiceException {
925
        return this.createSpatialIndex((String) parameters.getDynValue("serviceName"), parameters);
926
    }
927
928
    public class CantExistsService extends ServiceException {
929
930
        public CantExistsService(String serviceName) {
931
            super("Can't existe service %(service).", "_Cant_existe_service_XserviceX", 100001);
932
            setValue("service", serviceName);
933
        }
934
935
    }
936 43171 jjdelcerro
937
    @Override
938
    public InformationbuilderWithGeometrySupport createInformacionBuilder() {
939
        return new BaseInformationBuilderWithGeometrySupport();
940
    }
941 43405 jjdelcerro
942
    @Override
943
    public boolean isSubtype(int geomTypeParent, int geomTypeChild) {
944
        // Esto es un implementacion patatera que habria que mejorar,
945
        // pero mejor aqui que esparcida por todas partes en donde se
946
        // necesite.
947
        if( geomTypeParent == geomTypeChild ) {
948
            return true;
949
        }
950 43563 jjdelcerro
        if( geomTypeParent == Geometry.TYPES.GEOMETRY ) {
951
            return true;
952
        }
953 43405 jjdelcerro
        switch(geomTypeParent) {
954
        case Geometry.TYPES.MULTICURVE:
955
            return geomTypeChild==Geometry.TYPES.MULTILINE ;
956 43429 jjdelcerro
        case Geometry.TYPES.MULTISURFACE:
957 43405 jjdelcerro
            return geomTypeChild==Geometry.TYPES.MULTIPOLYGON ;
958
        case Geometry.TYPES.MULTIPOINT:
959
            return geomTypeChild==Geometry.TYPES.MULTIPOINT ;
960 43489 jjdelcerro
961 43405 jjdelcerro
        case Geometry.TYPES.CURVE:
962 43524 fdiaz
            return
963
                geomTypeChild == Geometry.TYPES.CURVE ||
964 43489 jjdelcerro
                geomTypeChild == Geometry.TYPES.LINE ||
965
                geomTypeChild == Geometry.TYPES.ARC ||
966 43524 fdiaz
                geomTypeChild == Geometry.TYPES.SPLINE ||
967
                geomTypeChild == Geometry.TYPES.CIRCUMFERENCE ||
968
                geomTypeChild == Geometry.TYPES.PERIELLIPSE
969 43489 jjdelcerro
                ;
970 43429 jjdelcerro
        case Geometry.TYPES.SURFACE:
971 43524 fdiaz
            return
972
            geomTypeChild==Geometry.TYPES.SURFACE ||
973
            geomTypeChild==Geometry.TYPES.POLYGON ||
974
            geomTypeChild == Geometry.TYPES.CIRCLE ||
975
            geomTypeChild == Geometry.TYPES.ELLIPSE ||
976
            geomTypeChild == Geometry.TYPES.RING ||
977
            geomTypeChild == Geometry.TYPES.FILLEDSPLINE ||
978
            geomTypeChild == Geometry.TYPES.ELLIPTICARC
979
            ;
980 43405 jjdelcerro
        case Geometry.TYPES.POINT:
981
            return geomTypeChild==Geometry.TYPES.POINT ;
982
        }
983
        return false;
984
    }
985 45039 fdiaz
986
    @Override
987
    public boolean canAggregate(int geomTypeParent, int geomTypeChild) {
988
989
        switch(geomTypeParent) {
990
        case Geometry.TYPES.MULTICURVE:
991
        case Geometry.TYPES.MULTILINE:
992
            return isSubtype(Geometry.TYPES.CURVE, geomTypeChild);
993
        case Geometry.TYPES.MULTISURFACE:
994
        case Geometry.TYPES.MULTIPOLYGON:
995
            return isSubtype(Geometry.TYPES.SURFACE, geomTypeChild);
996
        case Geometry.TYPES.MULTIPOINT:
997
            return isSubtype(Geometry.TYPES.POINT, geomTypeChild);
998
        }
999
        return false;
1000
    }
1001 45673 jjdelcerro
1002
    @Override
1003
    public GeometryCoercionContext createGeometryCoercionContext() {
1004
        return new DefaultGeometryCoercionContext();
1005
    }
1006
1007 42260 fdiaz
}