Statistics
| Revision:

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

History | View | Annotate | Download (26.8 KB)

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

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

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

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

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

    
40
import org.gvsig.fmap.geom.Geometry;
41
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
42
import org.gvsig.fmap.geom.Geometry.TYPES;
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.aggregate.MultiCurve;
47
import org.gvsig.fmap.geom.aggregate.MultiSurface;
48
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
49
import org.gvsig.fmap.geom.exception.CreateGeometryException;
50
import org.gvsig.fmap.geom.operation.GeometryOperation;
51
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
52
import org.gvsig.fmap.geom.operation.GeometryOperationException;
53
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
54
import org.gvsig.fmap.geom.operation.fromwkt.FromWKTGeometryOperationContext;
55
import org.gvsig.fmap.geom.primitive.Curve;
56
import org.gvsig.fmap.geom.primitive.Envelope;
57
import org.gvsig.fmap.geom.primitive.GeneralPathX;
58
import org.gvsig.fmap.geom.primitive.NullGeometry;
59
import org.gvsig.fmap.geom.primitive.Point;
60
import org.gvsig.fmap.geom.primitive.PointGeometryType;
61
import org.gvsig.fmap.geom.primitive.Surface;
62
import org.gvsig.fmap.geom.primitive.impl.DefaultNullGeometry;
63
import org.gvsig.fmap.geom.primitive.impl.Envelope2D;
64
import org.gvsig.fmap.geom.primitive.impl.Envelope3D;
65
import org.gvsig.fmap.geom.type.GeometryType;
66
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
67
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
68
import org.gvsig.fmap.geom.type.impl.DefaultGeometryType;
69

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

    
78
public class DefaultGeometryManager implements GeometryManager {
79

    
80
    private static final Logger logger = LoggerFactory
81
    .getLogger(GeometryManager.class);
82
    private double flatness = 0.8;
83

    
84
    /**
85
     * This list holds the unique name of all registered geometry operations.
86
     * The index in which they are stored is also the operation code used to
87
     * invoke each one of them
88
     */
89
    private List geometryOperations = new ArrayList();
90

    
91
    /**
92
     * Common operations are registered here. Type specific operations are
93
     * registered in the corresponding GeometryType instance
94
     */
95
    // private List commonOperations = new ArrayList();
96

    
97
    /**
98
     * This map holds the instances of all registered GeometryType. The key is
99
     * the name of the specific Geometry subclass.
100
     * In other words, the string "org.gvsig.fmap.geom.primitive.Point2D" is the
101
     * hash key to obtain an instance of GeometryType holding the
102
     * operations associated to the class org.gvsig.fmap.geom.primitive.Point2D.
103
     */
104
    private Map geometryTypeName = new HashMap();
105

    
106
    /**
107
     * Matrix of geometry types by type (row) and subtype (column). This matrix
108
     * will contain null values in the cells where a GeometryType hasn't been
109
     * registered.
110
     */
111
    private GeometryType[][] geometryTypes;
112

    
113
    // Initially create a matrix of 17 x 6, which are the current default
114
    // types and subtypes. If another type or subtype is registered, the
115
    // matrix will grow as needed
116
    private static final int DEFAULT_TYPES_SIZE = 17;
117
    private static final int DEFAULT_SUBTYPES_SIZE = 6;
118

    
119
    public DefaultGeometryManager() {
120
        this(DEFAULT_TYPES_SIZE, DEFAULT_SUBTYPES_SIZE);
121
    }
122

    
123
    public DefaultGeometryManager(int initialTypesSize, int initialSubtypesSize) {
124
        geometryTypes = new GeometryType[initialTypesSize][initialSubtypesSize];
125
    }
126

    
127
    public int registerGeometryOperation(String geomOpName,
128
        GeometryOperation geomOp, GeometryType geomType) {
129
        if (geomOp == null) {
130
            throw new IllegalArgumentException("geomOp cannot be null.");
131
        }
132
        if (geomType == null) {
133
            throw new IllegalArgumentException("geomType cannot be null.");
134
        }
135

    
136
        int index = getGeometryOperationCode(geomOpName);
137

    
138
        geomType.setGeometryOperation(index, geomOp);
139

    
140
        return index;
141
    }
142

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

    
152
        int index = getGeometryOperationCode(geomOpName);
153

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

    
162
        return index;
163

    
164
    }
165

    
166
    public int registerGeometryOperation(String geomOpName,
167
        GeometryOperation geomOp, int type, int subType)
168
    throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
169
        GeometryType geometryType = getGeometryType(type, subType);
170
        return registerGeometryOperation(geomOpName, geomOp, geometryType);
171
    }
172

    
173
    public int registerGeometryOperation(String geomOpName,
174
        GeometryOperation geomOp, int type) {
175
        Iterator it = geometryTypeName.keySet().iterator();
176
        int code = -1;
177
        while (it.hasNext()) {
178
            String className = (String) it.next();
179
            GeometryType geometryType =
180
                (GeometryType) geometryTypeName.get(className);
181
            if ((type == geometryType.getType())) {
182
                code =
183
                    registerGeometryOperation(geomOpName, geomOp, geometryType);
184
            }
185
        }
186
        return code;
187
    }
188

    
189
    public int registerGeometryOperationBySubtype(String geomOpName,
190
        GeometryOperation geomOp, int subType) {
191
        Iterator it = geometryTypeName.keySet().iterator();
192
        int code = -1;
193
        while (it.hasNext()) {
194
            String className = (String) it.next();
195
            GeometryType geometryType =
196
                (GeometryType) geometryTypeName.get(className);
197
            if ((subType == geometryType.getSubType())) {
198
                code =
199
                    registerGeometryOperation(geomOpName, geomOp, geometryType);
200
            }
201
        }
202
        return code;
203
    }    
204

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

    
221
    public int registerGeometryOperationBySuperSubType(String geomOpName,
222
        GeometryOperation geomOp, int superSubType) {       
223
        Iterator it = geometryTypeName.keySet().iterator();
224
        int code = -1;
225
        while (it.hasNext()) {
226
            String className = (String) it.next();
227
            GeometryType geometryType =
228
                (GeometryType) geometryTypeName.get(className);
229
            if (geometryType.isSubTypeOf(superSubType)) {
230
                code =
231
                    registerGeometryOperation(geomOpName, geomOp, geometryType);
232
            }
233
        }
234
        return code;
235
    }
236

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

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

    
249
    public GeometryType registerGeometryType(Class geomClass, String name,
250
        int type, int subType, int superType) {
251
        return registerGeometryType(geomClass, name, type, subType,
252
            new int[]{superType}, new int[0]);
253
    }
254

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

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

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

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

    
327
        logger.debug("Class {} registered with name {}", geomClass,
328
            geomType.getName());
329

    
330
        return geomType;
331
    }
332

    
333
    public void registerGeometryType(GeometryType geometryType) {
334
        if (geometryType.getType() >= geometryTypes.length
335
            || geometryType.getSubType() >= geometryTypes[0].length) {
336

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

    
348
                for (int i = 0; i < geometryTypes.length; i++) {
349
                    System.arraycopy(geometryTypes[i], 0, newMatrix[i], 0,
350
                        geometryTypes[i].length);
351
                }
352
                geometryTypes = newMatrix;
353
        }
354

    
355
        geometryTypes[geometryType.getType()][geometryType.getSubType()] =
356
            geometryType;
357
    }
358

    
359
    public GeometryType registerGeometryType(Class geomClass, int type,
360
        int subType) {
361
        return registerGeometryType(geomClass, null, type, subType);
362
    }
363

    
364
    public GeometryType getGeometryType(String className)
365
    throws GeometryTypeNotSupportedException {
366
        if (!geometryTypeName.containsKey(className)) {
367
            throw new GeometryTypeNotSupportedException(className);
368
        }
369
        return (GeometryType) geometryTypeName.get(className);
370
    }
371

    
372
    public GeometryType getGeometryType(int type, int subType)
373
    throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
374
        GeometryType gType = null;
375
        if (type >= geometryTypes.length || subType >= geometryTypes[0].length) {
376
            throw new GeometryTypeNotValidException(type, subType);
377
        }
378

    
379
        gType = geometryTypes[type][subType];
380

    
381
        if (gType == null) {
382
            throw new GeometryTypeNotSupportedException(type, subType);
383
        }
384

    
385
        return gType;
386
    }
387

    
388
    public Geometry create(GeometryType geomType)
389
    throws CreateGeometryException {
390
        return geomType.create();
391
    }
392

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

    
401
    public Geometry create(int type, int subType)
402
    throws CreateGeometryException {
403
        try {
404
            return getGeometryType(type, subType).create();
405
        } catch (GeometryException e) {
406
            throw new CreateGeometryException(type, subType, e);
407
        }
408
    }
409

    
410
    public Curve createCurve(GeneralPathX generalPathX, int subType)
411
    throws CreateGeometryException {
412
        Curve curve = (Curve) create(TYPES.CURVE, subType);
413
        curve.setGeneralPath(generalPathX);
414
        return curve;
415
    }
416

    
417
    public NullGeometry createNullGeometry(int subType)
418
    throws CreateGeometryException {
419
        NullGeometry nullGeom = (NullGeometry) create(TYPES.NULL, subType);
420
        return nullGeom;
421
    }
422

    
423
    public Point createPoint(double x, double y, int subType)
424
    throws CreateGeometryException {
425
        Point point = (Point) create(TYPES.POINT, subType);
426
        point.setX(x);
427
        point.setY(y);
428
        return point;
429
    }
430

    
431
    public Surface createSurface(GeneralPathX generalPathX, int subType)
432
    throws CreateGeometryException {
433
        Surface surface = (Surface) create(TYPES.SURFACE, subType);
434
        surface.setGeneralPath(generalPathX);
435
        return surface;
436
    }
437

    
438
    public GeometryOperation getGeometryOperation(int opCode, int type,
439
        int subType) throws GeometryTypeNotSupportedException,
440
        GeometryOperationNotSupportedException, GeometryTypeNotValidException {
441
        GeometryType geometryType = getGeometryType(type, subType);
442
        return geometryType.getGeometryOperation(opCode);
443
    }
444

    
445
    public GeometryOperation getGeometryOperation(int opCode)
446
        throws GeometryOperationNotSupportedException {
447
        if (opCode < 0) {
448
            throw new GeometryOperationNotSupportedException(opCode);
449
        }
450
        GeometryType type =
451
            (GeometryType) geometryTypeName.get(DefaultNullGeometry.class
452
                .getName());
453
        if (type == null) {
454
            throw new GeometryOperationNotSupportedException(opCode);
455
        }
456
        return type.getGeometryOperation(opCode);
457
    }
458

    
459
    public Object invokeOperation(int opCode, Geometry geom,
460
        GeometryOperationContext ctx)
461
    throws GeometryOperationNotSupportedException,
462
    GeometryOperationException {
463
        GeometryOperation geomOp =
464
            geom.getGeometryType().getGeometryOperation(opCode);
465

    
466
        if (geomOp != null) {
467
            return geomOp.invoke(geom, ctx);
468
        }
469

    
470
        throw new GeometryOperationNotSupportedException(opCode,
471
            geom.getGeometryType());
472
    }
473

    
474
    public Object invokeOperation(String geomOpName, Geometry geom,
475
        GeometryOperationContext ctx)
476
    throws GeometryOperationNotSupportedException,
477
    GeometryOperationException {
478
        int index = geometryOperations.indexOf(geomOpName);
479
        if (index == -1) {
480
            throw new GeometryOperationNotSupportedException(-1);
481
        }
482
        return invokeOperation(index, geom, ctx);
483
    }
484

    
485
    public Object invokeOperation(String geomOpName,
486
        GeometryOperationContext ctx)
487
        throws GeometryOperationNotSupportedException,
488
        GeometryOperationException {
489
        int index = geometryOperations.indexOf(geomOpName);
490
        GeometryOperation geomOp = getGeometryOperation(index);
491
        return geomOp.invoke(null, ctx);
492
    }
493

    
494
    public GeometryType unregisterGeometryType(Class geomClass) {
495
        return (GeometryType) geometryTypeName.remove(geomClass.getName());
496
    }
497

    
498
    public Envelope createEnvelope(int subType) {
499
        // TODO: register the envelopes!!!
500
        switch (subType) {
501
        case SUBTYPES.GEOM3D:
502
            return new Envelope3D();
503
        default:
504
            return new Envelope2D();
505
        }
506
    }
507

    
508
    public Envelope createEnvelope(double minX, double minY, double maxX,
509
        double maxY, int subType) throws CreateEnvelopeException {
510
        org.gvsig.fmap.geom.primitive.Point min = null;
511
        org.gvsig.fmap.geom.primitive.Point max = null;
512
        try {
513
            PointGeometryType gType = (PointGeometryType) getGeometryType(TYPES.POINT, subType);
514
            min = gType.createPoint(minX, minY);
515
            max = gType.createPoint(maxX, maxY);
516
        } catch (GeometryTypeNotSupportedException e) {
517
            throw new CreateEnvelopeException(subType, e);
518
        } catch (GeometryTypeNotValidException e) {
519
            throw new CreateEnvelopeException(subType, e);
520
        }
521
        switch (subType) {
522
        case SUBTYPES.GEOM2D:
523
        case SUBTYPES.GEOM2DM:
524
            // Small optimization to directly create an Envelope2D
525
            // return new Envelope2D(minX, minY, maxX, maxY);
526
            return new Envelope2D(min, max);
527
        default:
528
            Envelope envelope = createEnvelope(subType);
529
            envelope.setLowerCorner(min);
530
            envelope.setUpperCorner(max);
531
            return envelope;
532
        }
533
    }
534

    
535
    public MultiCurve createMultiCurve(GeneralPathX generalPathX, int subType)
536
    throws CreateGeometryException {
537
        if (subType != SUBTYPES.GEOM2D) {
538
            // FIXME Exception
539
            throw new UnsupportedOperationException();
540
        }
541
        MultiCurve multiCurve = (MultiCurve) create(TYPES.MULTICURVE, subType);
542
        PathIterator piter = generalPathX.getPathIterator(null);
543
        GeneralPathX tmpPath = null;
544
        Curve tmpCurve = null;
545
        double[] coords = new double[6];
546
        double[] first = new double[6];
547
        int type;
548
        while (!piter.isDone()) {
549
            type = piter.currentSegment(coords);
550
            switch (type) {
551
            case PathIterator.SEG_MOVETO:
552
                if (tmpPath != null) {
553
                    tmpCurve = createCurve(tmpPath, subType);
554
                    multiCurve.addCurve(tmpCurve);
555
                }
556
                System.arraycopy(coords, 0, first, 0, 2);
557
                tmpPath = new GeneralPathX(piter.getWindingRule());
558
                tmpPath.moveTo(coords[0], coords[1]);
559
                break;
560

    
561
            case PathIterator.SEG_LINETO:
562
                if (tmpPath == null) {
563
                    System.arraycopy(coords, 0, first, 0, 2);
564
                    tmpPath = new GeneralPathX(piter.getWindingRule());
565
                }
566
                tmpPath.lineTo(coords[0], coords[1]);
567
                break;
568

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

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

    
586
            case PathIterator.SEG_CLOSE:
587
                tmpPath.lineTo(first[0], first[1]);
588
                break;
589

    
590
            } // end switch
591

    
592
            piter.next();
593

    
594
        }
595
        if (tmpPath != null) {
596
            tmpCurve = createCurve(tmpPath, subType);
597
            multiCurve.addCurve(tmpCurve);
598
        }
599

    
600
        return multiCurve;
601

    
602
    }
603

    
604
    public MultiSurface createMultiSurface(GeneralPathX generalPathX,
605
        int subType) throws CreateGeometryException {
606
        if (subType != SUBTYPES.GEOM2D) {
607
            // FIXME Exception
608
            throw new UnsupportedOperationException();
609
        }
610
        MultiSurface multiSurface =
611
            (MultiSurface) create(TYPES.MULTISURFACE, subType);
612
        PathIterator piter = generalPathX.getPathIterator(null);
613
        GeneralPathX tmpPath = null;
614
        Surface tmpSurface = null;
615
        double[] coords = new double[6];
616
        double[] first = new double[6];
617
        int type;
618
        while (!piter.isDone()) {
619
            type = piter.currentSegment(coords);
620
            switch (type) {
621
            case PathIterator.SEG_MOVETO:
622
                if (tmpPath != null) {
623
                    tmpSurface = createSurface(tmpPath, subType);
624
                    multiSurface.addSurface(tmpSurface);
625
                }
626
                System.arraycopy(coords, 0, first, 0, 2);
627
                tmpPath = new GeneralPathX(piter.getWindingRule());
628
                tmpPath.moveTo(coords[0], coords[1]);
629

    
630
            case PathIterator.SEG_LINETO:
631
                if (tmpPath == null) {
632
                    System.arraycopy(coords, 0, first, 0, 2);
633
                    tmpPath = new GeneralPathX(piter.getWindingRule());
634
                }
635
                tmpPath.lineTo(coords[0], coords[1]);
636
                break;
637

    
638
            case PathIterator.SEG_QUADTO:
639
                if (tmpPath == null) {
640
                    System.arraycopy(coords, 0, first, 0, 2);
641
                    tmpPath = new GeneralPathX(piter.getWindingRule());
642
                }
643
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
644
                break;
645

    
646
            case PathIterator.SEG_CUBICTO:
647
                if (tmpPath == null) {
648
                    System.arraycopy(coords, 0, first, 0, 2);
649
                    tmpPath = new GeneralPathX(piter.getWindingRule());
650
                }
651
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3],
652
                    coords[4], coords[5]);
653
                break;
654

    
655
            case PathIterator.SEG_CLOSE:
656
                tmpPath.lineTo(first[0], first[1]);
657
                break;
658
            } // end switch
659

    
660
            piter.next();
661

    
662
        }
663
        if (tmpPath != null) {
664
            tmpSurface = createSurface(tmpPath, subType);
665
            multiSurface.addSurface(tmpSurface);
666
        }
667

    
668
        return multiSurface;
669

    
670
    }
671

    
672
    public int getGeometryOperationCode(String geomOpName) {
673
        if (geomOpName == null) {
674
            throw new IllegalArgumentException("geomOpName cannot be null.");
675
        }
676

    
677
        int index = geometryOperations.indexOf(geomOpName);
678
        if (index == -1) {
679
            geometryOperations.add(geomOpName);
680
            index = geometryOperations.indexOf(geomOpName);
681
        }
682
        return index;
683
    }
684

    
685
    public List getGeometryOperationNames() {
686
        List operations = new ArrayList();
687
        for (int i = 0; i < operations.size(); i++) {
688
            operations.add(geometryOperations.get(i));
689
        }
690
        return operations;
691
    }
692

    
693
    public double getFlatness() {
694
        return flatness;
695
    }
696

    
697
    public void setFlatness(double flatness) {
698
        this.flatness = flatness;
699
    }
700

    
701
    public Geometry createFrom(String wkt, String srs) throws GeometryException {
702
        FromWKTGeometryOperationContext context =
703
            new FromWKTGeometryOperationContext(wkt, srs);
704
        try {
705
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
706
        } catch (GeometryOperationNotSupportedException e) {
707
            throw new GeometryException(e);
708
        } catch (GeometryOperationException e) {
709
            throw new GeometryException(e);
710
        }
711
    }
712

    
713
    public Geometry createFrom(String wkt) throws GeometryException {
714
        FromWKTGeometryOperationContext context =
715
            new FromWKTGeometryOperationContext(wkt, null);
716
        try {
717
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
718
        } catch (GeometryOperationNotSupportedException e) {
719
            throw new GeometryException(e);
720
        } catch (GeometryOperationException e) {
721
            throw new GeometryException(e);
722
        }
723
    }
724

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