Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extOracleSpatial / src / es / prodevelop / cit / gvsig / fmap / drivers / jdbc / oracle / OracleSpatialUtils.java @ 32891

History | View | Annotate | Download (99.8 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 java.awt.Shape;
46
import java.awt.geom.Arc2D;
47
import java.awt.geom.PathIterator;
48
import java.awt.geom.Point2D;
49
import java.awt.geom.Rectangle2D;
50
import java.io.BufferedReader;
51
import java.io.File;
52
import java.io.FileReader;
53
import java.lang.reflect.Array;
54
import java.net.URL;
55
import java.sql.Connection;
56
import java.sql.PreparedStatement;
57
import java.sql.ResultSet;
58
import java.sql.ResultSetMetaData;
59
import java.sql.SQLException;
60
import java.sql.Types;
61
import java.text.DecimalFormat;
62
import java.text.DecimalFormatSymbols;
63
import java.util.ArrayList;
64
import java.util.HashMap;
65
import java.util.Iterator;
66
import java.util.Random;
67

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

    
74
import org.apache.log4j.Logger;
75

    
76
import com.hardcode.gdbms.engine.spatial.fmap.FShapeGeneralPathX;
77
import com.iver.cit.gvsig.fmap.core.FCircle2D;
78
import com.iver.cit.gvsig.fmap.core.FGeometryCollection;
79
import com.iver.cit.gvsig.fmap.core.FMultiPoint2D;
80
import com.iver.cit.gvsig.fmap.core.FMultipoint3D;
81
import com.iver.cit.gvsig.fmap.core.FNullGeometry;
82
import com.iver.cit.gvsig.fmap.core.FPoint2D;
83
import com.iver.cit.gvsig.fmap.core.FPoint3D;
84
import com.iver.cit.gvsig.fmap.core.FPolygon2D;
85
import com.iver.cit.gvsig.fmap.core.FPolygon3D;
86
import com.iver.cit.gvsig.fmap.core.FPolyline2D;
87
import com.iver.cit.gvsig.fmap.core.FPolyline3D;
88
import com.iver.cit.gvsig.fmap.core.FShape;
89
import com.iver.cit.gvsig.fmap.core.FShape3D;
90
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
91
import com.iver.cit.gvsig.fmap.core.IGeometry;
92
import com.iver.cit.gvsig.fmap.core.IGeometry3D;
93
import com.iver.cit.gvsig.fmap.core.IGeometryM;
94
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
95
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
96
import com.iver.cit.gvsig.fmap.drivers.ConnectionJDBC;
97
import com.iver.cit.gvsig.fmap.drivers.DBLayerDefinition;
98
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
99
import com.iver.cit.gvsig.fmap.drivers.IConnection;
100
import com.iver.cit.gvsig.fmap.edition.UtilFunctions;
101
import com.vividsolutions.jts.algorithm.CGAlgorithms;
102
import com.vividsolutions.jts.algorithm.RobustCGAlgorithms;
103
import com.vividsolutions.jts.geom.Coordinate;
104
import com.vividsolutions.jts.geom.CoordinateArrays;
105
import com.vividsolutions.jts.geom.Envelope;
106
import com.vividsolutions.jts.geom.Geometry;
107
import com.vividsolutions.jts.geom.GeometryFactory;
108
import com.vividsolutions.jts.geom.LineString;
109
import com.vividsolutions.jts.geom.LinearRing;
110
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
111

    
112

    
113
/**
114
 * Utility class with static methods.
115
 *
116
 * @author jldominguez
117
 *
118
 */
119
public class OracleSpatialUtils {
120
    private static Logger logger = Logger.getLogger(OracleSpatialUtils.class.getName());
121
    private static double FLATNESS = 0.8;
122
    private static GeometryFactory geomFactory = new GeometryFactory();
123
    private static final double IRRELEVANT_DISTANCE = 0.00000001;
124
    private static Random rnd = new Random();
125
    private static DecimalFormat df = new DecimalFormat();
126
    private static DecimalFormatSymbols dfs = new DecimalFormatSymbols();
127
    public static final int ORACLE_GTYPE_UNKNOWN = 0;
128
    public static final int ORACLE_GTYPE_POINT = 1;
129
    public static final int ORACLE_GTYPE_LINE = 2;
130
    public static final int ORACLE_GTYPE_POLYGON = 3;
131
    public static final int ORACLE_GTYPE_COLLECTION = 4;
132
    public static final int ORACLE_GTYPE_MULTIPOINT = 5;
133
    public static final int ORACLE_GTYPE_MULTILINE = 6;
134
    public static final int ORACLE_GTYPE_MULTIPOLYGON = 7;
135

    
136
    public static final int ORACLE_GTYPE_COMPLEX_VOIDED_OR_NORMAL_POLYGON = 3;
137
    public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_LINE = 4;
138
    public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_POLYGON = 5;
139
    
140
    // req by wolfgang qual sept 2009
141
    public static final String ORACLE_GEOM_METADATA_TOLERANCE = "0.0005";
142
        public static final int FETCH_BLOCK_SIZE_BYTES = 50 * 1000 * 1000;
143

    
144

    
145
    /**
146
     * COnstructs a geometry from a file that contains a vertex per line:
147
     *
148
     * x1 y1 z1
149
     * x2 y2 z2
150
     * ...
151
     *
152
     * @param filepath vertices text file path
153
     * @param polygon whether it is a polygon or not
154
     * @return the created geometry
155
     */
156
    public static IGeometry readGeometry3D(URL filepath, boolean polygon) {
157
        GeneralPathX resp = new GeneralPathX();
158
        File file = new File(filepath.getFile());
159
        ArrayList z = new ArrayList();
160

    
161
        try {
162
            FileReader fr = new FileReader(file);
163
            BufferedReader br = new BufferedReader(fr);
164
            double[] coords = new double[3];
165

    
166
            boolean move = true;
167

    
168
            String line = br.readLine();
169

    
170
            while (line != null) {
171
                coords = parseLine(line);
172

    
173
                if (line.length() == 0) {
174
                    move = true;
175
                }
176
                else {
177
                    if (move) {
178
                        resp.moveTo(coords[0], coords[1]);
179
                        z.add(new Double(coords[2]));
180
                    }
181
                    else {
182
                        resp.lineTo(coords[0], coords[1]);
183
                        z.add(new Double(coords[2]));
184
                    }
185

    
186
                    move = false;
187
                }
188

    
189
                line = br.readLine();
190
            }
191
        }
192
        catch (Exception ex) {
193
                logger.error("While creating GeneralPathX: " +
194
                ex.getMessage());
195

    
196
            return null;
197
        }
198

    
199
        double[] zz = new double[z.size()];
200

    
201
        for (int i = 0; i < z.size(); i++) {
202
            zz[i] = ((Double) z.get(i)).doubleValue();
203
        }
204

    
205
        if (polygon) {
206
            return ShapeFactory.createPolygon3D(resp, zz);
207
        }
208
        else {
209
            return ShapeFactory.createPolyline3D(resp, zz);
210
        }
211
    }
212

    
213
    private static double[] parseLine(String line) {
214
        String[] sep = line.split(" ");
215
        double[] resp = new double[3];
216

    
217
        for (int i = 0; i < 3; i++)
218
            resp[i] = 0.0;
219

    
220
        try {
221
            resp[0] = Double.parseDouble(sep[0]);
222
        }
223
        catch (Exception ex) {
224
        }
225

    
226
        if (sep.length > 1) {
227
            try {
228
                resp[1] = Double.parseDouble(sep[1]);
229
            }
230
            catch (Exception ex) {
231
            }
232

    
233
            if (sep.length > 2) {
234
                try {
235
                    resp[2] = Double.parseDouble(sep[2]);
236
                }
237
                catch (Exception ex) {
238
                }
239
            }
240
        }
241

    
242
        return resp;
243
    }
244

    
245
    /**
246
     * Utility method to convert a gvSIG FShape into a oracle struct
247
     *
248
     * @param fshp the FShape object
249
     * @param c the connection
250
     * @param srid the SRS (oarcle code)
251
     * @param agu_b whether to check holes validity
252
     * @param hasSrid whether the SRS is non-NULL
253
     * @return a oracle struct representing the geometry
254
     *
255
     * @throws SQLException
256
     */
257
    public static STRUCT fShapeToSTRUCT(Object fshp, IConnection c, int srid,
258
        boolean agu_b, boolean hasSrid) throws SQLException {
259
        boolean three = false;
260

    
261
        if (fshp instanceof FShape3D) {
262
            three = true;
263
        }
264

    
265
        STRUCT resp = null;
266

    
267
        if (fshp instanceof FMultiPoint2D) {
268
            resp = multiPoint2DToStruct((FMultiPoint2D) fshp, c, srid, hasSrid);
269

    
270
            return resp;
271
        }
272

    
273
        if (!(fshp instanceof FShape)) {
274
            logger.error("Unknown geometry: " + fshp.toString());
275

    
276
            return null;
277
        }
278

    
279
        if (fshp instanceof FPoint2D) { // point 2/3d
280

    
281
            // resp = pointToWKT((FPoint2D) fshp, three);
282
            Coordinate p = getSingleCoordinate((FPoint2D) fshp);
283
            resp = getMultiPointAsStruct(p, srid, three, c, hasSrid);
284
        }
285
        else {
286
            if (fshp instanceof FPolygon2D) { // polygon 2/3d
287

    
288
                if (fshp instanceof FCircle2D) {
289
                    resp = getCircleAsStruct((FCircle2D) fshp, srid, c, hasSrid);
290
                }
291
                else {
292
                    // also FEllipse2D
293
                    resp = getMultiPolygonAsStruct((FShape) fshp, srid, three,
294
                            c, agu_b, hasSrid);
295

    
296
                    // ArrayList polys = getPolygonsEasily(fshp);
297
                    // resp = getMultiPolygonAsStruct(polys, srid, three, c);
298
                }
299
            }
300
            else { // line 2/3d
301

    
302
                ArrayList _lines = getLineStrings((FShape) fshp);
303
                resp = getMultiLineAsStruct(_lines, srid, three, c, hasSrid);
304
            }
305
        }
306

    
307
        return resp;
308
    }
309

    
310
    private static STRUCT multiPoint2DToStruct(FMultiPoint2D mp2d,
311
        IConnection c, int srid, boolean hasSrid) throws SQLException {
312
        int np = mp2d.getNumPoints();
313
        boolean threed = (mp2d instanceof FMultipoint3D);
314
        int gtype = 2005;
315
        int dim = 2;
316
        FMultipoint3D mp3d = null;
317

    
318
        if (threed) {
319
            gtype = 3005;
320
            dim = 3;
321
            mp3d = (FMultipoint3D) mp2d;
322
        }
323

    
324
        NUMBER[] indices = new NUMBER[3];
325
        indices[0] = new NUMBER(1);
326
        indices[1] = new NUMBER(1);
327
        indices[2] = new NUMBER(np);
328

    
329
        NUMBER[] ords = new NUMBER[dim * np];
330

    
331
        for (int i = 0; i < np; i++) {
332
            ords[dim * i] = new NUMBER(mp2d.getPoint(i).getX());
333
            ords[(dim * i) + 1] = new NUMBER(mp2d.getPoint(i).getY());
334

    
335
            if (threed) {
336
                ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]);
337
            }
338
        }
339

    
340
        STRUCT resp;
341
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
342
                        ((ConnectionJDBC)c).getConnection());
343
        Object[] obj = new Object[5];
344
        obj[0] = new NUMBER(gtype);
345

    
346
        if (hasSrid) {
347
            obj[1] = new NUMBER(srid);
348
        }
349
        else { // , boolean hasSrid
350
            obj[1] = null;
351
        }
352

    
353
        obj[2] = null;
354
        obj[3] = indices;
355
        obj[4] = ords;
356
        resp = new STRUCT(dsc, ((ConnectionJDBC)c).getConnection(), obj);
357

    
358
        return resp;
359
    }
360

    
361
    private static STRUCT getCircleAsStruct(FCircle2D fcirc, int srid,
362
        IConnection _conn, boolean hasSrid) throws SQLException {
363
        int geotype = 2003;
364
        NUMBER[] indices = new NUMBER[3];
365
        indices[0] = new NUMBER(1);
366
        indices[1] = new NUMBER(1003);
367
        indices[2] = new NUMBER(4);
368

    
369
        NUMBER[] ords = new NUMBER[6];
370
        Coordinate[] three_points = getThreePointsOfCircumference(fcirc.getCenter(),
371
                fcirc.getRadio());
372

    
373
        for (int i = 0; i < three_points.length; i++) {
374
            ords[i * 2] = new NUMBER(three_points[i].x);
375
            ords[(i * 2) + 1] = new NUMBER(three_points[i].y);
376
        }
377

    
378
        STRUCT resp;
379
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
380
                        ((ConnectionJDBC)_conn).getConnection());
381
        Object[] obj = new Object[5];
382
        obj[0] = new NUMBER(geotype);
383

    
384
        if (hasSrid) {
385
            obj[1] = new NUMBER(srid);
386
        }
387
        else {
388
            obj[1] = null;
389
        }
390

    
391
        obj[2] = null;
392
        obj[3] = indices;
393
        obj[4] = ords;
394
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
395

    
396
        return resp;
397
    }
398

    
399
    private static Coordinate[] getThreePointsOfCircumference(Point2D cntr,
400
        double radius) {
401
        Coordinate[] resp = new Coordinate[3];
402
        double x;
403
        double y;
404
        double alpha = 0;
405

    
406
        for (int i = 0; i < 3; i++) {
407
            alpha = (i * 120.0 * Math.PI) / 180.0;
408
            x = cntr.getX() + (radius * Math.cos(alpha));
409
            y = cntr.getY() + (radius * Math.sin(alpha));
410
            resp[i] = new Coordinate(x, y);
411
        }
412

    
413
        return resp;
414
    }
415

    
416
    private static Coordinate getSingleCoordinate(FPoint2D p2d) {
417
        // TODO Auto-generated method stub
418
        Coordinate resp = new Coordinate();
419
        resp.x = p2d.getX();
420
        resp.y = p2d.getY();
421

    
422
        if (p2d instanceof FPoint3D) {
423
            resp.z = ((FPoint3D) p2d).getZs()[0];
424
        }
425

    
426
        return resp;
427
    }
428

    
429
    private static ArrayList ensureSensibleLineString(ArrayList cc) {
430
        if (cc.size() == 2) {
431
            if (sameCoordinate((Coordinate) cc.get(0),
432
                        (Coordinate) cc.get(cc.size() - 1))) {
433
                ArrayList resp = new ArrayList();
434
                resp.add(cc.get(0));
435

    
436
                Coordinate newc = new Coordinate((Coordinate) cc.get(0));
437
                newc.x = newc.x + IRRELEVANT_DISTANCE;
438
                resp.add(newc);
439

    
440
                return resp;
441
            }
442
        }
443

    
444
        return cc;
445
    }
446

    
447
    private static boolean sameCoordinate(Coordinate c1, Coordinate c2) {
448
        if (c1.x != c2.x) {
449
            return false;
450
        }
451

    
452
        if (c1.y != c2.y) {
453
            return false;
454
        }
455

    
456
        return true;
457
    }
458

    
459
    private static ArrayList getClosedRelevantPolygon(ArrayList cc) {
460
        if (cc.size() == 2) {
461
            return getMinClosedCoords((Coordinate) cc.get(0));
462
        }
463

    
464
        if (cc.size() == 3) {
465
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(1))) {
466
                return getMinClosedCoords((Coordinate) cc.get(0));
467
            }
468

    
469
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(2))) {
470
                return getMinClosedCoords((Coordinate) cc.get(0));
471
            }
472

    
473
            if (sameCoordinate((Coordinate) cc.get(1), (Coordinate) cc.get(2))) {
474
                return getMinClosedCoords((Coordinate) cc.get(1));
475
            }
476

    
477
            cc.add(cc.get(0));
478

    
479
            return cc;
480
        }
481

    
482
        if (!sameCoordinate((Coordinate) cc.get(0),
483
                    (Coordinate) cc.get(cc.size() - 1))) {
484
            cc.add(cc.get(0));
485
        }
486

    
487
        return cc;
488
    }
489

    
490
    private static ArrayList getMinClosedCoords(Coordinate c) {
491
        ArrayList resp = new ArrayList();
492
        resp.add(c);
493

    
494
        Coordinate nc = new Coordinate(c);
495
        nc.x = nc.x + IRRELEVANT_DISTANCE;
496
        resp.add(nc);
497

    
498
        Coordinate nc2 = new Coordinate(nc);
499
        nc2.y = nc2.y + IRRELEVANT_DISTANCE;
500
        resp.add(nc2);
501

    
502
        resp.add(new Coordinate(c));
503

    
504
        return resp;
505
    }
506

    
507
    private static LinearRing getMinLinearRing(Coordinate c) {
508
        Coordinate[] p = new Coordinate[4];
509
        p[0] = c;
510

    
511
        Coordinate nc = new Coordinate(c);
512
        nc.x = nc.x + IRRELEVANT_DISTANCE;
513

    
514
        Coordinate nc2 = new Coordinate(nc);
515
        nc2.y = nc2.y - IRRELEVANT_DISTANCE;
516
        p[1] = nc;
517
        p[2] = nc2;
518
        p[3] = new Coordinate(c);
519

    
520
        CoordinateArraySequence cs = new CoordinateArraySequence(p);
521
        LinearRing ls = new LinearRing(cs, geomFactory);
522

    
523
        return ls;
524
    }
525

    
526
    private static double[] getMinLinearRingZ() {
527
        double[] resp = new double[4];
528

    
529
        for (int i = 0; i < 4; i++)
530
            resp[i] = 0.0;
531

    
532
        return resp;
533
    }
534

    
535
    private static boolean pointInList(Coordinate testPoint,
536
        Coordinate[] pointList) {
537
        int t;
538
        int numpoints;
539
        Coordinate p;
540

    
541
        numpoints = Array.getLength(pointList);
542

    
543
        for (t = 0; t < numpoints; t++) {
544
            p = pointList[t];
545

    
546
            if ((testPoint.x == p.x) && (testPoint.y == p.y) &&
547
                    ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
548
            ) {
549
                return true;
550
            }
551
        }
552

    
553
        return false;
554
    }
555

    
556
    private static ArrayList getPolygonsEasily(FShape mpolygon) {
557
        boolean threed = false;
558

    
559
        if (mpolygon instanceof FPolygon3D) {
560
            threed = true;
561
        }
562

    
563
        int start_ind = 0;
564
        int end_ind = 0;
565
        int ind = 0;
566
        int new_size;
567
        ArrayList arrayCoords = null;
568
        ArrayList resp = new ArrayList();
569
        Coordinate[] points = null;
570
        int theType = -99;
571
        double[] theData = new double[6];
572
        Coordinate onlyCoord = null;
573
        int numParts = 0;
574

    
575
        PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS);
576

    
577
        while (!theIterator.isDone()) {
578
            //while not done
579
            theType = theIterator.currentSegment(theData);
580

    
581
            if (onlyCoord == null) {
582
                onlyCoord = new Coordinate();
583
                onlyCoord.x = theData[0];
584
                onlyCoord.y = theData[1];
585
            }
586

    
587
            switch (theType) {
588
            case PathIterator.SEG_MOVETO:
589

    
590
                if (arrayCoords == null) {
591
                    arrayCoords = new ArrayList();
592
                }
593
                else {
594
                    end_ind = ind - 1;
595

    
596
                    arrayCoords = getClosedRelevantPolygon(arrayCoords);
597
                    new_size = arrayCoords.size();
598

    
599
                    if (arrayCoords != null) {
600
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
601

    
602
                        try {
603
                            LinearRing aux = geomFactory.createLinearRing(points);
604
                            double[] z = null;
605

    
606
                            if (threed) {
607
                                z = getZ((FPolygon3D) mpolygon, start_ind,
608
                                        end_ind, new_size);
609
                            }
610

    
611
                            LineString3D ring = new LineString3D(aux, z);
612

    
613
                            if (CGAlgorithms.isCCW(points)) {
614
                                resp.add(ring);
615
                            }
616
                            else {
617
                                resp.add(ring.createReverse());
618
                            }
619
                        }
620
                        catch (Exception e) {
621
                                logger.error("Topology exception: " +
622
                                e.getMessage());
623

    
624
                            return null;
625
                        }
626
                    }
627

    
628
                    arrayCoords = new ArrayList();
629

    
630
                    start_ind = ind;
631
                }
632

    
633
                numParts++;
634

    
635
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
636
                ind++;
637

    
638
                break;
639

    
640
            case PathIterator.SEG_LINETO:
641
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
642
                ind++;
643

    
644
                break;
645

    
646
            case PathIterator.SEG_QUADTO:
647
                    logger.info("SEG_QUADTO Not supported here");
648
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
649
                arrayCoords.add(new Coordinate(theData[2], theData[3]));
650
                ind++;
651
                ind++;
652

    
653
                break;
654

    
655
            case PathIterator.SEG_CUBICTO:
656
                    logger.info("SEG_CUBICTO Not supported here");
657
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
658
                arrayCoords.add(new Coordinate(theData[2], theData[3]));
659
                arrayCoords.add(new Coordinate(theData[4], theData[5]));
660
                ind++;
661
                ind++;
662
                ind++;
663

    
664
                break;
665

    
666
            case PathIterator.SEG_CLOSE:
667

    
668
                // Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
669
                // arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
670
                break;
671
            } //end switch
672

    
673
            theIterator.next();
674
        } //end while loop
675

    
676
        end_ind = ind - 1;
677

    
678
        // null shape:
679
        if (arrayCoords == null) {
680
            arrayCoords = new ArrayList();
681

    
682
            Coordinate _c = new Coordinate(0, 0, 0);
683
            arrayCoords.add(new Coordinate(_c));
684
            arrayCoords.add(new Coordinate(_c));
685
        }
686

    
687
        // --------------------------------------------
688
        arrayCoords = getClosedRelevantPolygon(arrayCoords);
689
        new_size = arrayCoords.size();
690

    
691
        if (arrayCoords != null) {
692
            points = CoordinateArrays.toCoordinateArray(arrayCoords);
693

    
694
            try {
695
                LinearRing aux = geomFactory.createLinearRing(points);
696
                double[] z = null;
697

    
698
                if (threed) {
699
                    z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size);
700
                }
701

    
702
                LineString3D ring = new LineString3D(aux, z);
703

    
704
                if (CGAlgorithms.isCCW(points)) {
705
                    resp.add(ring);
706
                }
707
                else {
708
                    resp.add(ring.createReverse());
709
                }
710
            }
711
            catch (Exception e) {
712
                    logger.error("Topology exception: " + e.getMessage());
713

    
714
                return null;
715
            }
716
        }
717

    
718
        if (resp.size() == 0) {
719
            resp.add(new LineString3D(getMinLinearRing(onlyCoord),
720
                    getMinLinearRingZ()));
721
        }
722

    
723
        return resp;
724
    }
725

    
726
    /**
727
     * Utility method to reverse an array of doubles.
728
     *
729
     * @param _z an array of doubles to be reversed.
730
     *
731
     * @return the reversed array of doubles
732
     */
733
    public static double[] reverseArray(double[] _z) {
734
        int size = _z.length;
735
        double[] resp = new double[size];
736

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

    
741
        return resp;
742
    }
743

    
744
    /**
745
     * Utility method to reverse an array of coordinates
746
     *
747
     * @param _z an array of coordinaes to be reversed.
748
     *
749
     * @return the reversed array of coordinates
750
     */
751
    public static Coordinate[] reverseCoordinateArray(Coordinate[] _z) {
752
        int size = _z.length;
753
        Coordinate[] resp = new Coordinate[size];
754

    
755
        for (int i = 0; i < size; i++) {
756
            resp[i] = _z[size - 1 - i];
757
        }
758

    
759
        return resp;
760
    }
761

    
762
    private static double[] getZ(FShape3D p3d, int _str, int _end, int size) {
763
        double[] resp = new double[size];
764
        double[] allz = p3d.getZs();
765

    
766
        for (int i = _str; ((i <= _end) && ((i - _str) < size)); i++) {
767
            resp[i - _str] = allz[i];
768
        }
769

    
770
        if ((_end - _str + 1) < size) {
771
            double repe = allz[_end];
772

    
773
            for (int i = (_end - _str + 1); i < size; i++) {
774
                resp[i] = repe;
775
            }
776
        }
777

    
778
        return resp;
779
    }
780

    
781
    private static ArrayList getLineStrings(FShape mlines) {
782
        boolean threed = false;
783

    
784
        if (mlines instanceof FPolyline3D) {
785
            threed = true;
786
        }
787

    
788
        int start_ind = 0;
789
        int end_ind = 0;
790
        int ind = 0;
791
        int new_size = 0;
792

    
793
        LineString3D lin;
794

    
795
        ArrayList arrayLines = new ArrayList();
796
        PathIterator theIterator = mlines.getPathIterator(null, FLATNESS);
797
        int theType = -99;
798
        double[] theData = new double[6];
799
        ArrayList arrayCoords = null;
800
        int numParts = 0;
801

    
802
        while (!theIterator.isDone()) {
803
            //while not done
804
            theType = theIterator.currentSegment(theData);
805

    
806
            switch (theType) {
807
            case PathIterator.SEG_MOVETO:
808

    
809
                if (arrayCoords == null) {
810
                    arrayCoords = new ArrayList();
811
                }
812
                else {
813
                    end_ind = ind - 1;
814
                    arrayCoords = ensureSensibleLineString(arrayCoords);
815
                    new_size = arrayCoords.size();
816

    
817
                    LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
818
                                arrayCoords));
819
                    double[] z = null;
820

    
821
                    if (threed) {
822
                        z = getZ((FPolyline3D) mlines, start_ind, end_ind,
823
                                new_size);
824
                    }
825

    
826
                    lin = new LineString3D(aux, z);
827
                    arrayLines.add(lin);
828
                    arrayCoords = new ArrayList();
829

    
830
                    start_ind = ind;
831
                }
832

    
833
                numParts++;
834
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
835

    
836
                break;
837

    
838
            case PathIterator.SEG_LINETO:
839
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
840

    
841
                break;
842

    
843
            case PathIterator.SEG_QUADTO:
844
                    logger.info("Not supported here: SEG_QUADTO");
845

    
846
                break;
847

    
848
            case PathIterator.SEG_CUBICTO:
849
                    logger.info("Not supported here: SEG_CUBICTO");
850

    
851
                break;
852

    
853
            case PathIterator.SEG_CLOSE:
854

    
855
                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
856
                arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
857

    
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

    
868
        LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
869
                    arrayCoords));
870
        double[] z = null;
871

    
872
        if (threed) {
873
            z = getZ((FPolyline3D) mlines, start_ind, end_ind, new_size);
874
        }
875

    
876
        lin = new LineString3D(aux, z);
877
        arrayLines.add(lin);
878

    
879
        return arrayLines;
880
    }
881

    
882
    private static String lineStringToWKT(LineString3D ls, boolean threed) {
883
        String resp = "(";
884
        Coordinate[] cc = ls.getLs().getCoordinates();
885
        double[] z = ls.getZc();
886
        int size = cc.length;
887

    
888
        if (threed) {
889
            for (int i = 0; i < size; i++) {
890
                resp = resp + cc[i].x + " " + cc[i].y + " " + z[i] + ", ";
891
            }
892

    
893
            resp = resp.substring(0, resp.length() - 2);
894
            resp = resp + ")";
895
        }
896
        else {
897
            for (int i = 0; i < size; i++) {
898
                resp = resp + cc[i].x + " " + cc[i].y + ", ";
899
            }
900

    
901
            resp = resp.substring(0, resp.length() - 2);
902
            resp = resp + ")";
903
        }
904

    
905
        return resp;
906
    }
907

    
908
    private static String multiLineStringToWKT(ArrayList ml, boolean threed) {
909
        String resp = "MULTILINESTRING(";
910

    
911
        for (int i = 0; i < ml.size(); i++) {
912
            LineString3D ls = (LineString3D) ml.get(i);
913
            resp = resp + lineStringToWKT(ls, threed) + ", ";
914
        }
915

    
916
        resp = resp.substring(0, resp.length() - 2) + ")";
917

    
918
        return resp;
919
    }
920

    
921
    private static String polygonsToWKT(ArrayList pols, boolean threed) {
922
        String resp = "MULTIPOLYGON(";
923
        LineString3D ls = null;
924

    
925
        for (int i = 0; i < pols.size(); i++) {
926
            ls = (LineString3D) pols.get(i);
927
            resp = resp + "(" + lineStringToWKT(ls, threed) + "), ";
928
        }
929

    
930
        resp = resp.substring(0, resp.length() - 2) + ")";
931

    
932
        return resp;
933
    }
934

    
935
    private static String shellAndHolesToWKT(LineString3D shell,
936
        ArrayList holes, boolean threed) {
937
        String resp = "(";
938
        resp = resp + lineStringToWKT(shell, threed);
939

    
940
        if (holes.size() > 0) {
941
            for (int i = 0; i < holes.size(); i++) {
942
                LineString3D ls = (LineString3D) holes.get(i);
943
                resp = resp + ", " + lineStringToWKT(ls, threed);
944
            }
945
        }
946

    
947
        resp = resp + ")";
948

    
949
        return resp;
950
    }
951

    
952
    private static String multiPolygonToWKT(ArrayList shells, ArrayList hFs,
953
        boolean threed) {
954
        String resp = "MULTIPOLYGON(";
955
        LineString3D ls = null;
956
        ArrayList holes;
957

    
958
        for (int i = 0; i < shells.size(); i++) {
959
            ls = (LineString3D) shells.get(i);
960
            holes = (ArrayList) hFs.get(i);
961
            resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
962
        }
963

    
964
        resp = resp.substring(0, resp.length() - 2) + ")";
965

    
966
        return resp;
967
    }
968

    
969
    private static String pointToWKT(FPoint2D point, boolean threed) {
970
        String resp = "POINT(" + point.getX() + " " + point.getY();
971

    
972
        if ((threed) && (point instanceof FPoint3D)) {
973
            resp = resp + " " + ((FPoint3D) point).getZs()[0];
974
        }
975

    
976
        resp = resp + ")";
977

    
978
        return resp;
979
    }
980

    
981
    private static int twoDIndexToDimsIndex(int n, int d) {
982
        return ((d * (n - 1)) / 2) + 1;
983
    }
984

    
985
    private static ARRAY setSubelementsToDim(ARRAY old, int d)
986
        throws SQLException {
987
        Datum[] infos = (Datum[]) old.getOracleArray();
988

    
989
        for (int i = 3; i < infos.length; i = i + 3) {
990
            int oldind = infos[i].intValue();
991
            oldind = twoDIndexToDimsIndex(oldind, d);
992
            infos[i] = new NUMBER(oldind);
993

    
994
            //
995
            oldind = infos[i + 1].intValue();
996
            infos[i + 1] = new NUMBER(infos[1].intValue());
997
        }
998

    
999
        ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(),
1000
                infos);
1001

    
1002
        return resp;
1003
    }
1004

    
1005
    private static boolean isPointInsideLineString(Coordinate p, LineString ls) {
1006
        Envelope env = ls.getEnvelopeInternal();
1007

    
1008
        if (!env.contains(p)) {
1009
            return false;
1010
        }
1011

    
1012
        return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
1013
    }
1014

    
1015
    private static boolean lineString3DIsContainedBy(LineString3D contained,
1016
        LineString3D container) {
1017
        int samples = 10;
1018
        LineString _in = contained.getLs();
1019
        LineString _out = container.getLs();
1020
        Coordinate[] inc = _in.getCoordinates();
1021
        Coordinate aux;
1022
        int size = inc.length;
1023

    
1024
        if (size <= 10) {
1025
            for (int i = 0; i < size; i++) {
1026
                aux = inc[i];
1027

    
1028
                if (!isPointInsideLineString(aux, _out)) {
1029
                    return false;
1030
                }
1031
            }
1032

    
1033
            return true;
1034
        }
1035
        else {
1036
            for (int i = 0; i < samples; i++) {
1037
                aux = inc[rnd.nextInt(size)];
1038

    
1039
                if (!isPointInsideLineString(aux, _out)) {
1040
                    return false;
1041
                }
1042
            }
1043

    
1044
            return true;
1045
        }
1046
    }
1047

    
1048
    private static STRUCT getMultiPolygonAsStruct(ArrayList pols, int srid,
1049
        boolean threed, IConnection _conn, boolean agu_bien, boolean hasSrid)
1050
        throws SQLException {
1051
        int size = pols.size();
1052
        int geotype = 2007;
1053
        int dim = 2;
1054
        int acum = 0;
1055

    
1056
        if (threed) {
1057
            geotype = 3007;
1058
            dim = 3;
1059
        }
1060

    
1061
        NUMBER[] indices = new NUMBER[3 * size];
1062

    
1063
        for (int i = 0; i < size; i++) {
1064
            indices[3 * i] = new NUMBER(acum + 1);
1065
            indices[(3 * i) + 1] = new NUMBER(1003);
1066
            indices[(3 * i) + 2] = new NUMBER(1);
1067
            acum = acum +
1068
                (dim * ((LineString3D) pols.get(i)).getLs().getNumPoints());
1069
        }
1070

    
1071
        int _ind = 0;
1072
        NUMBER[] ords = new NUMBER[acum];
1073

    
1074
        for (int i = 0; i < size; i++) {
1075
            LineString3D ls = (LineString3D) pols.get(i);
1076
            int num_p = ls.getLs().getNumPoints();
1077

    
1078
            for (int j = 0; j < num_p; j++) {
1079
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1080
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1081

    
1082
                if (threed) {
1083
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1084
                }
1085

    
1086
                _ind = _ind + dim;
1087
            }
1088
        }
1089

    
1090
        STRUCT resp;
1091
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1092
                        ((ConnectionJDBC)_conn).getConnection());
1093
        Object[] obj = new Object[5];
1094
        obj[0] = new NUMBER(geotype);
1095

    
1096
        if (hasSrid) {
1097
            obj[1] = new NUMBER(srid);
1098
        }
1099
        else {
1100
            obj[1] = null;
1101
        }
1102

    
1103
        obj[2] = null;
1104
        obj[3] = indices;
1105
        obj[4] = ords;
1106
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1107

    
1108
        return resp;
1109
    }
1110

    
1111
    private static STRUCT getMultiLineAsStruct(ArrayList lines, int srid,
1112
        boolean threed, IConnection _conn, boolean hasSrid)
1113
        throws SQLException {
1114
        /*
1115
        if (lines.size() == 1) {
1116
                return getOneLineStringAsStruct((LineString3D) lines.get(0), srid, threed, _conn);
1117
        }
1118
        */
1119
        int size = lines.size();
1120
        int geotype = 2006;
1121
        int dim = 2;
1122
        int acum = 0;
1123

    
1124
        if (threed) {
1125
            geotype = 3006;
1126
            dim = 3;
1127
        }
1128

    
1129
        NUMBER[] indices = new NUMBER[3 * size];
1130

    
1131
        for (int i = 0; i < size; i++) {
1132
            indices[3 * i] = new NUMBER(acum + 1);
1133
            indices[(3 * i) + 1] = new NUMBER(2);
1134
            indices[(3 * i) + 2] = new NUMBER(1);
1135
            acum = acum +
1136
                (dim * ((LineString3D) lines.get(i)).getLs().getNumPoints());
1137
        }
1138

    
1139
        int _ind = 0;
1140
        NUMBER[] ords = new NUMBER[acum];
1141

    
1142
        for (int i = 0; i < size; i++) {
1143
            LineString3D ls = (LineString3D) lines.get(i);
1144
            int num_p = ls.getLs().getNumPoints();
1145

    
1146
            for (int j = 0; j < num_p; j++) {
1147
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1148
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1149

    
1150
                if (threed) {
1151
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1152
                }
1153

    
1154
                _ind = _ind + dim;
1155
            }
1156
        }
1157

    
1158
        STRUCT resp;
1159
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1160
                        ((ConnectionJDBC)_conn).getConnection());
1161
        Object[] obj = new Object[5];
1162
        obj[0] = new NUMBER(geotype);
1163

    
1164
        if (hasSrid) {
1165
            obj[1] = new NUMBER(srid);
1166
        }
1167
        else {
1168
            obj[1] = null;
1169
        }
1170

    
1171
        obj[2] = null;
1172
        obj[3] = indices;
1173
        obj[4] = ords;
1174
        resp = new STRUCT(dsc,((ConnectionJDBC)_conn).getConnection(), obj);
1175

    
1176
        return resp;
1177
    }
1178

    
1179
    private static STRUCT getMultiPointAsStruct(Coordinate pnt, int srid,
1180
        boolean threed, IConnection _conn, boolean hasSrid)
1181
        throws SQLException {
1182
        int geotype = 2001;
1183
        int dim = 2;
1184

    
1185
        if (threed) {
1186
            geotype = 3001;
1187
            dim = 3;
1188
        }
1189

    
1190
        Object[] ords = new Object[3];
1191
        ords[0] = new NUMBER(pnt.x);
1192
        ords[1] = new NUMBER(pnt.y);
1193
        ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null; // ole ole y ole
1194

    
1195
        StructDescriptor ord_dsc = StructDescriptor.createDescriptor("MDSYS.SDO_POINT_TYPE",
1196
                        ((ConnectionJDBC)_conn).getConnection());
1197
        STRUCT ords_st = new STRUCT(ord_dsc, ((ConnectionJDBC)_conn).getConnection(), ords);
1198

    
1199
        STRUCT resp;
1200

    
1201
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1202
                        ((ConnectionJDBC)_conn).getConnection());
1203
        Object[] obj = new Object[5];
1204

    
1205
        obj[0] = new NUMBER(geotype);
1206

    
1207
        if (hasSrid) {
1208
            obj[1] = new NUMBER(srid);
1209
        }
1210
        else {
1211
            obj[1] = null;
1212
        }
1213

    
1214
        obj[2] = ords_st;
1215
        obj[3] = null;
1216
        obj[4] = null;
1217
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1218

    
1219
        return resp;
1220
    }
1221

    
1222
    /**
1223
     * Utility method to compute a circle's center and radius from three given points.
1224
     *
1225
     * @param points three points of a circumference
1226
     * @return a 2-item array with the circumference's center (Point2D) and radius (Double)
1227
     */
1228
    public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) {
1229
        Object[] resp = new Object[2];
1230
        resp[0] = new Point2D.Double(0, 0);
1231
        resp[1] = new Double(0);
1232

    
1233
        double m11;
1234
        double m12;
1235
        double m13;
1236
        double m14;
1237

    
1238
        if (points.length != 3) {
1239
            logger.error("Needs 3 points (found " + points.length +
1240
                ") - circle cannot be computed.");
1241

    
1242
            // not a circle
1243
            return resp;
1244
        }
1245

    
1246
        double[][] a = new double[3][3];
1247

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

    
1254
        m11 = determinant(a, 3);
1255

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

    
1263
        m12 = determinant(a, 3);
1264

    
1265
        for (int i = 0; i < 3; i++) // find minor 13
1266
         {
1267
            a[i][0] = (points[i].getX() * points[i].getX()) +
1268
                (points[i].getY() * points[i].getY());
1269
            a[i][1] = points[i].getX();
1270
            a[i][2] = 1;
1271
        }
1272

    
1273
        m13 = determinant(a, 3);
1274

    
1275
        for (int i = 0; i < 3; i++) { // find minor 14
1276
            a[i][0] = (points[i].getX() * points[i].getX()) +
1277
                (points[i].getY() * points[i].getY());
1278
            a[i][1] = points[i].getX();
1279
            a[i][2] = points[i].getY();
1280
        }
1281

    
1282
        m14 = determinant(a, 3);
1283

    
1284
        Double resp_radius = new Double(0);
1285
        Point2D resp_center = new Point2D.Double(0, 0);
1286

    
1287
        if (m11 == 0) {
1288
            logger.error("Three points aligned - circle cannot be computed."); // not a circle
1289
        }
1290
        else {
1291
            double x = (0.5 * m12) / m11;
1292
            double y = (-0.5 * m13) / m11;
1293
            resp_center.setLocation(x, y);
1294
            resp_radius = new Double(Math.sqrt((x * x) + (y * y) + (m14 / m11)));
1295
            resp[0] = resp_center;
1296
            resp[1] = resp_radius;
1297
        }
1298

    
1299
        return resp;
1300
    }
1301

    
1302
    /**
1303
     * Utility method to compute a matrix determinant
1304
     * @param a the matrix
1305
     * @param n matrix size
1306
     * @return the matrix's determinant
1307
     */
1308
    public static double determinant(double[][] a, int n) {
1309
        double resp = 0;
1310
        double[][] m = new double[3][3];
1311

    
1312
        if (n == 2) { // terminate recursion
1313
            resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]);
1314
        }
1315
        else {
1316
            resp = 0;
1317

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

    
1320
                for (int i = 1; i < n; i++) { // create minor
1321

    
1322
                    int j2 = 0;
1323

    
1324
                    for (int j = 0; j < n; j++) {
1325
                        if (j == j1) {
1326
                            continue;
1327
                        }
1328

    
1329
                        m[i - 1][j2] = a[i][j];
1330
                        j2++;
1331
                    }
1332
                }
1333

    
1334
                // sum (+/-)cofactor * minor
1335
                resp = resp +
1336
                    (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1));
1337
            }
1338
        }
1339

    
1340
        return resp;
1341
    }
1342

    
1343
    private static int getSmallestContainerExcept(LineString3D ls,
1344
        ArrayList list, int self) {
1345
        int resp = -1;
1346
        ArrayList provList = new ArrayList();
1347

    
1348
        int size = list.size();
1349

    
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

    
1356
        for (int i = (self + 1); i < size; i++) {
1357
            if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1358
                provList.add(new Integer(i));
1359
            }
1360
        }
1361

    
1362
        if (provList.size() == 0) {
1363
            // logger.debug("LineString is not contained by any other ls.");
1364
        }
1365
        else {
1366
            if (provList.size() == 1) {
1367
                resp = ((Integer) provList.get(0)).intValue();
1368
            }
1369
            else {
1370
                if (provList.size() == 2) {
1371
                    int ind_1 = ((Integer) provList.get(0)).intValue();
1372
                    int ind_2 = ((Integer) provList.get(1)).intValue();
1373
                    LineString3D ls1 = (LineString3D) list.get(ind_1);
1374
                    LineString3D ls2 = (LineString3D) list.get(ind_2);
1375

    
1376
                    if (lineString3DIsContainedBy(ls1, ls2)) {
1377
                        resp = ind_1;
1378
                    }
1379
                    else {
1380
                        resp = ind_2;
1381
                    }
1382
                }
1383
                else {
1384
                    // not so deep, sorry!
1385
                    // it's going to be a shell: resp = -1;
1386
                }
1387
            }
1388
        }
1389

    
1390
        return resp;
1391
    }
1392

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

    
1396
        for (int i = 0; i < containings.length; i++) {
1397
            if (containings[i] == -1) {
1398
                resp.add(new Integer(i));
1399
            }
1400
        }
1401

    
1402
        int size = resp.size();
1403
        int[] _resp = new int[size];
1404

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

    
1409
        return _resp;
1410
    }
1411

    
1412
    private static int[] getIndicesOfHoles(int[] containings, int[] shells) {
1413
        ArrayList resp = new ArrayList();
1414

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

    
1418
            if ((cont_by != -1) && (isOneOf(cont_by, shells))) {
1419
                resp.add(new Integer(i));
1420
            }
1421
        }
1422

    
1423
        int size = resp.size();
1424
        int[] _resp = new int[size];
1425

    
1426
        for (int i = 0; i < size; i++) {
1427
            _resp[i] = ((Integer) resp.get(i)).intValue();
1428
        }
1429

    
1430
        return _resp;
1431
    }
1432

    
1433
    private static int[] getFinalContainings(int[] containings, int[] holes) {
1434
        ArrayList resp = new ArrayList();
1435

    
1436
        for (int i = 0; i < containings.length; i++) {
1437
            int cont_by = containings[i];
1438

    
1439
            if (isOneOf(cont_by, holes)) {
1440
                resp.add(new Integer(-1));
1441
            }
1442
            else {
1443
                resp.add(new Integer(cont_by));
1444
            }
1445
        }
1446

    
1447
        int size = resp.size();
1448
        int[] _resp = new int[size];
1449

    
1450
        for (int i = 0; i < size; i++) {
1451
            _resp[i] = ((Integer) resp.get(i)).intValue();
1452
        }
1453

    
1454
        return _resp;
1455
    }
1456

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

    
1461
        for (int i = 0; i < final_contn.length; i++) {
1462
            if (final_contn[i] == ind) {
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
    private static ArrayList getShellsIn(int[] final_contn, ArrayList all) {
1478
        ArrayList resp_ind = new ArrayList();
1479

    
1480
        for (int i = 0; i < final_contn.length; i++) {
1481
            if (final_contn[i] == -1) {
1482
                resp_ind.add(new Integer(i));
1483
            }
1484
        }
1485

    
1486
        ArrayList resp = new ArrayList();
1487

    
1488
        for (int i = 0; i < resp_ind.size(); i++) {
1489
            Integer aux = (Integer) resp_ind.get(i);
1490
            resp.add(all.get(aux.intValue()));
1491
        }
1492

    
1493
        return resp;
1494
    }
1495

    
1496
    /**
1497
     * This method tries to guess who is a shell and who is a hole from a set of
1498
     * linestrings.
1499
     *
1500
     * @param all_ls a set of linestrings to be checked.
1501
     *
1502
     * @return a 2-item array. the first is an arraylist of linestrings thought to be shells.
1503
     * the second is an array of arraylists containing the holes of each shell found in the
1504
     * first item
1505
     *
1506
     */
1507
    public static Object[] getHolesForShells(ArrayList all_ls) {
1508
        int no_of_ls = all_ls.size();
1509
        int[] containedby = new int[no_of_ls];
1510
        int[] shells;
1511
        int[] holes;
1512
        int[] final_cont;
1513

    
1514
        for (int i = 0; i < no_of_ls; i++) {
1515
            LineString3D ls_aux = (LineString3D) all_ls.get(i);
1516
            containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i);
1517
        }
1518

    
1519
        shells = getIndicesOfShells(containedby);
1520
        holes = getIndicesOfHoles(containedby, shells);
1521
        final_cont = getFinalContainings(containedby, holes);
1522

    
1523
        // true shells:
1524
        shells = getIndicesOfShells(final_cont);
1525

    
1526
        ArrayList resp_shells = new ArrayList();
1527
        ArrayList resp_holes_for_shells = new ArrayList();
1528
        ArrayList aux_holes;
1529

    
1530
        for (int i = 0; i < shells.length; i++) {
1531
            resp_shells.add(all_ls.get(shells[i]));
1532
            aux_holes = getHolesOf(i, final_cont, all_ls);
1533
            resp_holes_for_shells.add(aux_holes);
1534
        }
1535

    
1536
        Object[] _resp = new Object[2];
1537
        _resp[0] = resp_shells;
1538
        _resp[1] = resp_holes_for_shells;
1539

    
1540
        return _resp;
1541
    }
1542

    
1543
    private static int getTotalSize(ArrayList listOfLists) {
1544
        int resp = 0;
1545

    
1546
        for (int i = 0; i < listOfLists.size(); i++) {
1547
            resp = resp + ((ArrayList) listOfLists.get(i)).size();
1548
        }
1549

    
1550
        return resp;
1551
    }
1552

    
1553
    // private static STRUCT // private static ArrayList getPolygonsEasily(FShape mpolygon) {
1554
    private static STRUCT getMultiPolygonAsStruct(FShape mpol, int srid,
1555
        boolean threed, IConnection _conn, boolean agu_bien, boolean hasSrid)
1556
        throws SQLException {
1557
        ArrayList all_ls = getPolygonsEasily(mpol);
1558
        Object[] hs = getHolesForShells(all_ls);
1559
        ArrayList sh = (ArrayList) hs[0];
1560
        ArrayList _ho = (ArrayList) hs[1];
1561
        ArrayList ho = reverseHoles(_ho);
1562

    
1563
        return getMultiPolygonAsStruct(sh, ho, srid, threed, _conn, agu_bien,
1564
            hasSrid);
1565
    }
1566

    
1567
    private static ArrayList reverseHoles(ArrayList hh) {
1568
        ArrayList resp = new ArrayList();
1569

    
1570
        for (int i = 0; i < hh.size(); i++) {
1571
            ArrayList item = (ArrayList) hh.get(i);
1572
            ArrayList newitem = new ArrayList();
1573

    
1574
            for (int j = 0; j < item.size(); j++) {
1575
                LineString3D ls = (LineString3D) item.get(j);
1576
                newitem.add(ls.createReverse());
1577
            }
1578

    
1579
            resp.add(newitem);
1580
        }
1581

    
1582
        return resp;
1583
    }
1584

    
1585
    private static STRUCT getMultiPolygonAsStruct(ArrayList shells,
1586
        ArrayList holes, int srid, boolean threed, IConnection _conn,
1587
        boolean explicito, boolean hasSrid) throws SQLException {
1588
        int t = 1003;
1589

    
1590
        if (explicito) {
1591
            t = 2003;
1592
        }
1593

    
1594
        int size = shells.size() + getTotalSize(holes);
1595
        int geotype = 2003;
1596
        if (size > 1) geotype = 2007;
1597

    
1598
        int dim = 2;
1599

    
1600
        if (threed) {
1601
            geotype = geotype + 1000;
1602
            dim = 3;
1603
        }
1604

    
1605
        NUMBER[] indices = new NUMBER[3 * size];
1606

    
1607
        int acum = 0;
1608
        int start_ind = 0;
1609

    
1610
        for (int i = 0; i < shells.size(); i++) {
1611
            indices[start_ind] = new NUMBER(acum + 1);
1612
            indices[start_ind + 1] = new NUMBER(1003);
1613
            indices[start_ind + 2] = new NUMBER(1);
1614
            start_ind = start_ind + 3;
1615
            acum = acum +
1616
                (dim * ((LineString3D) shells.get(i)).getLs().getNumPoints());
1617

    
1618
            ArrayList item_holes = (ArrayList) holes.get(i);
1619

    
1620
            for (int j = 0; j < item_holes.size(); j++) {
1621
                indices[start_ind] = new NUMBER(acum + 1);
1622
                indices[start_ind + 1] = new NUMBER(t); // 1003
1623
                indices[start_ind + 2] = new NUMBER(1);
1624
                start_ind = start_ind + 3;
1625
                acum = acum +
1626
                    (dim * ((LineString3D) item_holes.get(j)).getLs()
1627
                            .getNumPoints());
1628
            }
1629
        }
1630

    
1631
        int _ind = 0;
1632
        NUMBER[] ords = new NUMBER[acum];
1633

    
1634
        for (int i = 0; i < shells.size(); i++) {
1635
            // --------------------------------
1636
            LineString3D ls = (LineString3D) shells.get(i);
1637
            int num_p = ls.getLs().getNumPoints();
1638

    
1639
            for (int j = 0; j < num_p; j++) {
1640
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1641
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1642

    
1643
                if (threed) {
1644
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1645
                }
1646

    
1647
                _ind = _ind + dim;
1648
            }
1649

    
1650
            // -------------------------------
1651
            ArrayList item_holes = (ArrayList) holes.get(i);
1652

    
1653
            for (int j = 0; j < item_holes.size(); j++) {
1654
                ls = (LineString3D) item_holes.get(j);
1655
                num_p = ls.getLs().getNumPoints();
1656

    
1657
                for (int k = 0; k < num_p; k++) {
1658
                    ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(k).x);
1659
                    ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y);
1660

    
1661
                    if (threed) {
1662
                        ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1663
                    }
1664

    
1665
                    _ind = _ind + dim;
1666
                }
1667
            }
1668
        }
1669

    
1670
        STRUCT resp;
1671
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1672
                        ((ConnectionJDBC)_conn).getConnection());
1673
        Object[] obj = new Object[5];
1674
        obj[0] = new NUMBER(geotype);
1675

    
1676
        if (hasSrid) {
1677
            obj[1] = new NUMBER(srid);
1678
        }
1679
        else {
1680
            obj[1] = null;
1681
        }
1682

    
1683
        obj[2] = null;
1684
        obj[3] = indices;
1685
        obj[4] = ords;
1686

    
1687
        // String ind_str = printArray(indices);
1688
        // String ord_str = printArray(ords);
1689
        // obj = getTestPolygon();
1690
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1691

    
1692
        return resp;
1693
    }
1694

    
1695
    private static Object[] getTestPolygon(boolean b) throws SQLException {
1696
            
1697
        Object[] resp = new Object[5];
1698
        resp[0] = new NUMBER(3005);
1699
               resp[1] = null;
1700

    
1701
               NUMBER[] _ind = new NUMBER[6];
1702
               _ind[0] = new NUMBER(1.0);
1703
               _ind[1] = new NUMBER(2005.0);
1704
               _ind[2] = new NUMBER(1.0);
1705
               _ind[3] = new NUMBER(1.0);
1706
               _ind[4] = new NUMBER(2.0);
1707
               _ind[5] = new NUMBER(2.0);
1708

    
1709
               NUMBER[] _ord = new NUMBER[33];
1710
               _ord[0] = new NUMBER(4478106.584);
1711
               _ord[1] = new NUMBER(5345524.3355);
1712
               _ord[2] = new NUMBER(0.0); 
1713
               _ord[3] = new NUMBER(4478103.55781412);
1714
               _ord[4] = new NUMBER(5345520.13869913);
1715
               _ord[5] = new NUMBER(0.0); 
1716
               _ord[6] = new NUMBER(4478094.627);
1717
               _ord[7] = new NUMBER(5345517.0485);
1718
               _ord[8] = new NUMBER(0.0 );
1719
               _ord[9] = new NUMBER(4478088.31210806);
1720
               _ord[10] = new NUMBER(5345521.30429374);
1721
               _ord[11] = new NUMBER(0.0 );
1722
               _ord[12] = new NUMBER(4478087.661);
1723
               _ord[13] = new NUMBER(5345528.8915);
1724
               _ord[14] = new NUMBER(0.0 );
1725
               _ord[15] = new NUMBER(4478093.20816592);
1726
               _ord[16] = new NUMBER(5345537.22495391);
1727
               _ord[17] = new NUMBER(0.0 );
1728
               _ord[18] = new NUMBER(4478103.219);
1729
               _ord[19] = new NUMBER(5345537.2515);
1730
               _ord[20] = new NUMBER(0.0 );
1731
               _ord[21] = new NUMBER(4478107.61580098);
1732
               _ord[22] = new NUMBER(5345529.07024585);
1733
               _ord[23] = new NUMBER(0.0 );
1734
               _ord[24] = new NUMBER(4478107.585);
1735
               _ord[25] = new NUMBER(5345528.688);
1736
               _ord[26] = new NUMBER(0.0 );
1737
               _ord[27] = new NUMBER(4478107.28586386);
1738
               _ord[28] = new NUMBER(5345526.46542887);
1739
               _ord[29] = new NUMBER(0.0 );
1740
               _ord[30] = new NUMBER(4478106.584);
1741
               _ord[31] = new NUMBER(5345524.3355);
1742
               _ord[32] = new NUMBER(0.0);
1743
               
1744
        resp[2] = null;
1745
        resp[3] = _ind;
1746
        resp[4] = _ord;
1747
            
1748
                return resp;
1749
        }
1750

    
1751
        public static String printArray(NUMBER[] array) {
1752
        String resp = "[ ";
1753

    
1754
        for (int i = 0; i < array.length; i++) {
1755
            resp = resp + " " + array[i].doubleValue() + " , ";
1756
        }
1757

    
1758
        resp = resp.substring(0, resp.length() - 2) + "]";
1759

    
1760
        return resp;
1761
    }
1762

    
1763
    private static boolean isOneOf(int ind, int[] list) {
1764
        for (int i = 0; i < list.length; i++) {
1765
            if (list[i] == ind) {
1766
                return true;
1767
            }
1768
        }
1769

    
1770
        return false;
1771
    }
1772

    
1773
    /**
1774
     * This method appends the geometries from a geometry collection in one STRUCT.
1775
     *
1776
     * @param co the geometry collection
1777
     * @param _forced_type a type that has to be used as the struct's main type
1778
     * @param _conn the connection
1779
     * @param _o_srid the geometry's SRS (oracle code)
1780
     * @param withSrid whether the SRS is non-NULL
1781
     * @param agu_bien whether to check holes' validity
1782
     * @param _isGeoCS whether the SRS is geodetic
1783
     * @return the STRUCT with the appended geometries
1784
     */
1785
    public static STRUCT appendGeometriesInStruct(FGeometryCollection co,
1786
        int _forced_type, IConnection _conn, String _o_srid, boolean withSrid,
1787
        boolean agu_bien, boolean _isGeoCS) {
1788
        IGeometry[] geoms = co.getGeometries();
1789
        int size = geoms.length;
1790
        STRUCT[] sts = new STRUCT[size];
1791

    
1792
        for (int i = 0; i < size; i++) {
1793
            sts[i] = OracleSpatialDriver.iGeometryToSTRUCT(geoms[i],
1794
                    _forced_type, _conn, _o_srid, withSrid, agu_bien, _isGeoCS);
1795
        }
1796

    
1797
        if (size == 1) {
1798
            return sts[0];
1799
        }
1800

    
1801
        STRUCT aux = sts[0];
1802

    
1803
        for (int i = 1; i < size; i++) {
1804
            aux = appendStructs(aux, sts[i], _conn);
1805
        }
1806

    
1807
        return aux;
1808
    }
1809

    
1810
    private static STRUCT appendStructs(STRUCT st1, STRUCT st2, IConnection _conn) {
1811
        try {
1812
            ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1813
            int length_of_head_ords = _ords.getOracleArray().length;
1814

    
1815
            NUMBER gtype = new NUMBER(4 +
1816
                    (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000));
1817
            NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1818
            NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1819

    
1820
            ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1821
            ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1822
            ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1823
            ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1824

    
1825
            Datum[] info = appendDatumArrays(info1.getOracleArray(),
1826
                    info2.getOracleArray(), length_of_head_ords);
1827

    
1828
            Datum[] ords = appendDatumArrays(ords1.getOracleArray(),
1829
                    ords2.getOracleArray(), 0);
1830

    
1831
            StructDescriptor dsc = st1.getDescriptor();
1832

    
1833
            Object[] atts = new Object[5];
1834
            atts[0] = gtype;
1835
            atts[1] = srid;
1836
            atts[2] = middle;
1837
            atts[3] = info;
1838
            atts[4] = ords;
1839

    
1840
            STRUCT resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), atts);
1841

    
1842
            return resp;
1843
        }
1844
        catch (SQLException sqle) {
1845
            logger.error("While appending structs: " + sqle.getMessage(), sqle);
1846
        }
1847

    
1848
        return null;
1849
    }
1850

    
1851
    private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail,
1852
        int offset) {
1853
        int head_l = head.length;
1854
        int tail_l = tail.length;
1855
        Datum[] resp = new Datum[head_l + tail_l];
1856

    
1857
        for (int i = 0; i < head_l; i++)
1858
            resp[i] = head[i];
1859

    
1860
        if (offset == 0) {
1861
            for (int i = 0; i < tail_l; i++)
1862
                resp[head_l + i] = tail[i];
1863
        }
1864
        else {
1865
            try {
1866
                for (int i = 0; i < tail_l; i++) {
1867
                    if ((i % 3) == 0) {
1868
                        resp[head_l + i] = new NUMBER(tail[i].intValue() +
1869
                                offset);
1870
                    }
1871
                    else {
1872
                        resp[head_l + i] = tail[i];
1873
                    }
1874
                }
1875
            }
1876
            catch (SQLException se) {
1877
                logger.error("Unexpected error: " + se.getMessage());
1878
            }
1879
        }
1880

    
1881
        return resp;
1882
    }
1883

    
1884
    /**
1885
     * Utility method to get an ineteger as a formatted string.
1886
     *
1887
     * @param n the integer
1888
     * @return the formatted string
1889
     */
1890
    public static String getFormattedInteger(int n) {
1891
        df.setGroupingUsed(true);
1892
        df.setGroupingSize(3);
1893
        dfs.setGroupingSeparator('.');
1894
        df.setDecimalFormatSymbols(dfs);
1895

    
1896
        return df.format(n);
1897
    }
1898

    
1899
    /**
1900
     * Tells whether these arrays belong to a rectangle polygon.
1901
     *
1902
     * @param info the struct's element info array
1903
     * @param ords the struct's coordinate array
1904
     * @return true if it is a rectangle polygon. false otherwise.
1905
     */
1906
    public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
1907
        try {
1908
            int[] infos = info.getIntArray();
1909

    
1910
            return ((infos[2] == 3) && (infos.length == 3));
1911
        }
1912
        catch (SQLException se) {
1913
            logger.error("While ckecking rectangle: " + se.getMessage(), se);
1914
        }
1915

    
1916
        return false;
1917
    }
1918

    
1919
    /**
1920
     * Utility method to deal with oracle info arrays.
1921
     */
1922
    public static ARRAY getDevelopedInfoArray(ARRAY info) {
1923
        ARRAY _resp = null;
1924

    
1925
        try {
1926
            Datum[] resp = new Datum[3];
1927
            Datum[] in = info.getOracleArray();
1928
            resp[0] = in[0];
1929
            resp[1] = in[1];
1930
            resp[2] = new NUMBER(1);
1931
            _resp = new ARRAY(info.getDescriptor(),
1932
                    info.getInternalConnection(), resp);
1933
        }
1934
        catch (SQLException se) {
1935
            logger.error("While creating ARRAY: " + se.getMessage(), se);
1936
        }
1937

    
1938
        return _resp;
1939
    }
1940

    
1941
    /**
1942
     * Utility method to deal with oracle coordinate arrays.
1943
     */
1944
        public static ARRAY getDevelopedOrdsArray(ARRAY ords, int dim) {
1945
                ARRAY _resp = null;
1946

    
1947
                try {
1948
                        int n = 5*2; // dim = 2, ignored dim, 3d makes no sense
1949
                        Datum[] resp = new Datum[n];
1950
                        Datum[] corners = ords.getOracleArray();
1951

    
1952
                        for (int i=0; i<5; i++) {
1953
                                resp[i*2] = ((i==2) || (i==3)) ? corners[dim] : corners[0];
1954
                        }
1955
                        for (int i=0; i<5; i++) {
1956
                                resp[1+i*2] = ((i==1) || (i==2)) ? corners[dim+1] : corners[1];
1957
                        }
1958
                        _resp = new ARRAY(ords.getDescriptor(), ords
1959
                                        .getInternalConnection(), resp);
1960
                } catch (SQLException se) {
1961
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
1962
                }
1963

    
1964
                return _resp;
1965
        }
1966

    
1967
    /**
1968
     * utility method to convert a STRUCT into a GeneralPathX
1969
     * @param aux the struct's datum array
1970
     * @return the ExtendedGeneralPathX instance created
1971
     */
1972
    public static ExtendedGeneralPathX structToGPX(Datum[] aux) {
1973
            
1974
            ExtendedGeneralPathX resp = new ExtendedGeneralPathX();
1975
        ARRAY infoARRAY = null;
1976
        ARRAY ordsARRAY = null;
1977
        Datum[] info_array = null;
1978
        Datum[] ords_array = null;
1979
        int info_array_size = 0;
1980
        int[] start_ind;
1981
        int[] end_ind;
1982
        
1983
        int dims = 0;
1984
        boolean next_must_do_first = true;
1985

    
1986
        try {
1987
            infoARRAY = (ARRAY) aux[3];
1988
            ordsARRAY = (ARRAY) aux[4];
1989

    
1990
            dims = ((NUMBER) aux[0]).intValue() / 1000;
1991

    
1992
            if (dims == 0) {
1993
                dims = 2;
1994
            }
1995

    
1996
            if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
1997
                infoARRAY = getDevelopedInfoArray(infoARRAY);
1998
                ordsARRAY = getDevelopedOrdsArray(ordsARRAY, dims);
1999
                dims = 2;
2000
            }
2001

    
2002
            info_array = (Datum[]) infoARRAY.getOracleArray();
2003
            ords_array = (Datum[]) ordsARRAY.getOracleArray();
2004
            info_array_size = info_array.length / 3;
2005

    
2006
            int last_index = ords_array.length - dims + 1;
2007

    
2008
            // set indices:
2009
            start_ind = new int[info_array_size];
2010
            end_ind = new int[info_array_size];
2011

    
2012
            for (int i = 0; i < info_array_size; i++)
2013
                start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
2014

    
2015
            for (int i = 0; i < (info_array_size - 1); i++)
2016
                end_ind[i] = start_ind[i + 1] - 1;
2017

    
2018
            end_ind[info_array_size - 1] = last_index;
2019

    
2020
            int lineType = PathIterator.SEG_LINETO;
2021

    
2022
            if (end_ind[0] == 0) { // collection of paths
2023

    
2024
                for (int i = 1; i < info_array_size; i++) {
2025
                    lineType = getLineToType(info_array, i);
2026

    
2027
                    // -----------------------
2028
                    if (end_ind[i] == (start_ind[i] - 1))
2029
                            lineType = PathIterator.SEG_MOVETO;
2030
                    // -----------------------
2031

    
2032
                    next_must_do_first = addOrdsToGPX(resp, start_ind[i] - 1,
2033
                            end_ind[i] - 1, ords_array, dims, lineType,
2034
                            (i == 1) || (lineType == PathIterator.SEG_MOVETO),
2035
                            next_must_do_first);
2036
                }
2037
            } else {
2038
                    
2039
                // standard case, do the moveto always
2040
                for (int i = 0; i < info_array_size; i++) {
2041
                    lineType = getLineToType(info_array, i);
2042
                    addOrdsToGPX(resp, start_ind[i] - 1, end_ind[i] - 1,
2043
                        ords_array, dims, lineType, true, true);
2044
                }
2045
            }
2046
        }
2047
        catch (SQLException se) {
2048
            logger.error("While creating GPX: " + se.getMessage(), se);
2049
        }
2050

    
2051
        return resp;
2052
    }
2053

    
2054
    private static int getLineToType(Datum[] infos, int i) {
2055
        int resp = PathIterator.SEG_LINETO;
2056

    
2057
        try {
2058
            if (((NUMBER) infos[(3 * i) + 2]).intValue() == 2) {
2059
                resp = PathIterator.SEG_QUADTO;
2060
            }
2061
        }
2062
        catch (SQLException e) {
2063
            logger.error("While getting line-to type: " + e.getMessage() +
2064
                " (returned SEG_LINETO)");
2065
        }
2066

    
2067
        return resp;
2068
    }
2069

    
2070
    private static boolean addOrdsToGPX(ExtendedGeneralPathX gpx, int zero_based_start,
2071
        int zero_based_include_end, Datum[] ords, int d, int ltype,
2072
        boolean do_the_move, boolean must_do_first) {
2073
        int length = ords.length;
2074
        boolean return_following_must_do_first = true;
2075

    
2076
        double x = ((NUMBER) ords[zero_based_start]).doubleValue();
2077
        double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue();
2078

    
2079
        if (must_do_first) {
2080
            if (do_the_move) {
2081
                gpx.moveTo(x, y);
2082
            }
2083
            else {
2084
                gpx.lineTo(x, y);
2085
            }
2086
        }
2087

    
2088
        int ind = 1;
2089

    
2090
        int size = ((zero_based_include_end - zero_based_start) / d) + 1;
2091
        int indx;
2092
        int indx2;
2093

    
2094
        if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
2095

    
2096
            double x2;
2097
            double y2;
2098

    
2099
            while (ind < size) {
2100
                indx = zero_based_start + (ind * d);
2101
                x = ((NUMBER) ords[indx]).doubleValue();
2102
                y = ((NUMBER) ords[indx + 1]).doubleValue();
2103

    
2104
                indx2 = zero_based_start + ((ind + 1) * d);
2105

    
2106
                if (indx >= length) {
2107
                    indx2 = zero_based_start;
2108
                }
2109

    
2110
                x2 = ((NUMBER) ords[indx2]).doubleValue();
2111
                y2 = ((NUMBER) ords[indx2 + 1]).doubleValue();
2112
                if (false) { // System.currentTimeMillis() % 2 == 0) {
2113
                    gpx.quadTo(x, y, x2, y2);
2114
                } else {
2115
                    arcTo(gpx, x, y, x2, y2, 20);
2116
                }
2117
                gpx.setLinearized(true);
2118
                ind++;
2119
                ind++;
2120
            }
2121

    
2122
            return_following_must_do_first = false;
2123
        }
2124
        else { // PathIterator.SEG_LINETO (interpretation = 1)
2125

    
2126
            while (ind < size) {
2127
                indx = zero_based_start + (ind * d);
2128
                x = ((NUMBER) ords[indx]).doubleValue();
2129
                y = ((NUMBER) ords[indx + 1]).doubleValue();
2130
                gpx.lineTo(x, y);
2131
                ind++;
2132
            }
2133
        }
2134

    
2135
        return return_following_must_do_first;
2136
    }
2137

    
2138
    private static void arcTo(
2139
                    GeneralPathX gpx,
2140
                    double x, double y,
2141
                        double x2, double y2,
2142
                        int ints) {
2143
            
2144
            Point2D p1 = gpx.getCurrentPoint();
2145
            // gpx.lineTo(p1.getX(), p1.getY());
2146
            
2147
            Point2D p2 = new Point2D.Double(x,y);
2148
            Point2D p3 = new Point2D.Double(x2,y2);
2149
            Point2D cent = UtilFunctions.getCenter(p1, p2, p3);
2150
            double r = p1.distance(cent);
2151
                double angle_ini = UtilFunctions.getAngle(cent, p1);
2152
                double angle_fin = UtilFunctions.getAngle(cent, p3);
2153
                
2154
                Coordinate[] coords = new Coordinate[4];
2155
                coords[0] = new Coordinate(p1.getX(), p1.getY());
2156
                coords[1] = new Coordinate(p2.getX(), p2.getY());
2157
                coords[2] = new Coordinate(p3.getX(), p3.getY());
2158
                coords[3] = new Coordinate(p1.getX(), p1.getY());
2159

    
2160
                double extent = 0;
2161
                if (CGAlgorithms.isCCW(coords)) {
2162
                        if (angle_fin > angle_ini) {
2163
                                extent = angle_fin - angle_ini;
2164
                        } else {
2165
                                extent = 2 * Math.PI - (angle_ini - angle_fin);
2166
                        }
2167
                } else {
2168
                        if (angle_fin > angle_ini) {
2169
                                extent = -(2 * Math.PI - (angle_fin - angle_ini));
2170
                        } else {
2171
                                extent = -(angle_ini - angle_fin);
2172
                        }
2173
                }
2174
                double anginc = extent / 20;
2175
            for (int i=0; i<ints; i++) {
2176
                    gpx.lineTo(
2177
                                    cent.getX() + r * Math.cos(angle_ini+i*anginc),
2178
                                    cent.getY() + r * Math.sin(angle_ini+i*anginc));
2179
            }
2180
                gpx.lineTo(x2,y2);
2181
        }
2182

    
2183
        /**
2184
     * Utility method. Gets FShape type from oracle geometry type.
2185
     * @param otype
2186
     * @return FShape type
2187
     */
2188
    public static int oracleGTypeToFShapeType(int otype) {
2189
        switch (otype) {
2190
        case ORACLE_GTYPE_UNKNOWN:
2191
            return FShape.NULL;
2192

    
2193
        case ORACLE_GTYPE_POINT:
2194
        case ORACLE_GTYPE_MULTIPOINT:
2195
            return FShape.POINT;
2196

    
2197
        case ORACLE_GTYPE_LINE:
2198
        case ORACLE_GTYPE_MULTILINE:
2199
            return FShape.LINE;
2200

    
2201
        case ORACLE_GTYPE_POLYGON:
2202
        case ORACLE_GTYPE_MULTIPOLYGON:
2203
            return FShape.POLYGON;
2204

    
2205
        case ORACLE_GTYPE_COLLECTION:
2206
            return FShape.MULTI;
2207
        }
2208

    
2209
        logger.warn("Unknown oracle geometry type: " + otype);
2210

    
2211
        return FShape.NULL;
2212
    }
2213

    
2214
    /**
2215
     * Utility method to get struct's type.
2216
     * @param the_data the struct's datum array
2217
     * @return the struct type
2218
     */
2219
    public static int getStructType(Datum[] the_data) {
2220
        int resp = -1;
2221

    
2222
        try {
2223
            resp = ((NUMBER) the_data[0]).intValue() % 1000;
2224
        }
2225
        catch (SQLException se) {
2226
            logger.error("Error: " + se.getMessage(), se);
2227
        }
2228

    
2229
        return resp;
2230
    }
2231

    
2232
    /**
2233
     * Utility method to get struct's SRID.
2234
     * @param the_data the struct's datum array
2235
     * @return the struct0's SRID
2236
     */
2237
    public static int getStructSRID(Datum[] the_data) {
2238
        int resp = -1;
2239

    
2240
        try {
2241
            resp = ((NUMBER) the_data[1]).intValue();
2242
        }
2243
        catch (SQLException se) {
2244
            logger.error("Error: " + se.getMessage(), se);
2245
        }
2246

    
2247
        return resp;
2248
    }
2249

    
2250
    /**
2251
     * Utility method to find out if  a struct is a circle.
2252
     *
2253
     * @param the_data the struct's datum array
2254
     * @return whether it is a circle
2255
     */
2256
    public static boolean isCircle(Datum[] the_data) {
2257
        int[] info = null;
2258

    
2259
        try {
2260
            info = ((ARRAY) the_data[3]).getIntArray();
2261
        }
2262
        catch (SQLException se) {
2263
            logger.error("While cheking circle: " + se.getMessage(), se);
2264

    
2265
            return false;
2266
        }
2267

    
2268
        if (info == null) {
2269
            return false;
2270
        }
2271

    
2272
        boolean resp = ((info.length == 3) && (info[2] == 4));
2273

    
2274
        return resp;
2275
    }
2276

    
2277
    /**
2278
     * Gets the struct's dimension size.
2279
     * @param st the struct
2280
     * @return the structs dimension
2281
     */
2282
    public static int getStructDimensions(STRUCT st) {
2283
        int resp = -1;
2284

    
2285
        try {
2286
            resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000;
2287
        }
2288
        catch (SQLException se) {
2289
            logger.error("Error: " + se.getMessage(), se);
2290
        }
2291

    
2292
        if (resp < 2) {
2293
            resp = 2;
2294
        }
2295

    
2296
        return resp;
2297
    }
2298

    
2299
    /**
2300
     * Gets a struct's coordinates array.
2301
     * @param the_data the struct's datum array
2302
     * @return the coordinates array
2303
     */
2304
    public static double[] getOrds(Datum[] the_data) {
2305
        double[] resp = null;
2306

    
2307
        try {
2308
            ARRAY aux = (ARRAY) the_data[4];
2309

    
2310
            if (aux == null) {
2311
                return null;
2312
            }
2313

    
2314
            resp = aux.getDoubleArray();
2315
        }
2316
        catch (SQLException se) {
2317
            logger.error("While getting ordinates: " + se.getMessage(), se);
2318
        }
2319

    
2320
        return resp;
2321
    }
2322

    
2323
    /**
2324
     * Utility method to create a struct with the given data.
2325
     * @param type struct type
2326
     * @param srid coordinate system
2327
     * @param info element info array
2328
     * @param ords coordinates array
2329
     * @param conn connection
2330
     * @return the created struct
2331
     */
2332
    public static STRUCT createStruct(NUMBER type, NUMBER srid, Datum[] info,
2333
        Datum[] ords, Connection conn) {
2334
        try {
2335
            StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
2336
                    conn);
2337
            Object[] obj = new Object[5];
2338
            obj[0] = type;
2339
            obj[1] = srid;
2340
            obj[2] = null;
2341
            obj[3] = info;
2342
            obj[4] = ords;
2343

    
2344
            return new STRUCT(dsc, conn, obj);
2345
        }
2346
        catch (SQLException se) {
2347
            logger.error("While creating STRUCT: " + se.getMessage(), se);
2348
        }
2349

    
2350
        return null;
2351
    }
2352

    
2353
    public static String getDimInfoAsString(ARRAY dim_info) {
2354
            String resp = "DIMENSIONS: ";
2355

    
2356
        if (dim_info == null) {
2357
            return "NULL" + "\n";
2358
        }
2359
        else {
2360
                try {
2361
                                Datum[] da = dim_info.getOracleArray();
2362
                                int size = da.length;
2363
                                resp = resp + size + "\n";
2364
                                for (int i = 0; i < size; i++) {
2365
                                        STRUCT dim_itemx = (STRUCT) da[i];
2366
                                        Object[] dim_desc = dim_itemx.getAttributes();
2367
                                        resp = resp + "DIMENSION " + i + ": " + ", NAME: "
2368
                                                        + dim_desc[0].toString() + ", MIN: "
2369
                                                        + dim_desc[1].toString() + ", MAX: "
2370
                                                        + dim_desc[2].toString() + ", TOL: "
2371
                                                        + dim_desc[3].toString();
2372
                                        if (i != (size -1)) {
2373
                                                resp = resp + "\n";
2374
                                        }
2375
                                }
2376
                        } catch (Exception ex) {
2377
                                return "ERROR: " + ex.getMessage() + "\n";
2378
                        }
2379
        }
2380
        return resp;
2381
    }
2382

    
2383
    public static STRUCT reprojectGeometry(IConnection conn, STRUCT fromStruct, String toSrid) {
2384

    
2385
            String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL";
2386
            STRUCT resp = null;
2387

    
2388
            try {
2389
                        PreparedStatement _st = ((ConnectionJDBC)conn).getConnection().prepareStatement(qry);
2390
                        _st.setObject(1, fromStruct);
2391
                        ResultSet _rs = _st.executeQuery();
2392

    
2393
                        if (_rs.next()) {
2394
                                resp = (STRUCT) _rs.getObject(1);
2395
                        } else {
2396
                                logger.error("While executing reprojection: empty resultset (?)");
2397
                                return fromStruct;
2398
                        }
2399
                } catch (Exception ex) {
2400
                        logger.error("While reprojecting: " + ex.getMessage());
2401
                        return fromStruct;
2402
                }
2403

    
2404
        if (resp == null) {
2405
                return fromStruct;
2406
        } else {
2407
                return resp;
2408
        }
2409
    }
2410
    
2411
    
2412
    public static void printStruct(STRUCT st) {
2413
            
2414
        logger.debug("----------------------------------------------");
2415
        logger.debug("-- 16 FEBRERO 2009 ---------------------------");
2416
        logger.debug("----------------------------------------------");
2417

    
2418
        try {
2419
            Object[] att = st.getAttributes();
2420
            int l = att.length;
2421

    
2422
            for (int i = 0; i < l; i++) {
2423
                    if (att[i] != null) {
2424
                            if (att[i] instanceof ARRAY) {
2425
                                    ARRAY arr = (ARRAY) att[i];
2426
                                    logger.debug("ATT " + i + ": ");
2427
                                    printARRAY(arr);
2428
                            } else {
2429
                                    logger.debug("ATT " + i + ": " + att[i].toString());
2430
                            }
2431
                    logger.debug("----------------------------------------------");
2432
                    }
2433
            }
2434
        }
2435
        catch (Exception ex) {
2436
                logger.debug("-- Error: " + ex.getMessage());
2437
        }
2438

    
2439
    }
2440

    
2441
        private static void printARRAY(ARRAY arr) throws Exception {
2442
                
2443
                int[] intarr = arr.getIntArray();
2444
                if (intarr == null) {
2445
                        float[] floarr = arr.getFloatArray();
2446
                        if (floarr == null) {
2447
                                logger.debug("INT NULL y FLOAT NULL (?)");
2448
                        } else {
2449
                                int len = floarr.length;
2450
                                for (int i=0; i<len; i++) {
2451
                                        if (Math.min(i, (len - i)) < 20) {
2452
                                                logger.debug("" + floarr[i]);
2453
                                        }
2454
                                }
2455
                        }
2456
                        
2457
                } else {
2458
                        int len = intarr.length;
2459
                        for (int i=0; i<len; i++) {
2460
                                if (Math.min(i, (len - i)) < 20) {
2461
                                        logger.debug("" + intarr[i]);
2462
                                }
2463
                        }
2464
                }
2465
        }
2466

    
2467
    /**
2468
     * Utility method. Gets FShape type from oracle geometry type.
2469
     * @param otype
2470
     * @return FShape type
2471
     */
2472
    public static int oracleGTypeToFShapeType(int full_otype, boolean complex) {
2473
            
2474
            int resp = FShape.NULL;
2475
            int simpl_otype = full_otype % 1000;
2476
            
2477
            if (complex) {
2478
                    
2479
                    switch (simpl_otype) {
2480
                    case ORACLE_GTYPE_COMPLEX_VOIDED_OR_NORMAL_POLYGON:
2481
                    case ORACLE_GTYPE_COMPLEX_COMPOUND_POLYGON:
2482
                            resp = FShape.POLYGON;
2483
                            break;
2484
                    case ORACLE_GTYPE_COMPLEX_COMPOUND_LINE:
2485
                            resp = FShape.LINE;
2486
                            break;
2487
                    default:
2488
                            return oracleGTypeToFShapeType(full_otype, false);
2489
                    }
2490

    
2491
            } else {
2492

    
2493
                    // =========== not complex =================
2494
            switch (simpl_otype) {
2495
            case ORACLE_GTYPE_UNKNOWN:
2496
                    resp = FShape.NULL;
2497
                break;
2498

    
2499
            case ORACLE_GTYPE_POINT:
2500
            case ORACLE_GTYPE_MULTIPOINT:
2501
                    resp = FShape.POINT;
2502
                break;
2503

    
2504
            case ORACLE_GTYPE_LINE:
2505
            case ORACLE_GTYPE_MULTILINE:
2506
                    resp = FShape.LINE;
2507
                break;
2508

    
2509
            case ORACLE_GTYPE_POLYGON:
2510
            case ORACLE_GTYPE_MULTIPOLYGON:
2511
                    resp = FShape.POLYGON;
2512
                break;
2513

    
2514
            case ORACLE_GTYPE_COLLECTION:
2515
                    resp = FShape.MULTI;
2516
                break;
2517
            }
2518
                    // =========== not complex =================
2519
            }
2520
            if (resp == FShape.NULL) {
2521
                    logger.error("Unknown oracle geometry type: " + full_otype);
2522
            }
2523
        return resp;
2524
    }
2525
    
2526
        public static void removeStructFields(DBLayerDefinition def, String[] arr) {
2527
                
2528
                FieldDescription[] flds = def.getFieldsDesc();
2529
                ArrayList aux = new ArrayList();
2530
                
2531
                for (int i=0; i<flds.length; i++) {
2532
                        if (!isOneOfThese(flds[i].getFieldName(), arr)) {
2533
                                aux.add(flds[i]);
2534
                        }
2535
                }
2536
                
2537
                FieldDescription[] flds_new =
2538
                        (FieldDescription[]) aux.toArray(new FieldDescription[0]);
2539
                def.setFieldsDesc(flds_new);
2540
        }
2541
        
2542
        private static boolean isOneOfThese(String name, String[] arr) {
2543

    
2544
                for (int i=0; i<arr.length; i++) {
2545
                                if (arr[i].compareToIgnoreCase(name) == 0) return true; 
2546
                        }
2547
                return false;
2548
        }
2549
        
2550
        public static void setUpperCase(DBLayerDefinition def) {
2551
                String aux = def.getCatalogName();
2552
                if (aux != null) def.setCatalogName(aux.toUpperCase());
2553

    
2554
                aux = def.getSchema();
2555
                if (aux != null) def.setSchema(aux.toUpperCase());
2556
        }
2557
        
2558
    public static boolean hasSeveralGeometryTypes(ArrayList tt, boolean are_dims) {
2559
        if (tt.size() == 0) {
2560
            return false;
2561
        }
2562

    
2563
        HashMap m = new HashMap();
2564

    
2565
        for (int i = 0; i < tt.size(); i++) {
2566
            Integer integ = (Integer) tt.get(i);
2567
            int val = integ.intValue();
2568

    
2569
            if ((val == 4) && (!are_dims)) {
2570
                return true;
2571
            }
2572

    
2573
            m.put("" + (val % 4), "a type");
2574
        }
2575

    
2576
        Iterator iter = m.keySet().iterator();
2577
        iter.next();
2578

    
2579
        return iter.hasNext();
2580
    }
2581

    
2582
    public static void showMemory() {
2583
        Runtime r = Runtime.getRuntime();
2584
        long mem = r.totalMemory() - r.freeMemory();
2585
        logger.info("Total memory : " + mem);
2586
    }
2587
    
2588

    
2589
    
2590
    private static double[] getIndDoublesModule(double[] input, int ind, int n) {
2591
        int size = input.length / n;
2592
        double[] resp = new double[size];
2593

    
2594
        for (int i = 0; i < size; i++) {
2595
            resp[i] = input[(i * n) + ind];
2596
        }
2597

    
2598
        return resp;
2599
    }
2600
    
2601
    private static double[] getIndBigDecimalModule(double[] input, int ind, int n) {
2602
        int size = input.length / n;
2603
        double[] resp = new double[size];
2604

    
2605
        for (int i = 0; i < size; i++) {
2606
            resp[i] = input[(i * n) + ind];
2607
        }
2608

    
2609
        return resp;
2610
    }
2611
    
2612
    public static IGeometry getFMapGeometryMultipolygon(Datum[] the_data, int dim) {
2613
        IGeometry ig = null;
2614

    
2615
        if (OracleSpatialUtils.isCircle(the_data)) {
2616
            ig = getCircleFromStruct(the_data);
2617
        }
2618
        else {
2619
                ExtendedGeneralPathX gpx = OracleSpatialUtils.structToGPX(the_data);
2620

    
2621
            if (dim == 2) {
2622
                ig = ShapeFactory.createPolygon2D(gpx);
2623
            }
2624
            else {
2625
                double[] ords = null;
2626

    
2627
                try {
2628
                    ords = ((ARRAY) the_data[4]).getDoubleArray();
2629
                } catch (SQLException se) {
2630
                    logger.error("While getting ordinates: " + se.getMessage(), se);
2631
                }
2632

    
2633
                double[] z = null;
2634
                
2635
                if (gpx.isLinearized()) {
2636
                        int count = countCoords(gpx);
2637
                        z = new double[count];
2638
                        logger.warn("Linearized a 3D GPX, z[i] = 0");
2639
                } else {
2640
                        z = getIndBigDecimalModule(ords, 2, dim);
2641
                }
2642
                
2643
                ig = ShapeFactory.createPolygon3D(gpx, z);
2644
            }
2645
        }
2646

    
2647
        return ig;
2648
    }
2649
    
2650
    private static IGeometry getCircleFromStruct(Datum[] the_data) {
2651
        double[] threep = null;
2652

    
2653
        try {
2654
            threep = ((ARRAY) the_data[4]).getDoubleArray();
2655
        }
2656
        catch (SQLException se) {
2657
            logger.error("While getting ords from struct: " + se.getMessage(),
2658
                se);
2659

    
2660
            return new FNullGeometry();
2661
        }
2662

    
2663
        Point2D[] three = new Point2D.Double[3];
2664
        three[0] = new Point2D.Double(threep[0], threep[1]);
2665
        three[1] = new Point2D.Double(threep[2], threep[3]);
2666
        three[2] = new Point2D.Double(threep[4], threep[5]);
2667

    
2668
        Object[] cent_rad = OracleSpatialUtils.getCenterAndRadiousOfCirc(three);
2669

    
2670
        Point2D cent = (Point2D) cent_rad[0];
2671
        double radius = ((Double) cent_rad[1]).doubleValue();
2672

    
2673
        IGeometry circ = ShapeFactory.createCircle(cent, radius);
2674

    
2675
        return circ;
2676
    }
2677
    
2678
    public static IGeometry getFMapGeometryMultiLineString(Datum[] the_data, int dim) {
2679
            ExtendedGeneralPathX gpx = OracleSpatialUtils.structToGPX(the_data);
2680
        IGeometry ig = null;
2681
        double[] ords = null;
2682

    
2683
        if (dim == 2) {
2684
            ig = ShapeFactory.createPolyline2D(gpx);
2685
        }
2686
        else {
2687
            ords = OracleSpatialUtils.getOrds(the_data);
2688

    
2689
            double[] z = null;
2690
            
2691
            if (gpx.isLinearized()) {
2692
                    int count = countCoords(gpx);
2693
                    z = new double[count];
2694
                    logger.warn("Linearized a 3D GPX, z[i] = 0");
2695
            } else {
2696
                    z = getIndBigDecimalModule(ords, 2, dim);
2697
            }
2698
            ig = ShapeFactory.createPolyline3D(gpx, z);
2699
        }
2700

    
2701
        return ig;
2702
    }
2703

    
2704
    
2705
    private static int countCoords(GeneralPathX gpx) {
2706
            
2707
            int resp = 0;
2708
            PathIterator piter = gpx.getPathIterator(null);
2709
            while (!piter.isDone()) {
2710
                    piter.next();
2711
                    resp++;
2712
            }
2713
                return resp;
2714
        }
2715

    
2716
        public static IGeometry getFMapGeometryPoint(Datum[] the_data, int dim) {
2717
        double[] ords = OracleSpatialUtils.getOrds(the_data);
2718

    
2719
        if (ords == null) { // sdo_point
2720

    
2721
            return getFMapGeometrySdoPoint(the_data, dim);
2722
        }
2723

    
2724
        IGeometry ig = null;
2725
        int total_size = ords.length;
2726
        int no_po = total_size / dim;
2727
        double[] x = new double[no_po];
2728
        double[] y = new double[no_po];
2729
        double[] z = new double[no_po];
2730

    
2731
        for (int i = 0; i < no_po; i++) {
2732
            x[i] = ords[i * dim]; // pp[i].getX();
2733
            y[i] = ords[(i * dim) + 1];
2734

    
2735
            if (dim >= 3) {
2736
                z[i] = ords[(i * dim) + 2];
2737
            }
2738
        }
2739

    
2740
        if (dim == 2) {
2741
            if (no_po == 1) {
2742
                ig = ShapeFactory.createPoint2D(x[0], y[0]);
2743
            }
2744
            else {
2745
                ig = ShapeFactory.createMultipoint2D(x, y);
2746
            }
2747
        }
2748
        else {
2749
            if (no_po == 1) {
2750
                ig = ShapeFactory.createPoint3D(x[0], y[0], z[0]);
2751
            }
2752
            else {
2753
                ig = ShapeFactory.createMultipoint3D(x, y, z);
2754
            }
2755
        }
2756

    
2757
        return ig;
2758
    }
2759
    
2760
    private static IGeometry getFMapGeometrySdoPoint(Datum[] the_data, int d) {
2761
        double x = 0;
2762
        double y = 0;
2763
        double z = 0;
2764

    
2765
        try {
2766
            Datum[] aux = ((STRUCT) the_data[2]).getOracleAttributes();
2767
            x = ((NUMBER) aux[0]).doubleValue();
2768
            y = ((NUMBER) aux[1]).doubleValue();
2769

    
2770
            if (d > 2) {
2771
                    if (aux[2] == null) {
2772
                            z = 0;
2773
                    } else {
2774
                            z = ((NUMBER) aux[2]).doubleValue();
2775
                    }
2776
            }
2777
        }
2778
        catch (SQLException se) {
2779
            logger.error("While getting sdo point ordinates: " +
2780
                se.getMessage(), se);
2781
        }
2782

    
2783
        IGeometry ig = null;
2784

    
2785
        if (d == 2) {
2786
            ig = ShapeFactory.createPoint2D(x, y);
2787
        }
2788
        else {
2789
            ig = ShapeFactory.createPoint3D(x, y, z);
2790
        }
2791

    
2792
        return ig;
2793
    }
2794

    
2795
    public static final int COLLECTION_VALUE_NOT_COLLECTION = 0;
2796
    public static final int COLLECTION_VALUE_YES_COLLECTION = 1;
2797
    public static final int COLLECTION_VALUE_MERGE_COLLECTION_IN_POLYGON = 2;
2798
    
2799
    public static int isCollection(Datum[] the_data) {
2800
        int[] info = null;
2801

    
2802
        try {
2803
            ARRAY aux = (ARRAY) the_data[3];
2804

    
2805
            if (aux == null) {
2806
                return COLLECTION_VALUE_NOT_COLLECTION;
2807
            }
2808

    
2809
            info = aux.getIntArray();
2810
        }
2811
        catch (SQLException se) {
2812
            logger.error("While checking collection: " + se.getMessage());
2813
            return COLLECTION_VALUE_NOT_COLLECTION;
2814
        }
2815

    
2816
        if (info == null) {
2817
            return COLLECTION_VALUE_NOT_COLLECTION; // sdo_point
2818
        }
2819

    
2820
        int size = info.length / 3;
2821

    
2822
        if (size == 1) {
2823
            return COLLECTION_VALUE_NOT_COLLECTION;
2824
        }
2825

    
2826
        if (size == 2) {
2827
                if (((info[1] == 1003) && (info[2] == 3 || info[2] == 4))
2828
                                || ((info[4] == 1003 || info[4] == 2003) && (info[5] == 3 || info[5] == 4))) {
2829
                        return COLLECTION_VALUE_MERGE_COLLECTION_IN_POLYGON;
2830
                } else {
2831
                        boolean aux = ((info[1] % 1000) != (info[4] % 1000))
2832
                && ( ! ((info[1] == 1005) && (info[4] == 2)) );
2833
                        if (aux) {
2834
                    return COLLECTION_VALUE_YES_COLLECTION;
2835
                        } else {
2836
                    return COLLECTION_VALUE_NOT_COLLECTION;
2837
                        }
2838
                }
2839
        }
2840
        
2841
        // ======================================== check no rects whsn size > 2
2842
        for (int i=0; i<size; i++) { // outer pol
2843
                if ((info[i*3+1] == 1003) && (info[i*3+2] == 3 || info[i*3+2] == 4)) {
2844
                        return COLLECTION_VALUE_MERGE_COLLECTION_IN_POLYGON; 
2845
                }
2846
        }
2847
        for (int i=1; i<size; i++) { // inner pol
2848
                if ((info[i*3+1] == 2003) && (info[i*3+2] == 3 || info[i*3+2] == 4)) {
2849
                        return COLLECTION_VALUE_MERGE_COLLECTION_IN_POLYGON; 
2850
                }
2851
        }
2852
        // =================================== 
2853

    
2854
        int _first = info[1] % 1000;
2855
        int second = info[4] % 1000;
2856
        int item = 0;
2857
        
2858
        for (int i = 2; i < size; i++) {
2859
                item = info[(i * 3) + 1] % 1000;
2860
            if ((item != second) &&
2861
                            ( ! ((item == 5) && (second == 2)) ) && 
2862
                            ( ! ((item == 2) && (second == 5)) )
2863
                            ) {
2864
                return COLLECTION_VALUE_YES_COLLECTION;
2865
            }
2866
        }
2867

    
2868
        return COLLECTION_VALUE_NOT_COLLECTION;
2869
    }
2870

    
2871
    
2872
    public static Datum[] updateIndexes(Datum[] info) {
2873
        int size = info.length / 3;
2874
        NUMBER[] resp = new NUMBER[3 * size];
2875

    
2876
        try {
2877
            int rest = info[0].intValue() - 1;
2878

    
2879
            for (int i = 0; i < size; i++) {
2880
                resp[3 * i] = new NUMBER(info[3 * i].intValue() - rest);
2881
                resp[(3 * i) + 1] = new NUMBER(info[(3 * i) + 1].intValue());
2882
                resp[(3 * i) + 2] = new NUMBER(info[(3 * i) + 2].intValue());
2883
            }
2884
        }
2885
        catch (SQLException se) {
2886
            logger.error("Unexpected error: " + se.getMessage());
2887
        }
2888

    
2889
        return resp;
2890
    }
2891
    
2892
    public static double[] getSubSet(double[] all, int first_inc, int last_inc) {
2893
        double[] resp = new double[last_inc - first_inc + 1];
2894

    
2895
        for (int i = first_inc; i <= last_inc; i++) {
2896
            resp[i - first_inc] = all[i];
2897
        }
2898

    
2899
        return resp;
2900
    }
2901
    
2902
    public static Object[] getOrdOfGroups(Datum[] all, Object[] groups) throws SQLException {
2903
        Object[] resp = new Object[groups.length];
2904

    
2905
        if (resp.length == 1) {
2906
            resp[0] = all;
2907

    
2908
            return resp;
2909
        }
2910

    
2911
        int ind = 0;
2912
        Datum[] aux = (Datum[]) groups[1];
2913
        int _end = aux[0].intValue() - 2;
2914
        Datum[] ord_aux = getSubSet(all, 0, _end);
2915

    
2916
        int _start = _end + 1;
2917
        resp[ind] = ord_aux;
2918
        ind++;
2919

    
2920
        for (int i = 2; i < groups.length; i++) {
2921
            aux = (Datum[]) groups[i];
2922
            _end = aux[0].intValue() - 2;
2923
            ord_aux = getSubSet(all, _start, _end);
2924
            resp[ind] = ord_aux;
2925
            ind++;
2926
            _start = _end + 1;
2927
        }
2928

    
2929
        // last
2930
        _end = all.length - 1;
2931
        ord_aux = getSubSet(all, _start, _end);
2932
        resp[groups.length - 1] = ord_aux;
2933

    
2934
        return resp;
2935
    }
2936
    
2937
    
2938
    
2939
    public static Object[] getOrdOfGroups(double[] all, Object[] groups) {
2940
        Object[] resp = new Object[groups.length];
2941

    
2942
        if (resp.length == 1) {
2943
            resp[0] = all;
2944

    
2945
            return resp;
2946
        }
2947

    
2948
        int ind = 0;
2949
        int[] aux = (int[]) groups[1];
2950
        int _end = aux[0] - 2;
2951
        double[] ord_aux = getSubSet(all, 0, _end);
2952

    
2953
        int _start = _end + 1;
2954
        resp[ind] = ord_aux;
2955
        ind++;
2956

    
2957
        for (int i = 2; i < groups.length; i++) {
2958
            aux = (int[]) groups[i];
2959
            _end = aux[0] - 2;
2960
            ord_aux = getSubSet(all, _start, _end);
2961
            resp[ind] = ord_aux;
2962
            ind++;
2963
            _start = _end + 1;
2964
        }
2965

    
2966
        // last
2967
        _end = all.length - 1;
2968
        ord_aux = getSubSet(all, _start, _end);
2969
        resp[groups.length - 1] = ord_aux;
2970

    
2971
        return resp;
2972
    }
2973
    
2974
    
2975
    public static Object[] groupByElement(int[] all_elem) {
2976
        ArrayList resp = new ArrayList();
2977

    
2978
        int size = all_elem.length / 3;
2979

    
2980
        int[] aux = getNthGroupOfThree(all_elem, 0);
2981

    
2982
        int[] newaux;
2983
        int i = 1;
2984

    
2985
        while (i < size) {
2986
            newaux = getNthGroupOfThree(all_elem, i);
2987

    
2988
            if (newaux[0] == aux[0]) {
2989
                // aux[2] says how many components
2990
                for (int j = 0; j < aux[2]; j++) {
2991
                    aux = appendIntArrays(aux,
2992
                            getNthGroupOfThree(all_elem, j + i));
2993
                }
2994

    
2995
                resp.add(aux);
2996
                i = i + aux[2];
2997
                aux = getNthGroupOfThree(all_elem, i);
2998
            }
2999
            else {
3000
                if (newaux[1] == 2003) {
3001
                    aux = appendIntArrays(aux, newaux);
3002
                }
3003
                else {
3004
                    resp.add(aux);
3005
                    aux = getNthGroupOfThree(all_elem, i);
3006
                }
3007
            }
3008

    
3009
            i++;
3010
        }
3011

    
3012
        resp.add(aux);
3013

    
3014
        return resp.toArray();
3015
    }
3016
    
3017
    public static boolean isSimpleCollectionOfLines(Datum[] all_elem) {
3018
            
3019
            try {
3020
                int size = all_elem.length;
3021
                if (all_elem[1].intValue() != 4) return false;
3022
                int size3 = size / 3;
3023
                
3024
                for (int i=1; i<size3; i++) {
3025
                        if (all_elem[3 * i + 1].intValue() != 2) return false; 
3026
                }
3027
                return true;
3028
                
3029
            } catch (SQLException ex) {
3030
                    logger.error("While is simple line collection: " + ex.getMessage());
3031
            }
3032
            
3033
            return false;
3034
    }
3035
    
3036
    public static Datum[] removeThreeFirst(Datum[] elem) {
3037
            int sz = elem.length;
3038
            Datum[] resp = new Datum[sz - 3];
3039
            for (int i=3; i<sz; i++) resp[i - 3] = elem[i];
3040
            return resp;
3041
    }
3042
    
3043
    public static Object[] groupByElement(Datum[] all_elem) {
3044
            
3045
            if (isSimpleCollectionOfLines(all_elem)) {
3046
                    Object[] r = new Object[1];
3047
                    r[0] = removeThreeFirst(all_elem);
3048
                    return r;
3049
            }
3050
            
3051
        ArrayList resp = new ArrayList();
3052

    
3053
        int size = all_elem.length / 3;
3054

    
3055
        Datum[] aux = getNthGroupOfThree(all_elem, 0);
3056

    
3057
        Datum[] newaux;
3058
        int i = 1;
3059
        boolean add_last_time = true;
3060

    
3061
        try {
3062
            while (i < size) {
3063
                newaux = getNthGroupOfThree(all_elem, i);
3064

    
3065
                if (newaux[0].intValue() == aux[0].intValue()) {
3066
                    // aux[2] says how many components
3067
                    for (int j = 0; j < ((NUMBER) aux[2]).intValue(); j++) {
3068
                        aux = appendDatArrays(aux,
3069
                                getNthGroupOfThree(all_elem, j + i));
3070
                    }
3071

    
3072
                    resp.add(aux);
3073
                    i = i + ((NUMBER) aux[2]).intValue();
3074
                    if (i < size) { // in some cases (line collection, 4)
3075
                            aux = getNthGroupOfThree(all_elem, i);
3076
                    } else {
3077
                            add_last_time = false;
3078
                    }
3079
                }
3080
                else {
3081
                        
3082
                    resp.add(aux);
3083
                    aux = getNthGroupOfThree(all_elem, i);
3084
                    // no complex subelements expected
3085
                    /*
3086
                    if (((NUMBER) newaux[1]).intValue() == 1003
3087
                                    || ((NUMBER) newaux[1]).intValue() == 2003) {
3088
                        resp.add(aux);
3089
                        aux = getNthGroupOfThree(all_elem, i);
3090
                    } else {
3091
                        aux = appendDatArrays(aux, newaux);
3092
                    }
3093
                    */
3094
                }
3095

    
3096
                i++;
3097
            }
3098
        }
3099
        catch (SQLException se) { 
3100
            logger.error("Unexpected error: " + se.getMessage());
3101
        }
3102

    
3103
        if (add_last_time) {
3104
                resp.add(aux);
3105
        }
3106

    
3107
        return resp.toArray();
3108
    }
3109
    
3110
    
3111
    
3112
    public static Geometry shapeToGeometry(Shape shp) {
3113
        if (shp == null) {
3114
            return null;
3115
        }
3116

    
3117
        int type = FShape.POLYGON;
3118

    
3119
        if ((shp instanceof FPolyline2D) && (!(shp instanceof FPolygon2D))) {
3120
            type = FShape.LINE;
3121
        }
3122

    
3123
        if (shp instanceof FPoint2D) {
3124
            type = FShape.POINT;
3125
        }
3126

    
3127
        if (shp instanceof FMultiPoint2D) {
3128
            type = FShape.MULTIPOINT;
3129
        }
3130

    
3131
        GeneralPathX wagp = new GeneralPathX(shp);
3132
        FShapeGeneralPathX fwagp = new FShapeGeneralPathX(wagp, type);
3133

    
3134
        return FConverter.java2d_to_jts(fwagp);
3135
    }
3136
    
3137
    public static STRUCT rectangleToStruct(Rectangle2D r, boolean hasSrid,
3138
            boolean isView, boolean _isGeogCS, String _oracleSRID, IConnection __conn) {
3139
            Point2D c1 = new Point2D.Double(r.getMinX(), r.getMinY());
3140
            Point2D c2 = new Point2D.Double(r.getMaxX(), r.getMaxY());
3141

    
3142
            if ((_isGeogCS) && (isView)) {
3143
                    // absurd cases for geodetic (user chose wrong epsg when loading the table) 
3144
                    if (r.getMinX() >= 180) {
3145
                        c1.setLocation(179, 0);
3146
                        c2.setLocation(180, 1);
3147
                    }
3148
                    
3149
                    if (r.getMaxX() <= -180) {
3150
                        c1.setLocation(-180, 0);
3151
                        c2.setLocation(-179, 1);
3152
                    }
3153
                    
3154
                    if (r.getMinY() >= 90) {
3155
                        c1.setLocation(0, 89);
3156
                        c2.setLocation(1, 90);
3157
                    }
3158
                    
3159
                    if (r.getMaxY() <= -90) {
3160
                        c1.setLocation(0, -90);
3161
                        c2.setLocation(1, -89);
3162
                    }
3163
            }
3164

    
3165
            STRUCT resp = null;
3166

    
3167
            try {
3168
                // System.out.println("ABIERTA: " + (!conn.isClosed()));
3169
                // resp = structCreator.toSTRUCT(rect_wkt.getBytes(), conn);
3170
                // Object[] old_obj = resp.getAttributes();
3171
                int size = 5;
3172
                Object[] new_obj = new Object[size];
3173

    
3174
                // for (int i=0; i<size; i++) new_obj[i] = old_obj[i];
3175
                new_obj[0] = new NUMBER(2003);
3176

    
3177
                if (hasSrid) {
3178
                    new_obj[1] = new NUMBER(_oracleSRID);
3179
                }
3180
                else {
3181
                    new_obj[1] = null;
3182
                }
3183

    
3184
                new_obj[2] = null;
3185

    
3186
                NUMBER[] elem_info = new NUMBER[3];
3187
                elem_info[0] = new NUMBER(1);
3188
                elem_info[1] = new NUMBER(1003);
3189
                elem_info[2] = new NUMBER(3);
3190
                new_obj[3] = elem_info;
3191

    
3192
                NUMBER[] ords = null;
3193
                ords = new NUMBER[4];
3194
                ords[0] = new NUMBER(c1.getX());
3195
                ords[1] = new NUMBER(c1.getY());
3196
                ords[2] = new NUMBER(c2.getX());
3197
                ords[3] = new NUMBER(c2.getY());
3198
                new_obj[4] = ords;
3199

    
3200
                // StructDescriptor dsc = StructDescriptor.createDescriptor("STRUCT", conn);
3201
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
3202
                                ((ConnectionJDBC)__conn).getConnection());
3203

    
3204
                resp = new STRUCT(dsc,((ConnectionJDBC)__conn).getConnection(), new_obj);
3205
            }
3206
            catch (Exception ex) {
3207
                logger.error("Error while creating rect struct: " +
3208
                    ex.getMessage(), ex);
3209
            }
3210

    
3211
            return resp;
3212
        }
3213
    
3214
    
3215
    public static Rectangle2D doIntersect(Rectangle2D r1, Rectangle2D r2) {
3216
        if (r1.getMaxX() <= r2.getMinX()) {
3217
            return null;
3218
        }
3219

    
3220
        if (r2.getMaxX() <= r1.getMinX()) {
3221
            return null;
3222
        }
3223

    
3224
        if (r1.getMaxY() <= r2.getMinY()) {
3225
            return null;
3226
        }
3227

    
3228
        if (r2.getMaxY() <= r1.getMinY()) {
3229
            return null;
3230
        }
3231

    
3232
        double minx = Math.max(r1.getMinX(), r2.getMinX());
3233
        double miny = Math.max(r1.getMinY(), r2.getMinY());
3234
        double maxx = Math.min(r1.getMaxX(), r2.getMaxX());
3235
        double maxy = Math.min(r1.getMaxY(), r2.getMaxY());
3236

    
3237
        double w = maxx - minx;
3238
        double h = maxy - miny;
3239

    
3240
        return new Rectangle2D.Double(minx, miny, w, h);
3241
    }
3242
    
3243
    
3244
    /**
3245
     * Utility method to find out if a coordinate system is geodetic or not.
3246
     *
3247
     * @param oracleSRID2 the coordinate system's oracle code
3248
     * @param thas whether the table has a coordinate system set.
3249
     * if not, the method returns false.
3250
     * @return whether the coordinate system is geodetic or not.
3251
     */
3252
    public static boolean getIsGCS(String oracleSRID2, boolean thas) {
3253

    
3254
        if (!thas) return false;
3255
        if (oracleSRID2 == null) return false;
3256
        
3257
        int ora_cs = 0;
3258

    
3259
        try {
3260
            ora_cs = Integer.parseInt(oracleSRID2);
3261
        }
3262
        catch (Exception ex) {
3263
            return false;
3264
        }
3265

    
3266
        if (((ora_cs >= 8000) && (ora_cs <= 8999)) || (ora_cs == 524288)) {
3267
            return true;
3268
        } else {
3269
                return false;
3270
        }
3271
    }
3272
    
3273
    
3274
    public static int getShapeTypeOfStruct(STRUCT sample) throws SQLException {
3275

    
3276
        int code = ((NUMBER) sample.getOracleAttributes()[0]).intValue();
3277
        
3278
        int type_part = code % 10;
3279
        int dim_part = code / 1000;
3280

    
3281
        int z_added = 0;
3282
        if (dim_part == 3) {
3283
                z_added = FShape.Z;
3284
        } else {
3285
            if (dim_part == 4) {
3286
                    z_added = FShape.Z | FShape.M;
3287
            }
3288
        }
3289

    
3290
        switch (type_part) {
3291
        case 1:
3292
            return z_added + FShape.POINT;
3293

    
3294
        case 2:
3295
            return z_added + FShape.LINE;
3296

    
3297
        case 3:
3298
            return z_added + FShape.POLYGON;
3299

    
3300
        case 4:
3301
            return z_added + FShape.MULTI;
3302

    
3303
        case 5:
3304
            return z_added + FShape.MULTIPOINT;
3305

    
3306
        case 6:
3307
            return z_added + FShape.LINE;
3308

    
3309
        case 7:
3310
            return z_added + FShape.POLYGON;
3311
        }
3312

    
3313
        logger.error("Unknown geometry type: " + code);
3314

    
3315
        return FShape.NULL;
3316
    }
3317
    
3318
    public static IGeometry NULL_GEOM = new FNullGeometry();
3319
    
3320

    
3321
    
3322
    
3323
    public static int[] updateIndexes(int[] info) {
3324
        int size = info.length / 3;
3325
        int[] resp = new int[3 * size];
3326
        int rest = info[0] - 1;
3327

    
3328
        for (int i = 0; i < size; i++) {
3329
            resp[3 * i] = info[3 * i] - rest;
3330
            resp[(3 * i) + 1] = info[(3 * i) + 1];
3331
            resp[(3 * i) + 2] = info[(3 * i) + 2];
3332
        }
3333

    
3334
        return resp;
3335
    }
3336
    
3337
    
3338

    
3339
    public static int[] appendIntArrays(int[] head, int[] tail) {
3340
        int[] resp = new int[head.length + tail.length];
3341
        int hsize = head.length;
3342

    
3343
        for (int i = 0; i < hsize; i++) {
3344
            resp[i] = head[i];
3345
        }
3346

    
3347
        for (int i = 0; i < tail.length; i++) {
3348
            resp[hsize + i] = tail[i];
3349
        }
3350

    
3351
        return resp;
3352
    }
3353
    
3354
    
3355
    public static Datum[] appendDatArrays(Datum[] head, Datum[] tail) {
3356
        Datum[] resp = new Datum[head.length + tail.length];
3357
        int hsize = head.length;
3358

    
3359
        for (int i = 0; i < hsize; i++) {
3360
            resp[i] = head[i];
3361
        }
3362

    
3363
        for (int i = 0; i < tail.length; i++) {
3364
            resp[hsize + i] = tail[i];
3365
        }
3366

    
3367
        return resp;
3368
    }
3369

    
3370
    public static int[] getNthGroupOfThree(int[] list, int n) {
3371
        int[] resp = new int[3];
3372
        resp[0] = list[3 * n];
3373
        resp[1] = list[(3 * n) + 1];
3374
        resp[2] = list[(3 * n) + 2];
3375

    
3376
        return resp;
3377
    }
3378

    
3379
    public static Datum[] getNthGroupOfThree(Datum[] list, int n) {
3380
        Datum[] resp = new Datum[3];
3381
        resp[0] = list[3 * n];
3382
        resp[1] = list[(3 * n) + 1];
3383
        resp[2] = list[(3 * n) + 2];
3384

    
3385
        return resp;
3386
    }
3387

    
3388
    public static Datum[] getSubSet(Datum[] all, int first_inc, int last_inc) {
3389
        Datum[] resp = new Datum[last_inc - first_inc + 1];
3390

    
3391
        for (int i = first_inc; i <= last_inc; i++) {
3392
            resp[i - first_inc] = all[i];
3393
        }
3394

    
3395
        return resp;
3396
    }
3397
    
3398
    
3399
    public static int maxSizeForFieldType(int _type) {
3400
        switch (_type) {
3401
        case Types.VARCHAR:
3402
        case Types.LONGVARCHAR:
3403
            return OracleSpatialDriver.VARCHAR2_MAX_SIZE;
3404
        }
3405

    
3406
        return -1;
3407
    }
3408
    
3409
    
3410
    
3411
    public static String EXPONENTIAL_INDICES_CONDITION = null;
3412
    
3413
    static {
3414
            
3415
            String sb = "";
3416
            int i=0;
3417
            sb = "(rownum = 1)";
3418
            for (i=2; i<20; i++) {
3419
                    sb = "(" + sb + " OR (rownum = " + i + "))";
3420
            }
3421
            int cnt = 0;
3422
            float aux = 1;
3423
            while (cnt < 35) {
3424
                    aux = aux * 1.5f;
3425
                    i = 20 + Math.round(aux);
3426
                    sb = "(" + sb + " OR (rownum = " + i + "))";
3427
                    cnt++;
3428
            }
3429
                aux = aux * 1.5f;
3430
                i = 20 + Math.round(aux);
3431
                sb = "(" + sb + " OR (rownum = " + i + "))";
3432
                EXPONENTIAL_INDICES_CONDITION = sb;
3433
    }
3434

    
3435
        public static IGeometry makeLinear(FPolygon2D shp) {
3436
                
3437
                
3438
                if (shp instanceof FPolygon3D) {
3439
                        
3440
                        double[] z = ((FPolygon3D) shp).getZs();
3441
                        PathIterator piter = shp.getPathIterator(null);
3442
                        GeneralPathX gpx = new GeneralPathX();
3443
                        gpx.append(piter, false);
3444
                        return ShapeFactory.createPolyline3D(gpx, z);
3445
                } else {
3446
                        PathIterator piter = shp.getPathIterator(null);
3447
                        GeneralPathX gpx = new GeneralPathX();
3448
                        gpx.append(piter, false);
3449
                        return ShapeFactory.createPolyline2D(gpx);
3450
                }
3451
        }
3452

    
3453
        public static IGeometry mergePolygons(FGeometryCollection gco) {
3454
                GeneralPathX gpx = new GeneralPathX();
3455
                
3456
                IGeometry[] gg = gco.getGeometries();
3457
                int cnt = gg.length;
3458
                IGeometry ig2d;
3459
                for (int i=0; i<cnt; i++) {
3460
                        ig2d = gg[i];
3461
                        gpx.append(ig2d.getPathIterator(null), false);
3462
                }
3463
                return ShapeFactory.createPolygon2D(gpx);
3464
        }
3465

    
3466
        public static int estimateGoodFetchSize(ResultSetMetaData md) { 
3467
                
3468
                int bytesum = 0;
3469
                try {
3470
                        int sz = md.getColumnCount();
3471
                        int inc = 0;
3472
                        for (int i=1; i<=sz; i++) {
3473
                                inc = md.getColumnDisplaySize(i);
3474
                                if ((inc >= 0) && (inc <= OracleSpatialDriver.VARCHAR2_MAX_SIZE)) {
3475
                                        bytesum = bytesum + inc;
3476
                                }
3477
                        }
3478
                        // TODO Auto-generated method stub
3479
                } catch (SQLException se) {
3480
                        logger.warn("Error while getting field sizes: " + se.getMessage());
3481
                        logger.warn("Used: row size = 5000 bytes.");
3482
                        bytesum = 5000;
3483
                }
3484
                
3485
                return Math.max(10, FETCH_BLOCK_SIZE_BYTES / bytesum);
3486
        }
3487
    
3488
        
3489

    
3490
}