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

History | View | Annotate | Download (45.3 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.io.IOException;
29
import java.io.Reader;
30
import java.util.ArrayList;
31
import java.util.HashMap;
32
import java.util.Iterator;
33
import java.util.List;
34
import java.util.Map;
35
import org.apache.commons.codec.binary.Hex;
36
import org.apache.commons.io.IOUtils;
37
import org.apache.commons.lang3.StringUtils;
38
import org.cresques.cts.IProjection;
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.GeometryCoercionContext;
43
import org.gvsig.fmap.geom.GeometryException;
44
import org.gvsig.fmap.geom.GeometryLocator;
45
import org.gvsig.fmap.geom.GeometryManager;
46
import org.gvsig.fmap.geom.GeometryUtils;
47
import org.gvsig.fmap.geom.InformationbuilderWithGeometrySupport;
48
import org.gvsig.fmap.geom.SpatialIndex;
49
import org.gvsig.fmap.geom.SpatialIndexFactory;
50
import org.gvsig.fmap.geom.aggregate.MultiCurve;
51
import org.gvsig.fmap.geom.aggregate.MultiLine;
52
import org.gvsig.fmap.geom.aggregate.MultiPoint;
53
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
54
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
55
import org.gvsig.fmap.geom.aggregate.MultiSurface;
56
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
57
import org.gvsig.fmap.geom.exception.CreateGeometryException;
58
import org.gvsig.fmap.geom.jts.coerce.DefaultGeometryCoercionContext;
59
import org.gvsig.fmap.geom.jts.gml.GMLReader;
60
import org.gvsig.fmap.geom.jts.gputils.DefaultGeneralPathX;
61
import org.gvsig.fmap.geom.jts.primitive.DefaultNullGeometry;
62
import org.gvsig.fmap.geom.jts.primitive.Envelope2D;
63
import org.gvsig.fmap.geom.jts.primitive.Envelope3D;
64
import org.gvsig.fmap.geom.jts.spatialindex.SpatialIndexFactoryJTSQuadtree;
65
import org.gvsig.fmap.geom.jts.util.GMLUtils;
66
import org.gvsig.fmap.geom.jts.util.JTSUtils;
67
import org.gvsig.fmap.geom.operation.GeometryOperation;
68
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
69
import org.gvsig.fmap.geom.operation.GeometryOperationException;
70
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
71
import org.gvsig.fmap.geom.primitive.Curve;
72
import org.gvsig.fmap.geom.primitive.Envelope;
73
import org.gvsig.fmap.geom.primitive.GeneralPathX;
74
import org.gvsig.fmap.geom.primitive.IGeneralPathX;
75
import org.gvsig.fmap.geom.primitive.Line;
76
import org.gvsig.fmap.geom.primitive.NullGeometry;
77
import org.gvsig.fmap.geom.primitive.Point;
78
import org.gvsig.fmap.geom.primitive.Polygon;
79
import org.gvsig.fmap.geom.primitive.Surface;
80
import org.gvsig.fmap.geom.type.GeometryType;
81
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
82
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
83
import org.gvsig.tools.dynobject.DynObject;
84
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
85
import org.gvsig.tools.service.Service;
86
import org.gvsig.tools.service.ServiceException;
87
import org.gvsig.tools.service.spi.ServiceFactory;
88
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
90

    
91
/**
92
 * Default implementation for the {@link GeometryManager}. When the
93
 * application starts, this class is registered in the {@link GeometryLocator}
94
 * using the {@link DefaultGeometryLibrary}.
95
 *
96
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
97
 */
98

    
99
@SuppressWarnings("UseSpecificCatch")
100
public class DefaultGeometryManager implements GeometryManager {
101

    
102
    private static final Logger LOGGER = LoggerFactory.getLogger(GeometryManager.class);
103
    
104
    /**
105
     * Offset for GeometryType -1 value (UNKNOWN)
106
     */
107
    private final int GEOMETRY_TYPE_OFFSET = 1;
108
    
109
    private double flatness = 0.8;
110

    
111
    private final Map spatialIndexFactories = new HashMap();
112

    
113
    /**
114
     * This list holds the unique name of all registered geometry operations.
115
     * The index in which they are stored is also the operation code used to
116
     * invoke each one of them
117
     */
118
    private final List geometryOperations = new ArrayList();
119

    
120
    /**
121
     * Common operations are registered here. Type specific operations are
122
     * registered in the corresponding GeometryType instance
123
     */
124
    // private List commonOperations = new ArrayList();
125

    
126
    /**
127
     * This map holds the instances of all registered GeometryType. The key is
128
     * the name of the specific Geometry subclass.
129
     * In other words, the string "org.gvsig.fmap.geom.primitive.Point2D" is the
130
     * hash key to obtain an instance of GeometryType holding the
131
     * operations associated to the class org.gvsig.fmap.geom.primitive.Point2D.
132
     */
133
    private final Map geometryTypeName = new HashMap();
134

    
135
    /**
136
     * Matrix of geometry types by type (row) and subtype (column). This matrix
137
     * will contain null values in the cells where a GeometryType hasn't been
138
     * registered.
139
     */
140
    private GeometryType[][] geometryTypes;
141
    
142
    // Initially create a matrix of 27 x 6, which are the current default
143
    // types and subtypes. If another type or subtype is registered, the
144
    // matrix will grow as needed
145
    private static final int DEFAULT_TYPES_SIZE = 27; // [-1, 25]
146
    private static final int DEFAULT_SUBTYPES_SIZE = 6;
147

    
148
    public DefaultGeometryManager() throws GeometryException {
149
        this(DEFAULT_TYPES_SIZE, DEFAULT_SUBTYPES_SIZE);
150
    }
151

    
152
    public DefaultGeometryManager(int initialTypesSize, int initialSubtypesSize) throws GeometryException {
153
        geometryTypes = new GeometryType[initialTypesSize][initialSubtypesSize];
154
    }
155

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

    
165
        int index = getGeometryOperationCode(geomOpName);
166

    
167
        geomType.setGeometryOperation(index, geomOp);
168

    
169
        return index;
170
    }
171

    
172
    @Override
173
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp) {
174
        if (geomOpName == null) {
175
            throw new IllegalArgumentException("geomOpName cannot be null.");
176
        }
177
        if (geomOp == null) {
178
            throw new IllegalArgumentException("geomOp cannot be null.");
179
        }
180

    
181
        int index = getGeometryOperationCode(geomOpName);
182

    
183
        Iterator it = geometryTypeName.values().iterator();
184
        while (it.hasNext()) {
185
            GeometryType geometryType = (GeometryType) it.next();
186
            registerGeometryOperation(geomOpName, geomOp, geometryType);
187
        }
188

    
189
        return index;
190

    
191
    }
192

    
193
    @SuppressWarnings("override")
194
    public int registerGeometryOperation(String geomOpName, GeometryOperation geomOp, int type, int subType)
195
        throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
196
        GeometryType geometryType = getGeometryType(type, subType);
197
        return registerGeometryOperation(geomOpName, geomOp, geometryType);
198
    }
199

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

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

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

    
239
    @Override
240
    public int registerGeometryOperationBySuperSubType(String geomOpName, GeometryOperation geomOp, int superSubType) {
241
        int code = -1;
242
        Iterator it = geometryTypeName.values().iterator();
243
        while (it.hasNext()) {
244
            GeometryType geometryType = (GeometryType) it.next();
245
            if (geometryType.isSubTypeOf(superSubType)) {
246
                code = registerGeometryOperation(geomOpName, geomOp, geometryType);
247
            }
248
        }
249
        return code;
250
    }
251

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

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

    
263
    @Override
264
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int superType) {
265
        return registerGeometryType(geomClass, name, type, subType, new int[] { superType }, new int[0]);
266
    }
267

    
268
    @Override
269
    public GeometryType registerGeometryType(Class geomClass, String name, int type, int subType, int[] superTypes) {
270
        return registerGeometryType(geomClass, name, type, subType, superTypes, new int[0]);
271
    }
272

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

    
322
        if (!Geometry.class.isAssignableFrom(geomClass)) {
323
            throw new IllegalArgumentException(geomClass.getName() + " must implement the Geometry interface");
324
        }
325

    
326
        int offsettedType = type + GEOMETRY_TYPE_OFFSET;
327
        // Check if it is registered
328
        GeometryType geomType = null;
329
        if (offsettedType >= geometryTypes.length || subType >= geometryTypes[0].length
330
            || (geomType = geometryTypes[offsettedType][subType]) == null) {
331
            geomType = new DefaultGeometryType(geomClass, name, type, subType, superTypes, superSubTypes); //Attention!
332
            registerGeometryType(geomType);
333
        }
334

    
335
        LOGGER.debug("Class {} registered with name {}", geomClass, geomType.getName());
336

    
337
        return geomType;
338
    }
339

    
340
    @Override
341
    public void registerGeometryType(GeometryType geometryType) {
342
        int offsettedType = geometryType.getType() + GEOMETRY_TYPE_OFFSET;
343
        if (offsettedType >= geometryTypes.length || geometryType.getSubType() >= geometryTypes[0].length) {
344

    
345
            // Recreate the geometry type matrix if the types
346
            // or subtypes don't fit
347
            int newTypesSize =
348
                offsettedType < geometryTypes.length ? geometryTypes.length : offsettedType + 1;
349
            int newSubTypesSize =
350
                geometryType.getSubType() < geometryTypes[0].length ? geometryTypes[0].length : geometryType
351
                    .getSubType() + 1;
352
            GeometryType[][] newMatrix = new GeometryType[newTypesSize][newSubTypesSize];
353

    
354
            for (int i = 0; i < geometryTypes.length; i++) {
355
                System.arraycopy(geometryTypes[i], 0, newMatrix[i], 0, geometryTypes[i].length);
356
            }
357
            geometryTypes = newMatrix;
358
        }
359

    
360
        geometryTypes[offsettedType][geometryType.getSubType()] = geometryType;
361
        geometryTypeName.put(geometryType.getName(), geometryType);
362
    }
363

    
364
    @Override
365
    public GeometryType registerGeometryType(Class geomClass, int type, int subType) {
366
        return registerGeometryType(geomClass, null, type, subType);
367
    }
368

    
369
    @Override
370
    public GeometryType getGeometryType(int type, int subType) throws GeometryTypeNotSupportedException,
371
        GeometryTypeNotValidException {
372

    
373
        int offsettedType = type + GEOMETRY_TYPE_OFFSET;
374
        
375
        if (offsettedType >= geometryTypes.length || subType >= geometryTypes[0].length) {
376
            throw new GeometryTypeNotValidException(type, subType);
377
        }
378
        GeometryType gType = geometryTypes[offsettedType][subType];
379
        if (gType == null) {
380
            throw new GeometryTypeNotSupportedException(type, subType);
381
        }
382
        return gType;
383
    }
384

    
385
    @Override
386
    public Geometry create(GeometryType geomType) throws CreateGeometryException {
387
        return geomType.create();
388
    }
389

    
390
    @Override
391
    public Geometry create(String name) throws CreateGeometryException {
392
        if (!geometryTypeName.containsKey(name)) {
393
            throw new IllegalArgumentException(name + " has not been registered yet.");
394
        }
395
        return ((GeometryType) geometryTypeName.get(name)).create();
396
    }
397

    
398
    @Override
399
    public Geometry create(int type, int subType) throws CreateGeometryException {
400
        try {
401
            return getGeometryType(type, subType).create();
402
        } catch (GeometryException e) {
403
            throw new CreateGeometryException(type, subType, e);
404
        }
405
    }
406

    
407
    @Override
408
    public Curve createCurve(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
409
        Curve curve = (Curve) create(TYPES.CURVE, subType);
410
        curve.setGeneralPath(generalPathX);
411
        return curve;
412
    }
413

    
414
    @Override
415
    public NullGeometry createNullGeometry(int subType) throws CreateGeometryException {
416
        NullGeometry nullGeom = (NullGeometry) create(TYPES.NULL, subType);
417
        return nullGeom;
418
    }
419

    
420
    @Override
421
    public Point createPoint(double x, double y, int subType) throws CreateGeometryException {
422
        Point point = (Point) create(TYPES.POINT, subType);
423
        point.setX(x);
424
        point.setY(y);
425
        return point;
426
    }
427

    
428
    @Override
429
    public Surface createSurface(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
430
        Surface surface = (Surface) create(TYPES.SURFACE, subType);
431
        surface.setGeneralPath(generalPathX);
432
        return surface;
433
    }
434

    
435
    @Override
436
    public GeometryOperation getGeometryOperation(int opCode, int type, int subType)
437
        throws GeometryTypeNotSupportedException, GeometryOperationNotSupportedException, GeometryTypeNotValidException {
438
        GeometryType geometryType = getGeometryType(type, subType);
439
        return geometryType.getGeometryOperation(opCode);
440
    }
441

    
442
    @Override
443
    public GeometryOperation getGeometryOperation(int opCode) throws GeometryOperationNotSupportedException {
444
        if (opCode < 0) {
445
            throw new GeometryOperationNotSupportedException(opCode);
446
        }
447
        GeometryType type = (GeometryType) geometryTypeName.get(DefaultNullGeometry.class.getName());
448
        if (type == null) {
449
            throw new GeometryOperationNotSupportedException(opCode);
450
        }
451
        return type.getGeometryOperation(opCode);
452
    }
453

    
454
    @Override
455
    public Object invokeOperation(int opCode, Geometry geom, GeometryOperationContext ctx)
456
        throws GeometryOperationNotSupportedException, GeometryOperationException {
457
        GeometryOperation geomOp = geom.getGeometryType().getGeometryOperation(opCode);
458

    
459
        if (geomOp != null) {
460
            return geomOp.invoke(geom, ctx);
461
        }
462

    
463
        throw new GeometryOperationNotSupportedException(opCode, geom.getGeometryType());
464
    }
465

    
466
    @Override
467
    public Object invokeOperation(String geomOpName, Geometry geom, GeometryOperationContext ctx)
468
        throws GeometryOperationNotSupportedException, GeometryOperationException {
469
        int index = geometryOperations.indexOf(geomOpName);
470
        if (index == -1) {
471
            throw new GeometryOperationNotSupportedException(-1);
472
        }
473
        return invokeOperation(index, geom, ctx);
474
    }
475

    
476
    @Override
477
    public Object invokeOperation(String geomOpName, GeometryOperationContext ctx)
478
        throws GeometryOperationNotSupportedException, GeometryOperationException {
479
        int index = geometryOperations.indexOf(geomOpName);
480
        GeometryOperation geomOp = getGeometryOperation(index);
481
        return geomOp.invoke(null, ctx);
482
    }
483

    
484
    @Override
485
    public Envelope createEnvelope(int subType) {
486
        // TODO: register the envelopes!!!
487
        switch (subType) {
488
        case SUBTYPES.GEOM3D:
489
            return new Envelope3D();
490
        default:
491
            return new Envelope2D();
492
        }
493
    }
494

    
495
    @Override
496
    public Envelope createEnvelope(double minX, double minY, double maxX, double maxY, int subType)
497
        throws CreateEnvelopeException {
498
        org.gvsig.fmap.geom.primitive.Point min = null;
499
        org.gvsig.fmap.geom.primitive.Point max = null;
500
        try {
501
            min = createPoint(minX, minY, subType);
502
            max = createPoint(maxX, maxY, subType);
503
        } catch (CreateGeometryException e) {
504
            throw new CreateEnvelopeException(subType, e);
505
        }
506
        switch (subType) {
507
        case SUBTYPES.GEOM2D:
508
        case SUBTYPES.GEOM2DM:
509
            // Small optimization to directly create an Envelope2D
510
            // return new Envelope2D(minX, minY, maxX, maxY);
511
            return new Envelope2D(min, max, null);
512
        default:
513
            Envelope envelope = createEnvelope(subType);
514
            envelope.setLowerCorner(min);
515
            envelope.setUpperCorner(max);
516
            return envelope;
517
        }
518
    }
519

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

    
546
            case PathIterator.SEG_LINETO:
547
                if (tmpPath == null) {
548
                    System.arraycopy(coords, 0, first, 0, 2);
549
                    tmpPath = new GeneralPathX(piter.getWindingRule());
550
                }
551
                tmpPath.lineTo(coords[0], coords[1]);
552
                break;
553

    
554
            case PathIterator.SEG_QUADTO:
555
                if (tmpPath == null) {
556
                    System.arraycopy(coords, 0, first, 0, 2);
557
                    tmpPath = new GeneralPathX(piter.getWindingRule());
558
                }
559
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
560
                break;
561

    
562
            case PathIterator.SEG_CUBICTO:
563
                if (tmpPath == null) {
564
                    System.arraycopy(coords, 0, first, 0, 2);
565
                    tmpPath = new GeneralPathX(piter.getWindingRule());
566
                }
567
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
568
                break;
569

    
570
            case PathIterator.SEG_CLOSE:
571
                tmpPath.lineTo(first[0], first[1]);
572
                break;
573

    
574
            } // end switch
575

    
576
            piter.next();
577

    
578
        }
579
        if (tmpPath != null) {
580
            tmpCurve = createCurve(tmpPath, subType);
581
            multiCurve.addCurve(tmpCurve);
582
        }
583

    
584
        return multiCurve;
585

    
586
    }
587

    
588
    @Override
589
    public MultiSurface createMultiSurface(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
590
        if (subType != SUBTYPES.GEOM2D) {
591
            // FIXME Exception
592
            throw new UnsupportedOperationException();
593
        }
594
        MultiSurface multiSurface = (MultiSurface) create(TYPES.MULTISURFACE, subType);
595
        PathIterator piter = generalPathX.getPathIterator(null);
596
        GeneralPathX tmpPath = null;
597
        Surface tmpSurface;
598
        double[] coords = new double[6];
599
        double[] first = new double[6];
600
        int type;
601
        while (!piter.isDone()) {
602
            type = piter.currentSegment(coords);
603
            switch (type) {
604
            case PathIterator.SEG_MOVETO:
605
                if (tmpPath != null) {
606
                    tmpSurface = createSurface(tmpPath, subType);
607
                    multiSurface.addSurface(tmpSurface);
608
                }
609
                System.arraycopy(coords, 0, first, 0, 2);
610
                tmpPath = new GeneralPathX(piter.getWindingRule());
611
                tmpPath.moveTo(coords[0], coords[1]);
612

    
613
            case PathIterator.SEG_LINETO:
614
                if (tmpPath == null) {
615
                    System.arraycopy(coords, 0, first, 0, 2);
616
                    tmpPath = new GeneralPathX(piter.getWindingRule());
617
                }
618
                tmpPath.lineTo(coords[0], coords[1]);
619
                break;
620

    
621
            case PathIterator.SEG_QUADTO:
622
                if (tmpPath == null) {
623
                    System.arraycopy(coords, 0, first, 0, 2);
624
                    tmpPath = new GeneralPathX(piter.getWindingRule());
625
                }
626
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
627
                break;
628

    
629
            case PathIterator.SEG_CUBICTO:
630
                if (tmpPath == null) {
631
                    System.arraycopy(coords, 0, first, 0, 2);
632
                    tmpPath = new GeneralPathX(piter.getWindingRule());
633
                }
634
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
635
                break;
636

    
637
            case PathIterator.SEG_CLOSE:
638
                tmpPath.lineTo(first[0], first[1]);
639
                break;
640
            } // end switch
641

    
642
            piter.next();
643

    
644
        }
645
        if (tmpPath != null) {
646
            tmpSurface = createSurface(tmpPath, subType);
647
            multiSurface.addSurface(tmpSurface);
648
        }
649

    
650
        return multiSurface;
651

    
652
    }
653

    
654
    @Override
655
    public MultiPoint createMultiPoint(GeneralPathX generalPathX, int subType) throws CreateGeometryException {
656
        if (subType != SUBTYPES.GEOM2D) {
657
            // FIXME Exception
658
            throw new UnsupportedOperationException();
659
        }
660
        MultiPoint multiPoint = (MultiPoint) create(TYPES.MULTIPOINT, subType);
661
        PathIterator piter = generalPathX.getPathIterator(null);
662
        Point tmpPoint;
663
        double[] coords = new double[6];
664
        int type;
665
        while (!piter.isDone()) {
666
            type = piter.currentSegment(coords);
667
            switch (type) {
668
            case PathIterator.SEG_MOVETO:
669
                tmpPoint = createPoint(coords[0], coords[1], subType);
670
                multiPoint.addPoint(tmpPoint);
671

    
672
            case PathIterator.SEG_LINETO:
673
                throw new IllegalArgumentException("The general have a SEG_LINETO.");
674

    
675
            case PathIterator.SEG_QUADTO:
676
                throw new IllegalArgumentException("The general have a SEG_QUADTO.");
677

    
678
            case PathIterator.SEG_CUBICTO:
679
                throw new IllegalArgumentException("The general have a SEG_CUBICTO.");
680

    
681
            case PathIterator.SEG_CLOSE:
682
                throw new IllegalArgumentException("The general have a SEG_CLOSE.");
683
            } // end switch
684

    
685
            piter.next();
686

    
687
        }
688
        return multiPoint;
689

    
690
    }
691

    
692
    @Override
693
    public int getGeometryOperationCode(String geomOpName) {
694
        if (geomOpName == null) {
695
            throw new IllegalArgumentException("geomOpName cannot be null.");
696
        }
697

    
698
        int index = geometryOperations.indexOf(geomOpName);
699
        if (index == -1) {
700
            geometryOperations.add(geomOpName);
701
            index = geometryOperations.indexOf(geomOpName);
702
        }
703
        return index;
704
    }
705

    
706
    @Override
707
    public List getGeometryOperationNames() {
708
        List operations = new ArrayList();
709
        for (int i = 0; i < operations.size(); i++) {
710
            operations.add(geometryOperations.get(i));
711
        }
712
        return operations;
713
    }
714

    
715
    @Override
716
    public double getFlatness() {
717
        return flatness;
718
    }
719

    
720
    @Override
721
    public void setFlatness(double flatness) {
722
        this.flatness = flatness;
723
    }
724

    
725
    @Override
726
    public Geometry createFrom(Object data) throws CreateGeometryException, GeometryException {
727
        if( data == null ) {
728
            throw new IllegalArgumentException("null data is not allowed");
729
        }
730
        if( data instanceof String ) {
731
            Geometry geom = GMLUtils.GML2Geometry((String) data);
732
            if( geom != null ) {
733
                return geom;
734
            }
735
            return this.createFrom((String)data);
736
        }
737
        if( data instanceof byte[] ) {
738
            return this.createFrom((byte[])data);
739
        }
740
        if( data instanceof com.vividsolutions.jts.geom.Geometry ) {
741
            return this.createFrom((com.vividsolutions.jts.geom.Geometry)data);
742
        }
743
        if( data instanceof Geometry ) {
744
            return ((Geometry)data).cloneGeometry();
745
        }
746
        throw new IllegalArgumentException("Type of data ("+data.getClass().getName()+") not supported.");
747
    }
748

    
749
    @Override
750
    public Geometry createFrom(String wkt, String srs) throws GeometryException {
751
        GeometryOperationContext context = new GeometryOperationContext();
752
        context.setAttribute("text", wkt);
753
        context.setAttribute("srs", srs);
754

    
755
        try {
756
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
757
        } catch (Exception e) {
758
            throw new GeometryException(e);
759
        }
760
    }
761

    
762
    private int firstNonBlank(String s) {
763
        char ch;
764
        int i=0;
765
        while(i < s.length()) {
766
            if( !Character.isWhitespace(ch = s.charAt(i++)) ) {
767
                return ch;
768
            }
769
        }
770
        return -1;
771
    } 
772
    
773
    private int firstNonBlank(Reader r) {
774
        try {
775
            int ch;
776
            int i=0;
777
            while( (ch=r.read())!= -1) {
778
                if( !Character.isWhitespace(ch) ) {
779
                    return ch;
780
                }
781
            }
782
            return -1;
783
        } catch (IOException ex) {
784
            return -1;
785
        }
786
    } 
787
    
788
    @Override
789
    public Geometry createFrom(String geom, IProjection srs) throws GeometryException {
790
        try {
791
            if( StringUtils.isBlank(geom) ) {
792
                return null;
793
            }
794
            int ch = firstNonBlank(geom);
795
            switch(ch) {
796
                case '0':
797
                case '1':
798
                    if( (geom.length() % 2) == 0  ) {
799
                        // it starts with 0 or 1 and the length is even. Assume it is hexwkb.
800
                        return createFrom(Hex.decodeHex(geom.toCharArray()), srs);
801
                    }
802
                    break;
803
                case '{':
804
                    try {
805
                        com.vividsolutions.jts.io.geojson.GeoJsonReader reader = new com.vividsolutions.jts.io.geojson.GeoJsonReader();
806
                        com.vividsolutions.jts.geom.Geometry geom_jts = reader.read(geom);
807
                        return JTSUtils.createGeometry(srs, geom_jts);
808
                    } catch(Exception ex) {
809
                        LOGGER.debug("Can't parse as GeoJson");
810
                    }
811
                    break;
812
                case '<':
813
                    try {
814
                        if( StringUtils.startsWithIgnoreCase(geom.trim(),"<gml:") ) {
815
                            com.vividsolutions.jts.io.gml2.GMLReader reader = new com.vividsolutions.jts.io.gml2.GMLReader();
816
                            com.vividsolutions.jts.geom.Geometry geom_jts = reader.read(
817
                                    geom, 
818
                                    new com.vividsolutions.jts.geom.GeometryFactory()
819
                            );
820
                            return JTSUtils.createGeometry(srs, geom_jts);
821
                        }
822
                    } catch(Exception ex) {
823
                        LOGGER.debug("Can't parse as GML");
824
                    }
825
                    break;
826
            }
827
            GeometryOperationContext context = new GeometryOperationContext();
828
            context.setAttribute("text", geom);
829
            context.setAttribute("srs", srs);
830

    
831
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
832
        } catch (Exception e) {
833
            throw new GeometryException(e);
834
        }
835
    }
836

    
837
    @Override
838
    public Geometry createFrom(Reader geom, IProjection srs) throws GeometryException {
839
        try {
840
            if( geom.markSupported() ) {
841
                geom.mark(10240);
842
                int ch = firstNonBlank(geom);
843
                switch(ch) {
844
                    case '0':
845
                    case '1':
846
                        geom.reset();
847
                        //FIXME: Habr?a que eliminar los blancos
848
                        return createFrom(Hex.decodeHex(IOUtils.toCharArray(geom)), srs);
849
                    case '{':
850
                        try {
851
                            geom.reset();
852
                            com.vividsolutions.jts.io.geojson.GeoJsonReader reader = new com.vividsolutions.jts.io.geojson.GeoJsonReader();
853
                            com.vividsolutions.jts.geom.Geometry geom_jts = reader.read(geom);
854
                            return JTSUtils.createGeometry(srs, geom_jts);
855
                        } catch(Exception ex) {
856
                            LOGGER.debug("Can't parse as GeoJson");
857
                        }
858
                        break;
859
                    case '<':
860
                        try {
861
                            char[] buffer = new char[100];
862
                            IOUtils.read(geom, buffer);
863
                            String s = new String(buffer);
864
                            if( StringUtils.startsWithIgnoreCase(s,"gml:") ) {
865
                                geom.reset();
866
                                GMLReader reader = new GMLReader();
867
                                com.vividsolutions.jts.geom.Geometry geom_jts = reader.read(
868
                                        geom, 
869
                                        new com.vividsolutions.jts.geom.GeometryFactory()
870
                                );
871
                                return JTSUtils.createGeometry(srs, geom_jts);
872
                            }
873
                        } catch(Exception ex) {
874
                            LOGGER.debug("Can't parse as GML", ex);
875
                        }
876
                        break;
877
                }
878
                geom.reset();
879
            }
880
            GeometryOperationContext context = new GeometryOperationContext();
881
            context.setAttribute("reader", geom);
882
            context.setAttribute("srs", srs);
883

    
884
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
885
        } catch (Exception e) {
886
            throw new GeometryException(e);
887
        }
888
    }
889

    
890
    @Override
891
    public Geometry createFrom(String wkt) throws GeometryException {
892
        return this.createFrom(wkt, (IProjection)null);
893
    }
894

    
895
    public Geometry createFrom(IProjection proj, com.vividsolutions.jts.geom.Geometry geom) throws GeometryException {
896
        return JTSUtils.createGeometry(proj, geom);
897
    }
898

    
899
    @Override
900
    public Geometry createFromQuietly(String wkt) {
901
        try {
902
            return this.createFrom(wkt);
903
        } catch(Exception ex) {
904
            return null;
905
        }
906
    }
907
    
908
    @Override
909
    public Geometry createFrom(byte[] wkb) throws GeometryException {
910
        GeometryOperationContext context = new GeometryOperationContext();
911
        context.setAttribute("data", wkb);
912
        try {
913
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
914
        } catch (GeometryOperationNotSupportedException e) {
915
            throw new GeometryException(e);
916
        } catch (GeometryOperationException e) {
917
            throw new GeometryException(e);
918
        }
919
    }
920

    
921
    @Override
922
    public Geometry createFrom(byte[] wkb, IProjection srs) throws GeometryException {
923
        GeometryOperationContext context = new GeometryOperationContext();
924
        context.setAttribute("data", wkb);
925
        context.setAttribute("srs", srs);
926
        try {
927
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
928
        } catch (Exception e) {
929
            throw new GeometryException(e);
930
        }
931
    }
932

    
933
    @Override
934
    public IGeneralPathX createGeneralPath(int rule, PathIterator pathIterator) {
935
        if (pathIterator == null) {
936
            return new DefaultGeneralPathX(rule);
937
        }
938
        return new DefaultGeneralPathX(pathIterator, false, 0);
939
    }
940

    
941
    @Override
942
    public MultiPoint createMultiPoint(int subType) throws CreateGeometryException {
943
        return (MultiPoint) create(TYPES.MULTIPOINT, subType);
944
    }
945

    
946
    @Override
947
    public Line createLine(int subType) throws CreateGeometryException {
948
        return (Line) create(TYPES.CURVE, subType);
949
    }
950

    
951
    @Override
952
    public Curve createCurve(int subType) throws CreateGeometryException {
953
        return (Curve) create(TYPES.CURVE, subType);
954
    }
955

    
956
    @Override
957
    public MultiCurve createMultiCurve(int subType) throws CreateGeometryException {
958
        return (MultiCurve) create(TYPES.MULTICURVE, subType);
959
    }
960

    
961
    @Override
962
    public MultiLine createMultiLine(int subType) throws CreateGeometryException {
963
        return (MultiLine) create(TYPES.MULTILINE, subType);
964
    }
965

    
966
    @Override
967
    public MultiSurface createMultiSurface(int subType) throws CreateGeometryException {
968
        return (MultiSurface) create(TYPES.MULTISURFACE, subType);
969
    }
970

    
971
    @Override
972
    public MultiPolygon createMultiPolygon(int subType) throws CreateGeometryException {
973
        return (MultiPolygon) create(TYPES.MULTIPOLYGON, subType);
974
    }
975

    
976
    @Override
977
    public Polygon createPolygon(int subType) throws CreateGeometryException {
978
        return (Polygon) create(TYPES.SURFACE, subType);
979
    }
980

    
981
    @Override
982
    public Surface createSurface(int subType) throws CreateGeometryException {
983
        return (Surface) create(TYPES.SURFACE, subType);
984
    }
985

    
986
    @Override
987
    public SpatialIndex createDefaultMemorySpatialIndex() throws ServiceException {
988
        return this.createSpatialIndex(SpatialIndexFactoryJTSQuadtree.NAME, null);
989
    }
990

    
991
    @Override
992
    public SpatialIndex createSpatialIndex(String name, DynObject parameters) throws ServiceException {
993
        SpatialIndexFactory factory = this.getSpatialIndexFactory(name);
994
        if (factory == null) {
995
            throw new CantExistsService(name);
996
        }
997
        return (SpatialIndex) factory.create(parameters, this);
998
    }
999

    
1000
    @Override
1001
    public SpatialIndexFactory getSpatialIndexFactory(String name) {
1002
        return (SpatialIndexFactory) this.spatialIndexFactories.get(name);
1003
    }
1004

    
1005
    @Override
1006
    public void addServiceFactory(ServiceFactory serviceFactory) {
1007
        serviceFactory.initialize();
1008
        this.spatialIndexFactories.put(serviceFactory.getName(), serviceFactory);
1009
    }
1010

    
1011
    @Override
1012
    public Service createService(DynObject serviceParameters) throws ServiceException {
1013
        throw new UnsupportedOperationException("Not supported yet.");
1014
    }
1015

    
1016
    @Override
1017
    public DynObject createServiceParameters(String serviceName) throws ServiceException {
1018
        SpatialIndexFactory factory = this.getSpatialIndexFactory(serviceName);
1019
        if (factory == null) {
1020
            throw new CantExistsService(serviceName);
1021
        }
1022
        return factory.createParameters();
1023
    }
1024

    
1025
    @Override
1026
    public Service getService(DynObject parameters) throws ServiceException {
1027
        return this.createSpatialIndex((String) parameters.getDynValue("serviceName"), parameters);
1028
    }
1029

    
1030
    @Override
1031
    public MultiPrimitive createMultiPrimitive(GeometryType geometryType) throws CreateGeometryException {
1032
        int type = geometryType.getType();
1033
        int subtype = geometryType.getSubType();
1034
        if(isSubtype(Geometry.TYPES.POINT, type)){
1035
            return createMultiPoint(subtype);
1036
        }
1037
        if(isSubtype(Geometry.TYPES.CURVE, type)){
1038
            return createMultiCurve(subtype);
1039
        }
1040
        if(isSubtype(Geometry.TYPES.SURFACE, type)){
1041
            return createMultiSurface(subtype);
1042
        }
1043
        
1044
        throw new CreateGeometryException(type, subtype, null);
1045
    }
1046

    
1047
    public class CantExistsService extends ServiceException {
1048

    
1049
        public CantExistsService(String serviceName) {
1050
            super("Can't existe service %(service).", "_Cant_existe_service_XserviceX", 100001);
1051
            setValue("service", serviceName);
1052
        }
1053

    
1054
    }
1055

    
1056
    @Override
1057
    public InformationbuilderWithGeometrySupport createInformacionBuilder() {
1058
        return new BaseInformationBuilderWithGeometrySupport();
1059
    }
1060

    
1061
    @Override
1062
    public boolean isSubtype(int geomTypeParent, int geomTypeChild) {
1063
        // Esto es un implementacion patatera que habria que mejorar,
1064
        // pero mejor aqui que esparcida por todas partes en donde se
1065
        // necesite.
1066
        if( geomTypeParent == geomTypeChild ) {
1067
            return true;
1068
        }
1069
        if( geomTypeParent == Geometry.TYPES.GEOMETRY ) {
1070
            return true;
1071
        }
1072
        switch(geomTypeParent) {
1073
        case Geometry.TYPES.MULTICURVE:
1074
            return geomTypeChild==Geometry.TYPES.MULTILINE ;
1075
        case Geometry.TYPES.MULTISURFACE:
1076
            return geomTypeChild==Geometry.TYPES.MULTIPOLYGON ;
1077
        case Geometry.TYPES.MULTIPOINT:
1078
            return geomTypeChild==Geometry.TYPES.MULTIPOINT ;
1079

    
1080
        case Geometry.TYPES.CURVE:
1081
            return
1082
                geomTypeChild == Geometry.TYPES.CURVE ||
1083
                geomTypeChild == Geometry.TYPES.LINE ||
1084
                geomTypeChild == Geometry.TYPES.ARC ||
1085
                geomTypeChild == Geometry.TYPES.SPLINE ||
1086
                geomTypeChild == Geometry.TYPES.CIRCUMFERENCE ||
1087
                geomTypeChild == Geometry.TYPES.PERIELLIPSE
1088
                ;
1089
        case Geometry.TYPES.SURFACE:
1090
            return
1091
            geomTypeChild==Geometry.TYPES.SURFACE ||
1092
            geomTypeChild==Geometry.TYPES.POLYGON ||
1093
            geomTypeChild == Geometry.TYPES.CIRCLE ||
1094
            geomTypeChild == Geometry.TYPES.ELLIPSE ||
1095
            geomTypeChild == Geometry.TYPES.RING ||
1096
            geomTypeChild == Geometry.TYPES.FILLEDSPLINE ||
1097
            geomTypeChild == Geometry.TYPES.ELLIPTICARC
1098
            ;
1099
        case Geometry.TYPES.POINT:
1100
            return geomTypeChild==Geometry.TYPES.POINT ;
1101
        }
1102
        return false;
1103
    }
1104
    
1105
    @Override
1106
    public boolean canAggregate(int geomTypeParent, int geomTypeChild) {
1107
        
1108
        switch(geomTypeParent) {
1109
        case Geometry.TYPES.MULTICURVE:
1110
        case Geometry.TYPES.MULTILINE:
1111
            return isSubtype(Geometry.TYPES.CURVE, geomTypeChild);
1112
        case Geometry.TYPES.MULTISURFACE:
1113
        case Geometry.TYPES.MULTIPOLYGON:
1114
            return isSubtype(Geometry.TYPES.SURFACE, geomTypeChild);
1115
        case Geometry.TYPES.MULTIPOINT:
1116
            return isSubtype(Geometry.TYPES.POINT, geomTypeChild);
1117
        }
1118
        return false;
1119
    }
1120

    
1121
    @Override
1122
    public GeometryCoercionContext createGeometryCoercionContext() {
1123
        return new DefaultGeometryCoercionContext();
1124
    }
1125
    
1126
    
1127
    public static void main(String[] args) throws GeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
1128
        String s;
1129
        new DefaultLibrariesInitializer().fullInitialize();
1130
//        s =  GeometryUtils.formatCoordinate("%-%d? %m' %s'' N", 39.89);
1131
//        System.out.println(s);
1132
//        s =  GeometryUtils.formatCoordinate("%-%d? %m' %.0s'' N", 39.89);
1133
//        System.out.println(s);
1134
//        s =  GeometryUtils.formatCoordinate("%+%d? %m' %.2s'' N (%4.4D)", 39.89);
1135
//        System.out.println(s);
1136
//        s =  GeometryUtils.formatCoordinate("%-%d? %m' N", -39.89);
1137
//        System.out.println(s);
1138
//        s =  GeometryUtils.formatCoordinate("%-%d? %m' N (%4.4D)", 39.89);
1139
//        System.out.println(s);
1140
        //Geometry g = GeometryUtils.createFrom("00000007d50000000100000007d20000002341258d57c2b73acf4150bf008a45b87241258d5eb2faa5364150befedb0f995841258d6aeb851eb84150befbeeb851ec41258d723d70a3d74150bef9d51eb85241258d7e428f5c294150bef677ae147b41258d9d147ae1484150beeea47ae14841258dbc28f5c28f4150bee72ae147ae41258dc7ae147ae14150bee468f5c28f41258dcc6b851eb84150bee31999999a41258dd1666666664150bee18b851eb841258dd8d70a3d714150bedf1d70a3d741258ddea8f5c28f4150bedc951eb85241258de3eb851eb84150bed99ccccccd41258dea3d70a3d74150bed6351eb85241258defbd70a3d74150bed3728f5c2941258df39999999a4150bed1751eb85241258df6c7ae147b4150bed01c28f5c341258df86b851eb84150becf1f5c28f641258dfa1999999a4150becd4666666641258dfb6147ae144150becbc51eb85241258dfd1999999a4150bec9a000000041258dfec28f5c294150bec753d70a3d41258e001eb851ec4150bec2f666666641258e047ae147ae4150beb73147ae1441258e054ccccccd4150beb3bc28f5c341258e054ccccccd4150beb2d70a3d7141258e05947ae1484150beb2047ae14841258e053d70a3d74150beb17333333341258e03a8f5c28f4150beb0e47ae14841258de69999999a4150beaca3d70a3d41258db10f5c28f64150bea46d70a3d741258dabdc28f5c34150bea3928f5c2941258da8dc28f5c34150bea300a3d70a41258da623d70a3d4150bea26147ae1441258da34ccccccd4150bea19d70a3d7");
1141
        //Geometry g = GeometryUtils.createFrom("MULTILINESTRING M ((745920.412801 4319733.74841197 -9999,745923.444481 4319733.242374 -9999,745930.962949 4319734.760282 -9999,745937.102608 4319738.899755 -9999,745941.242081 4319745.039415 -9999,745942.759989 4319752.557882 -9999,745941.242081 4319760.07635 -9999,745937.102608 4319766.216009 -9999,745930.962949 4319770.355482 -9999,745923.444481 4319771.87339 -9999,745915.926014 4319770.355482 -9999,745914.042603266 4319769.08565144 -9999,745911.2302267 4319767.2327453 -9999))");
1142
        Geometry g = GeometryUtils.createFrom("0105000060E66400000100000001020000400D00000016A75AD380C3264156FBE56F7D7A5041000000008087C3C07D0393E386C326413D0E834F7D7A5041000000008087C3C0BDA607ED95C32641D575A8B07D7A5041000000008087C3C029098934A2C32641FF9595B97E7A5041000000008087C3C0740AF27BAAC326417EC68542807A5041000000008087C3C039471D85ADC32641B456B423827A5041000000008087C3C0740AF27BAAC326411CEBE204847A5041000000008087C3C029098934A2C326416A17D38D857A5041000000008087C3C0BDA607ED95C326419337C096867A5041000000008087C3C07D0393E386C326412C9FE5F7867A5041000000008087C3C0CB811EDA77C326419337C096867A5041000000008087C3C06518D01574C3264130507B45867A5041000000008087C3C02646E0756EC32641894CE5CE857A5041000000008087C3C0");
1143
        String hexwkb = g.convertToHexWKB();
1144
        String hexewkb = g.convertToHexEWKB();
1145
        //byte[] b = g.convertToEWKB();
1146
        
1147
        System.out.println(hexwkb);
1148
        System.out.println(hexewkb);
1149
    }
1150
}