root / branches / v10 / extensions / extOracleSpatial / src / es / prodevelop / cit / gvsig / fmap / drivers / jdbc / oracle / OracleSpatialUtils.java @ 13996
History | View | Annotate | Download (65.3 KB)
1 | 13991 | jldominguez@prodevelop.es | /* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2006 Prodevelop and Generalitat Valenciana.
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
18 | *
|
||
19 | * For more information, contact:
|
||
20 | *
|
||
21 | * Generalitat Valenciana
|
||
22 | * Conselleria d'Infraestructures i Transport
|
||
23 | * Av. Blasco Ib??ez, 50
|
||
24 | * 46010 VALENCIA
|
||
25 | * SPAIN
|
||
26 | *
|
||
27 | * +34 963862235
|
||
28 | * gvsig@gva.es
|
||
29 | * www.gvsig.gva.es
|
||
30 | *
|
||
31 | * or
|
||
32 | *
|
||
33 | * Prodevelop Integraci?n de Tecnolog?as SL
|
||
34 | * Conde Salvatierra de ?lava , 34-10
|
||
35 | * 46004 Valencia
|
||
36 | * Spain
|
||
37 | *
|
||
38 | * +34 963 510 612
|
||
39 | * +34 963 510 968
|
||
40 | * gis@prodevelop.es
|
||
41 | * http://www.prodevelop.es
|
||
42 | */
|
||
43 | package es.prodevelop.cit.gvsig.fmap.drivers.jdbc.oracle; |
||
44 | |||
45 | import com.iver.cit.gvsig.fmap.core.FCircle2D; |
||
46 | import com.iver.cit.gvsig.fmap.core.FGeometryCollection; |
||
47 | import com.iver.cit.gvsig.fmap.core.FMultiPoint2D; |
||
48 | import com.iver.cit.gvsig.fmap.core.FMultipoint3D; |
||
49 | import com.iver.cit.gvsig.fmap.core.FPoint2D; |
||
50 | import com.iver.cit.gvsig.fmap.core.FPoint3D; |
||
51 | import com.iver.cit.gvsig.fmap.core.FPolygon2D; |
||
52 | import com.iver.cit.gvsig.fmap.core.FPolygon3D; |
||
53 | import com.iver.cit.gvsig.fmap.core.FPolyline3D; |
||
54 | import com.iver.cit.gvsig.fmap.core.FShape; |
||
55 | import com.iver.cit.gvsig.fmap.core.FShape3D; |
||
56 | import com.iver.cit.gvsig.fmap.core.GeneralPathX; |
||
57 | import com.iver.cit.gvsig.fmap.core.IGeometry; |
||
58 | import com.iver.cit.gvsig.fmap.core.ShapeFactory; |
||
59 | |||
60 | import com.vividsolutions.jts.algorithm.CGAlgorithms; |
||
61 | import com.vividsolutions.jts.geom.Coordinate; |
||
62 | import com.vividsolutions.jts.geom.CoordinateArrays; |
||
63 | import com.vividsolutions.jts.geom.Envelope; |
||
64 | import com.vividsolutions.jts.geom.GeometryFactory; |
||
65 | import com.vividsolutions.jts.geom.LineString; |
||
66 | import com.vividsolutions.jts.geom.LinearRing; |
||
67 | import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; |
||
68 | |||
69 | import oracle.sql.ARRAY; |
||
70 | import oracle.sql.Datum; |
||
71 | import oracle.sql.NUMBER; |
||
72 | import oracle.sql.STRUCT; |
||
73 | import oracle.sql.StructDescriptor; |
||
74 | |||
75 | import org.apache.log4j.Logger; |
||
76 | |||
77 | import java.awt.geom.PathIterator; |
||
78 | import java.awt.geom.Point2D; |
||
79 | import java.awt.geom.Rectangle2D; |
||
80 | |||
81 | import java.io.BufferedReader; |
||
82 | import java.io.File; |
||
83 | import java.io.FileReader; |
||
84 | |||
85 | import java.lang.reflect.Array; |
||
86 | |||
87 | import java.net.URL; |
||
88 | |||
89 | import java.sql.Connection; |
||
90 | import java.sql.PreparedStatement; |
||
91 | import java.sql.ResultSet; |
||
92 | import java.sql.SQLException; |
||
93 | import java.sql.Statement; |
||
94 | |||
95 | import java.text.DecimalFormat; |
||
96 | import java.text.DecimalFormatSymbols; |
||
97 | |||
98 | import java.util.ArrayList; |
||
99 | import java.util.Random; |
||
100 | |||
101 | |||
102 | /**
|
||
103 | * Utility class with static methods.
|
||
104 | *
|
||
105 | * @author jldominguez
|
||
106 | *
|
||
107 | */
|
||
108 | public class OracleSpatialUtils { |
||
109 | private static Logger logger = Logger.getLogger(OracleSpatialUtils.class.getName()); |
||
110 | private static double FLATNESS = 0.8; |
||
111 | private static GeometryFactory geomFactory = new GeometryFactory(); |
||
112 | private static final double IRRELEVANT_DISTANCE = 0.00000001; |
||
113 | private static Random rnd = new Random(); |
||
114 | private static DecimalFormat df = new DecimalFormat(); |
||
115 | private static DecimalFormatSymbols dfs = new DecimalFormatSymbols(); |
||
116 | public static final int ORACLE_GTYPE_UNKNOWN = 0; |
||
117 | public static final int ORACLE_GTYPE_POINT = 1; |
||
118 | public static final int ORACLE_GTYPE_LINE = 2; |
||
119 | public static final int ORACLE_GTYPE_POLYGON = 3; |
||
120 | public static final int ORACLE_GTYPE_COLLECTION = 4; |
||
121 | public static final int ORACLE_GTYPE_MULTIPOINT = 5; |
||
122 | public static final int ORACLE_GTYPE_MULTILINE = 6; |
||
123 | public static final int ORACLE_GTYPE_MULTIPOLYGON = 7; |
||
124 | |||
125 | /**
|
||
126 | * COnstructs a geometry from a file that contains a vertex per line:
|
||
127 | *
|
||
128 | * x1 y1 z1
|
||
129 | * x2 y2 z2
|
||
130 | * ...
|
||
131 | *
|
||
132 | * @param filepath vertices text file path
|
||
133 | * @param polygon whether it is a polygon or not
|
||
134 | * @return the created geometry
|
||
135 | */
|
||
136 | public static IGeometry readGeometry3D(URL filepath, boolean polygon) { |
||
137 | GeneralPathX resp = new GeneralPathX();
|
||
138 | File file = new File(filepath.getFile()); |
||
139 | ArrayList z = new ArrayList(); |
||
140 | |||
141 | try {
|
||
142 | FileReader fr = new FileReader(file); |
||
143 | BufferedReader br = new BufferedReader(fr); |
||
144 | double[] coords = new double[3]; |
||
145 | |||
146 | boolean move = true; |
||
147 | |||
148 | String line = br.readLine();
|
||
149 | |||
150 | while (line != null) { |
||
151 | coords = parseLine(line); |
||
152 | |||
153 | if (line.length() == 0) { |
||
154 | move = true;
|
||
155 | } |
||
156 | else {
|
||
157 | if (move) {
|
||
158 | resp.moveTo(coords[0], coords[1]); |
||
159 | z.add(new Double(coords[2])); |
||
160 | } |
||
161 | else {
|
||
162 | resp.lineTo(coords[0], coords[1]); |
||
163 | z.add(new Double(coords[2])); |
||
164 | } |
||
165 | |||
166 | move = false;
|
||
167 | } |
||
168 | |||
169 | line = br.readLine(); |
||
170 | } |
||
171 | } |
||
172 | catch (Exception ex) { |
||
173 | System.err.println("Error while creating GeneralPathX: " + |
||
174 | ex.getMessage()); |
||
175 | |||
176 | return null; |
||
177 | } |
||
178 | |||
179 | double[] zz = new double[z.size()]; |
||
180 | |||
181 | for (int i = 0; i < z.size(); i++) { |
||
182 | zz[i] = ((Double) z.get(i)).doubleValue();
|
||
183 | } |
||
184 | |||
185 | if (polygon) {
|
||
186 | return ShapeFactory.createPolygon3D(resp, zz);
|
||
187 | } |
||
188 | else {
|
||
189 | return ShapeFactory.createPolyline3D(resp, zz);
|
||
190 | } |
||
191 | } |
||
192 | |||
193 | private static double[] parseLine(String line) { |
||
194 | String[] sep = line.split(" "); |
||
195 | double[] resp = new double[3]; |
||
196 | |||
197 | for (int i = 0; i < 3; i++) |
||
198 | resp[i] = 0.0;
|
||
199 | |||
200 | try {
|
||
201 | resp[0] = Double.parseDouble(sep[0]); |
||
202 | } |
||
203 | catch (Exception ex) { |
||
204 | } |
||
205 | |||
206 | if (sep.length > 1) { |
||
207 | try {
|
||
208 | resp[1] = Double.parseDouble(sep[1]); |
||
209 | } |
||
210 | catch (Exception ex) { |
||
211 | } |
||
212 | |||
213 | if (sep.length > 2) { |
||
214 | try {
|
||
215 | resp[2] = Double.parseDouble(sep[2]); |
||
216 | } |
||
217 | catch (Exception ex) { |
||
218 | } |
||
219 | } |
||
220 | } |
||
221 | |||
222 | return resp;
|
||
223 | } |
||
224 | |||
225 | /**
|
||
226 | * Utility method to convert a gvSIG FShape into a oracle struct
|
||
227 | *
|
||
228 | * @param fshp the FShape object
|
||
229 | * @param c the connection
|
||
230 | * @param srid the SRS (oarcle code)
|
||
231 | * @param agu_b whether to check holes validity
|
||
232 | * @param hasSrid whether the SRS is non-NULL
|
||
233 | * @return a oracle struct representing the geometry
|
||
234 | *
|
||
235 | * @throws SQLException
|
||
236 | */
|
||
237 | public static STRUCT fShapeToSTRUCT(Object fshp, Connection c, int srid, |
||
238 | boolean agu_b, boolean hasSrid) throws SQLException { |
||
239 | boolean three = false; |
||
240 | |||
241 | if (fshp instanceof FShape3D) { |
||
242 | three = true;
|
||
243 | } |
||
244 | |||
245 | STRUCT resp = null;
|
||
246 | |||
247 | if (fshp instanceof FMultiPoint2D) { |
||
248 | resp = multiPoint2DToStruct((FMultiPoint2D) fshp, c, srid, hasSrid); |
||
249 | |||
250 | return resp;
|
||
251 | } |
||
252 | |||
253 | if (!(fshp instanceof FShape)) { |
||
254 | logger.error("Unknown geometry: " + fshp.toString());
|
||
255 | |||
256 | return null; |
||
257 | } |
||
258 | |||
259 | if (fshp instanceof FPoint2D) { // point 2/3d |
||
260 | |||
261 | // resp = pointToWKT((FPoint2D) fshp, three);
|
||
262 | Coordinate p = getSingleCoordinate((FPoint2D) fshp); |
||
263 | resp = getMultiPointAsStruct(p, srid, three, c, hasSrid); |
||
264 | } |
||
265 | else {
|
||
266 | if (fshp instanceof FPolygon2D) { // polygon 2/3d |
||
267 | |||
268 | if (fshp instanceof FCircle2D) { |
||
269 | resp = getCircleAsStruct((FCircle2D) fshp, srid, c, hasSrid); |
||
270 | } |
||
271 | else {
|
||
272 | // also FEllipse2D
|
||
273 | resp = getMultiPolygonAsStruct((FShape) fshp, srid, three, |
||
274 | c, agu_b, hasSrid); |
||
275 | |||
276 | // ArrayList polys = getPolygonsEasily(fshp);
|
||
277 | // resp = getMultiPolygonAsStruct(polys, srid, three, c);
|
||
278 | } |
||
279 | } |
||
280 | else { // line 2/3d |
||
281 | |||
282 | ArrayList _lines = getLineStrings((FShape) fshp);
|
||
283 | resp = getMultiLineAsStruct(_lines, srid, three, c, hasSrid); |
||
284 | } |
||
285 | } |
||
286 | |||
287 | return resp;
|
||
288 | } |
||
289 | |||
290 | private static STRUCT multiPoint2DToStruct(FMultiPoint2D mp2d, |
||
291 | Connection c, int srid, boolean hasSrid) throws SQLException { |
||
292 | int np = mp2d.getNumPoints();
|
||
293 | boolean threed = (mp2d instanceof FMultipoint3D); |
||
294 | int gtype = 2005; |
||
295 | int dim = 2; |
||
296 | FMultipoint3D mp3d = null;
|
||
297 | |||
298 | if (threed) {
|
||
299 | gtype = 3005;
|
||
300 | dim = 3;
|
||
301 | mp3d = (FMultipoint3D) mp2d; |
||
302 | } |
||
303 | |||
304 | NUMBER[] indices = new NUMBER[3]; |
||
305 | indices[0] = new NUMBER(1); |
||
306 | indices[1] = new NUMBER(1); |
||
307 | indices[2] = new NUMBER(np); |
||
308 | |||
309 | NUMBER[] ords = new NUMBER[dim * np]; |
||
310 | |||
311 | for (int i = 0; i < np; i++) { |
||
312 | ords[dim * i] = new NUMBER(mp2d.getPoint(i).getX());
|
||
313 | ords[(dim * i) + 1] = new NUMBER(mp2d.getPoint(i).getY()); |
||
314 | |||
315 | if (threed) {
|
||
316 | ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]); |
||
317 | } |
||
318 | } |
||
319 | |||
320 | STRUCT resp; |
||
321 | StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
|
||
322 | c); |
||
323 | Object[] obj = new Object[5]; |
||
324 | obj[0] = new NUMBER(gtype); |
||
325 | |||
326 | if (hasSrid) {
|
||
327 | obj[1] = new NUMBER(srid); |
||
328 | } |
||
329 | else { // , boolean hasSrid |
||
330 | obj[1] = null; |
||
331 | } |
||
332 | |||
333 | obj[2] = null; |
||
334 | obj[3] = indices;
|
||
335 | obj[4] = ords;
|
||
336 | resp = new STRUCT(dsc, c, obj);
|
||
337 | |||
338 | return resp;
|
||
339 | } |
||
340 | |||
341 | private static STRUCT getCircleAsStruct(FCircle2D fcirc, int srid, |
||
342 | Connection _conn, boolean hasSrid) throws SQLException { |
||
343 | int geotype = 2003; |
||
344 | NUMBER[] indices = new NUMBER[3]; |
||
345 | indices[0] = new NUMBER(1); |
||
346 | indices[1] = new NUMBER(1003); |
||
347 | indices[2] = new NUMBER(4); |
||
348 | |||
349 | NUMBER[] ords = new NUMBER[6]; |
||
350 | Coordinate[] three_points = getThreePointsOfCircumference(fcirc.getCenter(),
|
||
351 | fcirc.getRadio()); |
||
352 | |||
353 | for (int i = 0; i < three_points.length; i++) { |
||
354 | ords[i * 2] = new NUMBER(three_points[i].x); |
||
355 | ords[(i * 2) + 1] = new NUMBER(three_points[i].y); |
||
356 | } |
||
357 | |||
358 | STRUCT resp; |
||
359 | StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
|
||
360 | _conn); |
||
361 | Object[] obj = new Object[5]; |
||
362 | obj[0] = new NUMBER(geotype); |
||
363 | |||
364 | if (hasSrid) {
|
||
365 | obj[1] = new NUMBER(srid); |
||
366 | } |
||
367 | else {
|
||
368 | obj[1] = null; |
||
369 | } |
||
370 | |||
371 | obj[2] = null; |
||
372 | obj[3] = indices;
|
||
373 | obj[4] = ords;
|
||
374 | resp = new STRUCT(dsc, _conn, obj);
|
||
375 | |||
376 | return resp;
|
||
377 | } |
||
378 | |||
379 | private static Coordinate[] getThreePointsOfCircumference(Point2D cntr, |
||
380 | double radius) {
|
||
381 | Coordinate[] resp = new Coordinate[3]; |
||
382 | double x;
|
||
383 | double y;
|
||
384 | double alpha = 0; |
||
385 | |||
386 | for (int i = 0; i < 3; i++) { |
||
387 | alpha = (i * 120.0 * Math.PI) / 180.0; |
||
388 | x = cntr.getX() + (radius * Math.cos(alpha));
|
||
389 | y = cntr.getY() + (radius * Math.sin(alpha));
|
||
390 | resp[i] = new Coordinate(x, y);
|
||
391 | } |
||
392 | |||
393 | return resp;
|
||
394 | } |
||
395 | |||
396 | private static Coordinate getSingleCoordinate(FPoint2D p2d) { |
||
397 | // TODO Auto-generated method stub
|
||
398 | Coordinate resp = new Coordinate();
|
||
399 | resp.x = p2d.getX(); |
||
400 | resp.y = p2d.getY(); |
||
401 | |||
402 | if (p2d instanceof FPoint3D) { |
||
403 | resp.z = ((FPoint3D) p2d).getZs()[0];
|
||
404 | } |
||
405 | |||
406 | return resp;
|
||
407 | } |
||
408 | |||
409 | private static ArrayList ensureSensibleLineString(ArrayList cc) { |
||
410 | if (cc.size() == 2) { |
||
411 | if (sameCoordinate((Coordinate) cc.get(0), |
||
412 | (Coordinate) cc.get(cc.size() - 1))) {
|
||
413 | ArrayList resp = new ArrayList(); |
||
414 | resp.add(cc.get(0));
|
||
415 | |||
416 | Coordinate newc = new Coordinate((Coordinate) cc.get(0)); |
||
417 | newc.x = newc.x + IRRELEVANT_DISTANCE; |
||
418 | resp.add(newc); |
||
419 | |||
420 | return resp;
|
||
421 | } |
||
422 | } |
||
423 | |||
424 | return cc;
|
||
425 | } |
||
426 | |||
427 | private static boolean sameCoordinate(Coordinate c1, Coordinate c2) { |
||
428 | if (c1.x != c2.x) {
|
||
429 | return false; |
||
430 | } |
||
431 | |||
432 | if (c1.y != c2.y) {
|
||
433 | return false; |
||
434 | } |
||
435 | |||
436 | return true; |
||
437 | } |
||
438 | |||
439 | private static ArrayList getClosedRelevantPolygon(ArrayList cc) { |
||
440 | if (cc.size() == 2) { |
||
441 | return getMinClosedCoords((Coordinate) cc.get(0)); |
||
442 | } |
||
443 | |||
444 | if (cc.size() == 3) { |
||
445 | if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(1))) { |
||
446 | return getMinClosedCoords((Coordinate) cc.get(0)); |
||
447 | } |
||
448 | |||
449 | if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(2))) { |
||
450 | return getMinClosedCoords((Coordinate) cc.get(0)); |
||
451 | } |
||
452 | |||
453 | if (sameCoordinate((Coordinate) cc.get(1), (Coordinate) cc.get(2))) { |
||
454 | return getMinClosedCoords((Coordinate) cc.get(1)); |
||
455 | } |
||
456 | |||
457 | cc.add(cc.get(0));
|
||
458 | |||
459 | return cc;
|
||
460 | } |
||
461 | |||
462 | if (!sameCoordinate((Coordinate) cc.get(0), |
||
463 | (Coordinate) cc.get(cc.size() - 1))) {
|
||
464 | cc.add(cc.get(0));
|
||
465 | } |
||
466 | |||
467 | return cc;
|
||
468 | } |
||
469 | |||
470 | private static ArrayList getMinClosedCoords(Coordinate c) { |
||
471 | ArrayList resp = new ArrayList(); |
||
472 | resp.add(c); |
||
473 | |||
474 | Coordinate nc = new Coordinate(c);
|
||
475 | nc.x = nc.x + IRRELEVANT_DISTANCE; |
||
476 | resp.add(nc); |
||
477 | |||
478 | Coordinate nc2 = new Coordinate(nc);
|
||
479 | nc2.y = nc2.y + IRRELEVANT_DISTANCE; |
||
480 | resp.add(nc2); |
||
481 | |||
482 | resp.add(new Coordinate(c));
|
||
483 | |||
484 | return resp;
|
||
485 | } |
||
486 | |||
487 | private static LinearRing getMinLinearRing(Coordinate c) { |
||
488 | Coordinate[] p = new Coordinate[4]; |
||
489 | p[0] = c;
|
||
490 | |||
491 | Coordinate nc = new Coordinate(c);
|
||
492 | nc.x = nc.x + IRRELEVANT_DISTANCE; |
||
493 | |||
494 | Coordinate nc2 = new Coordinate(nc);
|
||
495 | nc2.y = nc2.y - IRRELEVANT_DISTANCE; |
||
496 | p[1] = nc;
|
||
497 | p[2] = nc2;
|
||
498 | p[3] = new Coordinate(c); |
||
499 | |||
500 | CoordinateArraySequence cs = new CoordinateArraySequence(p);
|
||
501 | LinearRing ls = new LinearRing(cs, geomFactory);
|
||
502 | |||
503 | return ls;
|
||
504 | } |
||
505 | |||
506 | private static double[] getMinLinearRingZ() { |
||
507 | double[] resp = new double[4]; |
||
508 | |||
509 | for (int i = 0; i < 4; i++) |
||
510 | resp[i] = 0.0;
|
||
511 | |||
512 | return resp;
|
||
513 | } |
||
514 | |||
515 | private static boolean pointInList(Coordinate testPoint, |
||
516 | Coordinate[] pointList) {
|
||
517 | int t;
|
||
518 | int numpoints;
|
||
519 | Coordinate p; |
||
520 | |||
521 | numpoints = Array.getLength(pointList);
|
||
522 | |||
523 | for (t = 0; t < numpoints; t++) { |
||
524 | p = pointList[t]; |
||
525 | |||
526 | if ((testPoint.x == p.x) && (testPoint.y == p.y) &&
|
||
527 | ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
|
||
528 | ) { |
||
529 | return true; |
||
530 | } |
||
531 | } |
||
532 | |||
533 | return false; |
||
534 | } |
||
535 | |||
536 | private static ArrayList getPolygonsEasily(FShape mpolygon) { |
||
537 | boolean threed = false; |
||
538 | |||
539 | if (mpolygon instanceof FPolygon3D) { |
||
540 | threed = true;
|
||
541 | } |
||
542 | |||
543 | int start_ind = 0; |
||
544 | int end_ind = 0; |
||
545 | int ind = 0; |
||
546 | int new_size;
|
||
547 | ArrayList arrayCoords = null; |
||
548 | ArrayList resp = new ArrayList(); |
||
549 | Coordinate[] points = null; |
||
550 | int theType = -99; |
||
551 | double[] theData = new double[6]; |
||
552 | Coordinate onlyCoord = null;
|
||
553 | int numParts = 0; |
||
554 | |||
555 | PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS); |
||
556 | |||
557 | while (!theIterator.isDone()) {
|
||
558 | //while not done
|
||
559 | theType = theIterator.currentSegment(theData); |
||
560 | |||
561 | if (onlyCoord == null) { |
||
562 | onlyCoord = new Coordinate();
|
||
563 | onlyCoord.x = theData[0];
|
||
564 | onlyCoord.y = theData[1];
|
||
565 | } |
||
566 | |||
567 | switch (theType) {
|
||
568 | case PathIterator.SEG_MOVETO: |
||
569 | |||
570 | if (arrayCoords == null) { |
||
571 | arrayCoords = new ArrayList(); |
||
572 | } |
||
573 | else {
|
||
574 | end_ind = ind - 1;
|
||
575 | |||
576 | arrayCoords = getClosedRelevantPolygon(arrayCoords); |
||
577 | new_size = arrayCoords.size(); |
||
578 | |||
579 | if (arrayCoords != null) { |
||
580 | points = CoordinateArrays.toCoordinateArray(arrayCoords); |
||
581 | |||
582 | try {
|
||
583 | LinearRing aux = geomFactory.createLinearRing(points); |
||
584 | double[] z = null; |
||
585 | |||
586 | if (threed) {
|
||
587 | z = getZ((FPolygon3D) mpolygon, start_ind, |
||
588 | end_ind, new_size); |
||
589 | } |
||
590 | |||
591 | LineString3D ring = new LineString3D(aux, z);
|
||
592 | |||
593 | if (CGAlgorithms.isCCW(points)) {
|
||
594 | resp.add(ring); |
||
595 | } |
||
596 | else {
|
||
597 | resp.add(ring.createReverse()); |
||
598 | } |
||
599 | } |
||
600 | catch (Exception e) { |
||
601 | System.err.println("Topology exception: " + |
||
602 | e.getMessage()); |
||
603 | |||
604 | return null; |
||
605 | } |
||
606 | } |
||
607 | |||
608 | arrayCoords = new ArrayList(); |
||
609 | |||
610 | start_ind = ind; |
||
611 | } |
||
612 | |||
613 | numParts++; |
||
614 | |||
615 | arrayCoords.add(new Coordinate(theData[0], theData[1])); |
||
616 | ind++; |
||
617 | |||
618 | break;
|
||
619 | |||
620 | case PathIterator.SEG_LINETO: |
||
621 | arrayCoords.add(new Coordinate(theData[0], theData[1])); |
||
622 | ind++; |
||
623 | |||
624 | break;
|
||
625 | |||
626 | case PathIterator.SEG_QUADTO: |
||
627 | System.out.println("SEG_QUADTO Not supported here"); |
||
628 | arrayCoords.add(new Coordinate(theData[0], theData[1])); |
||
629 | arrayCoords.add(new Coordinate(theData[2], theData[3])); |
||
630 | ind++; |
||
631 | ind++; |
||
632 | |||
633 | break;
|
||
634 | |||
635 | case PathIterator.SEG_CUBICTO: |
||
636 | System.out.println("SEG_CUBICTO Not supported here"); |
||
637 | arrayCoords.add(new Coordinate(theData[0], theData[1])); |
||
638 | arrayCoords.add(new Coordinate(theData[2], theData[3])); |
||
639 | arrayCoords.add(new Coordinate(theData[4], theData[5])); |
||
640 | ind++; |
||
641 | ind++; |
||
642 | ind++; |
||
643 | |||
644 | break;
|
||
645 | |||
646 | case PathIterator.SEG_CLOSE: |
||
647 | |||
648 | // Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
|
||
649 | // arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
|
||
650 | break;
|
||
651 | } //end switch
|
||
652 | |||
653 | theIterator.next(); |
||
654 | } //end while loop
|
||
655 | |||
656 | end_ind = ind - 1;
|
||
657 | |||
658 | // null shape:
|
||
659 | if (arrayCoords == null) { |
||
660 | arrayCoords = new ArrayList(); |
||
661 | |||
662 | Coordinate _c = new Coordinate(0, 0, 0); |
||
663 | arrayCoords.add(new Coordinate(_c));
|
||
664 | arrayCoords.add(new Coordinate(_c));
|
||
665 | } |
||
666 | |||
667 | // --------------------------------------------
|
||
668 | arrayCoords = getClosedRelevantPolygon(arrayCoords); |
||
669 | new_size = arrayCoords.size(); |
||
670 | |||
671 | if (arrayCoords != null) { |
||
672 | points = CoordinateArrays.toCoordinateArray(arrayCoords); |
||
673 | |||
674 | try {
|
||
675 | LinearRing aux = geomFactory.createLinearRing(points); |
||
676 | double[] z = null; |
||
677 | |||
678 | if (threed) {
|
||
679 | z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size); |
||
680 | } |
||
681 | |||
682 | LineString3D ring = new LineString3D(aux, z);
|
||
683 | |||
684 | if (CGAlgorithms.isCCW(points)) {
|
||
685 | resp.add(ring); |
||
686 | } |
||
687 | else {
|
||
688 | resp.add(ring.createReverse()); |
||
689 | } |
||
690 | } |
||
691 | catch (Exception e) { |
||
692 | System.err.println("Topology exception: " + e.getMessage()); |
||
693 | |||
694 | return null; |
||
695 | } |
||
696 | } |
||
697 | |||
698 | if (resp.size() == 0) { |
||
699 | resp.add(new LineString3D(getMinLinearRing(onlyCoord),
|
||
700 | getMinLinearRingZ())); |
||
701 | } |
||
702 | |||
703 | return resp;
|
||
704 | } |
||
705 | |||
706 | /**
|
||
707 | * Utility method to reverse an array of doubles.
|
||
708 | *
|
||
709 | * @param _z an array of doubles to be reversed.
|
||
710 | *
|
||
711 | * @return the reversed array of doubles
|
||
712 | */
|
||
713 | public static double[] reverseArray(double[] _z) { |
||
714 | int size = _z.length;
|
||
715 | double[] resp = new double[size]; |
||
716 | |||
717 | for (int i = 0; i < size; i++) { |
||
718 | resp[i] = _z[size - 1 - i];
|
||
719 | } |
||
720 | |||
721 | return resp;
|
||
722 | } |
||
723 | |||
724 | /**
|
||
725 | * Utility method to reverse an array of coordinates
|
||
726 | *
|
||
727 | * @param _z an array of coordinaes to be reversed.
|
||
728 | *
|
||
729 | * @return the reversed array of coordinates
|
||
730 | */
|
||
731 | public static Coordinate[] reverseCoordinateArray(Coordinate[] _z) { |
||
732 | int size = _z.length;
|
||
733 | Coordinate[] resp = new Coordinate[size]; |
||
734 | |||
735 | for (int i = 0; i < size; i++) { |
||
736 | resp[i] = _z[size - 1 - i];
|
||
737 | } |
||
738 | |||
739 | return resp;
|
||
740 | } |
||
741 | |||
742 | private static double[] getZ(FShape3D p3d, int _str, int _end, int size) { |
||
743 | double[] resp = new double[size]; |
||
744 | double[] allz = p3d.getZs(); |
||
745 | |||
746 | for (int i = _str; ((i <= _end) && ((i - _str) < size)); i++) { |
||
747 | resp[i - _str] = allz[i]; |
||
748 | } |
||
749 | |||
750 | if ((_end - _str + 1) < size) { |
||
751 | double repe = allz[_end];
|
||
752 | |||
753 | for (int i = (_end - _str + 1); i < size; i++) { |
||
754 | resp[i] = repe; |
||
755 | } |
||
756 | } |
||
757 | |||
758 | return resp;
|
||
759 | } |
||
760 | |||
761 | private static ArrayList getLineStrings(FShape mlines) { |
||
762 | boolean threed = false; |
||
763 | |||
764 | if (mlines instanceof FPolyline3D) { |
||
765 | threed = true;
|
||
766 | } |
||
767 | |||
768 | int start_ind = 0; |
||
769 | int end_ind = 0; |
||
770 | int ind = 0; |
||
771 | int new_size = 0; |
||
772 | |||
773 | LineString3D lin; |
||
774 | |||
775 | ArrayList arrayLines = new ArrayList(); |
||
776 | PathIterator theIterator = mlines.getPathIterator(null, FLATNESS); |
||
777 | int theType = -99; |
||
778 | double[] theData = new double[6]; |
||
779 | ArrayList arrayCoords = null; |
||
780 | int numParts = 0; |
||
781 | |||
782 | while (!theIterator.isDone()) {
|
||
783 | //while not done
|
||
784 | theType = theIterator.currentSegment(theData); |
||
785 | |||
786 | switch (theType) {
|
||
787 | case PathIterator.SEG_MOVETO: |
||
788 | |||
789 | // System.out.println("SEG_MOVETO");
|
||
790 | if (arrayCoords == null) { |
||
791 | arrayCoords = new ArrayList(); |
||
792 | } |
||
793 | else {
|
||
794 | end_ind = ind - 1;
|
||
795 | arrayCoords = ensureSensibleLineString(arrayCoords); |
||
796 | new_size = arrayCoords.size(); |
||
797 | |||
798 | LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray( |
||
799 | arrayCoords)); |
||
800 | double[] z = null; |
||
801 | |||
802 | if (threed) {
|
||
803 | z = getZ((FPolyline3D) mlines, start_ind, end_ind, |
||
804 | new_size); |
||
805 | } |
||
806 | |||
807 | lin = new LineString3D(aux, z);
|
||
808 | arrayLines.add(lin); |
||
809 | arrayCoords = new ArrayList(); |
||
810 | |||
811 | start_ind = ind; |
||
812 | } |
||
813 | |||
814 | numParts++; |
||
815 | arrayCoords.add(new Coordinate(theData[0], theData[1])); |
||
816 | |||
817 | break;
|
||
818 | |||
819 | case PathIterator.SEG_LINETO: |
||
820 | arrayCoords.add(new Coordinate(theData[0], theData[1])); |
||
821 | |||
822 | break;
|
||
823 | |||
824 | case PathIterator.SEG_QUADTO: |
||
825 | System.out.println("Not supported here"); |
||
826 | |||
827 | break;
|
||
828 | |||
829 | case PathIterator.SEG_CUBICTO: |
||
830 | System.out.println("Not supported here"); |
||
831 | |||
832 | break;
|
||
833 | |||
834 | case PathIterator.SEG_CLOSE: |
||
835 | |||
836 | Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
|
||
837 | arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
|
||
838 | |||
839 | break;
|
||
840 | } //end switch
|
||
841 | |||
842 | theIterator.next(); |
||
843 | ind++; |
||
844 | } //end while loop
|
||
845 | |||
846 | arrayCoords = ensureSensibleLineString(arrayCoords); |
||
847 | new_size = arrayCoords.size(); |
||
848 | |||
849 | LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray( |
||
850 | arrayCoords)); |
||
851 | double[] z = null; |
||
852 | |||
853 | if (threed) {
|
||
854 | z = getZ((FPolyline3D) mlines, start_ind, end_ind, new_size); |
||
855 | } |
||
856 | |||
857 | lin = new LineString3D(aux, z);
|
||
858 | arrayLines.add(lin); |
||
859 | |||
860 | return arrayLines;
|
||
861 | } |
||
862 | |||
863 | private static String lineStringToWKT(LineString3D ls, boolean threed) { |
||
864 | String resp = "("; |
||
865 | Coordinate[] cc = ls.getLs().getCoordinates();
|
||
866 | double[] z = ls.getZc(); |
||
867 | int size = cc.length;
|
||
868 | |||
869 | if (threed) {
|
||
870 | for (int i = 0; i < size; i++) { |
||
871 | resp = resp + cc[i].x + " " + cc[i].y + " " + z[i] + ", "; |
||
872 | } |
||
873 | |||
874 | resp = resp.substring(0, resp.length() - 2); |
||
875 | resp = resp + ")";
|
||
876 | } |
||
877 | else {
|
||
878 | for (int i = 0; i < size; i++) { |
||
879 | resp = resp + cc[i].x + " " + cc[i].y + ", "; |
||
880 | } |
||
881 | |||
882 | resp = resp.substring(0, resp.length() - 2); |
||
883 | resp = resp + ")";
|
||
884 | } |
||
885 | |||
886 | return resp;
|
||
887 | } |
||
888 | |||
889 | private static String multiLineStringToWKT(ArrayList ml, boolean threed) { |
||
890 | String resp = "MULTILINESTRING("; |
||
891 | |||
892 | for (int i = 0; i < ml.size(); i++) { |
||
893 | LineString3D ls = (LineString3D) ml.get(i); |
||
894 | resp = resp + lineStringToWKT(ls, threed) + ", ";
|
||
895 | } |
||
896 | |||
897 | resp = resp.substring(0, resp.length() - 2) + ")"; |
||
898 | |||
899 | return resp;
|
||
900 | } |
||
901 | |||
902 | private static String polygonsToWKT(ArrayList pols, boolean threed) { |
||
903 | String resp = "MULTIPOLYGON("; |
||
904 | LineString3D ls = null;
|
||
905 | |||
906 | for (int i = 0; i < pols.size(); i++) { |
||
907 | ls = (LineString3D) pols.get(i); |
||
908 | resp = resp + "(" + lineStringToWKT(ls, threed) + "), "; |
||
909 | } |
||
910 | |||
911 | resp = resp.substring(0, resp.length() - 2) + ")"; |
||
912 | |||
913 | return resp;
|
||
914 | } |
||
915 | |||
916 | private static String shellAndHolesToWKT(LineString3D shell, |
||
917 | ArrayList holes, boolean threed) { |
||
918 | String resp = "("; |
||
919 | resp = resp + lineStringToWKT(shell, threed); |
||
920 | |||
921 | if (holes.size() > 0) { |
||
922 | for (int i = 0; i < holes.size(); i++) { |
||
923 | LineString3D ls = (LineString3D) holes.get(i); |
||
924 | resp = resp + ", " + lineStringToWKT(ls, threed);
|
||
925 | } |
||
926 | } |
||
927 | |||
928 | resp = resp + ")";
|
||
929 | |||
930 | return resp;
|
||
931 | } |
||
932 | |||
933 | private static String multiPolygonToWKT(ArrayList shells, ArrayList hFs, |
||
934 | boolean threed) {
|
||
935 | String resp = "MULTIPOLYGON("; |
||
936 | LineString3D ls = null;
|
||
937 | ArrayList holes;
|
||
938 | |||
939 | for (int i = 0; i < shells.size(); i++) { |
||
940 | ls = (LineString3D) shells.get(i); |
||
941 | holes = (ArrayList) hFs.get(i);
|
||
942 | resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
|
||
943 | } |
||
944 | |||
945 | resp = resp.substring(0, resp.length() - 2) + ")"; |
||
946 | |||
947 | return resp;
|
||
948 | } |
||
949 | |||
950 | private static String pointToWKT(FPoint2D point, boolean threed) { |
||
951 | String resp = "POINT(" + point.getX() + " " + point.getY(); |
||
952 | |||
953 | if ((threed) && (point instanceof FPoint3D)) { |
||
954 | resp = resp + " " + ((FPoint3D) point).getZs()[0]; |
||
955 | } |
||
956 | |||
957 | resp = resp + ")";
|
||
958 | |||
959 | return resp;
|
||
960 | } |
||
961 | |||
962 | private static int twoDIndexToDimsIndex(int n, int d) { |
||
963 | return ((d * (n - 1)) / 2) + 1; |
||
964 | } |
||
965 | |||
966 | private static ARRAY setSubelementsToDim(ARRAY old, int d) |
||
967 | throws SQLException { |
||
968 | Datum[] infos = (Datum[]) old.getOracleArray(); |
||
969 | |||
970 | for (int i = 3; i < infos.length; i = i + 3) { |
||
971 | int oldind = infos[i].intValue();
|
||
972 | oldind = twoDIndexToDimsIndex(oldind, d); |
||
973 | infos[i] = new NUMBER(oldind);
|
||
974 | |||
975 | //
|
||
976 | oldind = infos[i + 1].intValue();
|
||
977 | infos[i + 1] = new NUMBER(infos[1].intValue()); |
||
978 | } |
||
979 | |||
980 | ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(),
|
||
981 | infos); |
||
982 | |||
983 | return resp;
|
||
984 | } |
||
985 | |||
986 | private static boolean isPointInsideLineString(Coordinate p, LineString ls) { |
||
987 | Envelope env = ls.getEnvelopeInternal(); |
||
988 | |||
989 | if (!env.contains(p)) {
|
||
990 | return false; |
||
991 | } |
||
992 | |||
993 | return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
|
||
994 | } |
||
995 | |||
996 | private static boolean lineString3DIsContainedBy(LineString3D contained, |
||
997 | LineString3D container) { |
||
998 | int samples = 10; |
||
999 | LineString _in = contained.getLs(); |
||
1000 | LineString _out = container.getLs(); |
||
1001 | Coordinate[] inc = _in.getCoordinates();
|
||
1002 | Coordinate aux; |
||
1003 | int size = inc.length;
|
||
1004 | |||
1005 | if (size <= 10) { |
||
1006 | for (int i = 0; i < size; i++) { |
||
1007 | aux = inc[i]; |
||
1008 | |||
1009 | if (!isPointInsideLineString(aux, _out)) {
|
||
1010 | return false; |
||
1011 | } |
||
1012 | } |
||
1013 | |||
1014 | return true; |
||
1015 | } |
||
1016 | else {
|
||
1017 | for (int i = 0; i < samples; i++) { |
||
1018 | aux = inc[rnd.nextInt(size)]; |
||
1019 | |||
1020 | if (!isPointInsideLineString(aux, _out)) {
|
||
1021 | return false; |
||
1022 | } |
||
1023 | } |
||
1024 | |||
1025 | return true; |
||
1026 | } |
||
1027 | } |
||
1028 | |||
1029 | private static STRUCT getMultiPolygonAsStruct(ArrayList pols, int srid, |
||
1030 | boolean threed, Connection _conn, boolean agu_bien, boolean hasSrid) |
||
1031 | throws SQLException { |
||
1032 | int size = pols.size();
|
||
1033 | int geotype = 2007; |
||
1034 | int dim = 2; |
||
1035 | int acum = 0; |
||
1036 | |||
1037 | if (threed) {
|
||
1038 | geotype = 3007;
|
||
1039 | dim = 3;
|
||
1040 | } |
||
1041 | |||
1042 | NUMBER[] indices = new NUMBER[3 * size]; |
||
1043 | |||
1044 | for (int i = 0; i < size; i++) { |
||
1045 | indices[3 * i] = new NUMBER(acum + 1); |
||
1046 | indices[(3 * i) + 1] = new NUMBER(1003); |
||
1047 | indices[(3 * i) + 2] = new NUMBER(1); |
||
1048 | acum = acum + |
||
1049 | (dim * ((LineString3D) pols.get(i)).getLs().getNumPoints()); |
||
1050 | } |
||
1051 | |||
1052 | int _ind = 0; |
||
1053 | NUMBER[] ords = new NUMBER[acum]; |
||
1054 | |||
1055 | for (int i = 0; i < size; i++) { |
||
1056 | LineString3D ls = (LineString3D) pols.get(i); |
||
1057 | int num_p = ls.getLs().getNumPoints();
|
||
1058 | |||
1059 | for (int j = 0; j < num_p; j++) { |
||
1060 | ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
|
||
1061 | ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y); |
||
1062 | |||
1063 | if (threed) {
|
||
1064 | ords[_ind + 2] = new NUMBER(ls.getZc()[j]); |
||
1065 | } |
||
1066 | |||
1067 | _ind = _ind + dim; |
||
1068 | } |
||
1069 | } |
||
1070 | |||
1071 | STRUCT resp; |
||
1072 | StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
|
||
1073 | _conn); |
||
1074 | Object[] obj = new Object[5]; |
||
1075 | obj[0] = new NUMBER(geotype); |
||
1076 | |||
1077 | if (hasSrid) {
|
||
1078 | obj[1] = new NUMBER(srid); |
||
1079 | } |
||
1080 | else {
|
||
1081 | obj[1] = null; |
||
1082 | } |
||
1083 | |||
1084 | obj[2] = null; |
||
1085 | obj[3] = indices;
|
||
1086 | obj[4] = ords;
|
||
1087 | resp = new STRUCT(dsc, _conn, obj);
|
||
1088 | |||
1089 | return resp;
|
||
1090 | } |
||
1091 | |||
1092 | private static STRUCT getMultiLineAsStruct(ArrayList lines, int srid, |
||
1093 | boolean threed, Connection _conn, boolean hasSrid) |
||
1094 | throws SQLException { |
||
1095 | /*
|
||
1096 | if (lines.size() == 1) {
|
||
1097 | return getOneLineStringAsStruct((LineString3D) lines.get(0), srid, threed, _conn);
|
||
1098 | }
|
||
1099 | */
|
||
1100 | int size = lines.size();
|
||
1101 | int geotype = 2006; |
||
1102 | int dim = 2; |
||
1103 | int acum = 0; |
||
1104 | |||
1105 | if (threed) {
|
||
1106 | geotype = 3006;
|
||
1107 | dim = 3;
|
||
1108 | } |
||
1109 | |||
1110 | NUMBER[] indices = new NUMBER[3 * size]; |
||
1111 | |||
1112 | for (int i = 0; i < size; i++) { |
||
1113 | indices[3 * i] = new NUMBER(acum + 1); |
||
1114 | indices[(3 * i) + 1] = new NUMBER(2); |
||
1115 | indices[(3 * i) + 2] = new NUMBER(1); |
||
1116 | acum = acum + |
||
1117 | (dim * ((LineString3D) lines.get(i)).getLs().getNumPoints()); |
||
1118 | } |
||
1119 | |||
1120 | int _ind = 0; |
||
1121 | NUMBER[] ords = new NUMBER[acum]; |
||
1122 | |||
1123 | for (int i = 0; i < size; i++) { |
||
1124 | LineString3D ls = (LineString3D) lines.get(i); |
||
1125 | int num_p = ls.getLs().getNumPoints();
|
||
1126 | |||
1127 | for (int j = 0; j < num_p; j++) { |
||
1128 | ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
|
||
1129 | ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y); |
||
1130 | |||
1131 | if (threed) {
|
||
1132 | ords[_ind + 2] = new NUMBER(ls.getZc()[j]); |
||
1133 | } |
||
1134 | |||
1135 | _ind = _ind + dim; |
||
1136 | } |
||
1137 | } |
||
1138 | |||
1139 | STRUCT resp; |
||
1140 | StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
|
||
1141 | _conn); |
||
1142 | Object[] obj = new Object[5]; |
||
1143 | obj[0] = new NUMBER(geotype); |
||
1144 | |||
1145 | if (hasSrid) {
|
||
1146 | obj[1] = new NUMBER(srid); |
||
1147 | } |
||
1148 | else {
|
||
1149 | obj[1] = null; |
||
1150 | } |
||
1151 | |||
1152 | obj[2] = null; |
||
1153 | obj[3] = indices;
|
||
1154 | obj[4] = ords;
|
||
1155 | resp = new STRUCT(dsc, _conn, obj);
|
||
1156 | |||
1157 | return resp;
|
||
1158 | } |
||
1159 | |||
1160 | private static STRUCT getMultiPointAsStruct(Coordinate pnt, int srid, |
||
1161 | boolean threed, Connection _conn, boolean hasSrid) |
||
1162 | throws SQLException { |
||
1163 | int geotype = 2001; |
||
1164 | int dim = 2; |
||
1165 | |||
1166 | if (threed) {
|
||
1167 | geotype = 3001;
|
||
1168 | dim = 3;
|
||
1169 | } |
||
1170 | |||
1171 | Object[] ords = new Object[3]; |
||
1172 | ords[0] = new NUMBER(pnt.x); |
||
1173 | ords[1] = new NUMBER(pnt.y); |
||
1174 | ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null; // ole ole y ole |
||
1175 | |||
1176 | StructDescriptor ord_dsc = StructDescriptor.createDescriptor("MDSYS.SDO_POINT_TYPE",
|
||
1177 | _conn); |
||
1178 | STRUCT ords_st = new STRUCT(ord_dsc, _conn, ords);
|
||
1179 | |||
1180 | STRUCT resp; |
||
1181 | |||
1182 | StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
|
||
1183 | _conn); |
||
1184 | Object[] obj = new Object[5]; |
||
1185 | |||
1186 | obj[0] = new NUMBER(geotype); |
||
1187 | |||
1188 | if (hasSrid) {
|
||
1189 | obj[1] = new NUMBER(srid); |
||
1190 | } |
||
1191 | else {
|
||
1192 | obj[1] = null; |
||
1193 | } |
||
1194 | |||
1195 | obj[2] = ords_st;
|
||
1196 | obj[3] = null; |
||
1197 | obj[4] = null; |
||
1198 | resp = new STRUCT(dsc, _conn, obj);
|
||
1199 | |||
1200 | return resp;
|
||
1201 | } |
||
1202 | |||
1203 | /**
|
||
1204 | * Utility method to compute a circle's center and radius from three given points.
|
||
1205 | *
|
||
1206 | * @param points three points of a circumference
|
||
1207 | * @return a 2-item array with the circumference's center (Point2D) and radius (Double)
|
||
1208 | */
|
||
1209 | public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) { |
||
1210 | Object[] resp = new Object[2]; |
||
1211 | resp[0] = new Point2D.Double(0, 0); |
||
1212 | resp[1] = new Double(0); |
||
1213 | |||
1214 | double m11;
|
||
1215 | double m12;
|
||
1216 | double m13;
|
||
1217 | double m14;
|
||
1218 | |||
1219 | if (points.length != 3) { |
||
1220 | logger.error("Needs 3 points (found " + points.length +
|
||
1221 | ") - circle cannot be computed.");
|
||
1222 | |||
1223 | // not a circle
|
||
1224 | return resp;
|
||
1225 | } |
||
1226 | |||
1227 | double[][] a = new double[3][3]; |
||
1228 | |||
1229 | for (int i = 0; i < 3; i++) { // find minor 11 |
||
1230 | a[i][0] = points[i].getX();
|
||
1231 | a[i][1] = points[i].getY();
|
||
1232 | a[i][2] = 1; |
||
1233 | } |
||
1234 | |||
1235 | m11 = determinant(a, 3);
|
||
1236 | |||
1237 | for (int i = 0; i < 3; i++) { // find minor 12 |
||
1238 | a[i][0] = (points[i].getX() * points[i].getX()) +
|
||
1239 | (points[i].getY() * points[i].getY()); |
||
1240 | a[i][1] = points[i].getY();
|
||
1241 | a[i][2] = 1; |
||
1242 | } |
||
1243 | |||
1244 | m12 = determinant(a, 3);
|
||
1245 | |||
1246 | for (int i = 0; i < 3; i++) // find minor 13 |
||
1247 | { |
||
1248 | a[i][0] = (points[i].getX() * points[i].getX()) +
|
||
1249 | (points[i].getY() * points[i].getY()); |
||
1250 | a[i][1] = points[i].getX();
|
||
1251 | a[i][2] = 1; |
||
1252 | } |
||
1253 | |||
1254 | m13 = determinant(a, 3);
|
||
1255 | |||
1256 | for (int i = 0; i < 3; i++) { // find minor 14 |
||
1257 | a[i][0] = (points[i].getX() * points[i].getX()) +
|
||
1258 | (points[i].getY() * points[i].getY()); |
||
1259 | a[i][1] = points[i].getX();
|
||
1260 | a[i][2] = points[i].getY();
|
||
1261 | } |
||
1262 | |||
1263 | m14 = determinant(a, 3);
|
||
1264 | |||
1265 | Double resp_radius = new Double(0); |
||
1266 | Point2D resp_center = new Point2D.Double(0, 0); |
||
1267 | |||
1268 | if (m11 == 0) { |
||
1269 | logger.error("Three points aligned - circle cannot be computed."); // not a circle |
||
1270 | } |
||
1271 | else {
|
||
1272 | double x = (0.5 * m12) / m11; |
||
1273 | double y = (-0.5 * m13) / m11; |
||
1274 | resp_center.setLocation(x, y); |
||
1275 | resp_radius = new Double(Math.sqrt((x * x) + (y * y) + (m14 / m11))); |
||
1276 | resp[0] = resp_center;
|
||
1277 | resp[1] = resp_radius;
|
||
1278 | } |
||
1279 | |||
1280 | return resp;
|
||
1281 | } |
||
1282 | |||
1283 | /**
|
||
1284 | * Utility method to compute a matrix determinant
|
||
1285 | * @param a the matrix
|
||
1286 | * @param n matrix size
|
||
1287 | * @return the matrix's determinant
|
||
1288 | */
|
||
1289 | public static double determinant(double[][] a, int n) { |
||
1290 | double resp = 0; |
||
1291 | double[][] m = new double[3][3]; |
||
1292 | |||
1293 | if (n == 2) { // terminate recursion |
||
1294 | resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]); |
||
1295 | } |
||
1296 | else {
|
||
1297 | resp = 0;
|
||
1298 | |||
1299 | for (int j1 = 0; j1 < n; j1++) { // do each column |
||
1300 | |||
1301 | for (int i = 1; i < n; i++) { // create minor |
||
1302 | |||
1303 | int j2 = 0; |
||
1304 | |||
1305 | for (int j = 0; j < n; j++) { |
||
1306 | if (j == j1) {
|
||
1307 | continue;
|
||
1308 | } |
||
1309 | |||
1310 | m[i - 1][j2] = a[i][j];
|
||
1311 | j2++; |
||
1312 | } |
||
1313 | } |
||
1314 | |||
1315 | // sum (+/-)cofactor * minor
|
||
1316 | resp = resp + |
||
1317 | (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1)); |
||
1318 | } |
||
1319 | } |
||
1320 | |||
1321 | return resp;
|
||
1322 | } |
||
1323 | |||
1324 | private static int getSmallestContainerExcept(LineString3D ls, |
||
1325 | ArrayList list, int self) { |
||
1326 | int resp = -1; |
||
1327 | ArrayList provList = new ArrayList(); |
||
1328 | |||
1329 | int size = list.size();
|
||
1330 | |||
1331 | for (int i = 0; i < self; i++) { |
||
1332 | if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
|
||
1333 | provList.add(new Integer(i)); |
||
1334 | } |
||
1335 | } |
||
1336 | |||
1337 | for (int i = (self + 1); i < size; i++) { |
||
1338 | if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
|
||
1339 | provList.add(new Integer(i)); |
||
1340 | } |
||
1341 | } |
||
1342 | |||
1343 | if (provList.size() == 0) { |
||
1344 | // logger.debug("LineString is not contained by any other ls.");
|
||
1345 | } |
||
1346 | else {
|
||
1347 | if (provList.size() == 1) { |
||
1348 | resp = ((Integer) provList.get(0)).intValue(); |
||
1349 | } |
||
1350 | else {
|
||
1351 | if (provList.size() == 2) { |
||
1352 | int ind_1 = ((Integer) provList.get(0)).intValue(); |
||
1353 | int ind_2 = ((Integer) provList.get(1)).intValue(); |
||
1354 | LineString3D ls1 = (LineString3D) list.get(ind_1); |
||
1355 | LineString3D ls2 = (LineString3D) list.get(ind_2); |
||
1356 | |||
1357 | if (lineString3DIsContainedBy(ls1, ls2)) {
|
||
1358 | resp = ind_1; |
||
1359 | } |
||
1360 | else {
|
||
1361 | resp = ind_2; |
||
1362 | } |
||
1363 | } |
||
1364 | else {
|
||
1365 | // not so deep, sorry!
|
||
1366 | // it's going to be a shell: resp = -1;
|
||
1367 | } |
||
1368 | } |
||
1369 | } |
||
1370 | |||
1371 | return resp;
|
||
1372 | } |
||
1373 | |||
1374 | private static int[] getIndicesOfShells(int[] containings) { |
||
1375 | ArrayList resp = new ArrayList(); |
||
1376 | |||
1377 | for (int i = 0; i < containings.length; i++) { |
||
1378 | if (containings[i] == -1) { |
||
1379 | resp.add(new Integer(i)); |
||
1380 | } |
||
1381 | } |
||
1382 | |||
1383 | int size = resp.size();
|
||
1384 | int[] _resp = new int[size]; |
||
1385 | |||
1386 | for (int i = 0; i < size; i++) { |
||
1387 | _resp[i] = ((Integer) resp.get(i)).intValue();
|
||
1388 | } |
||
1389 | |||
1390 | return _resp;
|
||
1391 | } |
||
1392 | |||
1393 | private static int[] getIndicesOfHoles(int[] containings, int[] shells) { |
||
1394 | ArrayList resp = new ArrayList(); |
||
1395 | |||
1396 | for (int i = 0; i < containings.length; i++) { |
||
1397 | int cont_by = containings[i];
|
||
1398 | |||
1399 | if ((cont_by != -1) && (isOneOf(cont_by, shells))) { |
||
1400 | resp.add(new Integer(i)); |
||
1401 | } |
||
1402 | } |
||
1403 | |||
1404 | int size = resp.size();
|
||
1405 | int[] _resp = new int[size]; |
||
1406 | |||
1407 | for (int i = 0; i < size; i++) { |
||
1408 | _resp[i] = ((Integer) resp.get(i)).intValue();
|
||
1409 | } |
||
1410 | |||
1411 | return _resp;
|
||
1412 | } |
||
1413 | |||
1414 | private static int[] getFinalContainings(int[] containings, int[] holes) { |
||
1415 | ArrayList resp = new ArrayList(); |
||
1416 | |||
1417 | for (int i = 0; i < containings.length; i++) { |
||
1418 | int cont_by = containings[i];
|
||
1419 | |||
1420 | if (isOneOf(cont_by, holes)) {
|
||
1421 | resp.add(new Integer(-1)); |
||
1422 | } |
||
1423 | else {
|
||
1424 | resp.add(new Integer(cont_by)); |
||
1425 | } |
||
1426 | } |
||
1427 | |||
1428 | int size = resp.size();
|
||
1429 | int[] _resp = new int[size]; |
||
1430 | |||
1431 | for (int i = 0; i < size; i++) { |
||
1432 | _resp[i] = ((Integer) resp.get(i)).intValue();
|
||
1433 | } |
||
1434 | |||
1435 | return _resp;
|
||
1436 | } |
||
1437 | |||
1438 | private static ArrayList getHolesOf(int ind, int[] final_contn, |
||
1439 | ArrayList all) {
|
||
1440 | ArrayList resp_ind = new ArrayList(); |
||
1441 | |||
1442 | for (int i = 0; i < final_contn.length; i++) { |
||
1443 | if (final_contn[i] == ind) {
|
||
1444 | resp_ind.add(new Integer(i)); |
||
1445 | } |
||
1446 | } |
||
1447 | |||
1448 | ArrayList resp = new ArrayList(); |
||
1449 | |||
1450 | for (int i = 0; i < resp_ind.size(); i++) { |
||
1451 | Integer aux = (Integer) resp_ind.get(i); |
||
1452 | resp.add(all.get(aux.intValue())); |
||
1453 | } |
||
1454 | |||
1455 | return resp;
|
||
1456 | } |
||
1457 | |||
1458 | private static ArrayList getShellsIn(int[] final_contn, ArrayList all) { |
||
1459 | ArrayList resp_ind = new ArrayList(); |
||
1460 | |||
1461 | for (int i = 0; i < final_contn.length; i++) { |
||
1462 | if (final_contn[i] == -1) { |
||
1463 | resp_ind.add(new Integer(i)); |
||
1464 | } |
||
1465 | } |
||
1466 | |||
1467 | ArrayList resp = new ArrayList(); |
||
1468 | |||
1469 | for (int i = 0; i < resp_ind.size(); i++) { |
||
1470 | Integer aux = (Integer) resp_ind.get(i); |
||
1471 | resp.add(all.get(aux.intValue())); |
||
1472 | } |
||
1473 | |||
1474 | return resp;
|
||
1475 | } |
||
1476 | |||
1477 | /**
|
||
1478 | * This method tries to guess who is a shell and who is a hole from a set of
|
||
1479 | * linestrings.
|
||
1480 | *
|
||
1481 | * @param all_ls a set of linestrings to be checked.
|
||
1482 | *
|
||
1483 | * @return a 2-item array. the first is an arraylist of linestrings thought to be shells.
|
||
1484 | * the second is an array of arraylists containing the holes of each shell found in the
|
||
1485 | * first item
|
||
1486 | *
|
||
1487 | */
|
||
1488 | public static Object[] getHolesForShells(ArrayList all_ls) { |
||
1489 | int no_of_ls = all_ls.size();
|
||
1490 | int[] containedby = new int[no_of_ls]; |
||
1491 | int[] shells; |
||
1492 | int[] holes; |
||
1493 | int[] final_cont; |
||
1494 | |||
1495 | for (int i = 0; i < no_of_ls; i++) { |
||
1496 | LineString3D ls_aux = (LineString3D) all_ls.get(i); |
||
1497 | containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i); |
||
1498 | } |
||
1499 | |||
1500 | shells = getIndicesOfShells(containedby); |
||
1501 | holes = getIndicesOfHoles(containedby, shells); |
||
1502 | final_cont = getFinalContainings(containedby, holes); |
||
1503 | |||
1504 | // true shells:
|
||
1505 | shells = getIndicesOfShells(final_cont); |
||
1506 | |||
1507 | ArrayList resp_shells = new ArrayList(); |
||
1508 | ArrayList resp_holes_for_shells = new ArrayList(); |
||
1509 | ArrayList aux_holes;
|
||
1510 | |||
1511 | for (int i = 0; i < shells.length; i++) { |
||
1512 | resp_shells.add(all_ls.get(shells[i])); |
||
1513 | aux_holes = getHolesOf(i, final_cont, all_ls); |
||
1514 | resp_holes_for_shells.add(aux_holes); |
||
1515 | } |
||
1516 | |||
1517 | Object[] _resp = new Object[2]; |
||
1518 | _resp[0] = resp_shells;
|
||
1519 | _resp[1] = resp_holes_for_shells;
|
||
1520 | |||
1521 | return _resp;
|
||
1522 | } |
||
1523 | |||
1524 | private static int getTotalSize(ArrayList listOfLists) { |
||
1525 | int resp = 0; |
||
1526 | |||
1527 | for (int i = 0; i < listOfLists.size(); i++) { |
||
1528 | resp = resp + ((ArrayList) listOfLists.get(i)).size();
|
||
1529 | } |
||
1530 | |||
1531 | return resp;
|
||
1532 | } |
||
1533 | |||
1534 | // private static STRUCT // private static ArrayList getPolygonsEasily(FShape mpolygon) {
|
||
1535 | private static STRUCT getMultiPolygonAsStruct(FShape mpol, int srid, |
||
1536 | boolean threed, Connection _conn, boolean agu_bien, boolean hasSrid) |
||
1537 | throws SQLException { |
||
1538 | ArrayList all_ls = getPolygonsEasily(mpol);
|
||
1539 | Object[] hs = getHolesForShells(all_ls); |
||
1540 | ArrayList sh = (ArrayList) hs[0]; |
||
1541 | ArrayList _ho = (ArrayList) hs[1]; |
||
1542 | ArrayList ho = reverseHoles(_ho);
|
||
1543 | |||
1544 | return getMultiPolygonAsStruct(sh, ho, srid, threed, _conn, agu_bien,
|
||
1545 | hasSrid); |
||
1546 | } |
||
1547 | |||
1548 | private static ArrayList reverseHoles(ArrayList hh) { |
||
1549 | ArrayList resp = new ArrayList(); |
||
1550 | |||
1551 | for (int i = 0; i < hh.size(); i++) { |
||
1552 | ArrayList item = (ArrayList) hh.get(i); |
||
1553 | ArrayList newitem = new ArrayList(); |
||
1554 | |||
1555 | for (int j = 0; j < item.size(); j++) { |
||
1556 | LineString3D ls = (LineString3D) item.get(j); |
||
1557 | newitem.add(ls.createReverse()); |
||
1558 | } |
||
1559 | |||
1560 | resp.add(newitem); |
||
1561 | } |
||
1562 | |||
1563 | return resp;
|
||
1564 | } |
||
1565 | |||
1566 | private static STRUCT getMultiPolygonAsStruct(ArrayList shells, |
||
1567 | ArrayList holes, int srid, boolean threed, Connection _conn, |
||
1568 | boolean explicito, boolean hasSrid) throws SQLException { |
||
1569 | int t = 1003; |
||
1570 | |||
1571 | if (explicito) {
|
||
1572 | t = 2003;
|
||
1573 | } |
||
1574 | |||
1575 | int size = shells.size() + getTotalSize(holes);
|
||
1576 | 13996 | jldominguez@prodevelop.es | int geotype = 2003; |
1577 | if (size > 1) geotype = 2007; |
||
1578 | |||
1579 | 13991 | jldominguez@prodevelop.es | int dim = 2; |
1580 | |||
1581 | if (threed) {
|
||
1582 | 13996 | jldominguez@prodevelop.es | geotype = geotype + 1000;
|
1583 | 13991 | jldominguez@prodevelop.es | dim = 3;
|
1584 | } |
||
1585 | |||
1586 | NUMBER[] indices = new NUMBER[3 * size]; |
||
1587 | |||
1588 | int acum = 0; |
||
1589 | int start_ind = 0; |
||
1590 | |||
1591 | for (int i = 0; i < shells.size(); i++) { |
||
1592 | indices[start_ind] = new NUMBER(acum + 1); |
||
1593 | indices[start_ind + 1] = new NUMBER(1003); |
||
1594 | indices[start_ind + 2] = new NUMBER(1); |
||
1595 | start_ind = start_ind + 3;
|
||
1596 | acum = acum + |
||
1597 | (dim * ((LineString3D) shells.get(i)).getLs().getNumPoints()); |
||
1598 | |||
1599 | ArrayList item_holes = (ArrayList) holes.get(i); |
||
1600 | |||
1601 | for (int j = 0; j < item_holes.size(); j++) { |
||
1602 | indices[start_ind] = new NUMBER(acum + 1); |
||
1603 | indices[start_ind + 1] = new NUMBER(t); // 1003 |
||
1604 | indices[start_ind + 2] = new NUMBER(1); |
||
1605 | start_ind = start_ind + 3;
|
||
1606 | acum = acum + |
||
1607 | (dim * ((LineString3D) item_holes.get(j)).getLs() |
||
1608 | .getNumPoints()); |
||
1609 | } |
||
1610 | } |
||
1611 | |||
1612 | int _ind = 0; |
||
1613 | NUMBER[] ords = new NUMBER[acum]; |
||
1614 | |||
1615 | for (int i = 0; i < shells.size(); i++) { |
||
1616 | // --------------------------------
|
||
1617 | LineString3D ls = (LineString3D) shells.get(i); |
||
1618 | int num_p = ls.getLs().getNumPoints();
|
||
1619 | |||
1620 | for (int j = 0; j < num_p; j++) { |
||
1621 | ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
|
||
1622 | ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y); |
||
1623 | |||
1624 | if (threed) {
|
||
1625 | ords[_ind + 2] = new NUMBER(ls.getZc()[j]); |
||
1626 | } |
||
1627 | |||
1628 | _ind = _ind + dim; |
||
1629 | } |
||
1630 | |||
1631 | // -------------------------------
|
||
1632 | ArrayList item_holes = (ArrayList) holes.get(i); |
||
1633 | |||
1634 | for (int j = 0; j < item_holes.size(); j++) { |
||
1635 | ls = (LineString3D) item_holes.get(j); |
||
1636 | num_p = ls.getLs().getNumPoints(); |
||
1637 | |||
1638 | for (int k = 0; k < num_p; k++) { |
||
1639 | ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(k).x);
|
||
1640 | ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y); |
||
1641 | |||
1642 | if (threed) {
|
||
1643 | ords[_ind + 2] = new NUMBER(ls.getZc()[k]); |
||
1644 | } |
||
1645 | |||
1646 | _ind = _ind + dim; |
||
1647 | } |
||
1648 | } |
||
1649 | } |
||
1650 | |||
1651 | STRUCT resp; |
||
1652 | StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
|
||
1653 | _conn); |
||
1654 | Object[] obj = new Object[5]; |
||
1655 | obj[0] = new NUMBER(geotype); |
||
1656 | |||
1657 | if (hasSrid) {
|
||
1658 | obj[1] = new NUMBER(srid); |
||
1659 | } |
||
1660 | else {
|
||
1661 | obj[1] = null; |
||
1662 | } |
||
1663 | |||
1664 | obj[2] = null; |
||
1665 | obj[3] = indices;
|
||
1666 | obj[4] = ords;
|
||
1667 | |||
1668 | // String ind_str = printArray(indices);
|
||
1669 | // String ord_str = printArray(ords);
|
||
1670 | resp = new STRUCT(dsc, _conn, obj);
|
||
1671 | |||
1672 | return resp;
|
||
1673 | } |
||
1674 | |||
1675 | public static String printArray(NUMBER[] array) { |
||
1676 | String resp = "[ "; |
||
1677 | |||
1678 | for (int i = 0; i < array.length; i++) { |
||
1679 | resp = resp + " " + array[i].doubleValue() + " , "; |
||
1680 | } |
||
1681 | |||
1682 | resp = resp.substring(0, resp.length() - 2) + "]"; |
||
1683 | |||
1684 | return resp;
|
||
1685 | } |
||
1686 | |||
1687 | private static boolean isOneOf(int ind, int[] list) { |
||
1688 | for (int i = 0; i < list.length; i++) { |
||
1689 | if (list[i] == ind) {
|
||
1690 | return true; |
||
1691 | } |
||
1692 | } |
||
1693 | |||
1694 | return false; |
||
1695 | } |
||
1696 | |||
1697 | /**
|
||
1698 | * This method appends the geometries from a geometry collection in one STRUCT.
|
||
1699 | *
|
||
1700 | * @param co the geometry collection
|
||
1701 | * @param _forced_type a type that has to be used as the struct's main type
|
||
1702 | * @param _conn the connection
|
||
1703 | * @param _o_srid the geometry's SRS (oracle code)
|
||
1704 | * @param withSrid whether the SRS is non-NULL
|
||
1705 | * @param agu_bien whether to check holes' validity
|
||
1706 | * @param _isGeoCS whether the SRS is geodetic
|
||
1707 | * @return the STRUCT with the appended geometries
|
||
1708 | */
|
||
1709 | public static STRUCT appendGeometriesInStruct(FGeometryCollection co, |
||
1710 | int _forced_type, Connection _conn, String _o_srid, boolean withSrid, |
||
1711 | boolean agu_bien, boolean _isGeoCS) { |
||
1712 | IGeometry[] geoms = co.getGeometries();
|
||
1713 | int size = geoms.length;
|
||
1714 | STRUCT[] sts = new STRUCT[size]; |
||
1715 | |||
1716 | for (int i = 0; i < size; i++) { |
||
1717 | sts[i] = OracleSpatialDriver.iGeometryToSTRUCT(geoms[i], |
||
1718 | _forced_type, _conn, _o_srid, withSrid, agu_bien, _isGeoCS); |
||
1719 | } |
||
1720 | |||
1721 | if (size == 1) { |
||
1722 | return sts[0]; |
||
1723 | } |
||
1724 | |||
1725 | STRUCT aux = sts[0];
|
||
1726 | |||
1727 | for (int i = 1; i < size; i++) { |
||
1728 | aux = appendStructs(aux, sts[i], _conn); |
||
1729 | } |
||
1730 | |||
1731 | return aux;
|
||
1732 | } |
||
1733 | |||
1734 | private static STRUCT appendStructs(STRUCT st1, STRUCT st2, Connection _conn) { |
||
1735 | try {
|
||
1736 | ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
|
||
1737 | int length_of_head_ords = _ords.getOracleArray().length;
|
||
1738 | |||
1739 | NUMBER gtype = new NUMBER(4 + |
||
1740 | (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000)); |
||
1741 | NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
|
||
1742 | NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
|
||
1743 | |||
1744 | ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
|
||
1745 | ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
|
||
1746 | ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
|
||
1747 | ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
|
||
1748 | |||
1749 | Datum[] info = appendDatumArrays(info1.getOracleArray(),
|
||
1750 | info2.getOracleArray(), length_of_head_ords); |
||
1751 | |||
1752 | Datum[] ords = appendDatumArrays(ords1.getOracleArray(),
|
||
1753 | ords2.getOracleArray(), 0);
|
||
1754 | |||
1755 | StructDescriptor dsc = st1.getDescriptor(); |
||
1756 | |||
1757 | Object[] atts = new Object[5]; |
||
1758 | atts[0] = gtype;
|
||
1759 | atts[1] = srid;
|
||
1760 | atts[2] = middle;
|
||
1761 | atts[3] = info;
|
||
1762 | atts[4] = ords;
|
||
1763 | |||
1764 | STRUCT resp = new STRUCT(dsc, _conn, atts);
|
||
1765 | |||
1766 | return resp;
|
||
1767 | } |
||
1768 | catch (SQLException sqle) { |
||
1769 | logger.error("While appending structs: " + sqle.getMessage(), sqle);
|
||
1770 | } |
||
1771 | |||
1772 | return null; |
||
1773 | } |
||
1774 | |||
1775 | private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail, |
||
1776 | int offset) {
|
||
1777 | int head_l = head.length;
|
||
1778 | int tail_l = tail.length;
|
||
1779 | Datum[] resp = new Datum[head_l + tail_l]; |
||
1780 | |||
1781 | for (int i = 0; i < head_l; i++) |
||
1782 | resp[i] = head[i]; |
||
1783 | |||
1784 | if (offset == 0) { |
||
1785 | for (int i = 0; i < tail_l; i++) |
||
1786 | resp[head_l + i] = tail[i]; |
||
1787 | } |
||
1788 | else {
|
||
1789 | try {
|
||
1790 | for (int i = 0; i < tail_l; i++) { |
||
1791 | if ((i % 3) == 0) { |
||
1792 | resp[head_l + i] = new NUMBER(tail[i].intValue() +
|
||
1793 | offset); |
||
1794 | } |
||
1795 | else {
|
||
1796 | resp[head_l + i] = tail[i]; |
||
1797 | } |
||
1798 | } |
||
1799 | } |
||
1800 | catch (SQLException se) { |
||
1801 | logger.error("Unexpected error: " + se.getMessage());
|
||
1802 | } |
||
1803 | } |
||
1804 | |||
1805 | return resp;
|
||
1806 | } |
||
1807 | |||
1808 | /**
|
||
1809 | * Utility method to get an ineteger as a formatted string.
|
||
1810 | *
|
||
1811 | * @param n the integer
|
||
1812 | * @return the formatted string
|
||
1813 | */
|
||
1814 | public static String getFormattedInteger(int n) { |
||
1815 | df.setGroupingUsed(true);
|
||
1816 | df.setGroupingSize(3);
|
||
1817 | dfs.setGroupingSeparator('.');
|
||
1818 | df.setDecimalFormatSymbols(dfs); |
||
1819 | |||
1820 | return df.format(n);
|
||
1821 | } |
||
1822 | |||
1823 | /**
|
||
1824 | * Tells whether these arrays belong to a rectangle polygon.
|
||
1825 | *
|
||
1826 | * @param info the struct's element info array
|
||
1827 | * @param ords the struct's coordinate array
|
||
1828 | * @return true if it is a rectangle polygon. false otherwise.
|
||
1829 | */
|
||
1830 | public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) { |
||
1831 | try {
|
||
1832 | int[] infos = info.getIntArray(); |
||
1833 | |||
1834 | return ((infos[2] == 3) && (infos.length == 3)); |
||
1835 | } |
||
1836 | catch (SQLException se) { |
||
1837 | logger.error("While ckecking rectangle: " + se.getMessage(), se);
|
||
1838 | } |
||
1839 | |||
1840 | return false; |
||
1841 | } |
||
1842 | |||
1843 | /**
|
||
1844 | * Utility method to deal with oracle info arrays.
|
||
1845 | */
|
||
1846 | public static ARRAY getDevelopedInfoArray(ARRAY info) { |
||
1847 | ARRAY _resp = null;
|
||
1848 | |||
1849 | try {
|
||
1850 | Datum[] resp = new Datum[3]; |
||
1851 | Datum[] in = info.getOracleArray();
|
||
1852 | resp[0] = in[0]; |
||
1853 | resp[1] = in[1]; |
||
1854 | resp[2] = new NUMBER(1); |
||
1855 | _resp = new ARRAY(info.getDescriptor(),
|
||
1856 | info.getInternalConnection(), resp); |
||
1857 | } |
||
1858 | catch (SQLException se) { |
||
1859 | logger.error("While creating ARRAY: " + se.getMessage(), se);
|
||
1860 | } |
||
1861 | |||
1862 | return _resp;
|
||
1863 | } |
||
1864 | |||
1865 | /**
|
||
1866 | * Utility method to deal with oracle coordinate arrays.
|
||
1867 | */
|
||
1868 | public static ARRAY getDevelopedOrdsArray(ARRAY ords) { |
||
1869 | ARRAY _resp = null;
|
||
1870 | |||
1871 | try {
|
||
1872 | Datum[] resp = new Datum[10]; |
||
1873 | Datum[] corners = ords.getOracleArray();
|
||
1874 | |||
1875 | // x
|
||
1876 | resp[0] = corners[0]; |
||
1877 | resp[2] = corners[2]; |
||
1878 | resp[4] = corners[2]; |
||
1879 | resp[6] = corners[0]; |
||
1880 | resp[8] = corners[0]; |
||
1881 | |||
1882 | // y
|
||
1883 | resp[1] = corners[1]; |
||
1884 | resp[3] = corners[1]; |
||
1885 | resp[5] = corners[3]; |
||
1886 | resp[7] = corners[3]; |
||
1887 | resp[9] = corners[1]; |
||
1888 | _resp = new ARRAY(ords.getDescriptor(),
|
||
1889 | ords.getInternalConnection(), resp); |
||
1890 | } |
||
1891 | catch (SQLException se) { |
||
1892 | logger.error("While creating ARRAY: " + se.getMessage(), se);
|
||
1893 | } |
||
1894 | |||
1895 | return _resp;
|
||
1896 | } |
||
1897 | |||
1898 | /**
|
||
1899 | * utility method to convert a STRUCT into a GeneralPathX
|
||
1900 | * @param aux the struct's datum array
|
||
1901 | * @return the GeneralPathX instance created
|
||
1902 | */
|
||
1903 | public static GeneralPathX structToGPX(Datum[] aux) { |
||
1904 | GeneralPathX resp = new GeneralPathX();
|
||
1905 | ARRAY infoARRAY = null;
|
||
1906 | ARRAY ordsARRAY = null;
|
||
1907 | Datum[] info_array = null; |
||
1908 | Datum[] ords_array = null; |
||
1909 | int info_array_size = 0; |
||
1910 | int[] start_ind; |
||
1911 | int[] end_ind; |
||
1912 | int dims = 0; |
||
1913 | boolean next_must_do_first = true; |
||
1914 | |||
1915 | try {
|
||
1916 | infoARRAY = (ARRAY) aux[3];
|
||
1917 | ordsARRAY = (ARRAY) aux[4];
|
||
1918 | |||
1919 | if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
|
||
1920 | infoARRAY = getDevelopedInfoArray(infoARRAY); |
||
1921 | ordsARRAY = getDevelopedOrdsArray(ordsARRAY); |
||
1922 | } |
||
1923 | |||
1924 | dims = ((NUMBER) aux[0]).intValue() / 1000; |
||
1925 | |||
1926 | if (dims == 0) { |
||
1927 | dims = 2;
|
||
1928 | } |
||
1929 | |||
1930 | info_array = (Datum[]) infoARRAY.getOracleArray();
|
||
1931 | ords_array = (Datum[]) ordsARRAY.getOracleArray();
|
||
1932 | info_array_size = info_array.length / 3;
|
||
1933 | |||
1934 | int last_index = ords_array.length - dims + 1; |
||
1935 | |||
1936 | // set indices:
|
||
1937 | start_ind = new int[info_array_size]; |
||
1938 | end_ind = new int[info_array_size]; |
||
1939 | |||
1940 | for (int i = 0; i < info_array_size; i++) |
||
1941 | start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
|
||
1942 | |||
1943 | for (int i = 0; i < (info_array_size - 1); i++) |
||
1944 | end_ind[i] = start_ind[i + 1] - 1; |
||
1945 | |||
1946 | end_ind[info_array_size - 1] = last_index;
|
||
1947 | |||
1948 | int lineType = PathIterator.SEG_LINETO; |
||
1949 | |||
1950 | if (end_ind[0] == 0) { // collection of paths |
||
1951 | |||
1952 | for (int i = 1; i < info_array_size; i++) { |
||
1953 | lineType = getLineToType(info_array, i); |
||
1954 | next_must_do_first = addOrdsToGPX(resp, start_ind[i] - 1,
|
||
1955 | end_ind[i] - 1, ords_array, dims, lineType,
|
||
1956 | (i == 1), next_must_do_first);
|
||
1957 | } |
||
1958 | } |
||
1959 | else {
|
||
1960 | // standard case, do the moveto always
|
||
1961 | for (int i = 0; i < info_array_size; i++) { |
||
1962 | lineType = getLineToType(info_array, i); |
||
1963 | addOrdsToGPX(resp, start_ind[i] - 1, end_ind[i] - 1, |
||
1964 | ords_array, dims, lineType, true, true); |
||
1965 | } |
||
1966 | } |
||
1967 | |||
1968 | // boolean do_the_moves = true;
|
||
1969 | } |
||
1970 | catch (SQLException se) { |
||
1971 | logger.error("While creating GPX: " + se.getMessage(), se);
|
||
1972 | } |
||
1973 | |||
1974 | return resp;
|
||
1975 | } |
||
1976 | |||
1977 | private static int getLineToType(Datum[] infos, int i) { |
||
1978 | int resp = PathIterator.SEG_LINETO; |
||
1979 | |||
1980 | try {
|
||
1981 | if (((NUMBER) infos[(3 * i) + 2]).intValue() == 2) { |
||
1982 | resp = PathIterator.SEG_QUADTO;
|
||
1983 | } |
||
1984 | } |
||
1985 | catch (SQLException e) { |
||
1986 | logger.error("While getting line-to type: " + e.getMessage() +
|
||
1987 | " (returned SEG_LINETO)");
|
||
1988 | } |
||
1989 | |||
1990 | return resp;
|
||
1991 | } |
||
1992 | |||
1993 | private static boolean addOrdsToGPX(GeneralPathX gpx, int zero_based_start, |
||
1994 | int zero_based_include_end, Datum[] ords, int d, int ltype, |
||
1995 | boolean do_the_move, boolean must_do_first) { |
||
1996 | int length = ords.length;
|
||
1997 | boolean return_following_must_do_first = true; |
||
1998 | |||
1999 | double x = ((NUMBER) ords[zero_based_start]).doubleValue();
|
||
2000 | double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue(); |
||
2001 | |||
2002 | if (must_do_first) {
|
||
2003 | if (do_the_move) {
|
||
2004 | gpx.moveTo(x, y); |
||
2005 | } |
||
2006 | else {
|
||
2007 | gpx.lineTo(x, y); |
||
2008 | } |
||
2009 | } |
||
2010 | |||
2011 | int ind = 1; |
||
2012 | |||
2013 | int size = ((zero_based_include_end - zero_based_start) / d) + 1; |
||
2014 | int indx;
|
||
2015 | int indx2;
|
||
2016 | |||
2017 | if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2) |
||
2018 | |||
2019 | double x2;
|
||
2020 | double y2;
|
||
2021 | |||
2022 | while (ind < size) {
|
||
2023 | indx = zero_based_start + (ind * d); |
||
2024 | x = ((NUMBER) ords[indx]).doubleValue(); |
||
2025 | y = ((NUMBER) ords[indx + 1]).doubleValue();
|
||
2026 | |||
2027 | indx2 = zero_based_start + ((ind + 1) * d);
|
||
2028 | |||
2029 | if (indx >= length) {
|
||
2030 | indx2 = zero_based_start; |
||
2031 | } |
||
2032 | |||
2033 | x2 = ((NUMBER) ords[indx2]).doubleValue(); |
||
2034 | y2 = ((NUMBER) ords[indx2 + 1]).doubleValue();
|
||
2035 | gpx.quadTo(x, y, x2, y2); |
||
2036 | ind++; |
||
2037 | ind++; |
||
2038 | } |
||
2039 | |||
2040 | return_following_must_do_first = false;
|
||
2041 | } |
||
2042 | else { // PathIterator.SEG_LINETO (interpretation = 1) |
||
2043 | |||
2044 | while (ind < size) {
|
||
2045 | indx = zero_based_start + (ind * d); |
||
2046 | x = ((NUMBER) ords[indx]).doubleValue(); |
||
2047 | y = ((NUMBER) ords[indx + 1]).doubleValue();
|
||
2048 | gpx.lineTo(x, y); |
||
2049 | ind++; |
||
2050 | } |
||
2051 | } |
||
2052 | |||
2053 | return return_following_must_do_first;
|
||
2054 | } |
||
2055 | |||
2056 | /**
|
||
2057 | * Utility method. Gets FShape type from oracle geometry type.
|
||
2058 | * @param otype
|
||
2059 | * @return FShape type
|
||
2060 | */
|
||
2061 | public static int oracleGTypeToFShapeType(int otype) { |
||
2062 | switch (otype) {
|
||
2063 | case ORACLE_GTYPE_UNKNOWN:
|
||
2064 | return FShape.NULL;
|
||
2065 | |||
2066 | case ORACLE_GTYPE_POINT:
|
||
2067 | case ORACLE_GTYPE_MULTIPOINT:
|
||
2068 | return FShape.POINT;
|
||
2069 | |||
2070 | case ORACLE_GTYPE_LINE:
|
||
2071 | case ORACLE_GTYPE_MULTILINE:
|
||
2072 | return FShape.LINE;
|
||
2073 | |||
2074 | case ORACLE_GTYPE_POLYGON:
|
||
2075 | case ORACLE_GTYPE_MULTIPOLYGON:
|
||
2076 | return FShape.POLYGON;
|
||
2077 | |||
2078 | case ORACLE_GTYPE_COLLECTION:
|
||
2079 | return FShape.MULTI;
|
||
2080 | } |
||
2081 | |||
2082 | logger.warn("Unknown oracle geometry type: " + otype);
|
||
2083 | |||
2084 | return FShape.NULL;
|
||
2085 | } |
||
2086 | |||
2087 | /**
|
||
2088 | * Utility method to get struct's type.
|
||
2089 | * @param the_data the struct's datum array
|
||
2090 | * @return the struct type
|
||
2091 | */
|
||
2092 | public static int getStructType(Datum[] the_data) { |
||
2093 | int resp = -1; |
||
2094 | |||
2095 | try {
|
||
2096 | resp = ((NUMBER) the_data[0]).intValue() % 1000; |
||
2097 | } |
||
2098 | catch (SQLException se) { |
||
2099 | logger.error("Error: " + se.getMessage(), se);
|
||
2100 | } |
||
2101 | |||
2102 | return resp;
|
||
2103 | } |
||
2104 | |||
2105 | /**
|
||
2106 | * Utility method to get struct's SRID.
|
||
2107 | * @param the_data the struct's datum array
|
||
2108 | * @return the struct0's SRID
|
||
2109 | */
|
||
2110 | public static int getStructSRID(Datum[] the_data) { |
||
2111 | int resp = -1; |
||
2112 | |||
2113 | try {
|
||
2114 | resp = ((NUMBER) the_data[1]).intValue();
|
||
2115 | } |
||
2116 | catch (SQLException se) { |
||
2117 | logger.error("Error: " + se.getMessage(), se);
|
||
2118 | } |
||
2119 | |||
2120 | return resp;
|
||
2121 | } |
||
2122 | |||
2123 | /**
|
||
2124 | * Utility method to find out if a struct is a circle.
|
||
2125 | *
|
||
2126 | * @param the_data the struct's datum array
|
||
2127 | * @return whether it is a circle
|
||
2128 | */
|
||
2129 | public static boolean isCircle(Datum[] the_data) { |
||
2130 | int[] info = null; |
||
2131 | |||
2132 | try {
|
||
2133 | info = ((ARRAY) the_data[3]).getIntArray();
|
||
2134 | } |
||
2135 | catch (SQLException se) { |
||
2136 | logger.error("While cheking circle: " + se.getMessage(), se);
|
||
2137 | |||
2138 | return false; |
||
2139 | } |
||
2140 | |||
2141 | if (info == null) { |
||
2142 | return false; |
||
2143 | } |
||
2144 | |||
2145 | boolean resp = ((info.length == 3) && (info[2] == 4)); |
||
2146 | |||
2147 | return resp;
|
||
2148 | } |
||
2149 | |||
2150 | /**
|
||
2151 | * Gets the struct's dimension size.
|
||
2152 | * @param st the struct
|
||
2153 | * @return the structs dimension
|
||
2154 | */
|
||
2155 | public static int getStructDimensions(STRUCT st) { |
||
2156 | int resp = -1; |
||
2157 | |||
2158 | try {
|
||
2159 | resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000; |
||
2160 | } |
||
2161 | catch (SQLException se) { |
||
2162 | logger.error("Error: " + se.getMessage(), se);
|
||
2163 | } |
||
2164 | |||
2165 | if (resp < 2) { |
||
2166 | resp = 2;
|
||
2167 | } |
||
2168 | |||
2169 | return resp;
|
||
2170 | } |
||
2171 | |||
2172 | /**
|
||
2173 | * Gets a struct's coordinates array.
|
||
2174 | * @param the_data the struct's datum array
|
||
2175 | * @return the coordinates array
|
||
2176 | */
|
||
2177 | public static double[] getOrds(Datum[] the_data) { |
||
2178 | double[] resp = null; |
||
2179 | |||
2180 | try {
|
||
2181 | ARRAY aux = (ARRAY) the_data[4];
|
||
2182 | |||
2183 | if (aux == null) { |
||
2184 | return null; |
||
2185 | } |
||
2186 | |||
2187 | resp = aux.getDoubleArray(); |
||
2188 | } |
||
2189 | catch (SQLException se) { |
||
2190 | logger.error("While getting ordinates: " + se.getMessage(), se);
|
||
2191 | } |
||
2192 | |||
2193 | return resp;
|
||
2194 | } |
||
2195 | |||
2196 | /**
|
||
2197 | * Utility method to create a struct with the given data.
|
||
2198 | * @param type struct type
|
||
2199 | * @param srid coordinate system
|
||
2200 | * @param info element info array
|
||
2201 | * @param ords coordinates array
|
||
2202 | * @param conn connection
|
||
2203 | * @return the created struct
|
||
2204 | */
|
||
2205 | public static STRUCT createStruct(NUMBER type, NUMBER srid, Datum[] info, |
||
2206 | Datum[] ords, Connection conn) { |
||
2207 | try {
|
||
2208 | StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
|
||
2209 | conn); |
||
2210 | Object[] obj = new Object[5]; |
||
2211 | obj[0] = type;
|
||
2212 | obj[1] = srid;
|
||
2213 | obj[2] = null; |
||
2214 | obj[3] = info;
|
||
2215 | obj[4] = ords;
|
||
2216 | |||
2217 | return new STRUCT(dsc, conn, obj); |
||
2218 | } |
||
2219 | catch (SQLException se) { |
||
2220 | logger.error("While creating STRUCT: " + se.getMessage(), se);
|
||
2221 | } |
||
2222 | |||
2223 | return null; |
||
2224 | } |
||
2225 | |||
2226 | public static String getDimInfoAsString(ARRAY dim_info) { |
||
2227 | String resp = "DIMENSIONS: "; |
||
2228 | |||
2229 | if (dim_info == null) { |
||
2230 | return "NULL" + "\n"; |
||
2231 | } |
||
2232 | else {
|
||
2233 | try {
|
||
2234 | Datum[] da = dim_info.getOracleArray();
|
||
2235 | int size = da.length;
|
||
2236 | resp = resp + size + "\n";
|
||
2237 | for (int i = 0; i < size; i++) { |
||
2238 | STRUCT dim_itemx = (STRUCT) da[i]; |
||
2239 | Object[] dim_desc = dim_itemx.getAttributes(); |
||
2240 | resp = resp + "DIMENSION " + i + ": " + ", NAME: " |
||
2241 | + dim_desc[0].toString() + ", MIN: " |
||
2242 | + dim_desc[1].toString() + ", MAX: " |
||
2243 | + dim_desc[2].toString() + ", TOL: " |
||
2244 | + dim_desc[3].toString();
|
||
2245 | if (i != (size -1)) { |
||
2246 | resp = resp + "\n";
|
||
2247 | } |
||
2248 | } |
||
2249 | } catch (Exception ex) { |
||
2250 | return "ERROR: " + ex.getMessage() + "\n"; |
||
2251 | } |
||
2252 | } |
||
2253 | return resp;
|
||
2254 | } |
||
2255 | |||
2256 | public static STRUCT reprojectGeometry(Connection conn, STRUCT fromStruct, String toSrid) { |
||
2257 | |||
2258 | String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL"; |
||
2259 | STRUCT resp = null;
|
||
2260 | |||
2261 | try {
|
||
2262 | PreparedStatement _st = conn.prepareStatement(qry);
|
||
2263 | _st.setObject(1, fromStruct);
|
||
2264 | ResultSet _rs = _st.executeQuery();
|
||
2265 | |||
2266 | if (_rs.next()) {
|
||
2267 | resp = (STRUCT) _rs.getObject(1);
|
||
2268 | } else {
|
||
2269 | logger.error("While executing reprojection: empty resultset (?)");
|
||
2270 | return fromStruct;
|
||
2271 | } |
||
2272 | } catch (Exception ex) { |
||
2273 | logger.error("While reprojecting: " + ex.getMessage());
|
||
2274 | return fromStruct;
|
||
2275 | } |
||
2276 | |||
2277 | if (resp == null) { |
||
2278 | return fromStruct;
|
||
2279 | } else {
|
||
2280 | return resp;
|
||
2281 | } |
||
2282 | } |
||
2283 | |||
2284 | } |