Statistics
| Revision:

root / tags / v2_0_0_Build_2050 / libraries / libFMap_geometries / src / org / gvsig / fmap / geom / impl / DefaultGeometryManager.java @ 38677

History | View | Annotate | Download (26 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.values().iterator();
155
        while (it.hasNext()) {
156
            GeometryType geometryType = (GeometryType) it.next();
157
            registerGeometryOperation(geomOpName, geomOp, geometryType);
158
        }
159

    
160
        return index;
161

    
162
    }
163

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

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

    
185
    public int registerGeometryOperationBySubtype(String geomOpName,
186
        GeometryOperation geomOp, int subType) {
187
        int code = -1;
188
        Iterator it = geometryTypeName.values().iterator();
189
        while (it.hasNext()) {
190
            GeometryType geometryType = (GeometryType) it.next();
191
            if ((subType == geometryType.getSubType())) {
192
                code =
193
                    registerGeometryOperation(geomOpName, geomOp, geometryType);
194
            }
195
        }
196
        return code;
197
    }    
198

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

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

    
227
    public GeometryType registerGeometryType(Class geomClass, String name,
228
        int type, int subType) {
229
        return registerGeometryType(geomClass, name, type, subType,
230
            new int[0], new int[0]);
231
    }    
232

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

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

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

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

    
301
        if (!Geometry.class.isAssignableFrom(geomClass)) {
302
            throw new IllegalArgumentException(geomClass.getName()
303
                + " must implement the Geometry interface");
304
        }
305

    
306
        // Check if it is registered
307
        GeometryType geomType = null;
308
        if (type >= geometryTypes.length || subType >= geometryTypes[0].length
309
            || (geomType = geometryTypes[type][subType]) == null) {
310
            geomType =
311
                new DefaultGeometryType(geomClass, name, type, subType,
312
                    superTypes, superSubTypes);
313
            registerGeometryType(geomType);
314
        }
315

    
316
        logger.debug("Class {} registered with name {}", geomClass,
317
            geomType.getName());
318

    
319
        return geomType;
320
    }
321

    
322
    public void registerGeometryType(GeometryType geometryType) {
323
        if (geometryType.getType() >= geometryTypes.length
324
            || geometryType.getSubType() >= geometryTypes[0].length) {
325

    
326
            // Recreate the geometry type matrix if the types
327
            // or subtypes don't fit
328
            int newTypesSize =
329
                geometryType.getType() < geometryTypes.length
330
                ? geometryTypes.length : geometryType.getType() + 1;
331
            int newSubTypesSize =
332
                geometryType.getSubType() < geometryTypes[0].length
333
                ? geometryTypes[0].length : geometryType.getSubType() + 1;
334
                GeometryType[][] newMatrix =
335
                    new GeometryType[newTypesSize][newSubTypesSize];
336

    
337
                for (int i = 0; i < geometryTypes.length; i++) {
338
                    System.arraycopy(geometryTypes[i], 0, newMatrix[i], 0,
339
                        geometryTypes[i].length);
340
                }
341
                geometryTypes = newMatrix;
342
        }
343

    
344
        geometryTypes[geometryType.getType()][geometryType.getSubType()] =
345
            geometryType;
346
        geometryTypeName.put(geometryType.getName(), geometryType);
347
    }
348

    
349
    public GeometryType registerGeometryType(Class geomClass, int type,
350
        int subType) {
351
        return registerGeometryType(geomClass, null, type, subType);
352
    }
353

    
354
    public GeometryType getGeometryType(int type, int subType)
355
    throws GeometryTypeNotSupportedException, GeometryTypeNotValidException {
356
        GeometryType gType = null;
357
        if (type >= geometryTypes.length || subType >= geometryTypes[0].length) {
358
            throw new GeometryTypeNotValidException(type, subType);
359
        }
360

    
361
        gType = geometryTypes[type][subType];
362

    
363
        if (gType == null) {
364
            throw new GeometryTypeNotSupportedException(type, subType);
365
        }
366

    
367
        return gType;
368
    }
369

    
370
    public Geometry create(GeometryType geomType)
371
    throws CreateGeometryException {
372
        return geomType.create();
373
    }
374

    
375
    public Geometry create(String name) throws CreateGeometryException {
376
        if (!geometryTypeName.containsKey(name)) {
377
            throw new IllegalArgumentException(name
378
                + " has not been registered yet.");
379
        }
380
        return ((GeometryType) geometryTypeName.get(name)).create();
381
    }
382

    
383
    public Geometry create(int type, int subType)
384
    throws CreateGeometryException {
385
        try {
386
            return getGeometryType(type, subType).create();
387
        } catch (GeometryException e) {
388
            throw new CreateGeometryException(type, subType, e);
389
        }
390
    }
391

    
392
    public Curve createCurve(GeneralPathX generalPathX, int subType)
393
    throws CreateGeometryException {
394
        Curve curve = (Curve) create(TYPES.CURVE, subType);
395
        curve.setGeneralPath(generalPathX);
396
        return curve;
397
    }
398

    
399
    public NullGeometry createNullGeometry(int subType)
400
    throws CreateGeometryException {
401
        NullGeometry nullGeom = (NullGeometry) create(TYPES.NULL, subType);
402
        return nullGeom;
403
    }
404

    
405
    public Point createPoint(double x, double y, int subType)
406
    throws CreateGeometryException {
407
        Point point = (Point) create(TYPES.POINT, subType);
408
        point.setX(x);
409
        point.setY(y);
410
        return point;
411
    }
412

    
413
    public Surface createSurface(GeneralPathX generalPathX, int subType)
414
    throws CreateGeometryException {
415
        Surface surface = (Surface) create(TYPES.SURFACE, subType);
416
        surface.setGeneralPath(generalPathX);
417
        return surface;
418
    }
419

    
420
    public GeometryOperation getGeometryOperation(int opCode, int type,
421
        int subType) throws GeometryTypeNotSupportedException,
422
        GeometryOperationNotSupportedException, GeometryTypeNotValidException {
423
        GeometryType geometryType = getGeometryType(type, subType);
424
        return geometryType.getGeometryOperation(opCode);
425
    }
426

    
427
    public GeometryOperation getGeometryOperation(int opCode)
428
        throws GeometryOperationNotSupportedException {
429
        if (opCode < 0) {
430
            throw new GeometryOperationNotSupportedException(opCode);
431
        }
432
        GeometryType type =
433
            (GeometryType) geometryTypeName.get(DefaultNullGeometry.class
434
                .getName());
435
        if (type == null) {
436
            throw new GeometryOperationNotSupportedException(opCode);
437
        }
438
        return type.getGeometryOperation(opCode);
439
    }
440

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

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

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

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

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

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

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

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

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

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

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

    
564
            case PathIterator.SEG_CLOSE:
565
                tmpPath.lineTo(first[0], first[1]);
566
                break;
567

    
568
            } // end switch
569

    
570
            piter.next();
571

    
572
        }
573
        if (tmpPath != null) {
574
            tmpCurve = createCurve(tmpPath, subType);
575
            multiCurve.addCurve(tmpCurve);
576
        }
577

    
578
        return multiCurve;
579

    
580
    }
581

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

    
608
            case PathIterator.SEG_LINETO:
609
                if (tmpPath == null) {
610
                    System.arraycopy(coords, 0, first, 0, 2);
611
                    tmpPath = new GeneralPathX(piter.getWindingRule());
612
                }
613
                tmpPath.lineTo(coords[0], coords[1]);
614
                break;
615

    
616
            case PathIterator.SEG_QUADTO:
617
                if (tmpPath == null) {
618
                    System.arraycopy(coords, 0, first, 0, 2);
619
                    tmpPath = new GeneralPathX(piter.getWindingRule());
620
                }
621
                tmpPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
622
                break;
623

    
624
            case PathIterator.SEG_CUBICTO:
625
                if (tmpPath == null) {
626
                    System.arraycopy(coords, 0, first, 0, 2);
627
                    tmpPath = new GeneralPathX(piter.getWindingRule());
628
                }
629
                tmpPath.curveTo(coords[0], coords[1], coords[2], coords[3],
630
                    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
    public int getGeometryOperationCode(String geomOpName) {
651
        if (geomOpName == null) {
652
            throw new IllegalArgumentException("geomOpName cannot be null.");
653
        }
654

    
655
        int index = geometryOperations.indexOf(geomOpName);
656
        if (index == -1) {
657
            geometryOperations.add(geomOpName);
658
            index = geometryOperations.indexOf(geomOpName);
659
        }
660
        return index;
661
    }
662

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

    
671
    public double getFlatness() {
672
        return flatness;
673
    }
674

    
675
    public void setFlatness(double flatness) {
676
        this.flatness = flatness;
677
    }
678

    
679
    public Geometry createFrom(String wkt, String srs) throws GeometryException {
680
        FromWKTGeometryOperationContext context =
681
            new FromWKTGeometryOperationContext(wkt, srs);
682
        try {
683
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
684
        } catch (GeometryOperationNotSupportedException e) {
685
            throw new GeometryException(e);
686
        } catch (GeometryOperationException e) {
687
            throw new GeometryException(e);
688
        }
689
    }
690

    
691
    public Geometry createFrom(String wkt) throws GeometryException {
692
        FromWKTGeometryOperationContext context =
693
            new FromWKTGeometryOperationContext(wkt, null);
694
        try {
695
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKT, context);
696
        } catch (GeometryOperationNotSupportedException e) {
697
            throw new GeometryException(e);
698
        } catch (GeometryOperationException e) {
699
            throw new GeometryException(e);
700
        }
701
    }
702

    
703
    public Geometry createFrom(byte[] wkb) throws GeometryException {
704
        GeometryOperationContext context = new GeometryOperationContext();
705
        context.setAttribute("data", wkb);
706
        try {
707
            return (Geometry) this.invokeOperation(OPERATIONS.FROMWKB, context);
708
        } catch (GeometryOperationNotSupportedException e) {
709
            throw new GeometryException(e);
710
        } catch (GeometryOperationException e) {
711
            throw new GeometryException(e);
712
        }
713
    }
714
}