Statistics
| Revision:

svn-gvsig-desktop / branches / v10 / extensions / extJDBC / src / com / iver / cit / gvsig / fmap / drivers / jdbc / oracle / OracleSpatialUtils.java @ 10152

History | View | Annotate | Download (58.2 KB)

1
package com.iver.cit.gvsig.fmap.drivers.jdbc.oracle;
2

    
3
import java.awt.geom.PathIterator;
4
import java.awt.geom.Point2D;
5
import java.io.BufferedReader;
6
import java.io.File;
7
import java.io.FileReader;
8
import java.lang.reflect.Array;
9
import java.net.URL;
10
import java.sql.Connection;
11
import java.sql.SQLException;
12
import java.text.DecimalFormat;
13
import java.text.DecimalFormatSymbols;
14
import java.util.ArrayList;
15
import java.util.Random;
16

    
17
import oracle.sql.ARRAY;
18
import oracle.sql.Datum;
19
import oracle.sql.NUMBER;
20
import oracle.sql.STRUCT;
21
import oracle.sql.StructDescriptor;
22

    
23
import org.apache.log4j.Logger;
24

    
25
import com.iver.cit.gvsig.fmap.core.FCircle2D;
26
import com.iver.cit.gvsig.fmap.core.FGeometryCollection;
27
import com.iver.cit.gvsig.fmap.core.FMultiPoint2D;
28
import com.iver.cit.gvsig.fmap.core.FMultipoint3D;
29
import com.iver.cit.gvsig.fmap.core.FPoint2D;
30
import com.iver.cit.gvsig.fmap.core.FPoint3D;
31
import com.iver.cit.gvsig.fmap.core.FPolygon2D;
32
import com.iver.cit.gvsig.fmap.core.FPolygon3D;
33
import com.iver.cit.gvsig.fmap.core.FPolyline3D;
34
import com.iver.cit.gvsig.fmap.core.FShape;
35
import com.iver.cit.gvsig.fmap.core.FShape3D;
36
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
37
import com.iver.cit.gvsig.fmap.core.IGeometry;
38
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
39
import com.vividsolutions.jts.algorithm.CGAlgorithms;
40
import com.vividsolutions.jts.geom.Coordinate;
41
import com.vividsolutions.jts.geom.CoordinateArrays;
42
import com.vividsolutions.jts.geom.Envelope;
43
import com.vividsolutions.jts.geom.GeometryFactory;
44
import com.vividsolutions.jts.geom.LineString;
45
import com.vividsolutions.jts.geom.LinearRing;
46
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
47

    
48
/**
49
 * Utility class with static methods.
50
 * 
51
 * @author jldominguez
52
 *
53
 */
54
public class OracleSpatialUtils {
55
        
56
        private static Logger logger = Logger.getLogger(OracleSpatialUtils.class.getName());
57
        
58
        private static double FLATNESS = 0.8;
59
        private static GeometryFactory geomFactory = new GeometryFactory();
60
        private static final double IRRELEVANT_DISTANCE = 0.00000001;
61
        private static Random rnd = new Random();
62
        private static DecimalFormat df = new DecimalFormat();
63
        private static DecimalFormatSymbols dfs = new DecimalFormatSymbols();
64
        
65

    
66
        public static IGeometry readGeometry3D(URL filepath, boolean polygon) {
67

    
68
                GeneralPathX resp = new GeneralPathX();
69
                File file = new File(filepath.getFile());
70
                ArrayList z = new ArrayList();
71

    
72
                try {
73

    
74
                        FileReader fr = new FileReader(file);
75
                        BufferedReader br = new BufferedReader(fr);
76
                        double[] coords = new double[3];
77
                        
78
                        boolean move = true;
79

    
80
                        String line = br.readLine();
81
                        while (line != null) {
82
                                coords = parseLine(line);
83
                                if (line.length() == 0) {
84
                                        move = true;
85
                                } else {
86
                                        if (move) {
87
                                                resp.moveTo(coords[0], coords[1]);
88
                                                z.add(new Double(coords[2]));
89
                                        } else {
90
                                                resp.lineTo(coords[0], coords[1]);
91
                                                z.add(new Double(coords[2]));
92
                                        }
93
                                        move = false;
94
                                }
95
                                line = br.readLine();
96
                        }
97
                } catch (Exception ex) {
98
                        System.err.println("Error while creating GeneralPathX: "
99
                                        + ex.getMessage());
100
                        return null;
101
                }
102
                
103
                double[] zz = new double[z.size()];
104
                for (int i=0; i<z.size(); i++) {
105
                        zz[i] = ((Double) z.get(i)).doubleValue();
106
                }
107
                
108
                if (polygon) {
109
                        return ShapeFactory.createPolygon3D(resp, zz);
110
                } else {
111
                        return ShapeFactory.createPolyline3D(resp, zz);
112
                }
113
                
114
        }
115

    
116
        private static double[] parseLine(String line) {
117
                String[] sep = line.split(" ");
118
                double[] resp = new double[3];
119

    
120
                for (int i = 0; i < 3; i++)
121
                        resp[i] = 0.0;
122

    
123
                try {
124
                        resp[0] = Double.parseDouble(sep[0]);
125
                } catch (Exception ex) {
126
                }
127

    
128
                if (sep.length > 1) {
129
                        try {
130
                                resp[1] = Double.parseDouble(sep[1]);
131
                        } catch (Exception ex) {
132
                        }
133
                        if (sep.length > 2) {
134
                                try {
135
                                        resp[2] = Double.parseDouble(sep[2]);
136
                                } catch (Exception ex) {
137
                                }
138
                        }
139
                }
140
                return resp;
141
        }
142
        
143
        
144
        public static STRUCT fShapeToSTRUCT(Object fshp, Connection c,
145
                        int srid, boolean agu_b, boolean hasSrid) throws SQLException {
146
                
147
                boolean three = false;
148
                if (fshp instanceof FShape3D) three = true;
149
                STRUCT resp = null;
150
                
151
                if (fshp instanceof FMultiPoint2D) {
152
                        resp = multiPoint2DToStruct((FMultiPoint2D) fshp, c, srid, hasSrid);
153
                        return resp;
154
                }
155

    
156
                if (!(fshp instanceof FShape)) {
157
                        logger.error("Unknown geometry: " + fshp.toString());
158
                        return null;
159
                }
160

    
161
                if (fshp instanceof FPoint2D) { // point 2/3d
162
                        
163
                        // resp = pointToWKT((FPoint2D) fshp, three);
164
                        Coordinate p = getSingleCoordinate((FPoint2D) fshp);
165
                        resp = getMultiPointAsStruct(p, srid, three, c, hasSrid);
166
                        
167
                } else {
168
                        if (fshp instanceof FPolygon2D) { // polygon 2/3d
169
                                if (fshp instanceof FCircle2D) {
170
                                        resp = getCircleAsStruct((FCircle2D) fshp, srid, c, hasSrid);
171
                                } else {
172
                                        // also FEllipse2D
173
                                        resp = getMultiPolygonAsStruct((FShape) fshp, srid, three, c,
174
                                                        agu_b, hasSrid);
175
                                        // ArrayList polys = getPolygonsEasily(fshp);
176
                                        // resp = getMultiPolygonAsStruct(polys, srid, three, c);
177
                                        }
178
                        } else { // line 2/3d
179
                                ArrayList _lines = getLineStrings((FShape) fshp);
180
                                resp = getMultiLineAsStruct(_lines, srid, three, c, hasSrid);
181
                        }
182
                }
183

    
184
                return resp;
185
        }
186

    
187
        private static STRUCT multiPoint2DToStruct(FMultiPoint2D mp2d,
188
                        Connection c, int srid, boolean hasSrid) throws SQLException {
189
                
190
                int np = mp2d.getNumPoints();
191
                boolean threed = (mp2d instanceof FMultipoint3D);
192
                int gtype = 2005;
193
                int dim = 2;
194
                FMultipoint3D mp3d = null;
195
                if (threed) {
196
                        gtype = 3005;
197
                        dim = 3;
198
                        mp3d = (FMultipoint3D) mp2d;
199
                }
200
                
201
                NUMBER[] indices = new NUMBER[3];
202
                indices[0] = new NUMBER(1);
203
                indices[1] = new NUMBER(1);
204
                indices[2] = new NUMBER(np);
205

    
206
                NUMBER[] ords = new NUMBER[dim * np];
207
                for (int i=0; i<np; i++) {
208
                        ords[dim * i] =     new NUMBER(mp2d.getPoint(i).getX());
209
                        ords[dim * i + 1] = new NUMBER(mp2d.getPoint(i).getY());
210
                        if (threed) {
211
                                ords[dim * i + 2] = new NUMBER(mp3d.getZs()[i]);
212
                        }
213
                }
214

    
215
                STRUCT resp;
216
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", c);
217
                Object[] obj = new Object[5];
218
                obj[0] = new NUMBER(gtype);
219
                
220
                if (hasSrid) {
221
                        obj[1] = new NUMBER(srid);
222
                } else { // , boolean hasSrid
223
                        obj[1] = null;
224
                }
225
                
226
                obj[2] = null;
227
                obj[3] = indices;
228
                obj[4] = ords;
229
                resp = new STRUCT(dsc, c, obj);
230

    
231
                return resp;
232
        }
233

    
234
        private static STRUCT getCircleAsStruct(FCircle2D fcirc,
235
                        int srid, Connection _conn, boolean hasSrid) throws SQLException {
236
                int geotype = 2003;
237
                NUMBER[] indices = new NUMBER[3];
238
                indices[0] = new NUMBER(1);
239
                indices[1] = new NUMBER(1003);
240
                indices[2] = new NUMBER(4);
241

    
242
                NUMBER[] ords = new NUMBER[6];
243
                Coordinate[] three_points = getThreePointsOfCircumference(fcirc.getCenter(), fcirc.getRadio());
244
                for (int i=0; i<three_points.length; i++) {
245
                        ords[i*2] = new NUMBER(three_points[i].x);
246
                        ords[i*2 + 1] = new NUMBER(three_points[i].y);
247
                }
248
                STRUCT resp;
249
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", _conn);
250
                Object[] obj = new Object[5];
251
                obj[0] = new NUMBER(geotype);
252
                
253
                if (hasSrid) {
254
                        obj[1] = new NUMBER(srid);
255
                } else {
256
                        obj[1] = null;
257
                }
258
                
259
                obj[2] = null;
260
                obj[3] = indices;
261
                obj[4] = ords;
262
                resp = new STRUCT(dsc, _conn, obj);
263
                return resp;
264
        }
265

    
266
        private static Coordinate[] getThreePointsOfCircumference(Point2D cntr, double radius) {
267
                
268
                Coordinate[] resp = new Coordinate[3];
269
                double x, y, alpha = 0;
270
                for (int i=0; i<3; i++) {
271
                        alpha  = i * 120.0 * Math.PI / 180.0;
272
                        x = cntr.getX() + radius * Math.cos(alpha);
273
                        y = cntr.getY() + radius * Math.sin(alpha);
274
                        resp[i] = new Coordinate(x, y);
275
                }
276
                return resp;
277
        }
278

    
279
        private static Coordinate getSingleCoordinate(FPoint2D p2d) {
280
                // TODO Auto-generated method stub
281
                Coordinate resp = new Coordinate();
282
                resp.x = p2d.getX();
283
                resp.y = p2d.getY();
284
                if (p2d instanceof FPoint3D) {
285
                        resp.z = ((FPoint3D) p2d).getZs()[0];
286
                }
287
                return resp;
288
        }
289

    
290
        private static ArrayList ensureSensibleLineString(ArrayList cc) {
291
                if (cc.size() == 2) {
292
                        if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(cc
293
                                        .size() - 1))) {
294
                                ArrayList resp = new ArrayList();
295
                                resp.add(cc.get(0));
296
                                Coordinate newc = new Coordinate((Coordinate) cc.get(0));
297
                                newc.x = newc.x + IRRELEVANT_DISTANCE;
298
                                resp.add(newc);
299
                                return resp;
300
                        }
301
                }
302
                return cc;
303
        }
304
        
305
        private static boolean sameCoordinate(Coordinate c1, Coordinate c2) {
306
                if (c1.x != c2.x) {
307
                        return false;
308
                }
309
                if (c1.y != c2.y) {
310
                        return false;
311
                }
312
                return true;
313
        }
314

    
315
        
316

    
317
        private static ArrayList getClosedRelevantPolygon(ArrayList cc) {
318
                if (cc.size() == 2) {
319
                        return getMinClosedCoords((Coordinate) cc.get(0));
320
                }
321
                if (cc.size() == 3) {
322
                        if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(1)))
323
                                return getMinClosedCoords((Coordinate) cc.get(0));
324
                        if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(2)))
325
                                return getMinClosedCoords((Coordinate) cc.get(0));
326
                        if (sameCoordinate((Coordinate) cc.get(1), (Coordinate) cc.get(2)))
327
                                return getMinClosedCoords((Coordinate) cc.get(1));
328
                        cc.add(cc.get(0));
329
                        return cc;
330
                }
331
                if (!sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(cc
332
                                .size() - 1))) {
333
                        cc.add(cc.get(0));
334
                }
335
                return cc;
336
        }
337

    
338
        private static ArrayList getMinClosedCoords(Coordinate c) {
339
                
340
                ArrayList resp = new ArrayList();
341
                resp.add(c);
342
                
343
                Coordinate nc = new Coordinate(c);
344
                nc.x = nc.x + IRRELEVANT_DISTANCE;
345
                resp.add(nc);
346
                
347
                Coordinate nc2 = new Coordinate(nc);
348
                nc2.y = nc2.y + IRRELEVANT_DISTANCE;
349
                resp.add(nc2);
350
                
351
                resp.add(new Coordinate(c));
352
                
353
                return resp;
354
        }
355
        
356
        private static LinearRing getMinLinearRing(Coordinate c) {
357
                Coordinate[] p = new Coordinate[4];
358
                p[0] = c;
359
                Coordinate nc = new Coordinate(c);
360
                nc.x = nc.x + IRRELEVANT_DISTANCE;
361
                Coordinate nc2 = new Coordinate(nc);
362
                nc2.y = nc2.y - IRRELEVANT_DISTANCE;
363
                p[1] = nc;
364
                p[2] = nc2;
365
                p[3] = new Coordinate(c);
366
                CoordinateArraySequence cs = new CoordinateArraySequence(p);
367
                LinearRing ls = new LinearRing(cs, geomFactory);
368
                return ls;
369
        }
370
        
371
        private static double[] getMinLinearRingZ() {
372
                double[] resp = new double[4];
373
                for (int i=0; i<4; i++) resp[i] = 0.0;
374
                return resp;
375
        }
376
        
377
        
378
        
379
        private static boolean pointInList(Coordinate testPoint, Coordinate[] pointList) {
380
                int t;
381
                int numpoints;
382
                Coordinate p;
383

    
384
                numpoints = Array.getLength(pointList);
385

    
386
                for (t = 0; t < numpoints; t++) {
387
                        p = pointList[t];
388

    
389
                        if ((testPoint.x == p.x)
390
                                        && (testPoint.y == p.y)
391
                                        && ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
392
                        ) {
393
                                return true;
394
                        }
395
                }
396

    
397
                return false;
398
        }
399
        
400
        /*
401
        private static Object[] getHolesForShells(FShape mpolygon) {
402
                
403
                boolean threed = false;
404
                if (mpolygon instanceof FPolygon3D) {
405
                        threed = true;
406
                }
407
                
408
                int start_ind = 0;
409
                int end_ind = 0;
410
                int ind = 0;
411
                int new_size;
412

413
                ArrayList arrayCoords = null;
414
                ArrayList shells = new ArrayList();
415
                ArrayList holes = new ArrayList();
416
                Coordinate[] points = null;
417
                int theType = -99;
418
                double[] theData = new double[6];
419
                Coordinate onlyCoord = null;
420
                int numParts = 0;
421
                Object[] resp = new Object[2];
422

423
                PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS);
424

425
                while (!theIterator.isDone()) {
426
                        //while not done
427
                        theType = theIterator.currentSegment(theData);
428

429
                        if (onlyCoord == null) {
430
                                onlyCoord = new Coordinate();
431
                                onlyCoord.x = theData[0];
432
                                onlyCoord.y = theData[1];
433
                        }
434

435
                        switch (theType) {
436
                        case PathIterator.SEG_MOVETO:
437
                                if (arrayCoords == null) {
438
                                        
439
                                        arrayCoords = new ArrayList();
440
                                        
441
                                } else {
442
                                        end_ind = ind - 1;
443
                                        
444
                                        arrayCoords = getClosedRelevantPolygon(arrayCoords);
445
                                        new_size = arrayCoords.size();
446

447
                                        if (arrayCoords != null) {
448
                                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
449
                                                try {
450
                                                        LinearRing aux = geomFactory.createLinearRing(points);
451
                                                        double[] z = null;
452
                                                        if (threed) {
453
                                                                z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size);
454
                                                        }
455
                                                        LineString3D ring = new LineString3D(aux, z);
456
                                                        
457
                                                        if (CGAlgorithms.isCCW(points)) {
458
                                                                holes.add(ring);
459
                                                        } else {
460
                                                                shells.add(ring);
461
                                                        }
462
                                                } catch (Exception e) {
463
                                                        System.err.println("Topology exception: "
464
                                                                        + e.getMessage());
465
                                                        return null;
466
                                                }
467
                                        }
468
                                        arrayCoords = new ArrayList();
469
                                        
470
                                        start_ind = ind;
471
                                }
472
                                numParts++;
473
                                
474
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
475
                                ind++;
476
                                break;
477

478
                        case PathIterator.SEG_LINETO:
479
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
480
                                ind++;
481
                                break;
482

483
                        case PathIterator.SEG_QUADTO:
484
                                System.out.println("SEG_QUADTO Not supported here");
485
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
486
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
487
                                ind++; ind++;
488
                                break;
489

490
                        case PathIterator.SEG_CUBICTO:
491
                                System.out.println("SEG_CUBICTO Not supported here");
492
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
493
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
494
                                arrayCoords.add(new Coordinate(theData[4], theData[5]));
495
                                ind++; ind++; ind++;
496
                                break;
497

498
                        case PathIterator.SEG_CLOSE:
499
                                // Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
500
                                // arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
501
                                break;
502
                        } //end switch
503
                        theIterator.next();
504
                        
505
                } //end while loop
506

507
                end_ind = ind - 1;
508
                arrayCoords = getClosedRelevantPolygon(arrayCoords);
509
                new_size = arrayCoords.size();
510

511
                if (arrayCoords != null) {
512
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
513
                        try {
514
                                LinearRing aux = geomFactory.createLinearRing(points);
515
                                double[] z = null;
516
                                if (threed) {
517
                                        z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size);
518
                                }
519
                                LineString3D ring = new LineString3D(aux, z);
520
                                if (CGAlgorithms.isCCW(points)) {
521
                                        holes.add(ring);
522
                                } else {
523
                                        shells.add(ring);
524
                                }
525
                        } catch (Exception e) {
526
                                System.err.println("Topology exception: " + e.getMessage());
527
                                return null;
528
                        }
529
                }
530
                
531
                ArrayList holesForShells = new ArrayList(shells.size());
532

533
                if ((shells.size() == 0) && (holes.size() == 0)) {
534
                        shells.add(new LineString3D(getMinLinearRing(onlyCoord), getMinLinearRingZ()));
535
                        ArrayList inarray = new ArrayList();
536
                        inarray.add(new ArrayList());
537
                        holesForShells.add(inarray);
538
                        resp[0] = shells;
539
                        resp[1] = holesForShells;
540
                        return resp;
541
                }
542

543
                if ((shells.size() == 0) && (holes.size() > 0)) {
544
                        shells.addAll(holes); holes.clear();
545
                        ArrayList inarray = new ArrayList();
546
                        for (int i=0; i<shells.size(); i++) inarray.add(new ArrayList());
547
                        holesForShells.add(inarray);
548
                        resp[0] = shells;
549
                        resp[1] = holesForShells;
550
                        return resp;
551
                }
552

553
                for (int i = 0; i < shells.size(); i++) {
554
                        holesForShells.add(new ArrayList());
555
                }
556

557
                // find homes
558
                for (int i = 0; i < holes.size(); i++) {
559
                        LineString3D testRing = (LineString3D) holes.get(i);
560
                        LineString3D minShell = null;
561
                        Envelope minEnv = null;
562
                        Envelope testEnv = testRing.getLs().getEnvelopeInternal();
563
                        Coordinate testPt = testRing.getLs().getCoordinateN(0);
564
                        LineString3D tryRing = null;
565

566
                        for (int j = 0; j < shells.size(); j++) {
567
                                tryRing = (LineString3D) shells.get(j);
568
                                Envelope tryEnv = tryRing.getLs().getEnvelopeInternal();
569
                                if (minShell != null) {
570
                                        minEnv = minShell.getLs().getEnvelopeInternal();
571
                                }
572

573
                                boolean isContained = false;
574
                                Coordinate[] coordList = tryRing.getLs().getCoordinates();
575
                                if (tryEnv.contains(testEnv)
576
                                                && (CGAlgorithms.isPointInRing(testPt, coordList) || (pointInList(
577
                                                                testPt, coordList)))) {
578
                                        isContained = true;
579
                                }
580

581
                                // check if this new containing ring is smaller than the current minimum ring
582
                                if (isContained) {
583
                                        if ((minShell == null) || minEnv.contains(tryEnv)) {
584
                                                minShell = tryRing;
585
                                        }
586
                                }
587
                        }
588

589
                        if (minShell == null) {
590
                                System.out
591
                                                .println("polygon found with a hole thats not inside a shell");
592
                                //azabala: we do the assumption that this hole is really a shell (polygon)
593
                                //whose point werent digitized in the right order
594
                                Coordinate[] cs = testRing.getLs().getCoordinates();
595
                                double[] reversez = reverseArray(testRing.getZc());
596
                                Coordinate[] reversed = new Coordinate[cs.length];
597
                                int pointIndex = 0;
598
                                for (int z = cs.length - 1; z >= 0; z--) {
599
                                        reversed[pointIndex] = cs[z];
600
                                        pointIndex++;
601
                                }
602
                                LineString3D newRing = new LineString3D(geomFactory.createLinearRing(reversed), reversez);
603
                                shells.add(newRing);
604
                                holesForShells.add(new ArrayList());
605
                        } else {
606
                                ((ArrayList) holesForShells.get(shells.indexOf(minShell)))
607
                                                .add(testRing);
608
                        }
609
                }
610
                resp[0] = shells;
611
                resp[1] = holesForShells;
612
                return resp;
613
        }
614
        */
615
        
616
        private static ArrayList getPolygonsEasily(FShape mpolygon) {
617
                
618
                boolean threed = false;
619
                if (mpolygon instanceof FPolygon3D) {
620
                        threed = true;
621
                }
622
                
623
                int start_ind = 0;
624
                int end_ind = 0;
625
                int ind = 0;
626
                int new_size;
627
                ArrayList arrayCoords = null;
628
                ArrayList resp = new ArrayList();
629
                Coordinate[] points = null;
630
                int theType = -99;
631
                double[] theData = new double[6];
632
                Coordinate onlyCoord = null;
633
                int numParts = 0;
634

    
635
                PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS);
636

    
637
                while (!theIterator.isDone()) {
638
                        //while not done
639
                        theType = theIterator.currentSegment(theData);
640

    
641
                        if (onlyCoord == null) {
642
                                onlyCoord = new Coordinate();
643
                                onlyCoord.x = theData[0];
644
                                onlyCoord.y = theData[1];
645
                        }
646

    
647
                        switch (theType) {
648
                        case PathIterator.SEG_MOVETO:
649
                                if (arrayCoords == null) {
650
                                        
651
                                        arrayCoords = new ArrayList();
652
                                        
653
                                } else {
654
                                        end_ind = ind - 1;
655
                                        
656
                                        arrayCoords = getClosedRelevantPolygon(arrayCoords);
657
                                        new_size = arrayCoords.size();
658
                                        if (arrayCoords != null) {
659
                                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
660
                                                try {
661
                                                        LinearRing aux = geomFactory.createLinearRing(points);
662
                                                        double[] z = null;
663
                                                        if (threed) {
664
                                                                z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size);
665
                                                        }
666
                                                        LineString3D ring = new LineString3D(aux, z);
667
                                                        
668
                                                        if (CGAlgorithms.isCCW(points)) {
669
                                                                resp.add(ring);
670
                                                        } else {
671
                                                                resp.add(ring.createReverse());
672
                                                        }
673
                                                } catch (Exception e) {
674
                                                        System.err.println("Topology exception: "
675
                                                                        + e.getMessage());
676
                                                        return null;
677
                                                }
678
                                        }
679
                                        arrayCoords = new ArrayList();
680
                                        
681
                                        start_ind = ind;
682
                                }
683
                                numParts++;
684
                                
685
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
686
                                ind++;
687
                                break;
688

    
689
                        case PathIterator.SEG_LINETO:
690
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
691
                                ind++;
692
                                break;
693

    
694
                        case PathIterator.SEG_QUADTO:
695
                                System.out.println("SEG_QUADTO Not supported here");
696
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
697
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
698
                                ind++; ind++;
699
                                break;
700

    
701
                        case PathIterator.SEG_CUBICTO:
702
                                System.out.println("SEG_CUBICTO Not supported here");
703
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
704
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
705
                                arrayCoords.add(new Coordinate(theData[4], theData[5]));
706
                                ind++; ind++; ind++;
707
                                break;
708

    
709
                        case PathIterator.SEG_CLOSE:
710
                                // Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
711
                                // arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
712
                                break;
713
                        } //end switch
714
                        theIterator.next();
715
                        
716
                } //end while loop
717

    
718
                end_ind = ind - 1;
719
                
720
                // null shape:
721
                if (arrayCoords == null) {
722
                        arrayCoords = new ArrayList();
723
                        Coordinate _c = new Coordinate(0, 0, 0);
724
                        arrayCoords.add(new Coordinate(_c));
725
                        arrayCoords.add(new Coordinate(_c));
726
                }
727
                // --------------------------------------------
728
                
729
                arrayCoords = getClosedRelevantPolygon(arrayCoords);
730
                new_size = arrayCoords.size();
731

    
732
                if (arrayCoords != null) {
733
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
734
                        try {
735
                                LinearRing aux = geomFactory.createLinearRing(points);
736
                                double[] z = null;
737
                                if (threed) {
738
                                        z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size);
739
                                }
740
                                LineString3D ring = new LineString3D(aux, z);
741
                                if (CGAlgorithms.isCCW(points)) {
742
                                        resp.add(ring);
743
                                } else {
744
                                        resp.add(ring.createReverse());
745
                                }
746
                        } catch (Exception e) {
747
                                System.err.println("Topology exception: " + e.getMessage());
748
                                return null;
749
                        }
750
                }
751
                if (resp.size() == 0) {
752
                        resp.add(new LineString3D(getMinLinearRing(onlyCoord), getMinLinearRingZ()));
753
                }
754
                return resp;
755
        }
756

    
757
        public static double[] reverseArray(double[] _z) {
758
                int size = _z.length;
759
                double[] resp = new double[size];
760
                for (int i=0; i<size; i++) {
761
                        resp[i] = _z[size - 1 - i];
762
                }
763
                return resp;
764
        }
765

    
766
        public static Coordinate[] reverseCoordinateArray(Coordinate[] _z) {
767
                int size = _z.length;
768
                Coordinate[] resp = new Coordinate[size];
769
                for (int i=0; i<size; i++) {
770
                        resp[i] = _z[size - 1 - i];
771
                }
772
                return resp;
773
        }
774

    
775
        private static double[] getZ(FShape3D p3d, int _str, int _end, int size) {
776
                
777
                double[] resp = new double[size];
778
                double[] allz = p3d.getZs();
779
                for (int i=_str; ((i<=_end) && ((i-_str)<size)); i++) {
780
                        resp[i - _str] = allz[i]; 
781
                }
782
                if ((_end - _str + 1) < size) {
783
                        double repe = allz[_end];
784
                        for (int i=(_end - _str + 1); i<size; i++) {
785
                                resp[i] = repe;
786
                        }
787
                }
788
                return resp;
789
        }
790

    
791
        private static ArrayList getLineStrings(FShape mlines) {
792
                
793
                boolean threed = false;
794
                if (mlines instanceof FPolyline3D) {
795
                        threed = true;
796
                }
797
                
798
                int start_ind = 0;
799
                int end_ind = 0;
800
                int ind = 0;
801
                int new_size = 0;
802

    
803
                LineString3D lin;
804
                
805
                ArrayList arrayLines = new ArrayList();
806
                PathIterator theIterator = mlines.getPathIterator(null, FLATNESS);
807
                int theType = -99;
808
                double[] theData = new double[6];
809
                ArrayList arrayCoords = null;
810
                int numParts = 0;
811

    
812
                while (!theIterator.isDone()) {
813
                        //while not done
814
                        theType = theIterator.currentSegment(theData);
815

    
816
                        switch (theType) {
817
                        case PathIterator.SEG_MOVETO:
818

    
819
                                // System.out.println("SEG_MOVETO");
820
                                if (arrayCoords == null) {
821
                                        arrayCoords = new ArrayList();
822
                                } else {
823
                                        end_ind = ind - 1;
824
                                        arrayCoords = ensureSensibleLineString(arrayCoords);
825
                                        new_size = arrayCoords.size();
826
                                        
827
                                        LineString aux = geomFactory.createLineString(CoordinateArrays
828
                                                        .toCoordinateArray(arrayCoords));
829
                                        double[] z = null;
830
                                        if (threed) {
831
                                                z = getZ((FPolyline3D) mlines, start_ind, end_ind, new_size);
832
                                        }
833
                                        lin = new LineString3D(aux, z);
834
                                        arrayLines.add(lin);
835
                                        arrayCoords = new ArrayList();
836
                                        
837
                                        start_ind = ind;
838
                                }
839
                                numParts++;
840
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
841
                                break;
842

    
843
                        case PathIterator.SEG_LINETO:
844
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
845
                                break;
846

    
847
                        case PathIterator.SEG_QUADTO:
848
                                System.out.println("Not supported here");
849
                                break;
850

    
851
                        case PathIterator.SEG_CUBICTO:
852
                                System.out.println("Not supported here");
853
                                break;
854

    
855
                        case PathIterator.SEG_CLOSE:
856
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
857
                                arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
858
                                break;
859
                        } //end switch
860

    
861
                        theIterator.next();
862
                        ind++;
863
                } //end while loop
864

    
865
                arrayCoords = ensureSensibleLineString(arrayCoords);
866
                new_size = arrayCoords.size();
867
                LineString aux = geomFactory.createLineString(CoordinateArrays
868
                                .toCoordinateArray(arrayCoords));
869
                double[] z = null;
870
                if (threed) {
871
                        z = getZ((FPolyline3D) mlines, start_ind, end_ind, new_size);
872
                }
873
                lin = new LineString3D(aux, z);
874
                arrayLines.add(lin);
875
                return arrayLines;
876
        }
877
        
878
        private static String lineStringToWKT(LineString3D ls, boolean threed) {
879
                
880
                String resp = "(";
881
                Coordinate[] cc = ls.getLs().getCoordinates();
882
                double[] z = ls.getZc();
883
                int size = cc.length;
884
                if (threed) {
885
                        for (int i=0; i<size; i++) {
886
                                resp = resp + cc[i].x + " " + cc[i].y + " " + z[i] + ", ";
887
                        }
888
                        resp = resp.substring(0, resp.length() - 2);
889
                        resp = resp + ")";
890
                } else {
891
                        for (int i=0; i<size; i++) {
892
                                resp = resp + cc[i].x + " " + cc[i].y + ", ";
893
                        }
894
                        resp = resp.substring(0, resp.length() - 2);
895
                        resp = resp + ")";
896
                }
897
                return resp;
898
        }
899
        
900
        private static String multiLineStringToWKT(ArrayList ml, boolean threed) {
901
                
902
                String resp = "MULTILINESTRING(";
903
                for (int i=0; i<ml.size(); i++) {
904
                        LineString3D ls = (LineString3D) ml.get(i);
905
                        resp = resp + lineStringToWKT(ls, threed) + ", ";
906
                }
907
                resp = resp.substring(0, resp.length() - 2) + ")";
908
                return resp;
909
        }
910
        
911
        private static String polygonsToWKT(ArrayList pols, boolean threed) {
912
                
913
                String resp = "MULTIPOLYGON(";
914
                LineString3D ls = null;
915
                for (int i=0; i<pols.size(); i++) {
916
                        ls = (LineString3D) pols.get(i);
917
                        resp = resp + "(" + lineStringToWKT(ls, threed) + "), ";
918
                }
919
                resp = resp.substring(0, resp.length() - 2) + ")";
920
                return resp;
921
        }
922
        
923
        private static String shellAndHolesToWKT(LineString3D shell, ArrayList holes, boolean threed) {
924

    
925
                String resp = "(";
926
                resp = resp + lineStringToWKT(shell, threed);
927
                if (holes.size() > 0) {
928
                        for (int i=0; i<holes.size(); i++) {
929
                                LineString3D ls = (LineString3D) holes.get(i);
930
                                resp = resp + ", " + lineStringToWKT(ls, threed);
931
                        }
932
                }
933
                resp = resp + ")";
934
                return resp;
935
        }
936
        
937
        private static String multiPolygonToWKT(ArrayList shells, ArrayList hFs, boolean threed) {
938
                
939
                String resp = "MULTIPOLYGON(";
940
                LineString3D ls = null;
941
                ArrayList holes;
942
                for (int i=0; i<shells.size(); i++) {
943
                        ls = (LineString3D) shells.get(i);
944
                        holes = (ArrayList) hFs.get(i);
945
                        resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
946
                }
947
                resp = resp.substring(0, resp.length() - 2) + ")";
948
                return resp;
949
        }
950
        
951
        private static String pointToWKT(FPoint2D point, boolean threed) {
952
                String resp = "POINT(" + point.getX() + " " + point.getY();
953
                if ((threed) && (point instanceof FPoint3D)) {
954
                        resp = resp + " " + ((FPoint3D) point).getZs()[0];
955
                }
956
                resp = resp + ")";
957
                return resp;
958
        }
959
        
960
        /*
961
        public static STRUCT addRandomDims(STRUCT st, int dims) {
962
                try {
963
                        ARRAY old_ord_array = (ARRAY) st.getAttributes()[4];
964
                        ARRAY new_ord_array = addRandomDims(old_ord_array, dims);
965
                        NUMBER oldtype = (NUMBER) st.getOracleAttributes()[0];
966
                        NUMBER newtype = new NUMBER((dims * 1000) + (oldtype.intValue() % 10));
967
                        Object[] newstruct = new Object[5];
968
                        newstruct[0] = newtype;
969
                        newstruct[1] = st.getAttributes()[1];
970
                        newstruct[2] = null;
971
                        
972
                        // -------------------
973
                        ARRAY old_info = (ARRAY) st.getAttributes()[3];
974
                        newstruct[3] = old_info;
975
                        if (old_info.length() > 3) {
976
                                ARRAY new_info = setSubelementsToDim(old_info, dims);
977
                                newstruct[3] = new_info;
978
                        } else {
979
                                newstruct[3] = old_info;
980
                        }
981
                        newstruct[4] = new_ord_array;
982
                        STRUCT resp = new STRUCT(st.getDescriptor(), st.getOracleConnection(), newstruct);
983
                        return resp;
984
                } catch (SQLException ex) {
985
                }
986
                return null;
987
        }
988
        */
989
        
990
        private static int twoDIndexToDimsIndex(int n, int d) {
991
                return (d * (n - 1) / 2) + 1;
992
        }
993
        
994
        private static ARRAY setSubelementsToDim(ARRAY old, int d) throws SQLException {
995
                Datum[] infos = (Datum[]) old.getOracleArray();
996
                for (int i=3; i<infos.length; i=i+3) {
997
                        int oldind = infos[i].intValue();
998
                        oldind = twoDIndexToDimsIndex(oldind, d);
999
                        infos[i] = new NUMBER(oldind);
1000
                        // 
1001
                        oldind = infos[i+1].intValue();
1002
                        infos[i+1] = new NUMBER(infos[1].intValue());
1003
                }
1004
                ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(), infos);
1005
                return resp;
1006
        }
1007

    
1008
        /*
1009
        private static ARRAY addRandomDims(ARRAY ord_array, int d) {
1010
                try {
1011
                        // ARRAY resp = new ARRAY();
1012
                        int sizebase = ord_array.length() / 2;
1013
                        BigDecimal[] oldcoords = (BigDecimal[]) ord_array.getArray();
1014
                        BigDecimal[] newcoords = new BigDecimal[d * sizebase];
1015
                        for (int i=0; i<sizebase; i++) {
1016
                                newcoords[i*d    ] = oldcoords[i*2    ];
1017
                                newcoords[i*d + 1] = oldcoords[i*2 + 1];
1018
                                for (int j=0; j<(d-2); j++) {
1019
                                        newcoords[i*d + 2 + j] = new BigDecimal(10.0);
1020
                                }
1021
                        }
1022
                        ARRAY resp =
1023
                                new ARRAY(ord_array.getDescriptor(), ord_array.getOracleConnection(), newcoords);
1024
                        return resp;
1025
                } catch (SQLException ex) {
1026
                        
1027
                }
1028
                return null;
1029
        }
1030
        */
1031
        
1032
        private static boolean isPointInsideLineString(Coordinate p, LineString ls) {
1033
                Envelope env = ls.getEnvelopeInternal();
1034
                if (!env.contains(p)) {
1035
                        return false;
1036
                }
1037
                return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
1038
        }
1039
        
1040
        private static boolean lineString3DIsContainedBy(LineString3D contained, LineString3D container) {
1041
                
1042
                int samples = 10;
1043
                LineString _in = contained.getLs();
1044
                LineString _out = container.getLs();
1045
                Coordinate[] inc = _in.getCoordinates();
1046
                Coordinate aux;
1047
                int size = inc.length;
1048
                if (size <= 10) {
1049
                        for (int i=0; i<size; i++) {
1050
                                aux = inc[i];
1051
                                if (!isPointInsideLineString(aux, _out)) return false;
1052
                        }
1053
                        return true;
1054
                } else {
1055
                        for (int i=0; i<samples; i++) {
1056
                                aux = inc[rnd.nextInt(size)];
1057
                                if (!isPointInsideLineString(aux, _out)) return false;
1058
                        }
1059
                        return true;
1060
                }
1061
        }
1062
        
1063
        private static STRUCT getMultiPolygonAsStruct(ArrayList pols,
1064
                        int srid, boolean threed, Connection _conn, boolean agu_bien,
1065
                        boolean hasSrid) throws SQLException {
1066
                
1067
                int size = pols.size();
1068
                int geotype = 2007;
1069
                int dim = 2;
1070
                int acum = 0;
1071
                if (threed) {
1072
                        geotype = 3007;
1073
                        dim = 3;
1074
                }
1075
                NUMBER[] indices = new NUMBER[3 * size];
1076
                
1077
                for (int i=0; i<size; i++) {
1078
                        indices[3 * i] = new NUMBER(acum + 1);
1079
                        indices[3 * i + 1] = new NUMBER(1003);
1080
                        indices[3 * i + 2] = new NUMBER(1);
1081
                        acum = acum + dim * ((LineString3D) pols.get(i)).getLs().getNumPoints();
1082
                }
1083
                
1084
                int _ind = 0;
1085
                NUMBER[] ords = new NUMBER[acum];
1086
                for (int i=0; i<size; i++) {
1087
                        LineString3D ls = (LineString3D) pols.get(i);
1088
                        int num_p = ls.getLs().getNumPoints();
1089
                        for (int j=0; j<num_p; j++) {
1090
                                ords[_ind] =     new NUMBER(ls.getLs().getCoordinateN(j).x);
1091
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1092
                                if (threed) {
1093
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1094
                                }
1095
                                _ind = _ind + dim;
1096
                        }
1097
                }
1098
                
1099
                STRUCT resp;
1100
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", _conn);
1101
                Object[] obj = new Object[5];
1102
                obj[0] = new NUMBER(geotype);
1103
                if (hasSrid) {
1104
                        obj[1] = new NUMBER(srid);
1105
                } else {
1106
                        obj[1] = null;
1107
                }
1108
                
1109
                obj[2] = null;
1110
                obj[3] = indices;
1111
                obj[4] = ords;
1112
                resp = new STRUCT(dsc, _conn, obj);
1113
                return resp;
1114
        }
1115
        
1116
        
1117
        
1118
        private static STRUCT getMultiLineAsStruct(ArrayList lines, int srid,
1119
                        boolean threed, Connection _conn, boolean hasSrid) throws SQLException {
1120
                
1121
                /*
1122
                if (lines.size() == 1) {
1123
                        return getOneLineStringAsStruct((LineString3D) lines.get(0), srid, threed, _conn);
1124
                }
1125
                */
1126
                
1127
                int size = lines.size();
1128
                int geotype = 2006;
1129
                int dim = 2;
1130
                int acum = 0;
1131
                if (threed) {
1132
                        geotype = 3006;
1133
                        dim = 3;
1134
                }
1135
                NUMBER[] indices = new NUMBER[3 * size];
1136
                
1137
                for (int i=0; i<size; i++) {
1138
                        indices[3 * i] = new NUMBER(acum + 1);
1139
                        indices[3 * i + 1] = new NUMBER(2);
1140
                        indices[3 * i + 2] = new NUMBER(1);
1141
                        acum = acum + dim * ((LineString3D) lines.get(i)).getLs().getNumPoints();
1142
                }
1143
                
1144
                int _ind = 0;
1145
                NUMBER[] ords = new NUMBER[acum];
1146
                for (int i=0; i<size; i++) {
1147
                        LineString3D ls = (LineString3D) lines.get(i);
1148
                        int num_p = ls.getLs().getNumPoints();
1149
                        for (int j=0; j<num_p; j++) {
1150
                                ords[_ind] =     new NUMBER(ls.getLs().getCoordinateN(j).x);
1151
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1152
                                if (threed) {
1153
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1154
                                }
1155
                                _ind = _ind + dim;
1156
                        }
1157
                }
1158
                
1159
                STRUCT resp;
1160
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", _conn);
1161
                Object[] obj = new Object[5];
1162
                obj[0] = new NUMBER(geotype);
1163
                if (hasSrid) {
1164
                        obj[1] = new NUMBER(srid);
1165
                } else {
1166
                        obj[1] = null;
1167
                }
1168
                
1169
                obj[2] = null;
1170
                obj[3] = indices;
1171
                obj[4] = ords;
1172
                resp = new STRUCT(dsc, _conn, obj);
1173
                return resp;
1174
        }
1175
        
1176
        private static STRUCT getMultiPointAsStruct(Coordinate pnt,
1177
                        int srid, boolean threed,
1178
                        Connection _conn, boolean hasSrid) throws SQLException {
1179
                
1180
                int geotype = 2001;
1181
                int dim = 2;
1182
                if (threed) {
1183
                        geotype = 3001;
1184
                        dim = 3;
1185
                }
1186
                Object[] ords = new Object[3];
1187
                ords[0] = new NUMBER(pnt.x);
1188
                ords[1] = new NUMBER(pnt.y);
1189
                ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null; // ole ole y ole
1190
                
1191
                StructDescriptor ord_dsc =
1192
                        StructDescriptor.createDescriptor("MDSYS.SDO_POINT_TYPE", _conn);
1193
                STRUCT ords_st = new STRUCT(ord_dsc, _conn, ords);
1194
                
1195
                STRUCT resp;
1196
                
1197
                StructDescriptor dsc =
1198
                        StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", _conn);
1199
                Object[] obj = new Object[5];
1200
                
1201
                obj[0] = new NUMBER(geotype);
1202
                
1203
                if (hasSrid) {
1204
                        obj[1] = new NUMBER(srid);
1205
                } else {
1206
                        obj[1] = null;
1207
                }
1208
                obj[2] = ords_st;
1209
                obj[3] = null;
1210
                obj[4] = null;
1211
                resp = new STRUCT(dsc, _conn, obj);
1212
                return resp;
1213
        }
1214
        
1215
        
1216
        /*
1217
        private static STRUCT getOneLineStringAsStruct(LineString3D line, int srid, boolean threed, Connection _conn) throws SQLException {
1218
                
1219
                int size = 1;
1220
                int geotype = 2002;
1221
                int dim = 2;
1222
                int acum = 0;
1223
                if (threed) {
1224
                        geotype = 3002;
1225
                        dim = 3;
1226
                }
1227
                BigDecimal[] indices = new BigDecimal[3];
1228
                indices[0] = new BigDecimal(acum + 1);
1229
                indices[1] = new BigDecimal(2);
1230
                indices[2] = new BigDecimal(1);
1231
                acum = acum + dim * ((LineString3D) lines.get(i)).getLs().getNumPoints();
1232

1233
                int _ind = 0;
1234
                BigDecimal[] ords = new BigDecimal[acum];
1235
                for (int i=0; i<size; i++) {
1236
                        LineString3D ls = (LineString3D) lines.get(i);
1237
                        for (int j=0; j<ls.getZc().length; j++) {
1238
                                ords[_ind] =     new BigDecimal(ls.getLs().getCoordinateN(j).x);
1239
                                ords[_ind + 1] = new BigDecimal(ls.getLs().getCoordinateN(j).y);
1240
                                if (threed) {
1241
                                        ords[_ind + 2] = new BigDecimal(ls.getZc()[j]);
1242
                                }
1243
                                _ind = _ind + dim;
1244
                        }
1245
                }
1246
                
1247
                STRUCT resp;
1248
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", _conn);
1249
                Object[] obj = new Object[5];
1250
                obj[0] = new BigDecimal(geotype);
1251
                obj[1] = new BigDecimal(srid);
1252
                obj[2] = null;
1253
                obj[3] = indices;
1254
                obj[4] = ords;
1255
                resp = new STRUCT(dsc, _conn, obj);
1256
                return resp;
1257
        }
1258
        */
1259
        
1260
        public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) {
1261

    
1262
                Object[] resp = new Object[2];
1263
                resp[0] = new Point2D.Double(0, 0);
1264
                resp[1] = new Double(0);
1265
                double m11, m12, m13, m14;
1266
                
1267
                if (points.length != 3) {
1268
                        logger.error("Needs 3 points (found " + points.length + ") - circle cannot be computed.");
1269
                        // not a circle
1270
                        return resp;
1271
                }
1272
                
1273
                double[][] a = new double[3][3];
1274
            for (int i = 0; i < 3; i++) {                    // find minor 11
1275
                a[i][0] = points[i].getX();
1276
                a[i][1] = points[i].getY();
1277
                a[i][2] = 1;
1278
            }
1279
            m11 = determinant(a, 3);
1280
            
1281
            for (int i = 0; i < 3; i++) {                    // find minor 12 
1282
                a[i][0] = points[i].getX()*points[i].getX() + points[i].getY()*points[i].getY();
1283
                a[i][1] = points[i].getY();
1284
                a[i][2] = 1;
1285
            }
1286
            m12 = determinant( a, 3 );
1287
            
1288
            for (int i = 0; i < 3; i++)                    // find minor 13
1289
            {
1290
                a[i][0] = points[i].getX()*points[i].getX() + points[i].getY()*points[i].getY();
1291
                a[i][1] = points[i].getX();
1292
                a[i][2] = 1;
1293
            }
1294
            m13 = determinant( a, 3 );
1295
            
1296
            for (int i = 0; i < 3; i++) {                    // find minor 14
1297
                a[i][0] = points[i].getX()*points[i].getX() + points[i].getY()*points[i].getY();
1298
                a[i][1] = points[i].getX();
1299
                a[i][2] = points[i].getY();
1300
            }
1301
            m14 = determinant( a, 3 );
1302
            
1303
                Double resp_radius = new Double(0);
1304
                Point2D resp_center = new Point2D.Double(0, 0);
1305
            
1306
            if (m11 == 0) {
1307
                    logger.error("Three points aligned - circle cannot be computed."); // not a circle
1308
            } else {
1309
                    double x = 0.5 * m12 / m11;
1310
                    double y = -0.5 * m13 / m11;
1311
                    resp_center.setLocation(x, y);
1312
                resp_radius  = new Double(Math.sqrt( x*x + y*y + m14/m11 ));
1313
                resp[0] = resp_center;
1314
                resp[1] = resp_radius;
1315
            }
1316
            return resp;
1317
        }
1318
        
1319
        public static double determinant(double[][] a, int n) {
1320
                
1321
                double resp = 0;
1322
                double[][] m = new double[3][3];
1323
                
1324
            if (n == 2) {                                // terminate recursion
1325
                resp = a[0][0]*a[1][1] - a[1][0]*a[0][1];
1326
            } else {
1327
                    
1328
                resp = 0;
1329
                for (int j1 = 0; j1 < n; j1++) {            // do each column
1330
                    for (int i = 1; i < n; i++) {            // create minor
1331
                        int j2 = 0;
1332
                        for (int j = 0; j < n; j++) {
1333
                            if (j == j1) continue;
1334
                            m[i-1][j2] = a[i][j];
1335
                            j2++;
1336
                        }
1337
                    }
1338
                    // sum (+/-)cofactor * minor  
1339
                    resp = resp + Math.pow(-1.0, j1)*a[0][j1]*determinant(m, n-1);
1340
                }
1341
            }
1342
            return resp;
1343
        }
1344
        
1345
        private static int getSmallestContainerExcept(LineString3D ls, ArrayList list, int self) {
1346
                int resp = -1;
1347
                ArrayList provList = new ArrayList();
1348
                
1349
                int size = list.size();
1350
                for (int i=0; i<self; i++) {
1351
                        if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1352
                                provList.add(new Integer(i));
1353
                        }
1354
                }
1355
                for (int i=(self+1); i<size; i++) {
1356
                        if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1357
                                provList.add(new Integer(i));
1358
                        }
1359
                }
1360
                
1361
                if (provList.size() == 0) {
1362
                        // logger.debug("LineString is not contained by any other ls.");
1363
                } else {
1364
                        if (provList.size() == 1) {
1365
                                resp = ((Integer) provList.get(0)).intValue();
1366
                        } else {
1367
                                if (provList.size() == 2) {
1368
                                        int ind_1 = ((Integer) provList.get(0)).intValue();
1369
                                        int ind_2 = ((Integer) provList.get(1)).intValue();
1370
                                        LineString3D ls1 = (LineString3D) list.get(ind_1);
1371
                                        LineString3D ls2 = (LineString3D) list.get(ind_2);
1372
                                        if (lineString3DIsContainedBy(ls1, ls2)) {
1373
                                                resp = ind_1;
1374
                                        } else {
1375
                                                resp = ind_2;
1376
                                        }
1377
                                } else {
1378
                                        // not so deep, sorry!
1379
                                        // it's going to be a shell: resp = -1;
1380
                                }
1381
                        }
1382
                }
1383
                return resp;
1384
        }
1385
        
1386
        private static int[] getIndicesOfShells(int[] containings) {
1387
                ArrayList resp = new ArrayList();
1388
                for (int i=0; i<containings.length; i++) {
1389
                        if (containings[i] == -1) resp.add(new Integer(i));
1390
                }
1391
                int size = resp.size();
1392
                int[] _resp = new int[size];
1393
                for (int i=0; i<size; i++) {
1394
                        _resp[i] = ((Integer) resp.get(i)).intValue();
1395
                }
1396
                return _resp;
1397
        }
1398
        
1399
        private static int[] getIndicesOfHoles(int[] containings, int[] shells) {
1400
                ArrayList resp = new ArrayList();
1401
                for (int i=0; i<containings.length; i++) {
1402
                        int cont_by = containings[i];
1403
                        if ((cont_by != -1) && (isOneOf(cont_by, shells))) {
1404
                                resp.add(new Integer(i));                                
1405
                        }
1406
                }
1407
                int size = resp.size();
1408
                int[] _resp = new int[size];
1409
                for (int i=0; i<size; i++) {
1410
                        _resp[i] = ((Integer) resp.get(i)).intValue();
1411
                }
1412
                return _resp;
1413
        }
1414
        
1415
        private static int[] getFinalContainings(int[] containings, int[] holes) {
1416
                ArrayList resp = new ArrayList();
1417
                for (int i=0; i<containings.length; i++) {
1418
                        int cont_by = containings[i];
1419
                        if (isOneOf(cont_by, holes)) {
1420
                                resp.add(new Integer(-1));
1421
                        } else {
1422
                                resp.add(new Integer(cont_by));
1423
                        }
1424
                }
1425
                int size = resp.size();
1426
                int[] _resp = new int[size];
1427
                for (int i=0; i<size; i++) {
1428
                        _resp[i] = ((Integer) resp.get(i)).intValue();
1429
                }
1430
                return _resp;
1431
        }
1432
        
1433
        private static ArrayList getHolesOf(int ind, int[] final_contn, ArrayList all) {
1434
                ArrayList resp_ind = new ArrayList();
1435
                for (int i=0; i<final_contn.length; i++) {
1436
                        if (final_contn[i] == ind) {
1437
                                resp_ind.add(new Integer(i));
1438
                        }
1439
                }
1440
                ArrayList resp = new ArrayList();
1441
                for (int i=0; i<resp_ind.size(); i++) {
1442
                        Integer aux = (Integer) resp_ind.get(i);
1443
                        resp.add(all.get(aux.intValue()));
1444
                }
1445
                return resp;
1446
        }
1447
        
1448
        private static ArrayList getShellsIn(int[] final_contn, ArrayList all) {
1449
                ArrayList resp_ind = new ArrayList();
1450
                for (int i=0; i<final_contn.length; i++) {
1451
                        if (final_contn[i] == -1) {
1452
                                resp_ind.add(new Integer(i));
1453
                        }
1454
                }
1455
                ArrayList resp = new ArrayList();
1456
                for (int i=0; i<resp_ind.size(); i++) {
1457
                        Integer aux = (Integer) resp_ind.get(i);
1458
                        resp.add(all.get(aux.intValue()));
1459
                }
1460
                return resp;
1461
        }
1462
        
1463
        public static Object[] getHolesForShells(ArrayList all_ls) {
1464
                
1465
                int no_of_ls = all_ls.size();
1466
                int[] containedby = new int[no_of_ls];
1467
                int[] shells, holes, final_cont;
1468
                for (int i=0; i<no_of_ls; i++) {
1469
                        LineString3D ls_aux = (LineString3D) all_ls.get(i);
1470
                        containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i);
1471
                }
1472
                shells = getIndicesOfShells(containedby);
1473
                holes = getIndicesOfHoles(containedby, shells);
1474
                final_cont = getFinalContainings(containedby, holes);
1475
                
1476
                // true shells:
1477
                shells = getIndicesOfShells(final_cont);
1478
                ArrayList resp_shells = new ArrayList();
1479
                ArrayList resp_holes_for_shells = new ArrayList();
1480
                ArrayList aux_holes;
1481
                for (int i=0; i<shells.length; i++) {
1482
                        resp_shells.add(all_ls.get(shells[i]));
1483
                        aux_holes = getHolesOf(i, final_cont, all_ls);
1484
                        resp_holes_for_shells.add(aux_holes);
1485
                }
1486
                
1487
                Object[] _resp = new Object[2];
1488
                _resp[0] = resp_shells;
1489
                _resp[1] = resp_holes_for_shells;
1490
                return _resp;
1491
        }
1492
        
1493
        private static int getTotalSize(ArrayList listOfLists) {
1494
                int resp = 0;
1495
                for (int i=0; i<listOfLists.size(); i++) {
1496
                        resp = resp + ((ArrayList) listOfLists.get(i)).size();
1497
                }
1498
                return resp;
1499
        }
1500
        
1501
        // private static STRUCT // private static ArrayList getPolygonsEasily(FShape mpolygon) {
1502
        private static STRUCT getMultiPolygonAsStruct(FShape mpol,
1503
                        int srid, boolean threed, Connection _conn,
1504
                        boolean agu_bien, boolean hasSrid) throws SQLException {
1505
                
1506
                ArrayList all_ls = getPolygonsEasily(mpol);
1507
                Object[] hs = getHolesForShells(all_ls);
1508
                ArrayList sh = (ArrayList) hs[0];
1509
                ArrayList _ho = (ArrayList) hs[1];
1510
                ArrayList ho = reverseHoles(_ho);
1511
                return getMultiPolygonAsStruct(sh, ho, srid, threed, _conn, agu_bien, hasSrid);
1512
        }
1513
        
1514
        
1515
        private static ArrayList reverseHoles(ArrayList hh) {
1516
                ArrayList resp = new ArrayList();
1517
                for (int i=0; i<hh.size(); i++) {
1518
                        ArrayList item = (ArrayList) hh.get(i);
1519
                        ArrayList newitem = new ArrayList();
1520
                        for (int j=0; j<item.size(); j++) {
1521
                                LineString3D ls = (LineString3D) item.get(j);
1522
                                newitem.add(ls.createReverse());
1523
                        }
1524
                        resp.add(newitem);
1525
                }
1526
                return resp;
1527
        }
1528

    
1529
        private static STRUCT getMultiPolygonAsStruct(ArrayList shells, ArrayList holes,
1530
                        int srid, boolean threed, Connection _conn, boolean explicito,
1531
                        boolean hasSrid) throws SQLException {
1532

    
1533
                int t = 1003;
1534
                if (explicito) {
1535
                        t = 2003;
1536
                }
1537

    
1538
                int size = shells.size() + getTotalSize(holes);
1539
                int geotype = 2007;
1540
                int dim = 2;
1541
                
1542
                if (threed) {
1543
                        geotype = 3007;
1544
                        dim = 3;
1545
                }
1546
                NUMBER[] indices = new NUMBER[3 * size];
1547
                
1548
                int acum = 0;
1549
                int start_ind = 0;
1550
                for (int i=0; i<shells.size(); i++) {
1551

    
1552
                        indices[start_ind    ] = new NUMBER(acum + 1);
1553
                        indices[start_ind + 1] = new NUMBER(1003);
1554
                        indices[start_ind + 2] = new NUMBER(1);
1555
                        start_ind = start_ind + 3;
1556
                        acum = acum + dim * ((LineString3D) shells.get(i)).getLs().getNumPoints();
1557
                        
1558
                        ArrayList item_holes = (ArrayList) holes.get(i);
1559
                        for (int j=0; j<item_holes.size(); j++) {
1560
                                indices[start_ind    ] = new NUMBER(acum + 1);
1561
                                indices[start_ind + 1] = new NUMBER(t); // 1003
1562
                                indices[start_ind + 2] = new NUMBER(1);
1563
                                start_ind = start_ind + 3;
1564
                                acum = acum + dim * ((LineString3D) item_holes.get(j)).getLs().getNumPoints();
1565
                        }
1566
                }
1567

    
1568
                int _ind = 0;
1569
                NUMBER[] ords = new NUMBER[acum];
1570
                for (int i=0; i<shells.size(); i++) {
1571
                        // --------------------------------
1572
                        LineString3D ls = (LineString3D) shells.get(i);
1573
                        int num_p = ls.getLs().getNumPoints();
1574
                        for (int j=0; j<num_p; j++) {
1575
                                ords[_ind] =     new NUMBER(ls.getLs().getCoordinateN(j).x);
1576
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1577
                                if (threed) {
1578
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1579
                                }
1580
                                _ind = _ind + dim;
1581
                        }
1582
                        // -------------------------------
1583
                        ArrayList item_holes = (ArrayList) holes.get(i);
1584
                        for (int j=0; j<item_holes.size(); j++) {
1585
                                ls = (LineString3D) item_holes.get(j);
1586
                                num_p = ls.getLs().getNumPoints();
1587
                                for (int k=0; k<num_p; k++) {
1588
                                        ords[_ind] =     new NUMBER(ls.getLs().getCoordinateN(k).x);
1589
                                        ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y);
1590
                                        if (threed) {
1591
                                                ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1592
                                        }
1593
                                        _ind = _ind + dim;
1594
                                }
1595
                        }
1596
                }
1597
                
1598
                STRUCT resp;
1599
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", _conn);
1600
                Object[] obj = new Object[5];
1601
                obj[0] = new NUMBER(geotype);
1602
                
1603
                if (hasSrid) {
1604
                        obj[1] = new NUMBER(srid);
1605
                } else {
1606
                        obj[1] = null;
1607
                }
1608

    
1609
                obj[2] = null;
1610
                obj[3] = indices;
1611
                obj[4] = ords;
1612
                
1613
                // String ind_str = printArray(indices);
1614
                // String ord_str = printArray(ords);
1615
                
1616
                resp = new STRUCT(dsc, _conn, obj);
1617
                return resp;
1618
        }
1619
        
1620
        public static String printArray(NUMBER[] array) {
1621
                String resp = "[ ";
1622
                for (int i=0; i<array.length; i++) {
1623
                        resp = resp + " " + array[i].doubleValue() + " , ";
1624
                }
1625
                resp = resp.substring(0, resp.length() - 2) + "]";
1626
                return resp;
1627
        }
1628
        
1629
        private static boolean isOneOf(int ind, int[] list) {
1630
                for (int i=0; i<list.length; i++) {
1631
                        if (list[i] == ind) return true;
1632
                }
1633
                return false;
1634
        }
1635
        
1636
        public static STRUCT appendGeometriesInStruct(FGeometryCollection co,
1637
                        int _forced_type, Connection _conn, String _o_srid, boolean withSrid,
1638
                        boolean agu_bien, boolean _isGeoCS) {
1639
                
1640
                IGeometry[] geoms = co.getGeometries();
1641
                int size = geoms.length;
1642
                STRUCT[] sts = new STRUCT[size];
1643
                for (int i=0; i<size; i++) {
1644
                        sts[i] = OracleSpatialDriver.iGeometryToSTRUCT(geoms[i], _forced_type, _conn,
1645
                                        _o_srid, withSrid, agu_bien, _isGeoCS);
1646
                }
1647
                
1648
                if (size == 1) {
1649
                        return sts[0];
1650
                }
1651
                
1652
                STRUCT aux = sts[0];
1653
                for (int i=1; i<size; i++) {
1654
                        aux = appendStructs(aux, sts[i], _conn);
1655
                }
1656
                return aux;
1657
        }
1658

    
1659
        private static STRUCT appendStructs(STRUCT st1, STRUCT st2, Connection _conn) {
1660
                
1661
                try {
1662
                        
1663
                        ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1664
                        int length_of_head_ords = _ords.getOracleArray().length;
1665

    
1666
                        NUMBER gtype = new NUMBER(4 + ((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000);
1667
                        NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1668
                        NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1669
                        
1670
                        ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1671
                        ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1672
                        ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1673
                        ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1674

    
1675
                        
1676
                        Datum[] info = appendDatumArrays(
1677
                                        info1.getOracleArray(),
1678
                                        info2.getOracleArray(), length_of_head_ords);
1679
                        
1680
                        Datum[] ords = appendDatumArrays(
1681
                                        ords1.getOracleArray(),
1682
                                        ords2.getOracleArray(), 0);
1683
                        
1684
                        StructDescriptor dsc = st1.getDescriptor();
1685

    
1686
                        Object[] atts = new Object[5];
1687
                        atts[0] = gtype;
1688
                        atts[1] = srid;
1689
                        atts[2] = middle;
1690
                        atts[3] = info;
1691
                        atts[4] = ords;
1692

    
1693
                        STRUCT resp = new STRUCT(dsc, _conn, atts);
1694
                        return resp;
1695
                        
1696
                } catch (SQLException sqle) {
1697
                        logger.error("While appending structs: " + sqle.getMessage(), sqle);
1698
                }
1699
                
1700
                return null;
1701
        }
1702

    
1703
        private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail, int offset) {
1704
                
1705
                int head_l = head.length;
1706
                int tail_l = tail.length;
1707
                Datum[] resp = new Datum[head_l + tail_l];
1708
                
1709
                for (int i=0; i<head_l; i++) resp[i] = head[i];
1710

    
1711
                if (offset == 0) {
1712
                        
1713
                        for (int i=0; i<tail_l; i++) resp[head_l + i] = tail[i];
1714
                        
1715
                } else {
1716
                        
1717
                        try {
1718
                                for (int i=0; i<tail_l; i++) {
1719
                                        if ((i % 3) == 0) {
1720
                                                resp[head_l + i] = new NUMBER(tail[i].intValue() + offset);
1721
                                        } else {
1722
                                                resp[head_l + i] = tail[i];        
1723
                                        }
1724
                                }
1725
                        } catch (SQLException se) {
1726
                                logger.error("Unexpected error: " + se.getMessage());
1727
                        }
1728
                        
1729
                }
1730

    
1731
                return resp;
1732
        }
1733
        
1734
        public static String getFormattedInteger(int n) {
1735
                df.setGroupingUsed(true);
1736
                df.setGroupingSize(3);
1737
                dfs.setGroupingSeparator('.');
1738
                df.setDecimalFormatSymbols(dfs);
1739
                return df.format(n);
1740
        }        
1741
        
1742
        public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
1743
                
1744
                try {
1745
                        int[] infos = info.getIntArray();
1746
                        return ((infos[2] == 3) && (infos.length == 3));
1747
                } catch (SQLException se) {
1748
                        logger.error("While ckecking rectangle: " + se.getMessage(), se);
1749
                }
1750
                return false;
1751
        }
1752
        
1753
        public static ARRAY getDevelopedInfoArray(ARRAY info) {
1754
                ARRAY _resp = null;
1755
                try {
1756
                        Datum[] resp = new Datum[3];
1757
                        Datum[] in = info.getOracleArray();
1758
                        resp[0] =  in[0];
1759
                        resp[1] =  in[1];
1760
                        resp[2] =  new NUMBER(1);
1761
                        _resp = new ARRAY(info.getDescriptor(), info.getInternalConnection(), resp);
1762
                } catch (SQLException se) {
1763
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
1764
                }
1765
                return _resp;
1766
        }
1767
        
1768
        public static ARRAY getDevelopedOrdsArray(ARRAY ords) {
1769
                ARRAY _resp = null;
1770
                try {
1771
                        Datum[] resp = new Datum[10];
1772
                        Datum[] corners = ords.getOracleArray();
1773
                        // x
1774
                        resp[0] =  corners[0];
1775
                        resp[2] =  corners[2];
1776
                        resp[4] =  corners[2];
1777
                        resp[6] =  corners[0];
1778
                        resp[8] =  corners[0];
1779
                        // y
1780
                        resp[1] =  corners[1];
1781
                        resp[3] =  corners[1];
1782
                        resp[5] =  corners[3];
1783
                        resp[7] =  corners[3];
1784
                        resp[9] =  corners[1];
1785
                        _resp = new ARRAY(ords.getDescriptor(), ords.getInternalConnection(), resp);
1786
                } catch (SQLException se) {
1787
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
1788
                }
1789
                return _resp;
1790
        }
1791
        
1792
        
1793
        public static GeneralPathX structToGPX(Datum[] aux) {
1794
                
1795
                GeneralPathX resp = new GeneralPathX();
1796
                ARRAY infoARRAY = null;
1797
                ARRAY ordsARRAY = null;
1798
                Datum[] info_array = null;
1799
                Datum[] ords_array = null;
1800
                int info_array_size = 0;
1801
                int[] start_ind, end_ind;
1802
                int dims = 0;
1803
                boolean next_must_do_first = true;
1804

    
1805
                try {
1806
                        infoARRAY = (ARRAY) aux[3];
1807
                        ordsARRAY = (ARRAY) aux[4];
1808
                        
1809
                        if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
1810
                                infoARRAY = getDevelopedInfoArray(infoARRAY);
1811
                                ordsARRAY = getDevelopedOrdsArray(ordsARRAY);
1812
                        }
1813
                        
1814
                        dims = ((NUMBER) aux[0]).intValue() / 1000;
1815
                        if (dims == 0) dims = 2;
1816

    
1817
                        info_array = (Datum[]) infoARRAY.getOracleArray();
1818
                        ords_array = (Datum[]) ordsARRAY.getOracleArray();
1819
                        info_array_size = info_array.length / 3;
1820
                        int last_index = ords_array.length - dims + 1;
1821

    
1822
                        // set indices:
1823
                        start_ind = new int[info_array_size];
1824
                        end_ind = new int[info_array_size];
1825
                        for (int i=0; i<info_array_size; i++) start_ind[i] =
1826
                                ((NUMBER) info_array[3 * i]).intValue();
1827
                        for (int i=0; i<(info_array_size-1); i++) end_ind[i] = start_ind[i + 1] - 1;
1828
                        end_ind[info_array_size-1] = last_index;
1829
                        
1830
                        int lineType = PathIterator.SEG_LINETO;
1831
                        
1832
                        if (end_ind[0] == 0) { // collection of paths
1833
                                
1834
                                for (int i=1; i<info_array_size; i++) {
1835
                                        lineType = getLineToType(info_array, i);
1836
                                        next_must_do_first = addOrdsToGPX(resp,
1837
                                                        start_ind[i] - 1, end_ind[i] - 1,
1838
                                                        ords_array, dims, lineType,
1839
                                                        (i == 1), next_must_do_first);
1840
                                }
1841
                                
1842
                        } else {
1843
                                
1844
                                // standard case, do the moveto always
1845
                                
1846
                                for (int i=0; i<info_array_size; i++) {
1847
                                        lineType = getLineToType(info_array, i);
1848
                                        addOrdsToGPX(resp,
1849
                                                        start_ind[i] - 1, end_ind[i] - 1,
1850
                                                        ords_array, dims, lineType,
1851
                                                        true, true);
1852
                                }
1853
                                
1854
                        }
1855
                        
1856
                        
1857
                        
1858
                        // boolean do_the_moves = true;
1859
                        
1860
                        
1861
                } catch (SQLException se) {
1862
                        logger.error("While creating GPX: " + se.getMessage(), se);
1863
                }
1864
                return resp;
1865
        }
1866
        
1867
        /*
1868
        public static GeneralPath structToGP(STRUCT st) {
1869
                
1870
                GeneralPath resp = new GeneralPath();
1871
                ARRAY infoARRAY = null;
1872
                ARRAY ordsARRAY = null;
1873
                BigDecimal[] info_array = null;
1874
                BigDecimal[] ords_array = null;
1875
                int info_array_size = 0;
1876
                int[] start_ind, end_ind;
1877
                int dims = 0;
1878
                boolean next_must_do_first = true;
1879

1880
                try {
1881
                        infoARRAY = (ARRAY) st.getAttributes()[3];
1882
                        ordsARRAY = (ARRAY) st.getAttributes()[4];
1883
                        
1884
                        if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
1885
                                infoARRAY = getDevelopedInfoArray(infoARRAY);
1886
                                ordsARRAY = getDevelopedOrdsArray(ordsARRAY);
1887
                        }
1888
                        
1889
                        dims = ((BigDecimal) st.getAttributes()[0]).intValue() / 1000;
1890
                        if (dims == 0) dims = 2;
1891

1892
                        info_array = (BigDecimal[]) infoARRAY.getArray();
1893
                        ords_array = (BigDecimal[]) ordsARRAY.getArray();
1894
                        info_array_size = info_array.length / 3;
1895
                        int last_index = ords_array.length - dims + 1;
1896

1897
                        // set indices:
1898
                        start_ind = new int[info_array_size];
1899
                        end_ind = new int[info_array_size];
1900
                        for (int i=0; i<info_array_size; i++) start_ind[i] = info_array[3 * i].intValue();
1901
                        for (int i=0; i<(info_array_size-1); i++) end_ind[i] = start_ind[i + 1] - 1;
1902
                        end_ind[info_array_size-1] = last_index;
1903
                        
1904
                        int lineType = PathIterator.SEG_LINETO;
1905
                        
1906
                        if (end_ind[0] == 0) { // collection of paths
1907
                                
1908
                                for (int i=1; i<info_array_size; i++) {
1909
                                        lineType = getLineToType(info_array, i);
1910
                                        next_must_do_first = addOrdsToGP(resp,
1911
                                                        start_ind[i] - 1, end_ind[i] - 1,
1912
                                                        ords_array, dims, lineType,
1913
                                                        (i == 1), next_must_do_first);
1914
                                }
1915
                                
1916
                        } else {
1917
                                
1918
                                // standard case, do the moveto always
1919
                                
1920
                                for (int i=0; i<info_array_size; i++) {
1921
                                        lineType = getLineToType(info_array, i);
1922
                                        addOrdsToGP(resp,
1923
                                                        start_ind[i] - 1, end_ind[i] - 1,
1924
                                                        ords_array, dims, lineType,
1925
                                                        true, true);
1926
                                }
1927
                                
1928
                        }
1929
                        
1930
                        
1931
                        
1932
                        // boolean do_the_moves = true;
1933
                        
1934
                        
1935
                } catch (SQLException se) {
1936
                        logger.error("While creating GPX: " + se.getMessage(), se);
1937
                }
1938
                return resp;
1939
        }
1940
        */
1941

    
1942
        private static int getLineToType(Datum[] infos, int i) {
1943
                
1944
                int resp = PathIterator.SEG_LINETO;
1945
                try {
1946
                        if (((NUMBER) infos[3 * i + 2]).intValue() == 2) {
1947
                                resp = PathIterator.SEG_QUADTO;
1948
                        }
1949
                } catch (SQLException e) {
1950
                        logger.error("While getting line-to type: " + e.getMessage() + " (returned SEG_LINETO)");
1951
                }
1952
                return resp;
1953
        }
1954

    
1955
        /*
1956
        private static boolean addOrdsToGP(GeneralPath gp,
1957
                        int zero_based_start, int zero_based_include_end,
1958
                        BigDecimal[] ords, int d, int ltype, boolean do_the_move, boolean must_do_first) {
1959
                
1960
                int length = ords.length;
1961
                boolean return_following_must_do_first = true;
1962
                
1963
                double x = ords[zero_based_start].doubleValue();
1964
                double y = ords[zero_based_start+1].doubleValue();
1965

1966
                if (must_do_first) {
1967
                        if (do_the_move) {
1968
                                gp.moveTo((float) x, (float) y);
1969
                        } else {
1970
                                gp.lineTo((float) x, (float) y);
1971
                        }
1972
                }
1973
                int ind = 1;
1974
                
1975
                
1976
                int size = ((zero_based_include_end - zero_based_start) / d) + 1;
1977
                int indx, indx2;
1978

1979
                if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
1980
                        
1981
                        double x2, y2;
1982
                        while (ind < size) {
1983
                                indx = zero_based_start + ind * d;
1984
                                x = ords[indx].doubleValue();
1985
                                y = ords[indx+1].doubleValue();
1986
                                
1987
                                indx2 = zero_based_start + (ind+1) * d;
1988
                                if (indx >= length) {
1989
                                        indx2 = zero_based_start;
1990
                                }
1991
                                
1992
                                x2 = ords[indx2].doubleValue();
1993
                                y2 = ords[indx2+1].doubleValue();
1994
                                gp.quadTo((float) x, (float) y, (float) x2, (float) y2);
1995
                                ind++; ind++;
1996
                        }
1997
                        
1998
                        return_following_must_do_first = false;
1999
                         
2000
                } else { // PathIterator.SEG_LINETO (interpretation = 1)
2001
                        
2002
                        while (ind < size) {
2003
                                indx = zero_based_start + ind * d;
2004
                                x = ords[indx].doubleValue();
2005
                                y = ords[indx+1].doubleValue();
2006
                                gp.lineTo((float) x, (float) y);
2007
                                ind++;
2008
                        }
2009
                        
2010
                }
2011
                
2012
                return return_following_must_do_first;
2013
        }
2014
        */
2015
        
2016
        private static boolean addOrdsToGPX(GeneralPathX gpx,
2017
                        int zero_based_start, int zero_based_include_end,
2018
                        Datum[] ords, int d, int ltype, boolean do_the_move, boolean must_do_first) {
2019
                
2020
                int length = ords.length;
2021
                boolean return_following_must_do_first = true;
2022
                
2023
                double x = ((NUMBER) ords[zero_based_start]).doubleValue();
2024
                double y = ((NUMBER) ords[zero_based_start+1]).doubleValue();
2025

    
2026
                if (must_do_first) {
2027
                        if (do_the_move) {
2028
                                gpx.moveTo( x, y);
2029
                        } else {
2030
                                gpx.lineTo( x, y);
2031
                        }
2032
                }
2033
                int ind = 1;
2034
                
2035
                
2036
                int size = ((zero_based_include_end - zero_based_start) / d) + 1;
2037
                int indx, indx2;
2038

    
2039
                if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
2040
                        
2041
                        double x2, y2;
2042
                        while (ind < size) {
2043
                                indx = zero_based_start + ind * d;
2044
                                x = ((NUMBER) ords[indx]).doubleValue();
2045
                                y = ((NUMBER) ords[indx+1]).doubleValue();
2046
                                
2047
                                indx2 = zero_based_start + (ind+1) * d;
2048
                                if (indx >= length) {
2049
                                        indx2 = zero_based_start;
2050
                                }
2051
                                
2052
                                x2 = ((NUMBER) ords[indx2]).doubleValue();
2053
                                y2 = ((NUMBER) ords[indx2+1]).doubleValue();
2054
                                gpx.quadTo( x,  y,  x2,  y2);
2055
                                ind++; ind++;
2056
                        }
2057
                        
2058
                        return_following_must_do_first = false;
2059
                         
2060
                } else { // PathIterator.SEG_LINETO (interpretation = 1)
2061
                        
2062
                        while (ind < size) {
2063
                                indx = zero_based_start + ind * d;
2064
                                x = ((NUMBER) ords[indx]).doubleValue();
2065
                                y = ((NUMBER) ords[indx+1]).doubleValue();
2066
                                gpx.lineTo( x,  y);
2067
                                ind++;
2068
                        }
2069
                        
2070
                }
2071
                
2072
                return return_following_must_do_first;
2073

    
2074
                /*
2075
                for (int go=zero_based_start+d; go<=zero_based_include_end; go=go+d) {
2076
                        x = ords[go].doubleValue();
2077
                        y = ords[go+1].doubleValue();
2078
                        gpx.lineTo(x, y);
2079
                }
2080
                */
2081
        }
2082
        
2083
        
2084
        public static int oracleGTypeToFShapeType(int otype) {
2085
                
2086
                switch (otype) {
2087
                case ORACLE_GTYPE_UNKNOWN:
2088
                        return FShape.NULL;
2089
                case ORACLE_GTYPE_POINT:
2090
                case ORACLE_GTYPE_MULTIPOINT:
2091
                        return FShape.POINT;
2092
                case ORACLE_GTYPE_LINE:
2093
                case ORACLE_GTYPE_MULTILINE:
2094
                        return FShape.LINE;
2095
                case ORACLE_GTYPE_POLYGON:
2096
                case ORACLE_GTYPE_MULTIPOLYGON:
2097
                        return FShape.POLYGON;
2098
                case ORACLE_GTYPE_COLLECTION:
2099
                        return FShape.MULTI;
2100
                }
2101
                logger.warn("Unknown oracle geometry type: " + otype);
2102
                return FShape.NULL;
2103
        }
2104
        
2105
        public static int getStructType(Datum[] the_data) {
2106
                int resp = -1;
2107
                try {
2108
                        resp = ((NUMBER) the_data[0]).intValue() % 1000;
2109
                } catch (SQLException se) {
2110
                        logger.error("Error: " + se.getMessage(), se);
2111
                }
2112
                return resp;
2113
        }
2114
        
2115
        public static int getStructSRID(Datum[] the_data) {
2116
                int resp = -1;
2117
                try {
2118
                        resp = ((NUMBER) the_data[1]).intValue();
2119
                } catch (SQLException se) {
2120
                        logger.error("Error: " + se.getMessage(), se);
2121
                }
2122
                return resp;
2123
        }
2124
        
2125
        public static boolean isCircle(Datum[] the_data) {
2126
                int[] info = null;
2127
                try {
2128
                        info = ((ARRAY) the_data[3]).getIntArray();
2129
                } catch (SQLException se) {
2130
                        logger.error("While cheking circle: " + se.getMessage(), se);
2131
                        return false;
2132
                }
2133
                if (info == null) {
2134
                        return false;
2135
                }
2136
                boolean resp = ((info.length == 3) && (info[2] == 4));
2137
                return resp;
2138
        }
2139
        
2140
        public static int getStructDimensions(STRUCT st) {
2141
                int resp = -1;
2142
                try {
2143
                        resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000;
2144
                } catch (SQLException se) {
2145
                        logger.error("Error: " + se.getMessage(), se);
2146
                }
2147
                if (resp < 2) resp = 2; 
2148
                return resp;
2149
        }
2150
        
2151
        public static double[] getOrds(Datum[] the_data) {
2152
                
2153
                double[] resp = null;
2154
                try {
2155
                        ARRAY aux = (ARRAY) the_data[4];
2156
                        if (aux == null) {
2157
                                return null;
2158
                        }
2159
                        resp = aux.getDoubleArray();
2160
                } catch (SQLException se) {
2161
                        logger.error("While getting ordinates: " + se.getMessage(), se);
2162
                }
2163
                return resp;
2164
        }
2165
        
2166
        public static STRUCT createStruct(NUMBER type, NUMBER srid,
2167
                        Datum[] info, Datum[] ords, Connection conn) {
2168
                
2169
                try {
2170
                        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", conn);
2171
                        Object[] obj = new Object[5];
2172
                        obj[0] = type;
2173
                        obj[1] = srid;
2174
                        obj[2] = null;
2175
                        obj[3] = info;
2176
                        obj[4] = ords;
2177
                        return new STRUCT(dsc, conn, obj);
2178
                } catch (SQLException se) {
2179
                        logger.error("While creating STRUCT: " + se.getMessage(), se);
2180
                }
2181
                return null;
2182
        }
2183
        
2184
        public static final int ORACLE_GTYPE_UNKNOWN =                        0;
2185
        public static final int ORACLE_GTYPE_POINT =                        1;
2186
        public static final int ORACLE_GTYPE_LINE =                                2;
2187
        public static final int ORACLE_GTYPE_POLYGON =                        3;
2188
        public static final int ORACLE_GTYPE_COLLECTION =                4;
2189
        public static final int ORACLE_GTYPE_MULTIPOINT =                5;
2190
        public static final int ORACLE_GTYPE_MULTILINE =                6;
2191
        public static final int ORACLE_GTYPE_MULTIPOLYGON =                7;
2192
}