Statistics
| Revision:

root / branches / v10 / extensions / extOracleSpatial / src / es / prodevelop / cit / gvsig / fmap / drivers / jdbc / oracle / OracleSpatialUtils.java @ 13991

History | View | Annotate | Download (65.2 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 Prodevelop and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *   Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *   +34 963862235
28
 *   gvsig@gva.es
29
 *   www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   Prodevelop Integraci?n de Tecnolog?as SL
34
 *   Conde Salvatierra de ?lava , 34-10
35
 *   46004 Valencia
36
 *   Spain
37
 *
38
 *   +34 963 510 612
39
 *   +34 963 510 968
40
 *   gis@prodevelop.es
41
 *   http://www.prodevelop.es
42
 */
43
package es.prodevelop.cit.gvsig.fmap.drivers.jdbc.oracle;
44

    
45
import com.iver.cit.gvsig.fmap.core.FCircle2D;
46
import com.iver.cit.gvsig.fmap.core.FGeometryCollection;
47
import com.iver.cit.gvsig.fmap.core.FMultiPoint2D;
48
import com.iver.cit.gvsig.fmap.core.FMultipoint3D;
49
import com.iver.cit.gvsig.fmap.core.FPoint2D;
50
import com.iver.cit.gvsig.fmap.core.FPoint3D;
51
import com.iver.cit.gvsig.fmap.core.FPolygon2D;
52
import com.iver.cit.gvsig.fmap.core.FPolygon3D;
53
import com.iver.cit.gvsig.fmap.core.FPolyline3D;
54
import com.iver.cit.gvsig.fmap.core.FShape;
55
import com.iver.cit.gvsig.fmap.core.FShape3D;
56
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
57
import com.iver.cit.gvsig.fmap.core.IGeometry;
58
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
59

    
60
import com.vividsolutions.jts.algorithm.CGAlgorithms;
61
import com.vividsolutions.jts.geom.Coordinate;
62
import com.vividsolutions.jts.geom.CoordinateArrays;
63
import com.vividsolutions.jts.geom.Envelope;
64
import com.vividsolutions.jts.geom.GeometryFactory;
65
import com.vividsolutions.jts.geom.LineString;
66
import com.vividsolutions.jts.geom.LinearRing;
67
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
68

    
69
import oracle.sql.ARRAY;
70
import oracle.sql.Datum;
71
import oracle.sql.NUMBER;
72
import oracle.sql.STRUCT;
73
import oracle.sql.StructDescriptor;
74

    
75
import org.apache.log4j.Logger;
76

    
77
import java.awt.geom.PathIterator;
78
import java.awt.geom.Point2D;
79
import java.awt.geom.Rectangle2D;
80

    
81
import java.io.BufferedReader;
82
import java.io.File;
83
import java.io.FileReader;
84

    
85
import java.lang.reflect.Array;
86

    
87
import java.net.URL;
88

    
89
import java.sql.Connection;
90
import java.sql.PreparedStatement;
91
import java.sql.ResultSet;
92
import java.sql.SQLException;
93
import java.sql.Statement;
94

    
95
import java.text.DecimalFormat;
96
import java.text.DecimalFormatSymbols;
97

    
98
import java.util.ArrayList;
99
import java.util.Random;
100

    
101

    
102
/**
103
 * Utility class with static methods.
104
 *
105
 * @author jldominguez
106
 *
107
 */
108
public class OracleSpatialUtils {
109
    private static Logger logger = Logger.getLogger(OracleSpatialUtils.class.getName());
110
    private static double FLATNESS = 0.8;
111
    private static GeometryFactory geomFactory = new GeometryFactory();
112
    private static final double IRRELEVANT_DISTANCE = 0.00000001;
113
    private static Random rnd = new Random();
114
    private static DecimalFormat df = new DecimalFormat();
115
    private static DecimalFormatSymbols dfs = new DecimalFormatSymbols();
116
    public static final int ORACLE_GTYPE_UNKNOWN = 0;
117
    public static final int ORACLE_GTYPE_POINT = 1;
118
    public static final int ORACLE_GTYPE_LINE = 2;
119
    public static final int ORACLE_GTYPE_POLYGON = 3;
120
    public static final int ORACLE_GTYPE_COLLECTION = 4;
121
    public static final int ORACLE_GTYPE_MULTIPOINT = 5;
122
    public static final int ORACLE_GTYPE_MULTILINE = 6;
123
    public static final int ORACLE_GTYPE_MULTIPOLYGON = 7;
124

    
125
    /**
126
     * COnstructs a geometry from a file that contains a vertex per line:
127
     *
128
     * x1 y1 z1
129
     * x2 y2 z2
130
     * ...
131
     *
132
     * @param filepath vertices text file path
133
     * @param polygon whether it is a polygon or not
134
     * @return the created geometry
135
     */
136
    public static IGeometry readGeometry3D(URL filepath, boolean polygon) {
137
        GeneralPathX resp = new GeneralPathX();
138
        File file = new File(filepath.getFile());
139
        ArrayList z = new ArrayList();
140

    
141
        try {
142
            FileReader fr = new FileReader(file);
143
            BufferedReader br = new BufferedReader(fr);
144
            double[] coords = new double[3];
145

    
146
            boolean move = true;
147

    
148
            String line = br.readLine();
149

    
150
            while (line != null) {
151
                coords = parseLine(line);
152

    
153
                if (line.length() == 0) {
154
                    move = true;
155
                }
156
                else {
157
                    if (move) {
158
                        resp.moveTo(coords[0], coords[1]);
159
                        z.add(new Double(coords[2]));
160
                    }
161
                    else {
162
                        resp.lineTo(coords[0], coords[1]);
163
                        z.add(new Double(coords[2]));
164
                    }
165

    
166
                    move = false;
167
                }
168

    
169
                line = br.readLine();
170
            }
171
        }
172
        catch (Exception ex) {
173
            System.err.println("Error while creating GeneralPathX: " +
174
                ex.getMessage());
175

    
176
            return null;
177
        }
178

    
179
        double[] zz = new double[z.size()];
180

    
181
        for (int i = 0; i < z.size(); i++) {
182
            zz[i] = ((Double) z.get(i)).doubleValue();
183
        }
184

    
185
        if (polygon) {
186
            return ShapeFactory.createPolygon3D(resp, zz);
187
        }
188
        else {
189
            return ShapeFactory.createPolyline3D(resp, zz);
190
        }
191
    }
192

    
193
    private static double[] parseLine(String line) {
194
        String[] sep = line.split(" ");
195
        double[] resp = new double[3];
196

    
197
        for (int i = 0; i < 3; i++)
198
            resp[i] = 0.0;
199

    
200
        try {
201
            resp[0] = Double.parseDouble(sep[0]);
202
        }
203
        catch (Exception ex) {
204
        }
205

    
206
        if (sep.length > 1) {
207
            try {
208
                resp[1] = Double.parseDouble(sep[1]);
209
            }
210
            catch (Exception ex) {
211
            }
212

    
213
            if (sep.length > 2) {
214
                try {
215
                    resp[2] = Double.parseDouble(sep[2]);
216
                }
217
                catch (Exception ex) {
218
                }
219
            }
220
        }
221

    
222
        return resp;
223
    }
224

    
225
    /**
226
     * Utility method to convert a gvSIG FShape into a oracle struct
227
     *
228
     * @param fshp the FShape object
229
     * @param c the connection
230
     * @param srid the SRS (oarcle code)
231
     * @param agu_b whether to check holes validity
232
     * @param hasSrid whether the SRS is non-NULL
233
     * @return a oracle struct representing the geometry
234
     *
235
     * @throws SQLException
236
     */
237
    public static STRUCT fShapeToSTRUCT(Object fshp, Connection c, int srid,
238
        boolean agu_b, boolean hasSrid) throws SQLException {
239
        boolean three = false;
240

    
241
        if (fshp instanceof FShape3D) {
242
            three = true;
243
        }
244

    
245
        STRUCT resp = null;
246

    
247
        if (fshp instanceof FMultiPoint2D) {
248
            resp = multiPoint2DToStruct((FMultiPoint2D) fshp, c, srid, hasSrid);
249

    
250
            return resp;
251
        }
252

    
253
        if (!(fshp instanceof FShape)) {
254
            logger.error("Unknown geometry: " + fshp.toString());
255

    
256
            return null;
257
        }
258

    
259
        if (fshp instanceof FPoint2D) { // point 2/3d
260

    
261
            // resp = pointToWKT((FPoint2D) fshp, three);
262
            Coordinate p = getSingleCoordinate((FPoint2D) fshp);
263
            resp = getMultiPointAsStruct(p, srid, three, c, hasSrid);
264
        }
265
        else {
266
            if (fshp instanceof FPolygon2D) { // polygon 2/3d
267

    
268
                if (fshp instanceof FCircle2D) {
269
                    resp = getCircleAsStruct((FCircle2D) fshp, srid, c, hasSrid);
270
                }
271
                else {
272
                    // also FEllipse2D
273
                    resp = getMultiPolygonAsStruct((FShape) fshp, srid, three,
274
                            c, agu_b, hasSrid);
275

    
276
                    // ArrayList polys = getPolygonsEasily(fshp);
277
                    // resp = getMultiPolygonAsStruct(polys, srid, three, c);
278
                }
279
            }
280
            else { // line 2/3d
281

    
282
                ArrayList _lines = getLineStrings((FShape) fshp);
283
                resp = getMultiLineAsStruct(_lines, srid, three, c, hasSrid);
284
            }
285
        }
286

    
287
        return resp;
288
    }
289

    
290
    private static STRUCT multiPoint2DToStruct(FMultiPoint2D mp2d,
291
        Connection c, int srid, boolean hasSrid) throws SQLException {
292
        int np = mp2d.getNumPoints();
293
        boolean threed = (mp2d instanceof FMultipoint3D);
294
        int gtype = 2005;
295
        int dim = 2;
296
        FMultipoint3D mp3d = null;
297

    
298
        if (threed) {
299
            gtype = 3005;
300
            dim = 3;
301
            mp3d = (FMultipoint3D) mp2d;
302
        }
303

    
304
        NUMBER[] indices = new NUMBER[3];
305
        indices[0] = new NUMBER(1);
306
        indices[1] = new NUMBER(1);
307
        indices[2] = new NUMBER(np);
308

    
309
        NUMBER[] ords = new NUMBER[dim * np];
310

    
311
        for (int i = 0; i < np; i++) {
312
            ords[dim * i] = new NUMBER(mp2d.getPoint(i).getX());
313
            ords[(dim * i) + 1] = new NUMBER(mp2d.getPoint(i).getY());
314

    
315
            if (threed) {
316
                ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]);
317
            }
318
        }
319

    
320
        STRUCT resp;
321
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
322
                c);
323
        Object[] obj = new Object[5];
324
        obj[0] = new NUMBER(gtype);
325

    
326
        if (hasSrid) {
327
            obj[1] = new NUMBER(srid);
328
        }
329
        else { // , boolean hasSrid
330
            obj[1] = null;
331
        }
332

    
333
        obj[2] = null;
334
        obj[3] = indices;
335
        obj[4] = ords;
336
        resp = new STRUCT(dsc, c, obj);
337

    
338
        return resp;
339
    }
340

    
341
    private static STRUCT getCircleAsStruct(FCircle2D fcirc, int srid,
342
        Connection _conn, boolean hasSrid) throws SQLException {
343
        int geotype = 2003;
344
        NUMBER[] indices = new NUMBER[3];
345
        indices[0] = new NUMBER(1);
346
        indices[1] = new NUMBER(1003);
347
        indices[2] = new NUMBER(4);
348

    
349
        NUMBER[] ords = new NUMBER[6];
350
        Coordinate[] three_points = getThreePointsOfCircumference(fcirc.getCenter(),
351
                fcirc.getRadio());
352

    
353
        for (int i = 0; i < three_points.length; i++) {
354
            ords[i * 2] = new NUMBER(three_points[i].x);
355
            ords[(i * 2) + 1] = new NUMBER(three_points[i].y);
356
        }
357

    
358
        STRUCT resp;
359
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
360
                _conn);
361
        Object[] obj = new Object[5];
362
        obj[0] = new NUMBER(geotype);
363

    
364
        if (hasSrid) {
365
            obj[1] = new NUMBER(srid);
366
        }
367
        else {
368
            obj[1] = null;
369
        }
370

    
371
        obj[2] = null;
372
        obj[3] = indices;
373
        obj[4] = ords;
374
        resp = new STRUCT(dsc, _conn, obj);
375

    
376
        return resp;
377
    }
378

    
379
    private static Coordinate[] getThreePointsOfCircumference(Point2D cntr,
380
        double radius) {
381
        Coordinate[] resp = new Coordinate[3];
382
        double x;
383
        double y;
384
        double alpha = 0;
385

    
386
        for (int i = 0; i < 3; i++) {
387
            alpha = (i * 120.0 * Math.PI) / 180.0;
388
            x = cntr.getX() + (radius * Math.cos(alpha));
389
            y = cntr.getY() + (radius * Math.sin(alpha));
390
            resp[i] = new Coordinate(x, y);
391
        }
392

    
393
        return resp;
394
    }
395

    
396
    private static Coordinate getSingleCoordinate(FPoint2D p2d) {
397
        // TODO Auto-generated method stub
398
        Coordinate resp = new Coordinate();
399
        resp.x = p2d.getX();
400
        resp.y = p2d.getY();
401

    
402
        if (p2d instanceof FPoint3D) {
403
            resp.z = ((FPoint3D) p2d).getZs()[0];
404
        }
405

    
406
        return resp;
407
    }
408

    
409
    private static ArrayList ensureSensibleLineString(ArrayList cc) {
410
        if (cc.size() == 2) {
411
            if (sameCoordinate((Coordinate) cc.get(0),
412
                        (Coordinate) cc.get(cc.size() - 1))) {
413
                ArrayList resp = new ArrayList();
414
                resp.add(cc.get(0));
415

    
416
                Coordinate newc = new Coordinate((Coordinate) cc.get(0));
417
                newc.x = newc.x + IRRELEVANT_DISTANCE;
418
                resp.add(newc);
419

    
420
                return resp;
421
            }
422
        }
423

    
424
        return cc;
425
    }
426

    
427
    private static boolean sameCoordinate(Coordinate c1, Coordinate c2) {
428
        if (c1.x != c2.x) {
429
            return false;
430
        }
431

    
432
        if (c1.y != c2.y) {
433
            return false;
434
        }
435

    
436
        return true;
437
    }
438

    
439
    private static ArrayList getClosedRelevantPolygon(ArrayList cc) {
440
        if (cc.size() == 2) {
441
            return getMinClosedCoords((Coordinate) cc.get(0));
442
        }
443

    
444
        if (cc.size() == 3) {
445
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(1))) {
446
                return getMinClosedCoords((Coordinate) cc.get(0));
447
            }
448

    
449
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(2))) {
450
                return getMinClosedCoords((Coordinate) cc.get(0));
451
            }
452

    
453
            if (sameCoordinate((Coordinate) cc.get(1), (Coordinate) cc.get(2))) {
454
                return getMinClosedCoords((Coordinate) cc.get(1));
455
            }
456

    
457
            cc.add(cc.get(0));
458

    
459
            return cc;
460
        }
461

    
462
        if (!sameCoordinate((Coordinate) cc.get(0),
463
                    (Coordinate) cc.get(cc.size() - 1))) {
464
            cc.add(cc.get(0));
465
        }
466

    
467
        return cc;
468
    }
469

    
470
    private static ArrayList getMinClosedCoords(Coordinate c) {
471
        ArrayList resp = new ArrayList();
472
        resp.add(c);
473

    
474
        Coordinate nc = new Coordinate(c);
475
        nc.x = nc.x + IRRELEVANT_DISTANCE;
476
        resp.add(nc);
477

    
478
        Coordinate nc2 = new Coordinate(nc);
479
        nc2.y = nc2.y + IRRELEVANT_DISTANCE;
480
        resp.add(nc2);
481

    
482
        resp.add(new Coordinate(c));
483

    
484
        return resp;
485
    }
486

    
487
    private static LinearRing getMinLinearRing(Coordinate c) {
488
        Coordinate[] p = new Coordinate[4];
489
        p[0] = c;
490

    
491
        Coordinate nc = new Coordinate(c);
492
        nc.x = nc.x + IRRELEVANT_DISTANCE;
493

    
494
        Coordinate nc2 = new Coordinate(nc);
495
        nc2.y = nc2.y - IRRELEVANT_DISTANCE;
496
        p[1] = nc;
497
        p[2] = nc2;
498
        p[3] = new Coordinate(c);
499

    
500
        CoordinateArraySequence cs = new CoordinateArraySequence(p);
501
        LinearRing ls = new LinearRing(cs, geomFactory);
502

    
503
        return ls;
504
    }
505

    
506
    private static double[] getMinLinearRingZ() {
507
        double[] resp = new double[4];
508

    
509
        for (int i = 0; i < 4; i++)
510
            resp[i] = 0.0;
511

    
512
        return resp;
513
    }
514

    
515
    private static boolean pointInList(Coordinate testPoint,
516
        Coordinate[] pointList) {
517
        int t;
518
        int numpoints;
519
        Coordinate p;
520

    
521
        numpoints = Array.getLength(pointList);
522

    
523
        for (t = 0; t < numpoints; t++) {
524
            p = pointList[t];
525

    
526
            if ((testPoint.x == p.x) && (testPoint.y == p.y) &&
527
                    ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
528
            ) {
529
                return true;
530
            }
531
        }
532

    
533
        return false;
534
    }
535

    
536
    private static ArrayList getPolygonsEasily(FShape mpolygon) {
537
        boolean threed = false;
538

    
539
        if (mpolygon instanceof FPolygon3D) {
540
            threed = true;
541
        }
542

    
543
        int start_ind = 0;
544
        int end_ind = 0;
545
        int ind = 0;
546
        int new_size;
547
        ArrayList arrayCoords = null;
548
        ArrayList resp = new ArrayList();
549
        Coordinate[] points = null;
550
        int theType = -99;
551
        double[] theData = new double[6];
552
        Coordinate onlyCoord = null;
553
        int numParts = 0;
554

    
555
        PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS);
556

    
557
        while (!theIterator.isDone()) {
558
            //while not done
559
            theType = theIterator.currentSegment(theData);
560

    
561
            if (onlyCoord == null) {
562
                onlyCoord = new Coordinate();
563
                onlyCoord.x = theData[0];
564
                onlyCoord.y = theData[1];
565
            }
566

    
567
            switch (theType) {
568
            case PathIterator.SEG_MOVETO:
569

    
570
                if (arrayCoords == null) {
571
                    arrayCoords = new ArrayList();
572
                }
573
                else {
574
                    end_ind = ind - 1;
575

    
576
                    arrayCoords = getClosedRelevantPolygon(arrayCoords);
577
                    new_size = arrayCoords.size();
578

    
579
                    if (arrayCoords != null) {
580
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
581

    
582
                        try {
583
                            LinearRing aux = geomFactory.createLinearRing(points);
584
                            double[] z = null;
585

    
586
                            if (threed) {
587
                                z = getZ((FPolygon3D) mpolygon, start_ind,
588
                                        end_ind, new_size);
589
                            }
590

    
591
                            LineString3D ring = new LineString3D(aux, z);
592

    
593
                            if (CGAlgorithms.isCCW(points)) {
594
                                resp.add(ring);
595
                            }
596
                            else {
597
                                resp.add(ring.createReverse());
598
                            }
599
                        }
600
                        catch (Exception e) {
601
                            System.err.println("Topology exception: " +
602
                                e.getMessage());
603

    
604
                            return null;
605
                        }
606
                    }
607

    
608
                    arrayCoords = new ArrayList();
609

    
610
                    start_ind = ind;
611
                }
612

    
613
                numParts++;
614

    
615
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
616
                ind++;
617

    
618
                break;
619

    
620
            case PathIterator.SEG_LINETO:
621
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
622
                ind++;
623

    
624
                break;
625

    
626
            case PathIterator.SEG_QUADTO:
627
                System.out.println("SEG_QUADTO Not supported here");
628
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
629
                arrayCoords.add(new Coordinate(theData[2], theData[3]));
630
                ind++;
631
                ind++;
632

    
633
                break;
634

    
635
            case PathIterator.SEG_CUBICTO:
636
                System.out.println("SEG_CUBICTO Not supported here");
637
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
638
                arrayCoords.add(new Coordinate(theData[2], theData[3]));
639
                arrayCoords.add(new Coordinate(theData[4], theData[5]));
640
                ind++;
641
                ind++;
642
                ind++;
643

    
644
                break;
645

    
646
            case PathIterator.SEG_CLOSE:
647

    
648
                // Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
649
                // arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
650
                break;
651
            } //end switch
652

    
653
            theIterator.next();
654
        } //end while loop
655

    
656
        end_ind = ind - 1;
657

    
658
        // null shape:
659
        if (arrayCoords == null) {
660
            arrayCoords = new ArrayList();
661

    
662
            Coordinate _c = new Coordinate(0, 0, 0);
663
            arrayCoords.add(new Coordinate(_c));
664
            arrayCoords.add(new Coordinate(_c));
665
        }
666

    
667
        // --------------------------------------------
668
        arrayCoords = getClosedRelevantPolygon(arrayCoords);
669
        new_size = arrayCoords.size();
670

    
671
        if (arrayCoords != null) {
672
            points = CoordinateArrays.toCoordinateArray(arrayCoords);
673

    
674
            try {
675
                LinearRing aux = geomFactory.createLinearRing(points);
676
                double[] z = null;
677

    
678
                if (threed) {
679
                    z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size);
680
                }
681

    
682
                LineString3D ring = new LineString3D(aux, z);
683

    
684
                if (CGAlgorithms.isCCW(points)) {
685
                    resp.add(ring);
686
                }
687
                else {
688
                    resp.add(ring.createReverse());
689
                }
690
            }
691
            catch (Exception e) {
692
                System.err.println("Topology exception: " + e.getMessage());
693

    
694
                return null;
695
            }
696
        }
697

    
698
        if (resp.size() == 0) {
699
            resp.add(new LineString3D(getMinLinearRing(onlyCoord),
700
                    getMinLinearRingZ()));
701
        }
702

    
703
        return resp;
704
    }
705

    
706
    /**
707
     * Utility method to reverse an array of doubles.
708
     *
709
     * @param _z an array of doubles to be reversed.
710
     *
711
     * @return the reversed array of doubles
712
     */
713
    public static double[] reverseArray(double[] _z) {
714
        int size = _z.length;
715
        double[] resp = new double[size];
716

    
717
        for (int i = 0; i < size; i++) {
718
            resp[i] = _z[size - 1 - i];
719
        }
720

    
721
        return resp;
722
    }
723

    
724
    /**
725
     * Utility method to reverse an array of coordinates
726
     *
727
     * @param _z an array of coordinaes to be reversed.
728
     *
729
     * @return the reversed array of coordinates
730
     */
731
    public static Coordinate[] reverseCoordinateArray(Coordinate[] _z) {
732
        int size = _z.length;
733
        Coordinate[] resp = new Coordinate[size];
734

    
735
        for (int i = 0; i < size; i++) {
736
            resp[i] = _z[size - 1 - i];
737
        }
738

    
739
        return resp;
740
    }
741

    
742
    private static double[] getZ(FShape3D p3d, int _str, int _end, int size) {
743
        double[] resp = new double[size];
744
        double[] allz = p3d.getZs();
745

    
746
        for (int i = _str; ((i <= _end) && ((i - _str) < size)); i++) {
747
            resp[i - _str] = allz[i];
748
        }
749

    
750
        if ((_end - _str + 1) < size) {
751
            double repe = allz[_end];
752

    
753
            for (int i = (_end - _str + 1); i < size; i++) {
754
                resp[i] = repe;
755
            }
756
        }
757

    
758
        return resp;
759
    }
760

    
761
    private static ArrayList getLineStrings(FShape mlines) {
762
        boolean threed = false;
763

    
764
        if (mlines instanceof FPolyline3D) {
765
            threed = true;
766
        }
767

    
768
        int start_ind = 0;
769
        int end_ind = 0;
770
        int ind = 0;
771
        int new_size = 0;
772

    
773
        LineString3D lin;
774

    
775
        ArrayList arrayLines = new ArrayList();
776
        PathIterator theIterator = mlines.getPathIterator(null, FLATNESS);
777
        int theType = -99;
778
        double[] theData = new double[6];
779
        ArrayList arrayCoords = null;
780
        int numParts = 0;
781

    
782
        while (!theIterator.isDone()) {
783
            //while not done
784
            theType = theIterator.currentSegment(theData);
785

    
786
            switch (theType) {
787
            case PathIterator.SEG_MOVETO:
788

    
789
                // System.out.println("SEG_MOVETO");
790
                if (arrayCoords == null) {
791
                    arrayCoords = new ArrayList();
792
                }
793
                else {
794
                    end_ind = ind - 1;
795
                    arrayCoords = ensureSensibleLineString(arrayCoords);
796
                    new_size = arrayCoords.size();
797

    
798
                    LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
799
                                arrayCoords));
800
                    double[] z = null;
801

    
802
                    if (threed) {
803
                        z = getZ((FPolyline3D) mlines, start_ind, end_ind,
804
                                new_size);
805
                    }
806

    
807
                    lin = new LineString3D(aux, z);
808
                    arrayLines.add(lin);
809
                    arrayCoords = new ArrayList();
810

    
811
                    start_ind = ind;
812
                }
813

    
814
                numParts++;
815
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
816

    
817
                break;
818

    
819
            case PathIterator.SEG_LINETO:
820
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
821

    
822
                break;
823

    
824
            case PathIterator.SEG_QUADTO:
825
                System.out.println("Not supported here");
826

    
827
                break;
828

    
829
            case PathIterator.SEG_CUBICTO:
830
                System.out.println("Not supported here");
831

    
832
                break;
833

    
834
            case PathIterator.SEG_CLOSE:
835

    
836
                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
837
                arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
838

    
839
                break;
840
            } //end switch
841

    
842
            theIterator.next();
843
            ind++;
844
        } //end while loop
845

    
846
        arrayCoords = ensureSensibleLineString(arrayCoords);
847
        new_size = arrayCoords.size();
848

    
849
        LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
850
                    arrayCoords));
851
        double[] z = null;
852

    
853
        if (threed) {
854
            z = getZ((FPolyline3D) mlines, start_ind, end_ind, new_size);
855
        }
856

    
857
        lin = new LineString3D(aux, z);
858
        arrayLines.add(lin);
859

    
860
        return arrayLines;
861
    }
862

    
863
    private static String lineStringToWKT(LineString3D ls, boolean threed) {
864
        String resp = "(";
865
        Coordinate[] cc = ls.getLs().getCoordinates();
866
        double[] z = ls.getZc();
867
        int size = cc.length;
868

    
869
        if (threed) {
870
            for (int i = 0; i < size; i++) {
871
                resp = resp + cc[i].x + " " + cc[i].y + " " + z[i] + ", ";
872
            }
873

    
874
            resp = resp.substring(0, resp.length() - 2);
875
            resp = resp + ")";
876
        }
877
        else {
878
            for (int i = 0; i < size; i++) {
879
                resp = resp + cc[i].x + " " + cc[i].y + ", ";
880
            }
881

    
882
            resp = resp.substring(0, resp.length() - 2);
883
            resp = resp + ")";
884
        }
885

    
886
        return resp;
887
    }
888

    
889
    private static String multiLineStringToWKT(ArrayList ml, boolean threed) {
890
        String resp = "MULTILINESTRING(";
891

    
892
        for (int i = 0; i < ml.size(); i++) {
893
            LineString3D ls = (LineString3D) ml.get(i);
894
            resp = resp + lineStringToWKT(ls, threed) + ", ";
895
        }
896

    
897
        resp = resp.substring(0, resp.length() - 2) + ")";
898

    
899
        return resp;
900
    }
901

    
902
    private static String polygonsToWKT(ArrayList pols, boolean threed) {
903
        String resp = "MULTIPOLYGON(";
904
        LineString3D ls = null;
905

    
906
        for (int i = 0; i < pols.size(); i++) {
907
            ls = (LineString3D) pols.get(i);
908
            resp = resp + "(" + lineStringToWKT(ls, threed) + "), ";
909
        }
910

    
911
        resp = resp.substring(0, resp.length() - 2) + ")";
912

    
913
        return resp;
914
    }
915

    
916
    private static String shellAndHolesToWKT(LineString3D shell,
917
        ArrayList holes, boolean threed) {
918
        String resp = "(";
919
        resp = resp + lineStringToWKT(shell, threed);
920

    
921
        if (holes.size() > 0) {
922
            for (int i = 0; i < holes.size(); i++) {
923
                LineString3D ls = (LineString3D) holes.get(i);
924
                resp = resp + ", " + lineStringToWKT(ls, threed);
925
            }
926
        }
927

    
928
        resp = resp + ")";
929

    
930
        return resp;
931
    }
932

    
933
    private static String multiPolygonToWKT(ArrayList shells, ArrayList hFs,
934
        boolean threed) {
935
        String resp = "MULTIPOLYGON(";
936
        LineString3D ls = null;
937
        ArrayList holes;
938

    
939
        for (int i = 0; i < shells.size(); i++) {
940
            ls = (LineString3D) shells.get(i);
941
            holes = (ArrayList) hFs.get(i);
942
            resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
943
        }
944

    
945
        resp = resp.substring(0, resp.length() - 2) + ")";
946

    
947
        return resp;
948
    }
949

    
950
    private static String pointToWKT(FPoint2D point, boolean threed) {
951
        String resp = "POINT(" + point.getX() + " " + point.getY();
952

    
953
        if ((threed) && (point instanceof FPoint3D)) {
954
            resp = resp + " " + ((FPoint3D) point).getZs()[0];
955
        }
956

    
957
        resp = resp + ")";
958

    
959
        return resp;
960
    }
961

    
962
    private static int twoDIndexToDimsIndex(int n, int d) {
963
        return ((d * (n - 1)) / 2) + 1;
964
    }
965

    
966
    private static ARRAY setSubelementsToDim(ARRAY old, int d)
967
        throws SQLException {
968
        Datum[] infos = (Datum[]) old.getOracleArray();
969

    
970
        for (int i = 3; i < infos.length; i = i + 3) {
971
            int oldind = infos[i].intValue();
972
            oldind = twoDIndexToDimsIndex(oldind, d);
973
            infos[i] = new NUMBER(oldind);
974

    
975
            // 
976
            oldind = infos[i + 1].intValue();
977
            infos[i + 1] = new NUMBER(infos[1].intValue());
978
        }
979

    
980
        ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(),
981
                infos);
982

    
983
        return resp;
984
    }
985

    
986
    private static boolean isPointInsideLineString(Coordinate p, LineString ls) {
987
        Envelope env = ls.getEnvelopeInternal();
988

    
989
        if (!env.contains(p)) {
990
            return false;
991
        }
992

    
993
        return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
994
    }
995

    
996
    private static boolean lineString3DIsContainedBy(LineString3D contained,
997
        LineString3D container) {
998
        int samples = 10;
999
        LineString _in = contained.getLs();
1000
        LineString _out = container.getLs();
1001
        Coordinate[] inc = _in.getCoordinates();
1002
        Coordinate aux;
1003
        int size = inc.length;
1004

    
1005
        if (size <= 10) {
1006
            for (int i = 0; i < size; i++) {
1007
                aux = inc[i];
1008

    
1009
                if (!isPointInsideLineString(aux, _out)) {
1010
                    return false;
1011
                }
1012
            }
1013

    
1014
            return true;
1015
        }
1016
        else {
1017
            for (int i = 0; i < samples; i++) {
1018
                aux = inc[rnd.nextInt(size)];
1019

    
1020
                if (!isPointInsideLineString(aux, _out)) {
1021
                    return false;
1022
                }
1023
            }
1024

    
1025
            return true;
1026
        }
1027
    }
1028

    
1029
    private static STRUCT getMultiPolygonAsStruct(ArrayList pols, int srid,
1030
        boolean threed, Connection _conn, boolean agu_bien, boolean hasSrid)
1031
        throws SQLException {
1032
        int size = pols.size();
1033
        int geotype = 2007;
1034
        int dim = 2;
1035
        int acum = 0;
1036

    
1037
        if (threed) {
1038
            geotype = 3007;
1039
            dim = 3;
1040
        }
1041

    
1042
        NUMBER[] indices = new NUMBER[3 * size];
1043

    
1044
        for (int i = 0; i < size; i++) {
1045
            indices[3 * i] = new NUMBER(acum + 1);
1046
            indices[(3 * i) + 1] = new NUMBER(1003);
1047
            indices[(3 * i) + 2] = new NUMBER(1);
1048
            acum = acum +
1049
                (dim * ((LineString3D) pols.get(i)).getLs().getNumPoints());
1050
        }
1051

    
1052
        int _ind = 0;
1053
        NUMBER[] ords = new NUMBER[acum];
1054

    
1055
        for (int i = 0; i < size; i++) {
1056
            LineString3D ls = (LineString3D) pols.get(i);
1057
            int num_p = ls.getLs().getNumPoints();
1058

    
1059
            for (int j = 0; j < num_p; j++) {
1060
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1061
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1062

    
1063
                if (threed) {
1064
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1065
                }
1066

    
1067
                _ind = _ind + dim;
1068
            }
1069
        }
1070

    
1071
        STRUCT resp;
1072
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1073
                _conn);
1074
        Object[] obj = new Object[5];
1075
        obj[0] = new NUMBER(geotype);
1076

    
1077
        if (hasSrid) {
1078
            obj[1] = new NUMBER(srid);
1079
        }
1080
        else {
1081
            obj[1] = null;
1082
        }
1083

    
1084
        obj[2] = null;
1085
        obj[3] = indices;
1086
        obj[4] = ords;
1087
        resp = new STRUCT(dsc, _conn, obj);
1088

    
1089
        return resp;
1090
    }
1091

    
1092
    private static STRUCT getMultiLineAsStruct(ArrayList lines, int srid,
1093
        boolean threed, Connection _conn, boolean hasSrid)
1094
        throws SQLException {
1095
        /*
1096
        if (lines.size() == 1) {
1097
                return getOneLineStringAsStruct((LineString3D) lines.get(0), srid, threed, _conn);
1098
        }
1099
        */
1100
        int size = lines.size();
1101
        int geotype = 2006;
1102
        int dim = 2;
1103
        int acum = 0;
1104

    
1105
        if (threed) {
1106
            geotype = 3006;
1107
            dim = 3;
1108
        }
1109

    
1110
        NUMBER[] indices = new NUMBER[3 * size];
1111

    
1112
        for (int i = 0; i < size; i++) {
1113
            indices[3 * i] = new NUMBER(acum + 1);
1114
            indices[(3 * i) + 1] = new NUMBER(2);
1115
            indices[(3 * i) + 2] = new NUMBER(1);
1116
            acum = acum +
1117
                (dim * ((LineString3D) lines.get(i)).getLs().getNumPoints());
1118
        }
1119

    
1120
        int _ind = 0;
1121
        NUMBER[] ords = new NUMBER[acum];
1122

    
1123
        for (int i = 0; i < size; i++) {
1124
            LineString3D ls = (LineString3D) lines.get(i);
1125
            int num_p = ls.getLs().getNumPoints();
1126

    
1127
            for (int j = 0; j < num_p; j++) {
1128
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1129
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1130

    
1131
                if (threed) {
1132
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1133
                }
1134

    
1135
                _ind = _ind + dim;
1136
            }
1137
        }
1138

    
1139
        STRUCT resp;
1140
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1141
                _conn);
1142
        Object[] obj = new Object[5];
1143
        obj[0] = new NUMBER(geotype);
1144

    
1145
        if (hasSrid) {
1146
            obj[1] = new NUMBER(srid);
1147
        }
1148
        else {
1149
            obj[1] = null;
1150
        }
1151

    
1152
        obj[2] = null;
1153
        obj[3] = indices;
1154
        obj[4] = ords;
1155
        resp = new STRUCT(dsc, _conn, obj);
1156

    
1157
        return resp;
1158
    }
1159

    
1160
    private static STRUCT getMultiPointAsStruct(Coordinate pnt, int srid,
1161
        boolean threed, Connection _conn, boolean hasSrid)
1162
        throws SQLException {
1163
        int geotype = 2001;
1164
        int dim = 2;
1165

    
1166
        if (threed) {
1167
            geotype = 3001;
1168
            dim = 3;
1169
        }
1170

    
1171
        Object[] ords = new Object[3];
1172
        ords[0] = new NUMBER(pnt.x);
1173
        ords[1] = new NUMBER(pnt.y);
1174
        ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null; // ole ole y ole
1175

    
1176
        StructDescriptor ord_dsc = StructDescriptor.createDescriptor("MDSYS.SDO_POINT_TYPE",
1177
                _conn);
1178
        STRUCT ords_st = new STRUCT(ord_dsc, _conn, ords);
1179

    
1180
        STRUCT resp;
1181

    
1182
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1183
                _conn);
1184
        Object[] obj = new Object[5];
1185

    
1186
        obj[0] = new NUMBER(geotype);
1187

    
1188
        if (hasSrid) {
1189
            obj[1] = new NUMBER(srid);
1190
        }
1191
        else {
1192
            obj[1] = null;
1193
        }
1194

    
1195
        obj[2] = ords_st;
1196
        obj[3] = null;
1197
        obj[4] = null;
1198
        resp = new STRUCT(dsc, _conn, obj);
1199

    
1200
        return resp;
1201
    }
1202

    
1203
    /**
1204
     * Utility method to compute a circle's center and radius from three given points.
1205
     *
1206
     * @param points three points of a circumference
1207
     * @return a 2-item array with the circumference's center (Point2D) and radius (Double)
1208
     */
1209
    public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) {
1210
        Object[] resp = new Object[2];
1211
        resp[0] = new Point2D.Double(0, 0);
1212
        resp[1] = new Double(0);
1213

    
1214
        double m11;
1215
        double m12;
1216
        double m13;
1217
        double m14;
1218

    
1219
        if (points.length != 3) {
1220
            logger.error("Needs 3 points (found " + points.length +
1221
                ") - circle cannot be computed.");
1222

    
1223
            // not a circle
1224
            return resp;
1225
        }
1226

    
1227
        double[][] a = new double[3][3];
1228

    
1229
        for (int i = 0; i < 3; i++) { // find minor 11
1230
            a[i][0] = points[i].getX();
1231
            a[i][1] = points[i].getY();
1232
            a[i][2] = 1;
1233
        }
1234

    
1235
        m11 = determinant(a, 3);
1236

    
1237
        for (int i = 0; i < 3; i++) { // find minor 12 
1238
            a[i][0] = (points[i].getX() * points[i].getX()) +
1239
                (points[i].getY() * points[i].getY());
1240
            a[i][1] = points[i].getY();
1241
            a[i][2] = 1;
1242
        }
1243

    
1244
        m12 = determinant(a, 3);
1245

    
1246
        for (int i = 0; i < 3; i++) // find minor 13
1247
         {
1248
            a[i][0] = (points[i].getX() * points[i].getX()) +
1249
                (points[i].getY() * points[i].getY());
1250
            a[i][1] = points[i].getX();
1251
            a[i][2] = 1;
1252
        }
1253

    
1254
        m13 = determinant(a, 3);
1255

    
1256
        for (int i = 0; i < 3; i++) { // find minor 14
1257
            a[i][0] = (points[i].getX() * points[i].getX()) +
1258
                (points[i].getY() * points[i].getY());
1259
            a[i][1] = points[i].getX();
1260
            a[i][2] = points[i].getY();
1261
        }
1262

    
1263
        m14 = determinant(a, 3);
1264

    
1265
        Double resp_radius = new Double(0);
1266
        Point2D resp_center = new Point2D.Double(0, 0);
1267

    
1268
        if (m11 == 0) {
1269
            logger.error("Three points aligned - circle cannot be computed."); // not a circle
1270
        }
1271
        else {
1272
            double x = (0.5 * m12) / m11;
1273
            double y = (-0.5 * m13) / m11;
1274
            resp_center.setLocation(x, y);
1275
            resp_radius = new Double(Math.sqrt((x * x) + (y * y) + (m14 / m11)));
1276
            resp[0] = resp_center;
1277
            resp[1] = resp_radius;
1278
        }
1279

    
1280
        return resp;
1281
    }
1282

    
1283
    /**
1284
     * Utility method to compute a matrix determinant
1285
     * @param a the matrix
1286
     * @param n matrix size
1287
     * @return the matrix's determinant
1288
     */
1289
    public static double determinant(double[][] a, int n) {
1290
        double resp = 0;
1291
        double[][] m = new double[3][3];
1292

    
1293
        if (n == 2) { // terminate recursion
1294
            resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]);
1295
        }
1296
        else {
1297
            resp = 0;
1298

    
1299
            for (int j1 = 0; j1 < n; j1++) { // do each column
1300

    
1301
                for (int i = 1; i < n; i++) { // create minor
1302

    
1303
                    int j2 = 0;
1304

    
1305
                    for (int j = 0; j < n; j++) {
1306
                        if (j == j1) {
1307
                            continue;
1308
                        }
1309

    
1310
                        m[i - 1][j2] = a[i][j];
1311
                        j2++;
1312
                    }
1313
                }
1314

    
1315
                // sum (+/-)cofactor * minor  
1316
                resp = resp +
1317
                    (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1));
1318
            }
1319
        }
1320

    
1321
        return resp;
1322
    }
1323

    
1324
    private static int getSmallestContainerExcept(LineString3D ls,
1325
        ArrayList list, int self) {
1326
        int resp = -1;
1327
        ArrayList provList = new ArrayList();
1328

    
1329
        int size = list.size();
1330

    
1331
        for (int i = 0; i < self; i++) {
1332
            if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1333
                provList.add(new Integer(i));
1334
            }
1335
        }
1336

    
1337
        for (int i = (self + 1); i < size; i++) {
1338
            if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1339
                provList.add(new Integer(i));
1340
            }
1341
        }
1342

    
1343
        if (provList.size() == 0) {
1344
            // logger.debug("LineString is not contained by any other ls.");
1345
        }
1346
        else {
1347
            if (provList.size() == 1) {
1348
                resp = ((Integer) provList.get(0)).intValue();
1349
            }
1350
            else {
1351
                if (provList.size() == 2) {
1352
                    int ind_1 = ((Integer) provList.get(0)).intValue();
1353
                    int ind_2 = ((Integer) provList.get(1)).intValue();
1354
                    LineString3D ls1 = (LineString3D) list.get(ind_1);
1355
                    LineString3D ls2 = (LineString3D) list.get(ind_2);
1356

    
1357
                    if (lineString3DIsContainedBy(ls1, ls2)) {
1358
                        resp = ind_1;
1359
                    }
1360
                    else {
1361
                        resp = ind_2;
1362
                    }
1363
                }
1364
                else {
1365
                    // not so deep, sorry!
1366
                    // it's going to be a shell: resp = -1;
1367
                }
1368
            }
1369
        }
1370

    
1371
        return resp;
1372
    }
1373

    
1374
    private static int[] getIndicesOfShells(int[] containings) {
1375
        ArrayList resp = new ArrayList();
1376

    
1377
        for (int i = 0; i < containings.length; i++) {
1378
            if (containings[i] == -1) {
1379
                resp.add(new Integer(i));
1380
            }
1381
        }
1382

    
1383
        int size = resp.size();
1384
        int[] _resp = new int[size];
1385

    
1386
        for (int i = 0; i < size; i++) {
1387
            _resp[i] = ((Integer) resp.get(i)).intValue();
1388
        }
1389

    
1390
        return _resp;
1391
    }
1392

    
1393
    private static int[] getIndicesOfHoles(int[] containings, int[] shells) {
1394
        ArrayList resp = new ArrayList();
1395

    
1396
        for (int i = 0; i < containings.length; i++) {
1397
            int cont_by = containings[i];
1398

    
1399
            if ((cont_by != -1) && (isOneOf(cont_by, shells))) {
1400
                resp.add(new Integer(i));
1401
            }
1402
        }
1403

    
1404
        int size = resp.size();
1405
        int[] _resp = new int[size];
1406

    
1407
        for (int i = 0; i < size; i++) {
1408
            _resp[i] = ((Integer) resp.get(i)).intValue();
1409
        }
1410

    
1411
        return _resp;
1412
    }
1413

    
1414
    private static int[] getFinalContainings(int[] containings, int[] holes) {
1415
        ArrayList resp = new ArrayList();
1416

    
1417
        for (int i = 0; i < containings.length; i++) {
1418
            int cont_by = containings[i];
1419

    
1420
            if (isOneOf(cont_by, holes)) {
1421
                resp.add(new Integer(-1));
1422
            }
1423
            else {
1424
                resp.add(new Integer(cont_by));
1425
            }
1426
        }
1427

    
1428
        int size = resp.size();
1429
        int[] _resp = new int[size];
1430

    
1431
        for (int i = 0; i < size; i++) {
1432
            _resp[i] = ((Integer) resp.get(i)).intValue();
1433
        }
1434

    
1435
        return _resp;
1436
    }
1437

    
1438
    private static ArrayList getHolesOf(int ind, int[] final_contn,
1439
        ArrayList all) {
1440
        ArrayList resp_ind = new ArrayList();
1441

    
1442
        for (int i = 0; i < final_contn.length; i++) {
1443
            if (final_contn[i] == ind) {
1444
                resp_ind.add(new Integer(i));
1445
            }
1446
        }
1447

    
1448
        ArrayList resp = new ArrayList();
1449

    
1450
        for (int i = 0; i < resp_ind.size(); i++) {
1451
            Integer aux = (Integer) resp_ind.get(i);
1452
            resp.add(all.get(aux.intValue()));
1453
        }
1454

    
1455
        return resp;
1456
    }
1457

    
1458
    private static ArrayList getShellsIn(int[] final_contn, ArrayList all) {
1459
        ArrayList resp_ind = new ArrayList();
1460

    
1461
        for (int i = 0; i < final_contn.length; i++) {
1462
            if (final_contn[i] == -1) {
1463
                resp_ind.add(new Integer(i));
1464
            }
1465
        }
1466

    
1467
        ArrayList resp = new ArrayList();
1468

    
1469
        for (int i = 0; i < resp_ind.size(); i++) {
1470
            Integer aux = (Integer) resp_ind.get(i);
1471
            resp.add(all.get(aux.intValue()));
1472
        }
1473

    
1474
        return resp;
1475
    }
1476

    
1477
    /**
1478
     * This method tries to guess who is a shell and who is a hole from a set of
1479
     * linestrings.
1480
     *
1481
     * @param all_ls a set of linestrings to be checked.
1482
     *
1483
     * @return a 2-item array. the first is an arraylist of linestrings thought to be shells.
1484
     * the second is an array of arraylists containing the holes of each shell found in the
1485
     * first item
1486
     *
1487
     */
1488
    public static Object[] getHolesForShells(ArrayList all_ls) {
1489
        int no_of_ls = all_ls.size();
1490
        int[] containedby = new int[no_of_ls];
1491
        int[] shells;
1492
        int[] holes;
1493
        int[] final_cont;
1494

    
1495
        for (int i = 0; i < no_of_ls; i++) {
1496
            LineString3D ls_aux = (LineString3D) all_ls.get(i);
1497
            containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i);
1498
        }
1499

    
1500
        shells = getIndicesOfShells(containedby);
1501
        holes = getIndicesOfHoles(containedby, shells);
1502
        final_cont = getFinalContainings(containedby, holes);
1503

    
1504
        // true shells:
1505
        shells = getIndicesOfShells(final_cont);
1506

    
1507
        ArrayList resp_shells = new ArrayList();
1508
        ArrayList resp_holes_for_shells = new ArrayList();
1509
        ArrayList aux_holes;
1510

    
1511
        for (int i = 0; i < shells.length; i++) {
1512
            resp_shells.add(all_ls.get(shells[i]));
1513
            aux_holes = getHolesOf(i, final_cont, all_ls);
1514
            resp_holes_for_shells.add(aux_holes);
1515
        }
1516

    
1517
        Object[] _resp = new Object[2];
1518
        _resp[0] = resp_shells;
1519
        _resp[1] = resp_holes_for_shells;
1520

    
1521
        return _resp;
1522
    }
1523

    
1524
    private static int getTotalSize(ArrayList listOfLists) {
1525
        int resp = 0;
1526

    
1527
        for (int i = 0; i < listOfLists.size(); i++) {
1528
            resp = resp + ((ArrayList) listOfLists.get(i)).size();
1529
        }
1530

    
1531
        return resp;
1532
    }
1533

    
1534
    // private static STRUCT // private static ArrayList getPolygonsEasily(FShape mpolygon) {
1535
    private static STRUCT getMultiPolygonAsStruct(FShape mpol, int srid,
1536
        boolean threed, Connection _conn, boolean agu_bien, boolean hasSrid)
1537
        throws SQLException {
1538
        ArrayList all_ls = getPolygonsEasily(mpol);
1539
        Object[] hs = getHolesForShells(all_ls);
1540
        ArrayList sh = (ArrayList) hs[0];
1541
        ArrayList _ho = (ArrayList) hs[1];
1542
        ArrayList ho = reverseHoles(_ho);
1543

    
1544
        return getMultiPolygonAsStruct(sh, ho, srid, threed, _conn, agu_bien,
1545
            hasSrid);
1546
    }
1547

    
1548
    private static ArrayList reverseHoles(ArrayList hh) {
1549
        ArrayList resp = new ArrayList();
1550

    
1551
        for (int i = 0; i < hh.size(); i++) {
1552
            ArrayList item = (ArrayList) hh.get(i);
1553
            ArrayList newitem = new ArrayList();
1554

    
1555
            for (int j = 0; j < item.size(); j++) {
1556
                LineString3D ls = (LineString3D) item.get(j);
1557
                newitem.add(ls.createReverse());
1558
            }
1559

    
1560
            resp.add(newitem);
1561
        }
1562

    
1563
        return resp;
1564
    }
1565

    
1566
    private static STRUCT getMultiPolygonAsStruct(ArrayList shells,
1567
        ArrayList holes, int srid, boolean threed, Connection _conn,
1568
        boolean explicito, boolean hasSrid) throws SQLException {
1569
        int t = 1003;
1570

    
1571
        if (explicito) {
1572
            t = 2003;
1573
        }
1574

    
1575
        int size = shells.size() + getTotalSize(holes);
1576
        int geotype = 2007;
1577
        int dim = 2;
1578

    
1579
        if (threed) {
1580
            geotype = 3007;
1581
            dim = 3;
1582
        }
1583

    
1584
        NUMBER[] indices = new NUMBER[3 * size];
1585

    
1586
        int acum = 0;
1587
        int start_ind = 0;
1588

    
1589
        for (int i = 0; i < shells.size(); i++) {
1590
            indices[start_ind] = new NUMBER(acum + 1);
1591
            indices[start_ind + 1] = new NUMBER(1003);
1592
            indices[start_ind + 2] = new NUMBER(1);
1593
            start_ind = start_ind + 3;
1594
            acum = acum +
1595
                (dim * ((LineString3D) shells.get(i)).getLs().getNumPoints());
1596

    
1597
            ArrayList item_holes = (ArrayList) holes.get(i);
1598

    
1599
            for (int j = 0; j < item_holes.size(); j++) {
1600
                indices[start_ind] = new NUMBER(acum + 1);
1601
                indices[start_ind + 1] = new NUMBER(t); // 1003
1602
                indices[start_ind + 2] = new NUMBER(1);
1603
                start_ind = start_ind + 3;
1604
                acum = acum +
1605
                    (dim * ((LineString3D) item_holes.get(j)).getLs()
1606
                            .getNumPoints());
1607
            }
1608
        }
1609

    
1610
        int _ind = 0;
1611
        NUMBER[] ords = new NUMBER[acum];
1612

    
1613
        for (int i = 0; i < shells.size(); i++) {
1614
            // --------------------------------
1615
            LineString3D ls = (LineString3D) shells.get(i);
1616
            int num_p = ls.getLs().getNumPoints();
1617

    
1618
            for (int j = 0; j < num_p; j++) {
1619
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1620
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1621

    
1622
                if (threed) {
1623
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1624
                }
1625

    
1626
                _ind = _ind + dim;
1627
            }
1628

    
1629
            // -------------------------------
1630
            ArrayList item_holes = (ArrayList) holes.get(i);
1631

    
1632
            for (int j = 0; j < item_holes.size(); j++) {
1633
                ls = (LineString3D) item_holes.get(j);
1634
                num_p = ls.getLs().getNumPoints();
1635

    
1636
                for (int k = 0; k < num_p; k++) {
1637
                    ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(k).x);
1638
                    ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y);
1639

    
1640
                    if (threed) {
1641
                        ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1642
                    }
1643

    
1644
                    _ind = _ind + dim;
1645
                }
1646
            }
1647
        }
1648

    
1649
        STRUCT resp;
1650
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1651
                _conn);
1652
        Object[] obj = new Object[5];
1653
        obj[0] = new NUMBER(geotype);
1654

    
1655
        if (hasSrid) {
1656
            obj[1] = new NUMBER(srid);
1657
        }
1658
        else {
1659
            obj[1] = null;
1660
        }
1661

    
1662
        obj[2] = null;
1663
        obj[3] = indices;
1664
        obj[4] = ords;
1665

    
1666
        // String ind_str = printArray(indices);
1667
        // String ord_str = printArray(ords);
1668
        resp = new STRUCT(dsc, _conn, obj);
1669

    
1670
        return resp;
1671
    }
1672

    
1673
    public static String printArray(NUMBER[] array) {
1674
        String resp = "[ ";
1675

    
1676
        for (int i = 0; i < array.length; i++) {
1677
            resp = resp + " " + array[i].doubleValue() + " , ";
1678
        }
1679

    
1680
        resp = resp.substring(0, resp.length() - 2) + "]";
1681

    
1682
        return resp;
1683
    }
1684

    
1685
    private static boolean isOneOf(int ind, int[] list) {
1686
        for (int i = 0; i < list.length; i++) {
1687
            if (list[i] == ind) {
1688
                return true;
1689
            }
1690
        }
1691

    
1692
        return false;
1693
    }
1694

    
1695
    /**
1696
     * This method appends the geometries from a geometry collection in one STRUCT.
1697
     *
1698
     * @param co the geometry collection
1699
     * @param _forced_type a type that has to be used as the struct's main type
1700
     * @param _conn the connection
1701
     * @param _o_srid the geometry's SRS (oracle code)
1702
     * @param withSrid whether the SRS is non-NULL
1703
     * @param agu_bien whether to check holes' validity
1704
     * @param _isGeoCS whether the SRS is geodetic
1705
     * @return the STRUCT with the appended geometries
1706
     */
1707
    public static STRUCT appendGeometriesInStruct(FGeometryCollection co,
1708
        int _forced_type, Connection _conn, String _o_srid, boolean withSrid,
1709
        boolean agu_bien, boolean _isGeoCS) {
1710
        IGeometry[] geoms = co.getGeometries();
1711
        int size = geoms.length;
1712
        STRUCT[] sts = new STRUCT[size];
1713

    
1714
        for (int i = 0; i < size; i++) {
1715
            sts[i] = OracleSpatialDriver.iGeometryToSTRUCT(geoms[i],
1716
                    _forced_type, _conn, _o_srid, withSrid, agu_bien, _isGeoCS);
1717
        }
1718

    
1719
        if (size == 1) {
1720
            return sts[0];
1721
        }
1722

    
1723
        STRUCT aux = sts[0];
1724

    
1725
        for (int i = 1; i < size; i++) {
1726
            aux = appendStructs(aux, sts[i], _conn);
1727
        }
1728

    
1729
        return aux;
1730
    }
1731

    
1732
    private static STRUCT appendStructs(STRUCT st1, STRUCT st2, Connection _conn) {
1733
        try {
1734
            ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1735
            int length_of_head_ords = _ords.getOracleArray().length;
1736

    
1737
            NUMBER gtype = new NUMBER(4 +
1738
                    (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000));
1739
            NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1740
            NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1741

    
1742
            ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1743
            ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1744
            ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1745
            ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1746

    
1747
            Datum[] info = appendDatumArrays(info1.getOracleArray(),
1748
                    info2.getOracleArray(), length_of_head_ords);
1749

    
1750
            Datum[] ords = appendDatumArrays(ords1.getOracleArray(),
1751
                    ords2.getOracleArray(), 0);
1752

    
1753
            StructDescriptor dsc = st1.getDescriptor();
1754

    
1755
            Object[] atts = new Object[5];
1756
            atts[0] = gtype;
1757
            atts[1] = srid;
1758
            atts[2] = middle;
1759
            atts[3] = info;
1760
            atts[4] = ords;
1761

    
1762
            STRUCT resp = new STRUCT(dsc, _conn, atts);
1763

    
1764
            return resp;
1765
        }
1766
        catch (SQLException sqle) {
1767
            logger.error("While appending structs: " + sqle.getMessage(), sqle);
1768
        }
1769

    
1770
        return null;
1771
    }
1772

    
1773
    private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail,
1774
        int offset) {
1775
        int head_l = head.length;
1776
        int tail_l = tail.length;
1777
        Datum[] resp = new Datum[head_l + tail_l];
1778

    
1779
        for (int i = 0; i < head_l; i++)
1780
            resp[i] = head[i];
1781

    
1782
        if (offset == 0) {
1783
            for (int i = 0; i < tail_l; i++)
1784
                resp[head_l + i] = tail[i];
1785
        }
1786
        else {
1787
            try {
1788
                for (int i = 0; i < tail_l; i++) {
1789
                    if ((i % 3) == 0) {
1790
                        resp[head_l + i] = new NUMBER(tail[i].intValue() +
1791
                                offset);
1792
                    }
1793
                    else {
1794
                        resp[head_l + i] = tail[i];
1795
                    }
1796
                }
1797
            }
1798
            catch (SQLException se) {
1799
                logger.error("Unexpected error: " + se.getMessage());
1800
            }
1801
        }
1802

    
1803
        return resp;
1804
    }
1805

    
1806
    /**
1807
     * Utility method to get an ineteger as a formatted string.
1808
     *
1809
     * @param n the integer
1810
     * @return the formatted string
1811
     */
1812
    public static String getFormattedInteger(int n) {
1813
        df.setGroupingUsed(true);
1814
        df.setGroupingSize(3);
1815
        dfs.setGroupingSeparator('.');
1816
        df.setDecimalFormatSymbols(dfs);
1817

    
1818
        return df.format(n);
1819
    }
1820

    
1821
    /**
1822
     * Tells whether these arrays belong to a rectangle polygon.
1823
     *
1824
     * @param info the struct's element info array
1825
     * @param ords the struct's coordinate array
1826
     * @return true if it is a rectangle polygon. false otherwise.
1827
     */
1828
    public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
1829
        try {
1830
            int[] infos = info.getIntArray();
1831

    
1832
            return ((infos[2] == 3) && (infos.length == 3));
1833
        }
1834
        catch (SQLException se) {
1835
            logger.error("While ckecking rectangle: " + se.getMessage(), se);
1836
        }
1837

    
1838
        return false;
1839
    }
1840

    
1841
    /**
1842
     * Utility method to deal with oracle info arrays.
1843
     */
1844
    public static ARRAY getDevelopedInfoArray(ARRAY info) {
1845
        ARRAY _resp = null;
1846

    
1847
        try {
1848
            Datum[] resp = new Datum[3];
1849
            Datum[] in = info.getOracleArray();
1850
            resp[0] = in[0];
1851
            resp[1] = in[1];
1852
            resp[2] = new NUMBER(1);
1853
            _resp = new ARRAY(info.getDescriptor(),
1854
                    info.getInternalConnection(), resp);
1855
        }
1856
        catch (SQLException se) {
1857
            logger.error("While creating ARRAY: " + se.getMessage(), se);
1858
        }
1859

    
1860
        return _resp;
1861
    }
1862

    
1863
    /**
1864
     * Utility method to deal with oracle coordinate arrays.
1865
     */
1866
    public static ARRAY getDevelopedOrdsArray(ARRAY ords) {
1867
        ARRAY _resp = null;
1868

    
1869
        try {
1870
            Datum[] resp = new Datum[10];
1871
            Datum[] corners = ords.getOracleArray();
1872

    
1873
            // x
1874
            resp[0] = corners[0];
1875
            resp[2] = corners[2];
1876
            resp[4] = corners[2];
1877
            resp[6] = corners[0];
1878
            resp[8] = corners[0];
1879

    
1880
            // y
1881
            resp[1] = corners[1];
1882
            resp[3] = corners[1];
1883
            resp[5] = corners[3];
1884
            resp[7] = corners[3];
1885
            resp[9] = corners[1];
1886
            _resp = new ARRAY(ords.getDescriptor(),
1887
                    ords.getInternalConnection(), resp);
1888
        }
1889
        catch (SQLException se) {
1890
            logger.error("While creating ARRAY: " + se.getMessage(), se);
1891
        }
1892

    
1893
        return _resp;
1894
    }
1895

    
1896
    /**
1897
     * utility method to convert a STRUCT into a GeneralPathX
1898
     * @param aux the struct's datum array
1899
     * @return the GeneralPathX instance created
1900
     */
1901
    public static GeneralPathX structToGPX(Datum[] aux) {
1902
        GeneralPathX resp = new GeneralPathX();
1903
        ARRAY infoARRAY = null;
1904
        ARRAY ordsARRAY = null;
1905
        Datum[] info_array = null;
1906
        Datum[] ords_array = null;
1907
        int info_array_size = 0;
1908
        int[] start_ind;
1909
        int[] end_ind;
1910
        int dims = 0;
1911
        boolean next_must_do_first = true;
1912

    
1913
        try {
1914
            infoARRAY = (ARRAY) aux[3];
1915
            ordsARRAY = (ARRAY) aux[4];
1916

    
1917
            if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
1918
                infoARRAY = getDevelopedInfoArray(infoARRAY);
1919
                ordsARRAY = getDevelopedOrdsArray(ordsARRAY);
1920
            }
1921

    
1922
            dims = ((NUMBER) aux[0]).intValue() / 1000;
1923

    
1924
            if (dims == 0) {
1925
                dims = 2;
1926
            }
1927

    
1928
            info_array = (Datum[]) infoARRAY.getOracleArray();
1929
            ords_array = (Datum[]) ordsARRAY.getOracleArray();
1930
            info_array_size = info_array.length / 3;
1931

    
1932
            int last_index = ords_array.length - dims + 1;
1933

    
1934
            // set indices:
1935
            start_ind = new int[info_array_size];
1936
            end_ind = new int[info_array_size];
1937

    
1938
            for (int i = 0; i < info_array_size; i++)
1939
                start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
1940

    
1941
            for (int i = 0; i < (info_array_size - 1); i++)
1942
                end_ind[i] = start_ind[i + 1] - 1;
1943

    
1944
            end_ind[info_array_size - 1] = last_index;
1945

    
1946
            int lineType = PathIterator.SEG_LINETO;
1947

    
1948
            if (end_ind[0] == 0) { // collection of paths
1949

    
1950
                for (int i = 1; i < info_array_size; i++) {
1951
                    lineType = getLineToType(info_array, i);
1952
                    next_must_do_first = addOrdsToGPX(resp, start_ind[i] - 1,
1953
                            end_ind[i] - 1, ords_array, dims, lineType,
1954
                            (i == 1), next_must_do_first);
1955
                }
1956
            }
1957
            else {
1958
                // standard case, do the moveto always
1959
                for (int i = 0; i < info_array_size; i++) {
1960
                    lineType = getLineToType(info_array, i);
1961
                    addOrdsToGPX(resp, start_ind[i] - 1, end_ind[i] - 1,
1962
                        ords_array, dims, lineType, true, true);
1963
                }
1964
            }
1965

    
1966
            // boolean do_the_moves = true;
1967
        }
1968
        catch (SQLException se) {
1969
            logger.error("While creating GPX: " + se.getMessage(), se);
1970
        }
1971

    
1972
        return resp;
1973
    }
1974

    
1975
    private static int getLineToType(Datum[] infos, int i) {
1976
        int resp = PathIterator.SEG_LINETO;
1977

    
1978
        try {
1979
            if (((NUMBER) infos[(3 * i) + 2]).intValue() == 2) {
1980
                resp = PathIterator.SEG_QUADTO;
1981
            }
1982
        }
1983
        catch (SQLException e) {
1984
            logger.error("While getting line-to type: " + e.getMessage() +
1985
                " (returned SEG_LINETO)");
1986
        }
1987

    
1988
        return resp;
1989
    }
1990

    
1991
    private static boolean addOrdsToGPX(GeneralPathX gpx, int zero_based_start,
1992
        int zero_based_include_end, Datum[] ords, int d, int ltype,
1993
        boolean do_the_move, boolean must_do_first) {
1994
        int length = ords.length;
1995
        boolean return_following_must_do_first = true;
1996

    
1997
        double x = ((NUMBER) ords[zero_based_start]).doubleValue();
1998
        double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue();
1999

    
2000
        if (must_do_first) {
2001
            if (do_the_move) {
2002
                gpx.moveTo(x, y);
2003
            }
2004
            else {
2005
                gpx.lineTo(x, y);
2006
            }
2007
        }
2008

    
2009
        int ind = 1;
2010

    
2011
        int size = ((zero_based_include_end - zero_based_start) / d) + 1;
2012
        int indx;
2013
        int indx2;
2014

    
2015
        if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
2016

    
2017
            double x2;
2018
            double y2;
2019

    
2020
            while (ind < size) {
2021
                indx = zero_based_start + (ind * d);
2022
                x = ((NUMBER) ords[indx]).doubleValue();
2023
                y = ((NUMBER) ords[indx + 1]).doubleValue();
2024

    
2025
                indx2 = zero_based_start + ((ind + 1) * d);
2026

    
2027
                if (indx >= length) {
2028
                    indx2 = zero_based_start;
2029
                }
2030

    
2031
                x2 = ((NUMBER) ords[indx2]).doubleValue();
2032
                y2 = ((NUMBER) ords[indx2 + 1]).doubleValue();
2033
                gpx.quadTo(x, y, x2, y2);
2034
                ind++;
2035
                ind++;
2036
            }
2037

    
2038
            return_following_must_do_first = false;
2039
        }
2040
        else { // PathIterator.SEG_LINETO (interpretation = 1)
2041

    
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
                gpx.lineTo(x, y);
2047
                ind++;
2048
            }
2049
        }
2050

    
2051
        return return_following_must_do_first;
2052
    }
2053

    
2054
    /**
2055
     * Utility method. Gets FShape type from oracle geometry type.
2056
     * @param otype
2057
     * @return FShape type
2058
     */
2059
    public static int oracleGTypeToFShapeType(int otype) {
2060
        switch (otype) {
2061
        case ORACLE_GTYPE_UNKNOWN:
2062
            return FShape.NULL;
2063

    
2064
        case ORACLE_GTYPE_POINT:
2065
        case ORACLE_GTYPE_MULTIPOINT:
2066
            return FShape.POINT;
2067

    
2068
        case ORACLE_GTYPE_LINE:
2069
        case ORACLE_GTYPE_MULTILINE:
2070
            return FShape.LINE;
2071

    
2072
        case ORACLE_GTYPE_POLYGON:
2073
        case ORACLE_GTYPE_MULTIPOLYGON:
2074
            return FShape.POLYGON;
2075

    
2076
        case ORACLE_GTYPE_COLLECTION:
2077
            return FShape.MULTI;
2078
        }
2079

    
2080
        logger.warn("Unknown oracle geometry type: " + otype);
2081

    
2082
        return FShape.NULL;
2083
    }
2084

    
2085
    /**
2086
     * Utility method to get struct's type.
2087
     * @param the_data the struct's datum array
2088
     * @return the struct type
2089
     */
2090
    public static int getStructType(Datum[] the_data) {
2091
        int resp = -1;
2092

    
2093
        try {
2094
            resp = ((NUMBER) the_data[0]).intValue() % 1000;
2095
        }
2096
        catch (SQLException se) {
2097
            logger.error("Error: " + se.getMessage(), se);
2098
        }
2099

    
2100
        return resp;
2101
    }
2102

    
2103
    /**
2104
     * Utility method to get struct's SRID.
2105
     * @param the_data the struct's datum array
2106
     * @return the struct0's SRID
2107
     */
2108
    public static int getStructSRID(Datum[] the_data) {
2109
        int resp = -1;
2110

    
2111
        try {
2112
            resp = ((NUMBER) the_data[1]).intValue();
2113
        }
2114
        catch (SQLException se) {
2115
            logger.error("Error: " + se.getMessage(), se);
2116
        }
2117

    
2118
        return resp;
2119
    }
2120

    
2121
    /**
2122
     * Utility method to find out if  a struct is a circle.
2123
     *
2124
     * @param the_data the struct's datum array
2125
     * @return whether it is a circle
2126
     */
2127
    public static boolean isCircle(Datum[] the_data) {
2128
        int[] info = null;
2129

    
2130
        try {
2131
            info = ((ARRAY) the_data[3]).getIntArray();
2132
        }
2133
        catch (SQLException se) {
2134
            logger.error("While cheking circle: " + se.getMessage(), se);
2135

    
2136
            return false;
2137
        }
2138

    
2139
        if (info == null) {
2140
            return false;
2141
        }
2142

    
2143
        boolean resp = ((info.length == 3) && (info[2] == 4));
2144

    
2145
        return resp;
2146
    }
2147

    
2148
    /**
2149
     * Gets the struct's dimension size.
2150
     * @param st the struct
2151
     * @return the structs dimension
2152
     */
2153
    public static int getStructDimensions(STRUCT st) {
2154
        int resp = -1;
2155

    
2156
        try {
2157
            resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000;
2158
        }
2159
        catch (SQLException se) {
2160
            logger.error("Error: " + se.getMessage(), se);
2161
        }
2162

    
2163
        if (resp < 2) {
2164
            resp = 2;
2165
        }
2166

    
2167
        return resp;
2168
    }
2169

    
2170
    /**
2171
     * Gets a struct's coordinates array.
2172
     * @param the_data the struct's datum array
2173
     * @return the coordinates array
2174
     */
2175
    public static double[] getOrds(Datum[] the_data) {
2176
        double[] resp = null;
2177

    
2178
        try {
2179
            ARRAY aux = (ARRAY) the_data[4];
2180

    
2181
            if (aux == null) {
2182
                return null;
2183
            }
2184

    
2185
            resp = aux.getDoubleArray();
2186
        }
2187
        catch (SQLException se) {
2188
            logger.error("While getting ordinates: " + se.getMessage(), se);
2189
        }
2190

    
2191
        return resp;
2192
    }
2193

    
2194
    /**
2195
     * Utility method to create a struct with the given data.
2196
     * @param type struct type
2197
     * @param srid coordinate system
2198
     * @param info element info array
2199
     * @param ords coordinates array
2200
     * @param conn connection
2201
     * @return the created struct
2202
     */
2203
    public static STRUCT createStruct(NUMBER type, NUMBER srid, Datum[] info,
2204
        Datum[] ords, Connection conn) {
2205
        try {
2206
            StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
2207
                    conn);
2208
            Object[] obj = new Object[5];
2209
            obj[0] = type;
2210
            obj[1] = srid;
2211
            obj[2] = null;
2212
            obj[3] = info;
2213
            obj[4] = ords;
2214

    
2215
            return new STRUCT(dsc, conn, obj);
2216
        }
2217
        catch (SQLException se) {
2218
            logger.error("While creating STRUCT: " + se.getMessage(), se);
2219
        }
2220

    
2221
        return null;
2222
    }
2223
    
2224
    public static String getDimInfoAsString(ARRAY dim_info) {
2225
            String resp = "DIMENSIONS: ";
2226

    
2227
        if (dim_info == null) {
2228
            return "NULL" + "\n";
2229
        }
2230
        else {
2231
                try {
2232
                                Datum[] da = dim_info.getOracleArray();
2233
                                int size = da.length;
2234
                                resp = resp + size + "\n";
2235
                                for (int i = 0; i < size; i++) {
2236
                                        STRUCT dim_itemx = (STRUCT) da[i];
2237
                                        Object[] dim_desc = dim_itemx.getAttributes();
2238
                                        resp = resp + "DIMENSION " + i + ": " + ", NAME: "
2239
                                                        + dim_desc[0].toString() + ", MIN: "
2240
                                                        + dim_desc[1].toString() + ", MAX: "
2241
                                                        + dim_desc[2].toString() + ", TOL: "
2242
                                                        + dim_desc[3].toString();
2243
                                        if (i != (size -1)) {
2244
                                                resp = resp + "\n";
2245
                                        }
2246
                                }
2247
                        } catch (Exception ex) {
2248
                                return "ERROR: " + ex.getMessage() + "\n";
2249
                        }
2250
        }
2251
        return resp;
2252
    }
2253
    
2254
    public static STRUCT reprojectGeometry(Connection conn, STRUCT fromStruct, String toSrid) {
2255

    
2256
            String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL";
2257
            STRUCT resp = null;
2258

    
2259
            try {
2260
                        PreparedStatement _st = conn.prepareStatement(qry);
2261
                        _st.setObject(1, fromStruct);
2262
                        ResultSet _rs = _st.executeQuery();
2263

    
2264
                        if (_rs.next()) {
2265
                                resp = (STRUCT) _rs.getObject(1);
2266
                        } else {
2267
                                logger.error("While executing reprojection: empty resultset (?)");
2268
                                return fromStruct;
2269
                        }
2270
                } catch (Exception ex) {
2271
                        logger.error("While reprojecting: " + ex.getMessage());
2272
                        return fromStruct;
2273
                }
2274

    
2275
        if (resp == null) {
2276
                return fromStruct;
2277
        } else {
2278
                return resp;
2279
        }
2280
    }
2281
    
2282
}