1 /*
2
3 gg_geometries.c -- Gaia geometric objects
4
5 version 5.0, 2020 August 1
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 ------------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2008-2021
28 the Initial Developer. All Rights Reserved.
29
30 Contributor(s):
31
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43
44 */
45
46 #include <sys/types.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <memory.h>
50 #include <math.h>
51 #include <float.h>
52
53 #if defined(_WIN32) && !defined(__MINGW32__)
54 #include "config-msvc.h"
55 #else
56 #include "config.h"
57 #endif
58
59 #include <spatialite/sqlite.h>
60
61 #include <spatialite/gaiageo.h>
62
63 GAIAGEO_DECLARE gaiaPointPtr
gaiaAllocPoint(double x,double y)64 gaiaAllocPoint (double x, double y)
65 {
66 /* POINT object constructor */
67 gaiaPointPtr p = malloc (sizeof (gaiaPoint));
68 p->X = x;
69 p->Y = y;
70 p->Z = 0.0;
71 p->M = 0.0;
72 p->DimensionModel = GAIA_XY;
73 p->Next = NULL;
74 p->Prev = NULL;
75 return p;
76 }
77
78 GAIAGEO_DECLARE gaiaPointPtr
gaiaAllocPointXYZ(double x,double y,double z)79 gaiaAllocPointXYZ (double x, double y, double z)
80 {
81 /* POINT object constructor */
82 gaiaPointPtr p = malloc (sizeof (gaiaPoint));
83 p->X = x;
84 p->Y = y;
85 p->Z = z;
86 p->M = 0.0;
87 p->DimensionModel = GAIA_XY_Z;
88 p->Next = NULL;
89 p->Prev = NULL;
90 return p;
91 }
92
93 GAIAGEO_DECLARE gaiaPointPtr
gaiaAllocPointXYM(double x,double y,double m)94 gaiaAllocPointXYM (double x, double y, double m)
95 {
96 /* POINT object constructor */
97 gaiaPointPtr p = malloc (sizeof (gaiaPoint));
98 p->X = x;
99 p->Y = y;
100 p->Z = 0.0;
101 p->M = m;
102 p->DimensionModel = GAIA_XY_M;
103 p->Next = NULL;
104 p->Prev = NULL;
105 return p;
106 }
107
108 GAIAGEO_DECLARE gaiaPointPtr
gaiaAllocPointXYZM(double x,double y,double z,double m)109 gaiaAllocPointXYZM (double x, double y, double z, double m)
110 {
111 /* POINT object constructor */
112 gaiaPointPtr p = malloc (sizeof (gaiaPoint));
113 p->X = x;
114 p->Y = y;
115 p->Z = z;
116 p->M = m;
117 p->DimensionModel = GAIA_XY_Z_M;
118 p->Next = NULL;
119 p->Prev = NULL;
120 return p;
121 }
122
123 GAIAGEO_DECLARE void
gaiaFreePoint(gaiaPointPtr ptr)124 gaiaFreePoint (gaiaPointPtr ptr)
125 {
126 /* POINT object destructor */
127 if (ptr != NULL)
128 free (ptr);
129 }
130
131 GAIAGEO_DECLARE gaiaLinestringPtr
gaiaAllocLinestring(int vert)132 gaiaAllocLinestring (int vert)
133 {
134 /* LINESTRING object constructor */
135 gaiaLinestringPtr p = malloc (sizeof (gaiaLinestring));
136 p->Coords = malloc (sizeof (double) * (vert * 2));
137 p->Points = vert;
138 p->MinX = DBL_MAX;
139 p->MinY = DBL_MAX;
140 p->MaxX = -DBL_MAX;
141 p->MaxY = -DBL_MAX;
142 p->DimensionModel = GAIA_XY;
143 p->Next = NULL;
144 return p;
145 }
146
147 GAIAGEO_DECLARE gaiaLinestringPtr
gaiaAllocLinestringXYZ(int vert)148 gaiaAllocLinestringXYZ (int vert)
149 {
150 /* LINESTRING object constructor */
151 gaiaLinestringPtr p = malloc (sizeof (gaiaLinestring));
152 p->Coords = malloc (sizeof (double) * (vert * 3));
153 p->Points = vert;
154 p->MinX = DBL_MAX;
155 p->MinY = DBL_MAX;
156 p->MaxX = -DBL_MAX;
157 p->MaxY = -DBL_MAX;
158 p->DimensionModel = GAIA_XY_Z;
159 p->Next = NULL;
160 return p;
161 }
162
163 GAIAGEO_DECLARE gaiaLinestringPtr
gaiaAllocLinestringXYM(int vert)164 gaiaAllocLinestringXYM (int vert)
165 {
166 /* LINESTRING object constructor */
167 gaiaLinestringPtr p = malloc (sizeof (gaiaLinestring));
168 p->Coords = malloc (sizeof (double) * (vert * 3));
169 p->Points = vert;
170 p->MinX = DBL_MAX;
171 p->MinY = DBL_MAX;
172 p->MaxX = -DBL_MAX;
173 p->MaxY = -DBL_MAX;
174 p->DimensionModel = GAIA_XY_M;
175 p->Next = NULL;
176 return p;
177 }
178
179 GAIAGEO_DECLARE gaiaLinestringPtr
gaiaAllocLinestringXYZM(int vert)180 gaiaAllocLinestringXYZM (int vert)
181 {
182 /* LINESTRING object constructor */
183 gaiaLinestringPtr p = malloc (sizeof (gaiaLinestring));
184 p->Coords = malloc (sizeof (double) * (vert * 4));
185 p->Points = vert;
186 p->MinX = DBL_MAX;
187 p->MinY = DBL_MAX;
188 p->MaxX = -DBL_MAX;
189 p->MaxY = -DBL_MAX;
190 p->DimensionModel = GAIA_XY_Z_M;
191 p->Next = NULL;
192 return p;
193 }
194
195 GAIAGEO_DECLARE void
gaiaFreeLinestring(gaiaLinestringPtr ptr)196 gaiaFreeLinestring (gaiaLinestringPtr ptr)
197 {
198 /* LINESTRING object desctructror */
199 if (ptr)
200 {
201 if (ptr->Coords)
202 free (ptr->Coords);
203 free (ptr);
204 }
205 }
206
207 GAIAGEO_DECLARE int
gaiaLineGetPoint(gaiaLinestringPtr ln,int v,double * x,double * y,double * z,double * m)208 gaiaLineGetPoint (gaiaLinestringPtr ln, int v, double *x, double *y, double *z,
209 double *m)
210 {
211 /* SAFE - getting coords for a vertex in LINESTRING */
212 double vx;
213 double vy;
214 double vz;
215 double vm;
216 *x = 0.0;
217 *y = 0.0;
218 *z = 0.0;
219 *m = 0.0;
220 if (!ln)
221 return 0;
222 if (v < 0 || v >= ln->Points)
223 return 0;
224 switch (ln->DimensionModel)
225 {
226 case GAIA_XY:
227 gaiaGetPoint (ln->Coords, v, &vx, &vy);
228 *x = vx;
229 *y = vy;
230 break;
231 case GAIA_XY_Z:
232 gaiaGetPointXYZ (ln->Coords, v, &vx, &vy, &vz);
233 *x = vx;
234 *y = vy;
235 *z = vz;
236 break;
237 case GAIA_XY_M:
238 gaiaGetPointXYM (ln->Coords, v, &vx, &vy, &vm);
239 *x = vx;
240 *y = vy;
241 *m = vm;
242 break;
243 case GAIA_XY_Z_M:
244 gaiaGetPointXYZM (ln->Coords, v, &vx, &vy, &vz, &vm);
245 *x = vx;
246 *y = vy;
247 *z = vz;
248 *m = vm;
249 break;
250 default:
251 return 0;
252 };
253 return 1;
254 }
255
256 GAIAGEO_DECLARE int
gaiaLineSetPoint(gaiaLinestringPtr ln,int v,double x,double y,double z,double m)257 gaiaLineSetPoint (gaiaLinestringPtr ln, int v, double x, double y, double z,
258 double m)
259 {
260 /* SAFE - setting coords for a vertex in RING */
261 if (!ln)
262 return 0;
263 if (v < 0 || v >= ln->Points)
264 return 0;
265 switch (ln->DimensionModel)
266 {
267 case GAIA_XY:
268 gaiaSetPoint (ln->Coords, v, x, y);
269 break;
270 case GAIA_XY_Z:
271 gaiaSetPointXYZ (ln->Coords, v, x, y, z);
272 break;
273 case GAIA_XY_M:
274 gaiaSetPointXYM (ln->Coords, v, x, y, m);
275 break;
276 case GAIA_XY_Z_M:
277 gaiaSetPointXYZM (ln->Coords, v, x, y, z, m);
278 break;
279 default:
280 return 0;
281 };
282 return 1;
283 }
284
285 GAIAGEO_DECLARE void
gaiaCopyLinestringCoords(gaiaLinestringPtr dst,gaiaLinestringPtr src)286 gaiaCopyLinestringCoords (gaiaLinestringPtr dst, gaiaLinestringPtr src)
287 {
288 /*
289 / copying coords from one Linestring to another
290 / maybe, converting from one Dimension Model to a different one
291 */
292 gaiaCopyLinestringCoordsEx (dst, src, 0.0, 0.0);
293 }
294
295 GAIAGEO_DECLARE void
gaiaCopyLinestringCoordsEx(gaiaLinestringPtr dst,gaiaLinestringPtr src,double z_no_data,double m_no_data)296 gaiaCopyLinestringCoordsEx (gaiaLinestringPtr dst, gaiaLinestringPtr src,
297 double z_no_data, double m_no_data)
298 {
299 /*
300 / copying coords from one Linestring to another
301 / maybe, converting from one Dimension Model to a different one
302 */
303 int iv;
304 double x;
305 double y;
306 double z;
307 double m;
308 if (!src)
309 return;
310 if (!dst)
311 return;
312 if (src->Points != dst->Points)
313 return;
314 for (iv = 0; iv < dst->Points; iv++)
315 {
316 z = z_no_data;
317 m = m_no_data;
318 if (src->DimensionModel == GAIA_XY_Z)
319 {
320 gaiaGetPointXYZ (src->Coords, iv, &x, &y, &z);
321 }
322 else if (src->DimensionModel == GAIA_XY_M)
323 {
324 gaiaGetPointXYM (src->Coords, iv, &x, &y, &m);
325 }
326 else if (src->DimensionModel == GAIA_XY_Z_M)
327 {
328 gaiaGetPointXYZM (src->Coords, iv, &x, &y, &z, &m);
329 }
330 else
331 {
332 gaiaGetPoint (src->Coords, iv, &x, &y);
333 }
334 if (dst->DimensionModel == GAIA_XY_Z)
335 {
336 gaiaSetPointXYZ (dst->Coords, iv, x, y, z);
337 }
338 else if (dst->DimensionModel == GAIA_XY_M)
339 {
340 gaiaSetPointXYM (dst->Coords, iv, x, y, m);
341 }
342 else if (dst->DimensionModel == GAIA_XY_Z_M)
343 {
344 gaiaSetPointXYZM (dst->Coords, iv, x, y, z, m);
345 }
346 else
347 {
348 gaiaSetPoint (dst->Coords, iv, x, y);
349 }
350 }
351 }
352
353 GAIAGEO_DECLARE gaiaLinestringPtr
gaiaCloneLinestring(gaiaLinestringPtr line)354 gaiaCloneLinestring (gaiaLinestringPtr line)
355 {
356 /* clones a LINESTRING */
357 gaiaLinestringPtr new_line;
358 if (!line)
359 return NULL;
360 if (line->DimensionModel == GAIA_XY_Z)
361 new_line = gaiaAllocLinestringXYZ (line->Points);
362 else if (line->DimensionModel == GAIA_XY_M)
363 new_line = gaiaAllocLinestringXYM (line->Points);
364 else if (line->DimensionModel == GAIA_XY_Z_M)
365 new_line = gaiaAllocLinestringXYZM (line->Points);
366 else
367 new_line = gaiaAllocLinestring (line->Points);
368 gaiaCopyLinestringCoords (new_line, line);
369 return new_line;
370 }
371
372 GAIAGEO_DECLARE void
gaiaCopyLinestringCoordsReverse(gaiaLinestringPtr dst,gaiaLinestringPtr src)373 gaiaCopyLinestringCoordsReverse (gaiaLinestringPtr dst, gaiaLinestringPtr src)
374 {
375 /*
376 / copying coords from one Linestring to another in reverse order
377 / maybe, converting from one Dimension Model to a different one
378 */
379 int iv;
380 int iv2 = 0;
381 double x;
382 double y;
383 double z;
384 double m;
385 if (!src)
386 return;
387 if (!dst)
388 return;
389 if (src->Points != dst->Points)
390 return;
391 for (iv = src->Points - 1; iv >= 0; iv--)
392 {
393 z = 0.0;
394 m = 0.0;
395 if (src->DimensionModel == GAIA_XY_Z)
396 {
397 gaiaGetPointXYZ (src->Coords, iv, &x, &y, &z);
398 }
399 else if (src->DimensionModel == GAIA_XY_M)
400 {
401 gaiaGetPointXYM (src->Coords, iv, &x, &y, &m);
402 }
403 else if (src->DimensionModel == GAIA_XY_Z_M)
404 {
405 gaiaGetPointXYZM (src->Coords, iv, &x, &y, &z, &m);
406 }
407 else
408 {
409 gaiaGetPoint (src->Coords, iv, &x, &y);
410 }
411 if (dst->DimensionModel == GAIA_XY_Z)
412 {
413 gaiaSetPointXYZ (dst->Coords, iv2, x, y, z);
414 }
415 else if (dst->DimensionModel == GAIA_XY_M)
416 {
417 gaiaSetPointXYM (dst->Coords, iv2, x, y, m);
418 }
419 else if (dst->DimensionModel == GAIA_XY_Z_M)
420 {
421 gaiaSetPointXYZM (dst->Coords, iv2, x, y, z, m);
422 }
423 else
424 {
425 gaiaSetPoint (dst->Coords, iv2, x, y);
426 }
427 iv2++;
428 }
429 }
430
431 GAIAGEO_DECLARE gaiaLinestringPtr
gaiaCloneLinestringSpecial(gaiaLinestringPtr line,int mode)432 gaiaCloneLinestringSpecial (gaiaLinestringPtr line, int mode)
433 {
434 /* clones a LINESTRING (special) */
435 gaiaLinestringPtr new_line;
436 if (!line)
437 return NULL;
438 if (mode != GAIA_REVERSE_ORDER)
439 return gaiaCloneLinestring (line);
440
441 if (line->DimensionModel == GAIA_XY_Z)
442 new_line = gaiaAllocLinestringXYZ (line->Points);
443 else if (line->DimensionModel == GAIA_XY_M)
444 new_line = gaiaAllocLinestringXYM (line->Points);
445 else if (line->DimensionModel == GAIA_XY_Z_M)
446 new_line = gaiaAllocLinestringXYZM (line->Points);
447 else
448 new_line = gaiaAllocLinestring (line->Points);
449 gaiaCopyLinestringCoordsReverse (new_line, line);
450 return new_line;
451 }
452
453 GAIAGEO_DECLARE gaiaRingPtr
gaiaAllocRing(int vert)454 gaiaAllocRing (int vert)
455 {
456 /* ring object constructor */
457 gaiaRingPtr p = malloc (sizeof (gaiaRing));
458 p->Coords = malloc (sizeof (double) * (vert * 2));
459 p->Points = vert;
460 p->Link = NULL;
461 p->Clockwise = 0;
462 p->MinX = DBL_MAX;
463 p->MinY = DBL_MAX;
464 p->MaxX = -DBL_MAX;
465 p->MaxY = -DBL_MAX;
466 p->DimensionModel = GAIA_XY;
467 p->Next = NULL;
468 return p;
469 }
470
471 GAIAGEO_DECLARE gaiaRingPtr
gaiaAllocRingXYZ(int vert)472 gaiaAllocRingXYZ (int vert)
473 {
474 /* ring object constructor */
475 gaiaRingPtr p = malloc (sizeof (gaiaRing));
476 p->Coords = malloc (sizeof (double) * (vert * 3));
477 p->Points = vert;
478 p->Link = NULL;
479 p->Clockwise = 0;
480 p->MinX = DBL_MAX;
481 p->MinY = DBL_MAX;
482 p->MaxX = -DBL_MAX;
483 p->MaxY = -DBL_MAX;
484 p->DimensionModel = GAIA_XY_Z;
485 p->Next = NULL;
486 return p;
487 }
488
489 GAIAGEO_DECLARE gaiaRingPtr
gaiaAllocRingXYM(int vert)490 gaiaAllocRingXYM (int vert)
491 {
492 /* ring object constructor */
493 gaiaRingPtr p = malloc (sizeof (gaiaRing));
494 p->Coords = malloc (sizeof (double) * (vert * 3));
495 p->Points = vert;
496 p->Link = NULL;
497 p->Clockwise = 0;
498 p->MinX = DBL_MAX;
499 p->MinY = DBL_MAX;
500 p->MaxX = -DBL_MAX;
501 p->MaxY = -DBL_MAX;
502 p->DimensionModel = GAIA_XY_M;
503 p->Next = NULL;
504 return p;
505 }
506
507 GAIAGEO_DECLARE gaiaRingPtr
gaiaAllocRingXYZM(int vert)508 gaiaAllocRingXYZM (int vert)
509 {
510 /* ring object constructor */
511 gaiaRingPtr p = malloc (sizeof (gaiaRing));
512 p->Coords = malloc (sizeof (double) * (vert * 4));
513 p->Points = vert;
514 p->Link = NULL;
515 p->Clockwise = 0;
516 p->MinX = DBL_MAX;
517 p->MinY = DBL_MAX;
518 p->MaxX = -DBL_MAX;
519 p->MaxY = -DBL_MAX;
520 p->DimensionModel = GAIA_XY_Z_M;
521 p->Next = NULL;
522 return p;
523 }
524
525 GAIAGEO_DECLARE void
gaiaFreeRing(gaiaRingPtr ptr)526 gaiaFreeRing (gaiaRingPtr ptr)
527 {
528 /* ring object destructor */
529 if (ptr)
530 {
531 if (ptr->Coords)
532 free (ptr->Coords);
533 free (ptr);
534 }
535 }
536
537 GAIAGEO_DECLARE int
gaiaRingGetPoint(gaiaRingPtr rng,int v,double * x,double * y,double * z,double * m)538 gaiaRingGetPoint (gaiaRingPtr rng, int v, double *x, double *y, double *z,
539 double *m)
540 {
541 /* SAFE - getting coords for a vertex in RING */
542 double vx;
543 double vy;
544 double vz;
545 double vm;
546 *x = 0.0;
547 *y = 0.0;
548 *z = 0.0;
549 *m = 0.0;
550 if (!rng)
551 return 0;
552 if (v < 0 || v >= rng->Points)
553 return 0;
554 switch (rng->DimensionModel)
555 {
556 case GAIA_XY:
557 gaiaGetPoint (rng->Coords, v, &vx, &vy);
558 *x = vx;
559 *y = vy;
560 break;
561 case GAIA_XY_Z:
562 gaiaGetPointXYZ (rng->Coords, v, &vx, &vy, &vz);
563 *x = vx;
564 *y = vy;
565 *z = vz;
566 break;
567 case GAIA_XY_M:
568 gaiaGetPointXYM (rng->Coords, v, &vx, &vy, &vm);
569 *x = vx;
570 *y = vy;
571 *m = vm;
572 break;
573 case GAIA_XY_Z_M:
574 gaiaGetPointXYZM (rng->Coords, v, &vx, &vy, &vz, &vm);
575 *x = vx;
576 *y = vy;
577 *z = vz;
578 *m = vm;
579 break;
580 default:
581 return 0;
582 };
583 return 1;
584 }
585
586 GAIAGEO_DECLARE int
gaiaRingSetPoint(gaiaRingPtr rng,int v,double x,double y,double z,double m)587 gaiaRingSetPoint (gaiaRingPtr rng, int v, double x, double y, double z,
588 double m)
589 {
590 /* SAFE - getting coords for a vertex in RING */
591 if (!rng)
592 return 0;
593 if (v < 0 || v >= rng->Points)
594 return 0;
595 switch (rng->DimensionModel)
596 {
597 case GAIA_XY:
598 gaiaSetPoint (rng->Coords, v, x, y);
599 break;
600 case GAIA_XY_Z:
601 gaiaSetPointXYZ (rng->Coords, v, x, y, z);
602 break;
603 case GAIA_XY_M:
604 gaiaSetPointXYM (rng->Coords, v, x, y, m);
605 break;
606 case GAIA_XY_Z_M:
607 gaiaSetPointXYZM (rng->Coords, v, x, y, z, m);
608 break;
609 default:
610 return 0;
611 };
612 return 1;
613 }
614
615 GAIAGEO_DECLARE void
gaiaCopyRingCoords(gaiaRingPtr dst,gaiaRingPtr src)616 gaiaCopyRingCoords (gaiaRingPtr dst, gaiaRingPtr src)
617 {
618 /*
619 / copying coords from one Ring to another
620 / maybe, converting from one Dimension Model to a different one
621 */
622 gaiaCopyRingCoordsEx (dst, src, 0.0, 0.0);
623 }
624
625 GAIAGEO_DECLARE void
gaiaCopyRingCoordsEx(gaiaRingPtr dst,gaiaRingPtr src,double z_no_data,double m_no_data)626 gaiaCopyRingCoordsEx (gaiaRingPtr dst, gaiaRingPtr src, double z_no_data,
627 double m_no_data)
628 {
629 /*
630 / copying coords from one Ring to another
631 / maybe, converting from one Dimension Model to a different one
632 */
633 int iv;
634 double x;
635 double y;
636 double z;
637 double m;
638 if (!src)
639 return;
640 if (!dst)
641 return;
642 if (src->Points != dst->Points)
643 return;
644 for (iv = 0; iv < dst->Points; iv++)
645 {
646 z = z_no_data;
647 m = m_no_data;
648 if (src->DimensionModel == GAIA_XY_Z)
649 {
650 gaiaGetPointXYZ (src->Coords, iv, &x, &y, &z);
651 }
652 else if (src->DimensionModel == GAIA_XY_M)
653 {
654 gaiaGetPointXYM (src->Coords, iv, &x, &y, &m);
655 }
656 else if (src->DimensionModel == GAIA_XY_Z_M)
657 {
658 gaiaGetPointXYZM (src->Coords, iv, &x, &y, &z, &m);
659 }
660 else
661 {
662 gaiaGetPoint (src->Coords, iv, &x, &y);
663 }
664 if (dst->DimensionModel == GAIA_XY_Z)
665 {
666 gaiaSetPointXYZ (dst->Coords, iv, x, y, z);
667 }
668 else if (dst->DimensionModel == GAIA_XY_M)
669 {
670 gaiaSetPointXYM (dst->Coords, iv, x, y, m);
671 }
672 else if (dst->DimensionModel == GAIA_XY_Z_M)
673 {
674 gaiaSetPointXYZM (dst->Coords, iv, x, y, z, m);
675 }
676 else
677 {
678 gaiaSetPoint (dst->Coords, iv, x, y);
679 }
680 }
681 }
682
683 GAIAGEO_DECLARE gaiaRingPtr
gaiaCloneRing(gaiaRingPtr ring)684 gaiaCloneRing (gaiaRingPtr ring)
685 {
686 /* clones a RING */
687 gaiaRingPtr new_ring;
688 if (!ring)
689 return NULL;
690 if (ring->DimensionModel == GAIA_XY_Z)
691 new_ring = gaiaAllocRingXYZ (ring->Points);
692 else if (ring->DimensionModel == GAIA_XY_M)
693 new_ring = gaiaAllocRingXYM (ring->Points);
694 else if (ring->DimensionModel == GAIA_XY_Z_M)
695 new_ring = gaiaAllocRingXYZM (ring->Points);
696 else
697 new_ring = gaiaAllocRing (ring->Points);
698 gaiaCopyRingCoords (new_ring, ring);
699 return new_ring;
700 }
701
702 GAIAGEO_DECLARE void
gaiaCopyRingCoordsReverse(gaiaRingPtr dst,gaiaRingPtr src)703 gaiaCopyRingCoordsReverse (gaiaRingPtr dst, gaiaRingPtr src)
704 {
705 /*
706 / copying coords from one Ring to another in reverse order
707 / maybe, converting from one Dimension Model to a different one
708 */
709 int iv;
710 int iv2 = 0;
711 double x;
712 double y;
713 double z;
714 double m;
715 if (!src)
716 return;
717 if (!dst)
718 return;
719 if (src->Points != dst->Points)
720 return;
721 for (iv = src->Points - 1; iv >= 0; iv--)
722 {
723 z = 0.0;
724 m = 0.0;
725 if (src->DimensionModel == GAIA_XY_Z)
726 {
727 gaiaGetPointXYZ (src->Coords, iv, &x, &y, &z);
728 }
729 else if (src->DimensionModel == GAIA_XY_M)
730 {
731 gaiaGetPointXYM (src->Coords, iv, &x, &y, &m);
732 }
733 else if (src->DimensionModel == GAIA_XY_Z_M)
734 {
735 gaiaGetPointXYZM (src->Coords, iv, &x, &y, &z, &m);
736 }
737 else
738 {
739 gaiaGetPoint (src->Coords, iv, &x, &y);
740 }
741 if (dst->DimensionModel == GAIA_XY_Z)
742 {
743 gaiaSetPointXYZ (dst->Coords, iv2, x, y, z);
744 }
745 else if (dst->DimensionModel == GAIA_XY_M)
746 {
747 gaiaSetPointXYM (dst->Coords, iv2, x, y, m);
748 }
749 else if (dst->DimensionModel == GAIA_XY_Z_M)
750 {
751 gaiaSetPointXYZM (dst->Coords, iv2, x, y, z, m);
752 }
753 else
754 {
755 gaiaSetPoint (dst->Coords, iv2, x, y);
756 }
757 iv2++;
758 }
759 }
760
761 GAIAGEO_DECLARE gaiaRingPtr
gaiaCloneRingSpecial(gaiaRingPtr ring,int mode)762 gaiaCloneRingSpecial (gaiaRingPtr ring, int mode)
763 {
764 /* clones a RING (special) */
765 gaiaRingPtr new_ring;
766 if (!ring)
767 return NULL;
768 if (mode != GAIA_REVERSE_ORDER)
769 return gaiaCloneRing (ring);
770
771 if (ring->DimensionModel == GAIA_XY_Z)
772 new_ring = gaiaAllocRingXYZ (ring->Points);
773 else if (ring->DimensionModel == GAIA_XY_M)
774 new_ring = gaiaAllocRingXYM (ring->Points);
775 else if (ring->DimensionModel == GAIA_XY_Z_M)
776 new_ring = gaiaAllocRingXYZM (ring->Points);
777 else
778 new_ring = gaiaAllocRing (ring->Points);
779 gaiaCopyRingCoordsReverse (new_ring, ring);
780 return new_ring;
781 }
782
783 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaClonePolygon(gaiaPolygonPtr polyg)784 gaiaClonePolygon (gaiaPolygonPtr polyg)
785 {
786 /* clones a POLYGON */
787 int ib;
788 gaiaPolygonPtr new_polyg;
789 gaiaRingPtr i_ring;
790 gaiaRingPtr o_ring;
791 if (!polyg)
792 return NULL;
793 i_ring = polyg->Exterior;
794 if (polyg->DimensionModel == GAIA_XY_Z)
795 new_polyg = gaiaAllocPolygonXYZ (i_ring->Points, polyg->NumInteriors);
796 else if (polyg->DimensionModel == GAIA_XY_M)
797 new_polyg = gaiaAllocPolygonXYM (i_ring->Points, polyg->NumInteriors);
798 else if (polyg->DimensionModel == GAIA_XY_Z_M)
799 new_polyg = gaiaAllocPolygonXYZM (i_ring->Points, polyg->NumInteriors);
800 else
801 new_polyg = gaiaAllocPolygon (i_ring->Points, polyg->NumInteriors);
802 o_ring = new_polyg->Exterior;
803 /* copying points for the EXTERIOR RING */
804 gaiaCopyRingCoords (o_ring, i_ring);
805 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
806 {
807 /* copying each INTERIOR RING [if any] */
808 i_ring = polyg->Interiors + ib;
809 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
810 gaiaCopyRingCoords (o_ring, i_ring);
811 }
812 return new_polyg;
813 }
814
815 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaClonePolygonSpecial(gaiaPolygonPtr polyg,int mode)816 gaiaClonePolygonSpecial (gaiaPolygonPtr polyg, int mode)
817 {
818 /* clones a POLYGON (special) */
819 int ib;
820 gaiaPolygonPtr new_polyg;
821 gaiaRingPtr i_ring;
822 gaiaRingPtr o_ring;
823 if (!polyg)
824 return NULL;
825 if (mode == GAIA_REVERSE_ORDER || mode == GAIA_CW_ORDER
826 || mode == GAIA_CCW_ORDER)
827 ;
828 else
829 return gaiaClonePolygon (polyg);
830
831 i_ring = polyg->Exterior;
832 if (polyg->DimensionModel == GAIA_XY_Z)
833 new_polyg = gaiaAllocPolygonXYZ (i_ring->Points, polyg->NumInteriors);
834 else if (polyg->DimensionModel == GAIA_XY_M)
835 new_polyg = gaiaAllocPolygonXYM (i_ring->Points, polyg->NumInteriors);
836 else if (polyg->DimensionModel == GAIA_XY_Z_M)
837 new_polyg = gaiaAllocPolygonXYZM (i_ring->Points, polyg->NumInteriors);
838 else
839 new_polyg = gaiaAllocPolygon (i_ring->Points, polyg->NumInteriors);
840 o_ring = new_polyg->Exterior;
841 /* copying points for the EXTERIOR RING */
842 if (mode == GAIA_REVERSE_ORDER)
843 gaiaCopyRingCoordsReverse (o_ring, i_ring);
844 else
845 {
846 gaiaClockwise (i_ring);
847 if (mode == GAIA_CCW_ORDER)
848 {
849 /* returning a Counter-Clockwise Polygon */
850 if (i_ring->Clockwise)
851 gaiaCopyRingCoordsReverse (o_ring, i_ring);
852 else
853 gaiaCopyRingCoords (o_ring, i_ring);
854 }
855 else
856 {
857 /* returning a Clockwise Polygon */
858 if (i_ring->Clockwise)
859 gaiaCopyRingCoords (o_ring, i_ring);
860 else
861 gaiaCopyRingCoordsReverse (o_ring, i_ring);
862 }
863 }
864 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
865 {
866 /* copying each INTERIOR RING [if any] */
867 i_ring = polyg->Interiors + ib;
868 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
869 if (mode == GAIA_REVERSE_ORDER)
870 gaiaCopyRingCoordsReverse (o_ring, i_ring);
871 else
872 {
873 if (mode == GAIA_CCW_ORDER)
874 {
875 /* returning a Counter-Clockwise Polygon */
876 if (i_ring->Clockwise)
877 gaiaCopyRingCoords (o_ring, i_ring);
878 else
879 gaiaCopyRingCoordsReverse (o_ring, i_ring);
880 }
881 else
882 {
883 /* returning a Clockwise Polygon */
884 gaiaClockwise (i_ring);
885 if (i_ring->Clockwise)
886 gaiaCopyRingCoordsReverse (o_ring, i_ring);
887 else
888 gaiaCopyRingCoords (o_ring, i_ring);
889 }
890 }
891 }
892 return new_polyg;
893 }
894
895 GAIAGEO_DECLARE int
gaiaCheckClockwise(gaiaGeomCollPtr geom)896 gaiaCheckClockwise (gaiaGeomCollPtr geom)
897 {
898 /* checking for a Clockwise Geometry */
899 int retval = 1;
900 gaiaPolygonPtr polyg;
901 int ib;
902 gaiaRingPtr i_ring;
903 if (!geom)
904 return 1;
905
906 polyg = geom->FirstPolygon;
907 while (polyg != NULL)
908 {
909 i_ring = polyg->Exterior;
910 gaiaClockwise (i_ring);
911 if (i_ring->Clockwise == 0)
912 retval = 0;
913 for (ib = 0; ib < polyg->NumInteriors; ib++)
914 {
915 /* checking each INTERIOR RING [if any] */
916 i_ring = polyg->Interiors + ib;
917 gaiaClockwise (i_ring);
918 if (i_ring->Clockwise)
919 retval = 0;
920 }
921 polyg = polyg->Next;
922 }
923 return retval;
924 }
925
926 GAIAGEO_DECLARE int
gaiaCheckCounterClockwise(gaiaGeomCollPtr geom)927 gaiaCheckCounterClockwise (gaiaGeomCollPtr geom)
928 {
929 /* checking for a CounterClockwise Geometry */
930 int retval = 1;
931 gaiaPolygonPtr polyg;
932 int ib;
933 gaiaRingPtr i_ring;
934 if (!geom)
935 return 1;
936
937 polyg = geom->FirstPolygon;
938 while (polyg != NULL)
939 {
940 i_ring = polyg->Exterior;
941 gaiaClockwise (i_ring);
942 if (i_ring->Clockwise)
943 retval = 0;
944 for (ib = 0; ib < polyg->NumInteriors; ib++)
945 {
946 /* checking each INTERIOR RING [if any] */
947 i_ring = polyg->Interiors + ib;
948 gaiaClockwise (i_ring);
949 if (i_ring->Clockwise == 0)
950 retval = 0;
951 }
952 polyg = polyg->Next;
953 }
954 return retval;
955 }
956
957 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaAllocPolygon(int vert,int excl)958 gaiaAllocPolygon (int vert, int excl)
959 {
960 /* POLYGON object constructor */
961 gaiaPolygonPtr p;
962 gaiaRingPtr pP;
963 int ind;
964 p = malloc (sizeof (gaiaPolygon));
965 p->Exterior = gaiaAllocRing (vert);
966 p->NumInteriors = excl;
967 p->NextInterior = 0;
968 p->Next = NULL;
969 if (excl == 0)
970 p->Interiors = NULL;
971 else
972 p->Interiors = malloc (sizeof (gaiaRing) * excl);
973 for (ind = 0; ind < p->NumInteriors; ind++)
974 {
975 pP = p->Interiors + ind;
976 pP->Points = 0;
977 pP->Coords = NULL;
978 pP->Next = NULL;
979 pP->Link = 0;
980 }
981 p->MinX = DBL_MAX;
982 p->MinY = DBL_MAX;
983 p->MaxX = -DBL_MAX;
984 p->MaxY = -DBL_MAX;
985 p->DimensionModel = GAIA_XY;
986 return p;
987 }
988
989 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaAllocPolygonXYZ(int vert,int excl)990 gaiaAllocPolygonXYZ (int vert, int excl)
991 {
992 /* POLYGON object constructor */
993 gaiaPolygonPtr p;
994 gaiaRingPtr pP;
995 int ind;
996 p = malloc (sizeof (gaiaPolygon));
997 p->Exterior = gaiaAllocRingXYZ (vert);
998 p->NumInteriors = excl;
999 p->NextInterior = 0;
1000 p->Next = NULL;
1001 if (excl == 0)
1002 p->Interiors = NULL;
1003 else
1004 p->Interiors = malloc (sizeof (gaiaRing) * excl);
1005 for (ind = 0; ind < p->NumInteriors; ind++)
1006 {
1007 pP = p->Interiors + ind;
1008 pP->Points = 0;
1009 pP->Coords = NULL;
1010 pP->Next = NULL;
1011 pP->Link = 0;
1012 }
1013 p->MinX = DBL_MAX;
1014 p->MinY = DBL_MAX;
1015 p->MaxX = -DBL_MAX;
1016 p->MaxY = -DBL_MAX;
1017 p->DimensionModel = GAIA_XY_Z;
1018 return p;
1019 }
1020
1021 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaAllocPolygonXYM(int vert,int excl)1022 gaiaAllocPolygonXYM (int vert, int excl)
1023 {
1024 /* POLYGON object constructor */
1025 gaiaPolygonPtr p;
1026 gaiaRingPtr pP;
1027 int ind;
1028 p = malloc (sizeof (gaiaPolygon));
1029 p->Exterior = gaiaAllocRingXYM (vert);
1030 p->NumInteriors = excl;
1031 p->NextInterior = 0;
1032 p->Next = NULL;
1033 if (excl == 0)
1034 p->Interiors = NULL;
1035 else
1036 p->Interiors = malloc (sizeof (gaiaRing) * excl);
1037 for (ind = 0; ind < p->NumInteriors; ind++)
1038 {
1039 pP = p->Interiors + ind;
1040 pP->Points = 0;
1041 pP->Coords = NULL;
1042 pP->Next = NULL;
1043 pP->Link = 0;
1044 }
1045 p->MinX = DBL_MAX;
1046 p->MinY = DBL_MAX;
1047 p->MaxX = -DBL_MAX;
1048 p->MaxY = -DBL_MAX;
1049 p->DimensionModel = GAIA_XY_M;
1050 return p;
1051 }
1052
1053 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaAllocPolygonXYZM(int vert,int excl)1054 gaiaAllocPolygonXYZM (int vert, int excl)
1055 {
1056 /* POLYGON object constructor */
1057 gaiaPolygonPtr p;
1058 gaiaRingPtr pP;
1059 int ind;
1060 p = malloc (sizeof (gaiaPolygon));
1061 p->Exterior = gaiaAllocRingXYZM (vert);
1062 p->NumInteriors = excl;
1063 p->NextInterior = 0;
1064 p->Next = NULL;
1065 if (excl == 0)
1066 p->Interiors = NULL;
1067 else
1068 p->Interiors = malloc (sizeof (gaiaRing) * excl);
1069 for (ind = 0; ind < p->NumInteriors; ind++)
1070 {
1071 pP = p->Interiors + ind;
1072 pP->Points = 0;
1073 pP->Coords = NULL;
1074 pP->Next = NULL;
1075 pP->Link = 0;
1076 }
1077 p->MinX = DBL_MAX;
1078 p->MinY = DBL_MAX;
1079 p->MaxX = -DBL_MAX;
1080 p->MaxY = -DBL_MAX;
1081 p->DimensionModel = GAIA_XY_Z_M;
1082 return p;
1083 }
1084
1085 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaCreatePolygon(gaiaRingPtr ring)1086 gaiaCreatePolygon (gaiaRingPtr ring)
1087 {
1088 /* POLYGON object constructor */
1089 gaiaPolygonPtr p;
1090 p = malloc (sizeof (gaiaPolygon));
1091 p->DimensionModel = ring->DimensionModel;
1092 if (ring->DimensionModel == GAIA_XY_Z)
1093 p->Exterior = gaiaAllocRingXYZ (ring->Points);
1094 else if (ring->DimensionModel == GAIA_XY_M)
1095 p->Exterior = gaiaAllocRingXYM (ring->Points);
1096 else if (ring->DimensionModel == GAIA_XY_Z_M)
1097 p->Exterior = gaiaAllocRingXYZM (ring->Points);
1098 else
1099 p->Exterior = gaiaAllocRing (ring->Points);
1100 p->NumInteriors = 0;
1101 p->NextInterior = 0;
1102 p->Next = NULL;
1103 p->Interiors = NULL;
1104 gaiaCopyRingCoords (p->Exterior, ring);
1105 p->MinX = DBL_MAX;
1106 p->MinY = DBL_MAX;
1107 p->MaxX = -DBL_MAX;
1108 p->MaxY = -DBL_MAX;
1109 return p;
1110 }
1111
1112 GAIAGEO_DECLARE void
gaiaFreePolygon(gaiaPolygonPtr p)1113 gaiaFreePolygon (gaiaPolygonPtr p)
1114 {
1115 /* POLYGON object destructor */
1116 gaiaRingPtr pP;
1117 int ind;
1118 if (p->Exterior)
1119 gaiaFreeRing (p->Exterior);
1120 for (ind = 0; ind < p->NumInteriors; ind++)
1121 {
1122 pP = p->Interiors + ind;
1123 if (pP->Coords)
1124 free (pP->Coords);
1125 }
1126 if (p->Interiors)
1127 free (p->Interiors);
1128 free (p);
1129 }
1130
1131 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCloneGeomColl(gaiaGeomCollPtr geom)1132 gaiaCloneGeomColl (gaiaGeomCollPtr geom)
1133 {
1134 /* clones a GEOMETRYCOLLECTION */
1135 int ib;
1136 gaiaPointPtr point;
1137 gaiaLinestringPtr line;
1138 gaiaLinestringPtr new_line;
1139 gaiaPolygonPtr polyg;
1140 gaiaPolygonPtr new_polyg;
1141 gaiaGeomCollPtr new_geom;
1142 gaiaRingPtr i_ring;
1143 gaiaRingPtr o_ring;
1144 if (!geom)
1145 return NULL;
1146 if (geom->DimensionModel == GAIA_XY_Z)
1147 new_geom = gaiaAllocGeomCollXYZ ();
1148 else if (geom->DimensionModel == GAIA_XY_M)
1149 new_geom = gaiaAllocGeomCollXYM ();
1150 else if (geom->DimensionModel == GAIA_XY_Z_M)
1151 new_geom = gaiaAllocGeomCollXYZM ();
1152 else
1153 new_geom = gaiaAllocGeomColl ();
1154 new_geom->Srid = geom->Srid;
1155 new_geom->DeclaredType = geom->DeclaredType;
1156 point = geom->FirstPoint;
1157 while (point)
1158 {
1159 /* copying POINTs */
1160 if (geom->DimensionModel == GAIA_XY_Z)
1161 gaiaAddPointToGeomCollXYZ (new_geom, point->X, point->Y,
1162 point->Z);
1163 else if (geom->DimensionModel == GAIA_XY_M)
1164 gaiaAddPointToGeomCollXYM (new_geom, point->X, point->Y,
1165 point->M);
1166 else if (geom->DimensionModel == GAIA_XY_Z_M)
1167 gaiaAddPointToGeomCollXYZM (new_geom, point->X, point->Y,
1168 point->Z, point->M);
1169 else
1170 gaiaAddPointToGeomColl (new_geom, point->X, point->Y);
1171 point = point->Next;
1172 }
1173 line = geom->FirstLinestring;
1174 while (line)
1175 {
1176 /* copying LINESTRINGs */
1177 new_line = gaiaAddLinestringToGeomColl (new_geom, line->Points);
1178 gaiaCopyLinestringCoords (new_line, line);
1179 line = line->Next;
1180 }
1181 polyg = geom->FirstPolygon;
1182 while (polyg)
1183 {
1184 /* copying POLYGONs */
1185 i_ring = polyg->Exterior;
1186 new_polyg =
1187 gaiaAddPolygonToGeomColl (new_geom, i_ring->Points,
1188 polyg->NumInteriors);
1189 o_ring = new_polyg->Exterior;
1190 /* copying points for the EXTERIOR RING */
1191 gaiaCopyRingCoords (o_ring, i_ring);
1192 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
1193 {
1194 /* copying each INTERIOR RING [if any] */
1195 i_ring = polyg->Interiors + ib;
1196 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
1197 gaiaCopyRingCoords (o_ring, i_ring);
1198 }
1199 polyg = polyg->Next;
1200 }
1201 return new_geom;
1202 }
1203
1204 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCloneGeomCollSpecial(gaiaGeomCollPtr geom,int mode)1205 gaiaCloneGeomCollSpecial (gaiaGeomCollPtr geom, int mode)
1206 {
1207 /* clones a GEOMETRYCOLLECTION (special) */
1208 int ib;
1209 gaiaPointPtr point;
1210 gaiaLinestringPtr line;
1211 gaiaLinestringPtr new_line;
1212 gaiaPolygonPtr polyg;
1213 gaiaPolygonPtr new_polyg;
1214 gaiaGeomCollPtr new_geom;
1215 gaiaRingPtr i_ring;
1216 gaiaRingPtr o_ring;
1217 if (!geom)
1218 return NULL;
1219 if (mode == GAIA_REVERSE_ORDER || mode == GAIA_CW_ORDER
1220 || mode == GAIA_CCW_ORDER)
1221 ;
1222 else
1223 return gaiaCloneGeomColl (geom);
1224
1225 if (geom->DimensionModel == GAIA_XY_Z)
1226 new_geom = gaiaAllocGeomCollXYZ ();
1227 else if (geom->DimensionModel == GAIA_XY_M)
1228 new_geom = gaiaAllocGeomCollXYM ();
1229 else if (geom->DimensionModel == GAIA_XY_Z_M)
1230 new_geom = gaiaAllocGeomCollXYZM ();
1231 else
1232 new_geom = gaiaAllocGeomColl ();
1233 new_geom->Srid = geom->Srid;
1234 new_geom->DeclaredType = geom->DeclaredType;
1235 point = geom->FirstPoint;
1236 while (point)
1237 {
1238 /* copying POINTs */
1239 if (geom->DimensionModel == GAIA_XY_Z)
1240 gaiaAddPointToGeomCollXYZ (new_geom, point->X, point->Y,
1241 point->Z);
1242 else if (geom->DimensionModel == GAIA_XY_M)
1243 gaiaAddPointToGeomCollXYM (new_geom, point->X, point->Y,
1244 point->M);
1245 else if (geom->DimensionModel == GAIA_XY_Z_M)
1246 gaiaAddPointToGeomCollXYZM (new_geom, point->X, point->Y,
1247 point->Z, point->M);
1248 else
1249 gaiaAddPointToGeomColl (new_geom, point->X, point->Y);
1250 point = point->Next;
1251 }
1252 line = geom->FirstLinestring;
1253 while (line)
1254 {
1255 /* copying LINESTRINGs */
1256 new_line = gaiaAddLinestringToGeomColl (new_geom, line->Points);
1257 if (mode == GAIA_REVERSE_ORDER)
1258 gaiaCopyLinestringCoordsReverse (new_line, line);
1259 else
1260 gaiaCopyLinestringCoords (new_line, line);
1261 line = line->Next;
1262 }
1263 polyg = geom->FirstPolygon;
1264 while (polyg)
1265 {
1266 /* copying POLYGONs */
1267 i_ring = polyg->Exterior;
1268 new_polyg =
1269 gaiaAddPolygonToGeomColl (new_geom, i_ring->Points,
1270 polyg->NumInteriors);
1271 o_ring = new_polyg->Exterior;
1272 /* copying points for the EXTERIOR RING */
1273 if (mode == GAIA_REVERSE_ORDER)
1274 gaiaCopyRingCoordsReverse (o_ring, i_ring);
1275 else
1276 {
1277 gaiaClockwise (i_ring);
1278 if (mode == GAIA_CCW_ORDER)
1279 {
1280 /* Counter-Clockwise Polygon */
1281 if (i_ring->Clockwise)
1282 gaiaCopyRingCoordsReverse (o_ring, i_ring);
1283 else
1284 gaiaCopyRingCoords (o_ring, i_ring);
1285 }
1286 else
1287 {
1288 /* Clockwise Polygon */
1289 if (i_ring->Clockwise)
1290 gaiaCopyRingCoords (o_ring, i_ring);
1291 else
1292 gaiaCopyRingCoordsReverse (o_ring, i_ring);
1293 }
1294 }
1295 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
1296 {
1297 /* copying each INTERIOR RING [if any] */
1298 i_ring = polyg->Interiors + ib;
1299 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
1300 if (mode == GAIA_REVERSE_ORDER)
1301 gaiaCopyRingCoordsReverse (o_ring, i_ring);
1302 else
1303 {
1304 gaiaClockwise (i_ring);
1305 if (mode == GAIA_CCW_ORDER)
1306 {
1307 /* Counter-Clockwise Polygon */
1308 if (i_ring->Clockwise)
1309 gaiaCopyRingCoords (o_ring, i_ring);
1310 else
1311 gaiaCopyRingCoordsReverse (o_ring, i_ring);
1312 }
1313 else
1314 {
1315 /* Clockwise Polygon */
1316 if (i_ring->Clockwise)
1317 gaiaCopyRingCoordsReverse (o_ring, i_ring);
1318 else
1319 gaiaCopyRingCoords (o_ring, i_ring);
1320 }
1321 }
1322 }
1323 polyg = polyg->Next;
1324 }
1325 return new_geom;
1326 }
1327
1328 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCloneGeomCollPoints(gaiaGeomCollPtr geom)1329 gaiaCloneGeomCollPoints (gaiaGeomCollPtr geom)
1330 {
1331 /* clones a GEOMETRYCOLLECTION (Points only) */
1332 gaiaPointPtr point;
1333 gaiaGeomCollPtr new_geom;
1334 if (!geom)
1335 return NULL;
1336 if (geom->DimensionModel == GAIA_XY_Z)
1337 new_geom = gaiaAllocGeomCollXYZ ();
1338 else if (geom->DimensionModel == GAIA_XY_M)
1339 new_geom = gaiaAllocGeomCollXYM ();
1340 else if (geom->DimensionModel == GAIA_XY_Z_M)
1341 new_geom = gaiaAllocGeomCollXYZM ();
1342 else
1343 new_geom = gaiaAllocGeomColl ();
1344 new_geom->Srid = geom->Srid;
1345 new_geom->DeclaredType = GAIA_MULTIPOINT;
1346 point = geom->FirstPoint;
1347 while (point)
1348 {
1349 /* copying POINTs */
1350 if (geom->DimensionModel == GAIA_XY_Z)
1351 gaiaAddPointToGeomCollXYZ (new_geom, point->X, point->Y,
1352 point->Z);
1353 else if (geom->DimensionModel == GAIA_XY_M)
1354 gaiaAddPointToGeomCollXYM (new_geom, point->X, point->Y,
1355 point->M);
1356 else if (geom->DimensionModel == GAIA_XY_Z_M)
1357 gaiaAddPointToGeomCollXYZM (new_geom, point->X, point->Y,
1358 point->Z, point->M);
1359 else
1360 gaiaAddPointToGeomColl (new_geom, point->X, point->Y);
1361 point = point->Next;
1362 }
1363 return new_geom;
1364 }
1365
1366 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCloneGeomCollLinestrings(gaiaGeomCollPtr geom)1367 gaiaCloneGeomCollLinestrings (gaiaGeomCollPtr geom)
1368 {
1369 /* clones a GEOMETRYCOLLECTION (Linestrings only) */
1370 gaiaLinestringPtr line;
1371 gaiaLinestringPtr new_line;
1372 gaiaGeomCollPtr new_geom;
1373 if (!geom)
1374 return NULL;
1375 if (geom->DimensionModel == GAIA_XY_Z)
1376 new_geom = gaiaAllocGeomCollXYZ ();
1377 else if (geom->DimensionModel == GAIA_XY_M)
1378 new_geom = gaiaAllocGeomCollXYM ();
1379 else if (geom->DimensionModel == GAIA_XY_Z_M)
1380 new_geom = gaiaAllocGeomCollXYZM ();
1381 else
1382 new_geom = gaiaAllocGeomColl ();
1383 new_geom->Srid = geom->Srid;
1384 new_geom->DeclaredType = GAIA_MULTILINESTRING;
1385 line = geom->FirstLinestring;
1386 while (line)
1387 {
1388 /* copying LINESTRINGs */
1389 new_line = gaiaAddLinestringToGeomColl (new_geom, line->Points);
1390 gaiaCopyLinestringCoords (new_line, line);
1391 line = line->Next;
1392 }
1393 return new_geom;
1394 }
1395
1396 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCloneGeomCollPolygons(gaiaGeomCollPtr geom)1397 gaiaCloneGeomCollPolygons (gaiaGeomCollPtr geom)
1398 {
1399 /* clones a GEOMETRYCOLLECTION (Polygons only) */
1400 int ib;
1401 gaiaPolygonPtr polyg;
1402 gaiaPolygonPtr new_polyg;
1403 gaiaGeomCollPtr new_geom;
1404 gaiaRingPtr i_ring;
1405 gaiaRingPtr o_ring;
1406 if (!geom)
1407 return NULL;
1408 if (geom->DimensionModel == GAIA_XY_Z)
1409 new_geom = gaiaAllocGeomCollXYZ ();
1410 else if (geom->DimensionModel == GAIA_XY_M)
1411 new_geom = gaiaAllocGeomCollXYM ();
1412 else if (geom->DimensionModel == GAIA_XY_Z_M)
1413 new_geom = gaiaAllocGeomCollXYZM ();
1414 else
1415 new_geom = gaiaAllocGeomColl ();
1416 new_geom->Srid = geom->Srid;
1417 new_geom->DeclaredType = GAIA_MULTIPOLYGON;
1418 polyg = geom->FirstPolygon;
1419 while (polyg)
1420 {
1421 /* copying POLYGONs */
1422 i_ring = polyg->Exterior;
1423 new_polyg =
1424 gaiaAddPolygonToGeomColl (new_geom, i_ring->Points,
1425 polyg->NumInteriors);
1426 o_ring = new_polyg->Exterior;
1427 /* copying points for the EXTERIOR RING */
1428 gaiaCopyRingCoords (o_ring, i_ring);
1429 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
1430 {
1431 /* copying each INTERIOR RING [if any] */
1432 i_ring = polyg->Interiors + ib;
1433 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
1434 gaiaCopyRingCoords (o_ring, i_ring);
1435 }
1436 polyg = polyg->Next;
1437 }
1438 return new_geom;
1439 }
1440
1441 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCastGeomCollToXY(gaiaGeomCollPtr geom)1442 gaiaCastGeomCollToXY (gaiaGeomCollPtr geom)
1443 {
1444 /* clones a GEOMETRYCOLLECTION converting to XY-dimensions */
1445 int ib;
1446 gaiaPointPtr point;
1447 gaiaLinestringPtr line;
1448 gaiaLinestringPtr new_line;
1449 gaiaPolygonPtr polyg;
1450 gaiaPolygonPtr new_polyg;
1451 gaiaGeomCollPtr new_geom;
1452 gaiaRingPtr i_ring;
1453 gaiaRingPtr o_ring;
1454 if (!geom)
1455 return NULL;
1456 new_geom = gaiaAllocGeomColl ();
1457 new_geom->Srid = geom->Srid;
1458 new_geom->DeclaredType = geom->DeclaredType;
1459 point = geom->FirstPoint;
1460 while (point)
1461 {
1462 /* copying POINTs */
1463 gaiaAddPointToGeomColl (new_geom, point->X, point->Y);
1464 point = point->Next;
1465 }
1466 line = geom->FirstLinestring;
1467 while (line)
1468 {
1469 /* copying LINESTRINGs */
1470 new_line = gaiaAddLinestringToGeomColl (new_geom, line->Points);
1471 gaiaCopyLinestringCoords (new_line, line);
1472 line = line->Next;
1473 }
1474 polyg = geom->FirstPolygon;
1475 while (polyg)
1476 {
1477 /* copying POLYGONs */
1478 i_ring = polyg->Exterior;
1479 new_polyg =
1480 gaiaAddPolygonToGeomColl (new_geom, i_ring->Points,
1481 polyg->NumInteriors);
1482 o_ring = new_polyg->Exterior;
1483 /* copying points for the EXTERIOR RING */
1484 gaiaCopyRingCoords (o_ring, i_ring);
1485 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
1486 {
1487 /* copying each INTERIOR RING [if any] */
1488 i_ring = polyg->Interiors + ib;
1489 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
1490 gaiaCopyRingCoords (o_ring, i_ring);
1491 }
1492 polyg = polyg->Next;
1493 }
1494 return new_geom;
1495 }
1496
1497 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCastGeomCollToXYZ(gaiaGeomCollPtr geom)1498 gaiaCastGeomCollToXYZ (gaiaGeomCollPtr geom)
1499 {
1500 /* clones a GEOMETRYCOLLECTION converting to XYZ-dimensions */
1501 return gaiaCastGeomCollToXYZnoData (geom, 0.0);
1502 }
1503
1504 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCastGeomCollToXYZnoData(gaiaGeomCollPtr geom,double no_data)1505 gaiaCastGeomCollToXYZnoData (gaiaGeomCollPtr geom, double no_data)
1506 {
1507 /* clones a GEOMETRYCOLLECTION converting to XYZ-dimensions */
1508 int ib;
1509 gaiaPointPtr point;
1510 gaiaLinestringPtr line;
1511 gaiaLinestringPtr new_line;
1512 gaiaPolygonPtr polyg;
1513 gaiaPolygonPtr new_polyg;
1514 gaiaGeomCollPtr new_geom;
1515 gaiaRingPtr i_ring;
1516 gaiaRingPtr o_ring;
1517 int has_z = 0;
1518 if (!geom)
1519 return NULL;
1520 if (geom->DimensionModel == GAIA_XY_Z
1521 || geom->DimensionModel == GAIA_XY_Z_M)
1522 has_z = 1;
1523 new_geom = gaiaAllocGeomCollXYZ ();
1524 new_geom->Srid = geom->Srid;
1525 new_geom->DeclaredType = geom->DeclaredType;
1526 point = geom->FirstPoint;
1527 while (point)
1528 {
1529 /* copying POINTs */
1530 if (has_z)
1531 gaiaAddPointToGeomCollXYZ (new_geom, point->X, point->Y,
1532 point->Z);
1533 else
1534 gaiaAddPointToGeomCollXYZ (new_geom, point->X, point->Y, no_data);
1535 point = point->Next;
1536 }
1537 line = geom->FirstLinestring;
1538 while (line)
1539 {
1540 /* copying LINESTRINGs */
1541 new_line = gaiaAddLinestringToGeomColl (new_geom, line->Points);
1542 gaiaCopyLinestringCoordsEx (new_line, line, no_data, 0.0);
1543 line = line->Next;
1544 }
1545 polyg = geom->FirstPolygon;
1546 while (polyg)
1547 {
1548 /* copying POLYGONs */
1549 i_ring = polyg->Exterior;
1550 new_polyg =
1551 gaiaAddPolygonToGeomColl (new_geom, i_ring->Points,
1552 polyg->NumInteriors);
1553 o_ring = new_polyg->Exterior;
1554 /* copying points for the EXTERIOR RING */
1555 gaiaCopyRingCoordsEx (o_ring, i_ring, no_data, 0.0);
1556 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
1557 {
1558 /* copying each INTERIOR RING [if any] */
1559 i_ring = polyg->Interiors + ib;
1560 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
1561 gaiaCopyRingCoordsEx (o_ring, i_ring, no_data, 0.0);
1562 }
1563 polyg = polyg->Next;
1564 }
1565 return new_geom;
1566 }
1567
1568 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCastGeomCollToXYM(gaiaGeomCollPtr geom)1569 gaiaCastGeomCollToXYM (gaiaGeomCollPtr geom)
1570 {
1571 /* clones a GEOMETRYCOLLECTION converting to XYM-dimensions */
1572 return gaiaCastGeomCollToXYMnoData (geom, 0.0);
1573 }
1574
1575 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCastGeomCollToXYMnoData(gaiaGeomCollPtr geom,double no_data)1576 gaiaCastGeomCollToXYMnoData (gaiaGeomCollPtr geom, double no_data)
1577 {
1578 /* clones a GEOMETRYCOLLECTION converting to XYM-dimensions */
1579 int ib;
1580 gaiaPointPtr point;
1581 gaiaLinestringPtr line;
1582 gaiaLinestringPtr new_line;
1583 gaiaPolygonPtr polyg;
1584 gaiaPolygonPtr new_polyg;
1585 gaiaGeomCollPtr new_geom;
1586 gaiaRingPtr i_ring;
1587 gaiaRingPtr o_ring;
1588 int has_m = 0;
1589 if (!geom)
1590 return NULL;
1591 if (geom->DimensionModel == GAIA_XY_M
1592 || geom->DimensionModel == GAIA_XY_Z_M)
1593 has_m = 1;
1594 new_geom = gaiaAllocGeomCollXYM ();
1595 new_geom->Srid = geom->Srid;
1596 new_geom->DeclaredType = geom->DeclaredType;
1597 point = geom->FirstPoint;
1598 while (point)
1599 {
1600 /* copying POINTs */
1601 if (has_m)
1602 gaiaAddPointToGeomCollXYM (new_geom, point->X, point->Y,
1603 point->M);
1604 else
1605 gaiaAddPointToGeomCollXYM (new_geom, point->X, point->Y, no_data);
1606 point = point->Next;
1607 }
1608 line = geom->FirstLinestring;
1609 while (line)
1610 {
1611 /* copying LINESTRINGs */
1612 new_line = gaiaAddLinestringToGeomColl (new_geom, line->Points);
1613 gaiaCopyLinestringCoordsEx (new_line, line, 0.0, no_data);
1614 line = line->Next;
1615 }
1616 polyg = geom->FirstPolygon;
1617 while (polyg)
1618 {
1619 /* copying POLYGONs */
1620 i_ring = polyg->Exterior;
1621 new_polyg =
1622 gaiaAddPolygonToGeomColl (new_geom, i_ring->Points,
1623 polyg->NumInteriors);
1624 o_ring = new_polyg->Exterior;
1625 /* copying points for the EXTERIOR RING */
1626 gaiaCopyRingCoordsEx (o_ring, i_ring, 0.0, no_data);
1627 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
1628 {
1629 /* copying each INTERIOR RING [if any] */
1630 i_ring = polyg->Interiors + ib;
1631 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
1632 gaiaCopyRingCoordsEx (o_ring, i_ring, 0.0, no_data);
1633 }
1634 polyg = polyg->Next;
1635 }
1636 return new_geom;
1637 }
1638
1639 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCastGeomCollToXYZM(gaiaGeomCollPtr geom)1640 gaiaCastGeomCollToXYZM (gaiaGeomCollPtr geom)
1641 {
1642 /* clones a GEOMETRYCOLLECTION converting to XYZM-dimensions */
1643 return gaiaCastGeomCollToXYZMnoData (geom, 0.0, 0.0);
1644 }
1645
1646 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaCastGeomCollToXYZMnoData(gaiaGeomCollPtr geom,double z_no_data,double m_no_data)1647 gaiaCastGeomCollToXYZMnoData (gaiaGeomCollPtr geom, double z_no_data,
1648 double m_no_data)
1649 {
1650 /* clones a GEOMETRYCOLLECTION converting to XYZM-dimensions */
1651 int ib;
1652 gaiaPointPtr point;
1653 gaiaLinestringPtr line;
1654 gaiaLinestringPtr new_line;
1655 gaiaPolygonPtr polyg;
1656 gaiaPolygonPtr new_polyg;
1657 gaiaGeomCollPtr new_geom;
1658 gaiaRingPtr i_ring;
1659 gaiaRingPtr o_ring;
1660 int has_z = 0;
1661 int has_m = 0;
1662 if (!geom)
1663 return NULL;
1664 if (geom->DimensionModel == GAIA_XY_Z
1665 || geom->DimensionModel == GAIA_XY_Z_M)
1666 has_z = 1;
1667 if (geom->DimensionModel == GAIA_XY_M
1668 || geom->DimensionModel == GAIA_XY_Z_M)
1669 has_m = 1;
1670 new_geom = gaiaAllocGeomCollXYZM ();
1671 new_geom->Srid = geom->Srid;
1672 new_geom->DeclaredType = geom->DeclaredType;
1673 point = geom->FirstPoint;
1674 while (point)
1675 {
1676 /* copying POINTs */
1677 if (has_z && has_m)
1678 gaiaAddPointToGeomCollXYZM (new_geom, point->X, point->Y,
1679 point->Z, point->M);
1680 else if (has_z)
1681 gaiaAddPointToGeomCollXYZM (new_geom, point->X, point->Y,
1682 point->Z, m_no_data);
1683 else if (has_m)
1684 gaiaAddPointToGeomCollXYZM (new_geom, point->X, point->Y,
1685 z_no_data, point->M);
1686 else
1687 gaiaAddPointToGeomCollXYZM (new_geom, point->X, point->Y,
1688 z_no_data, m_no_data);
1689 point = point->Next;
1690 }
1691 line = geom->FirstLinestring;
1692 while (line)
1693 {
1694 /* copying LINESTRINGs */
1695 new_line = gaiaAddLinestringToGeomColl (new_geom, line->Points);
1696 gaiaCopyLinestringCoordsEx (new_line, line, z_no_data, m_no_data);
1697 line = line->Next;
1698 }
1699 polyg = geom->FirstPolygon;
1700 while (polyg)
1701 {
1702 /* copying POLYGONs */
1703 i_ring = polyg->Exterior;
1704 new_polyg =
1705 gaiaAddPolygonToGeomColl (new_geom, i_ring->Points,
1706 polyg->NumInteriors);
1707 o_ring = new_polyg->Exterior;
1708 /* copying points for the EXTERIOR RING */
1709 gaiaCopyRingCoordsEx (o_ring, i_ring, z_no_data, m_no_data);
1710 for (ib = 0; ib < new_polyg->NumInteriors; ib++)
1711 {
1712 /* copying each INTERIOR RING [if any] */
1713 i_ring = polyg->Interiors + ib;
1714 o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points);
1715 gaiaCopyRingCoordsEx (o_ring, i_ring, z_no_data, m_no_data);
1716 }
1717 polyg = polyg->Next;
1718 }
1719 return new_geom;
1720 }
1721
1722 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaAllocGeomColl()1723 gaiaAllocGeomColl ()
1724 {
1725 /* GEOMETRYCOLLECTION object constructor */
1726 gaiaGeomCollPtr p = malloc (sizeof (gaiaGeomColl));
1727 p->Srid = 0;
1728 p->endian = ' ';
1729 p->offset = 0;
1730 p->FirstPoint = NULL;
1731 p->LastPoint = NULL;
1732 p->FirstLinestring = NULL;
1733 p->LastLinestring = NULL;
1734 p->FirstPolygon = NULL;
1735 p->LastPolygon = NULL;
1736 p->MinX = DBL_MAX;
1737 p->MinY = DBL_MAX;
1738 p->MaxX = -DBL_MAX;
1739 p->MaxY = -DBL_MAX;
1740 p->DimensionModel = GAIA_XY;
1741 p->DeclaredType = GAIA_UNKNOWN;
1742 p->Next = NULL;
1743 return p;
1744 }
1745
1746 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaAllocGeomCollXYZ()1747 gaiaAllocGeomCollXYZ ()
1748 {
1749 /* GEOMETRYCOLLECTION object constructor */
1750 gaiaGeomCollPtr p = malloc (sizeof (gaiaGeomColl));
1751 p->Srid = 0;
1752 p->endian = ' ';
1753 p->offset = 0;
1754 p->FirstPoint = NULL;
1755 p->LastPoint = NULL;
1756 p->FirstLinestring = NULL;
1757 p->LastLinestring = NULL;
1758 p->FirstPolygon = NULL;
1759 p->LastPolygon = NULL;
1760 p->MinX = DBL_MAX;
1761 p->MinY = DBL_MAX;
1762 p->MaxX = -DBL_MAX;
1763 p->MaxY = -DBL_MAX;
1764 p->DimensionModel = GAIA_XY_Z;
1765 p->DeclaredType = GAIA_UNKNOWN;
1766 p->Next = NULL;
1767 return p;
1768 }
1769
1770 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaAllocGeomCollXYM()1771 gaiaAllocGeomCollXYM ()
1772 {
1773 /* GEOMETRYCOLLECTION object constructor */
1774 gaiaGeomCollPtr p = malloc (sizeof (gaiaGeomColl));
1775 p->Srid = 0;
1776 p->endian = ' ';
1777 p->offset = 0;
1778 p->FirstPoint = NULL;
1779 p->LastPoint = NULL;
1780 p->FirstLinestring = NULL;
1781 p->LastLinestring = NULL;
1782 p->FirstPolygon = NULL;
1783 p->LastPolygon = NULL;
1784 p->MinX = DBL_MAX;
1785 p->MinY = DBL_MAX;
1786 p->MaxX = -DBL_MAX;
1787 p->MaxY = -DBL_MAX;
1788 p->DimensionModel = GAIA_XY_M;
1789 p->DeclaredType = GAIA_UNKNOWN;
1790 p->Next = NULL;
1791 return p;
1792 }
1793
1794 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaAllocGeomCollXYZM()1795 gaiaAllocGeomCollXYZM ()
1796 {
1797 /* GEOMETRYCOLLECTION object constructor */
1798 gaiaGeomCollPtr p = malloc (sizeof (gaiaGeomColl));
1799 p->Srid = 0;
1800 p->endian = ' ';
1801 p->offset = 0;
1802 p->FirstPoint = NULL;
1803 p->LastPoint = NULL;
1804 p->FirstLinestring = NULL;
1805 p->LastLinestring = NULL;
1806 p->FirstPolygon = NULL;
1807 p->LastPolygon = NULL;
1808 p->MinX = DBL_MAX;
1809 p->MinY = DBL_MAX;
1810 p->MaxX = -DBL_MAX;
1811 p->MaxY = -DBL_MAX;
1812 p->DimensionModel = GAIA_XY_Z_M;
1813 p->DeclaredType = GAIA_UNKNOWN;
1814 p->Next = NULL;
1815 return p;
1816 }
1817
1818 GAIAGEO_DECLARE void
gaiaFreeGeomColl(gaiaGeomCollPtr p)1819 gaiaFreeGeomColl (gaiaGeomCollPtr p)
1820 {
1821 /* GEOMETRYCOLLECTION object destructor */
1822 gaiaPointPtr pP;
1823 gaiaPointPtr pPn;
1824 gaiaLinestringPtr pL;
1825 gaiaLinestringPtr pLn;
1826 gaiaPolygonPtr pA;
1827 gaiaPolygonPtr pAn;
1828 if (!p)
1829 return;
1830 pP = p->FirstPoint;
1831 while (pP != NULL)
1832 {
1833 pPn = pP->Next;
1834 gaiaFreePoint (pP);
1835 pP = pPn;
1836 }
1837 pL = p->FirstLinestring;
1838 while (pL != NULL)
1839 {
1840 pLn = pL->Next;
1841 gaiaFreeLinestring (pL);
1842 pL = pLn;
1843 }
1844 pA = p->FirstPolygon;
1845 while (pA != NULL)
1846 {
1847 pAn = pA->Next;
1848 gaiaFreePolygon (pA);
1849 pA = pAn;
1850 }
1851 free (p);
1852 }
1853
1854 GAIAGEO_DECLARE void
gaiaAddPointToGeomColl(gaiaGeomCollPtr p,double x,double y)1855 gaiaAddPointToGeomColl (gaiaGeomCollPtr p, double x, double y)
1856 {
1857 /* adding a POINT to this GEOMETRYCOLLECTION */
1858 gaiaPointPtr point = gaiaAllocPoint (x, y);
1859 if (p->FirstPoint == NULL)
1860 p->FirstPoint = point;
1861 if (p->LastPoint != NULL)
1862 p->LastPoint->Next = point;
1863 p->LastPoint = point;
1864 }
1865
1866 GAIAGEO_DECLARE void
gaiaAddPointToGeomCollXYZ(gaiaGeomCollPtr p,double x,double y,double z)1867 gaiaAddPointToGeomCollXYZ (gaiaGeomCollPtr p, double x, double y, double z)
1868 {
1869 /* adding a POINT to this GEOMETRYCOLLECTION */
1870 gaiaPointPtr point = gaiaAllocPointXYZ (x, y, z);
1871 if (p->FirstPoint == NULL)
1872 p->FirstPoint = point;
1873 if (p->LastPoint != NULL)
1874 p->LastPoint->Next = point;
1875 p->LastPoint = point;
1876 }
1877
1878 GAIAGEO_DECLARE void
gaiaAddPointToGeomCollXYM(gaiaGeomCollPtr p,double x,double y,double m)1879 gaiaAddPointToGeomCollXYM (gaiaGeomCollPtr p, double x, double y, double m)
1880 {
1881 /* adding a POINT to this GEOMETRYCOLLECTION */
1882 gaiaPointPtr point = gaiaAllocPointXYM (x, y, m);
1883 if (p->FirstPoint == NULL)
1884 p->FirstPoint = point;
1885 if (p->LastPoint != NULL)
1886 p->LastPoint->Next = point;
1887 p->LastPoint = point;
1888 }
1889
1890 GAIAGEO_DECLARE void
gaiaAddPointToGeomCollXYZM(gaiaGeomCollPtr p,double x,double y,double z,double m)1891 gaiaAddPointToGeomCollXYZM (gaiaGeomCollPtr p, double x, double y, double z,
1892 double m)
1893 {
1894 /* adding a POINT to this GEOMETRYCOLLECTION */
1895 gaiaPointPtr point = gaiaAllocPointXYZM (x, y, z, m);
1896 if (p->FirstPoint == NULL)
1897 p->FirstPoint = point;
1898 if (p->LastPoint != NULL)
1899 p->LastPoint->Next = point;
1900 p->LastPoint = point;
1901 }
1902
1903 GAIAGEO_DECLARE gaiaLinestringPtr
gaiaAddLinestringToGeomColl(gaiaGeomCollPtr p,int vert)1904 gaiaAddLinestringToGeomColl (gaiaGeomCollPtr p, int vert)
1905 {
1906 /* adding a LINESTRING to this GEOMETRYCOLLECTION */
1907 gaiaLinestringPtr line;
1908 if (p->DimensionModel == GAIA_XY_Z)
1909 line = gaiaAllocLinestringXYZ (vert);
1910 else if (p->DimensionModel == GAIA_XY_M)
1911 line = gaiaAllocLinestringXYM (vert);
1912 else if (p->DimensionModel == GAIA_XY_Z_M)
1913 line = gaiaAllocLinestringXYZM (vert);
1914 else
1915 line = gaiaAllocLinestring (vert);
1916 if (p->FirstLinestring == NULL)
1917 p->FirstLinestring = line;
1918 if (p->LastLinestring != NULL)
1919 p->LastLinestring->Next = line;
1920 p->LastLinestring = line;
1921 return line;
1922 }
1923
1924 GAIAGEO_DECLARE void
gaiaInsertLinestringInGeomColl(gaiaGeomCollPtr p,gaiaLinestringPtr line)1925 gaiaInsertLinestringInGeomColl (gaiaGeomCollPtr p, gaiaLinestringPtr line)
1926 {
1927 /* adding an existing LINESTRING to this GEOMETRYCOLLECTION */
1928 if (p->FirstLinestring == NULL)
1929 p->FirstLinestring = line;
1930 if (p->LastLinestring != NULL)
1931 p->LastLinestring->Next = line;
1932 p->LastLinestring = line;
1933 }
1934
1935 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaAddPolygonToGeomColl(gaiaGeomCollPtr p,int vert,int interiors)1936 gaiaAddPolygonToGeomColl (gaiaGeomCollPtr p, int vert, int interiors)
1937 {
1938 /* adding a POLYGON to this GEOMETRYCOLLECTION */
1939 gaiaPolygonPtr polyg;
1940 if (p->DimensionModel == GAIA_XY_Z)
1941 polyg = gaiaAllocPolygonXYZ (vert, interiors);
1942 else if (p->DimensionModel == GAIA_XY_M)
1943 polyg = gaiaAllocPolygonXYM (vert, interiors);
1944 else if (p->DimensionModel == GAIA_XY_Z_M)
1945 polyg = gaiaAllocPolygonXYZM (vert, interiors);
1946 else
1947 polyg = gaiaAllocPolygon (vert, interiors);
1948 if (p->FirstPolygon == NULL)
1949 p->FirstPolygon = polyg;
1950 if (p->LastPolygon != NULL)
1951 p->LastPolygon->Next = polyg;
1952 p->LastPolygon = polyg;
1953 return polyg;
1954 }
1955
1956 GAIAGEO_DECLARE gaiaPolygonPtr
gaiaInsertPolygonInGeomColl(gaiaGeomCollPtr p,gaiaRingPtr ring)1957 gaiaInsertPolygonInGeomColl (gaiaGeomCollPtr p, gaiaRingPtr ring)
1958 {
1959 /* adding a POLYGON to this GEOMETRYCOLLECTION */
1960 gaiaPolygonPtr polyg;
1961 polyg = malloc (sizeof (gaiaPolygon));
1962 polyg->Exterior = ring;
1963 polyg->NumInteriors = 0;
1964 polyg->NextInterior = 0;
1965 polyg->DimensionModel = ring->DimensionModel;
1966 polyg->Next = NULL;
1967 polyg->Interiors = NULL;
1968 polyg->MinX = DBL_MAX;
1969 polyg->MinY = DBL_MAX;
1970 polyg->MaxX = -DBL_MAX;
1971 polyg->MaxY = -DBL_MAX;
1972 if (p->FirstPolygon == NULL)
1973 p->FirstPolygon = polyg;
1974 if (p->LastPolygon != NULL)
1975 p->LastPolygon->Next = polyg;
1976 p->LastPolygon = polyg;
1977 return polyg;
1978 }
1979
1980 GAIAGEO_DECLARE gaiaRingPtr
gaiaAddInteriorRing(gaiaPolygonPtr p,int pos,int vert)1981 gaiaAddInteriorRing (gaiaPolygonPtr p, int pos, int vert)
1982 {
1983 /* adding an interior ring to some polygon */
1984 gaiaRingPtr pP = p->Interiors + pos;
1985 pP->Points = vert;
1986 pP->DimensionModel = p->DimensionModel;
1987 if (pP->DimensionModel == GAIA_XY_Z)
1988 pP->Coords = malloc (sizeof (double) * (vert * 3));
1989 else if (pP->DimensionModel == GAIA_XY_M)
1990 pP->Coords = malloc (sizeof (double) * (vert * 3));
1991 else if (pP->DimensionModel == GAIA_XY_Z_M)
1992 pP->Coords = malloc (sizeof (double) * (vert * 4));
1993 else
1994 pP->Coords = malloc (sizeof (double) * (vert * 2));
1995 return pP;
1996 }
1997
1998 GAIAGEO_DECLARE void
gaiaInsertInteriorRing(gaiaPolygonPtr p,gaiaRingPtr ring)1999 gaiaInsertInteriorRing (gaiaPolygonPtr p, gaiaRingPtr ring)
2000 {
2001 /* adding an interior ring to some polygon */
2002 gaiaRingPtr hole;
2003 if (p->NumInteriors == 0)
2004 {
2005 /* this one is the first interior ring */
2006 p->NumInteriors++;
2007 p->Interiors = malloc (sizeof (gaiaRing));
2008 hole = p->Interiors;
2009 }
2010 else
2011 {
2012 /* some interior ring is already defined */
2013 gaiaRingPtr save = p->Interiors;
2014 p->Interiors = malloc (sizeof (gaiaRing) * (p->NumInteriors + 1));
2015 memcpy (p->Interiors, save, (sizeof (gaiaRing) * p->NumInteriors));
2016 free (save);
2017 hole = p->Interiors + p->NumInteriors;
2018 p->NumInteriors++;
2019 }
2020 hole->Points = ring->Points;
2021 hole->DimensionModel = p->DimensionModel;
2022 if (hole->DimensionModel == GAIA_XY_Z)
2023 hole->Coords = malloc (sizeof (double) * (hole->Points * 3));
2024 else if (hole->DimensionModel == GAIA_XY_M)
2025 hole->Coords = malloc (sizeof (double) * (hole->Points * 3));
2026 else if (hole->DimensionModel == GAIA_XY_Z_M)
2027 hole->Coords = malloc (sizeof (double) * (hole->Points * 4));
2028 else
2029 hole->Coords = malloc (sizeof (double) * (hole->Points * 2));
2030 gaiaCopyRingCoords (hole, ring);
2031 }
2032
2033 GAIAGEO_DECLARE void
gaiaAddRingToPolyg(gaiaPolygonPtr polyg,gaiaRingPtr ring)2034 gaiaAddRingToPolyg (gaiaPolygonPtr polyg, gaiaRingPtr ring)
2035 {
2036 /* adds an interior ring to this POLYGON */
2037 gaiaRingPtr old_interiors = NULL;
2038 if (!(polyg->Interiors))
2039 {
2040 /* this one is the first interior ring */
2041 polyg->Interiors = ring;
2042 polyg->NumInteriors = 1;
2043 }
2044 else
2045 {
2046 /* adding another interior ring */
2047 old_interiors = polyg->Interiors;
2048 polyg->Interiors =
2049 malloc (sizeof (gaiaRing) * (polyg->NumInteriors + 1));
2050 memcpy (polyg->Interiors, old_interiors,
2051 (sizeof (gaiaRing) * polyg->NumInteriors));
2052 memcpy (polyg->Interiors + polyg->NumInteriors, ring,
2053 sizeof (gaiaRing));
2054 (polyg->NumInteriors)++;
2055 free (old_interiors);
2056 free (ring);
2057 }
2058 }
2059
2060 GAIAGEO_DECLARE gaiaDynamicLinePtr
gaiaAllocDynamicLine()2061 gaiaAllocDynamicLine ()
2062 {
2063 /* DYNAMIC LINE object constructor */
2064 gaiaDynamicLinePtr p = malloc (sizeof (gaiaDynamicLine));
2065 p->Error = 0;
2066 p->Srid = 0;
2067 p->First = NULL;
2068 p->Last = NULL;
2069 return p;
2070 }
2071
2072 GAIAGEO_DECLARE void
gaiaFreeDynamicLine(gaiaDynamicLinePtr p)2073 gaiaFreeDynamicLine (gaiaDynamicLinePtr p)
2074 {
2075 /* DYNAMIC LINE object destructor */
2076 gaiaPointPtr pP;
2077 gaiaPointPtr pPn;
2078 pP = p->First;
2079 while (pP != NULL)
2080 {
2081 pPn = pP->Next;
2082 gaiaFreePoint (pP);
2083 pP = pPn;
2084 }
2085 free (p);
2086 }
2087
2088 GAIAGEO_DECLARE gaiaPointPtr
gaiaAppendPointToDynamicLine(gaiaDynamicLinePtr p,double x,double y)2089 gaiaAppendPointToDynamicLine (gaiaDynamicLinePtr p, double x, double y)
2090 {
2091 /* inserts a new POINT to this DYNAMIC LINE after the last one */
2092 gaiaPointPtr point = gaiaAllocPoint (x, y);
2093 point->Prev = p->Last;
2094 if (p->First == NULL)
2095 p->First = point;
2096 if (p->Last != NULL)
2097 p->Last->Next = point;
2098 p->Last = point;
2099 return point;
2100 }
2101
2102 GAIAGEO_DECLARE gaiaPointPtr
gaiaAppendPointZToDynamicLine(gaiaDynamicLinePtr p,double x,double y,double z)2103 gaiaAppendPointZToDynamicLine (gaiaDynamicLinePtr p, double x, double y,
2104 double z)
2105 {
2106 /* inserts a new POINT to this DYNAMIC LINE after the last one */
2107 gaiaPointPtr point = gaiaAllocPointXYZ (x, y, z);
2108 point->Prev = p->Last;
2109 if (p->First == NULL)
2110 p->First = point;
2111 if (p->Last != NULL)
2112 p->Last->Next = point;
2113 p->Last = point;
2114 return point;
2115 }
2116
2117 GAIAGEO_DECLARE gaiaPointPtr
gaiaAppendPointMToDynamicLine(gaiaDynamicLinePtr p,double x,double y,double m)2118 gaiaAppendPointMToDynamicLine (gaiaDynamicLinePtr p, double x, double y,
2119 double m)
2120 {
2121 /* inserts a new POINT to this DYNAMIC LINE after the last one */
2122 gaiaPointPtr point = gaiaAllocPointXYM (x, y, m);
2123 point->Prev = p->Last;
2124 if (p->First == NULL)
2125 p->First = point;
2126 if (p->Last != NULL)
2127 p->Last->Next = point;
2128 p->Last = point;
2129 return point;
2130 }
2131
2132 GAIAGEO_DECLARE gaiaPointPtr
gaiaAppendPointZMToDynamicLine(gaiaDynamicLinePtr p,double x,double y,double z,double m)2133 gaiaAppendPointZMToDynamicLine (gaiaDynamicLinePtr p, double x, double y,
2134 double z, double m)
2135 {
2136 /* inserts a new POINT to this DYNAMIC LINE after the last one */
2137 gaiaPointPtr point = gaiaAllocPointXYZM (x, y, z, m);
2138 point->Prev = p->Last;
2139 if (p->First == NULL)
2140 p->First = point;
2141 if (p->Last != NULL)
2142 p->Last->Next = point;
2143 p->Last = point;
2144 return point;
2145 }
2146
2147 GAIAGEO_DECLARE gaiaPointPtr
gaiaPrependPointToDynamicLine(gaiaDynamicLinePtr p,double x,double y)2148 gaiaPrependPointToDynamicLine (gaiaDynamicLinePtr p, double x, double y)
2149 {
2150 /* inserts a new POINT to this DYNAMIC LINE before the first one */
2151 gaiaPointPtr point = gaiaAllocPoint (x, y);
2152 point->Next = p->First;
2153 if (p->Last == NULL)
2154 p->Last = point;
2155 if (p->First != NULL)
2156 p->First->Prev = point;
2157 p->First = point;
2158 return point;
2159 }
2160
2161 GAIAGEO_DECLARE gaiaPointPtr
gaiaPrependPointZToDynamicLine(gaiaDynamicLinePtr p,double x,double y,double z)2162 gaiaPrependPointZToDynamicLine (gaiaDynamicLinePtr p, double x, double y,
2163 double z)
2164 {
2165 /* inserts a new POINT to this DYNAMIC LINE before the first one */
2166 gaiaPointPtr point = gaiaAllocPointXYZ (x, y, z);
2167 point->Next = p->First;
2168 if (p->Last == NULL)
2169 p->Last = point;
2170 if (p->First != NULL)
2171 p->First->Prev = point;
2172 p->First = point;
2173 return point;
2174 }
2175
2176 GAIAGEO_DECLARE gaiaPointPtr
gaiaPrependPointMToDynamicLine(gaiaDynamicLinePtr p,double x,double y,double m)2177 gaiaPrependPointMToDynamicLine (gaiaDynamicLinePtr p, double x, double y,
2178 double m)
2179 {
2180 /* inserts a new POINT to this DYNAMIC LINE before the first one */
2181 gaiaPointPtr point = gaiaAllocPointXYM (x, y, m);
2182 point->Next = p->First;
2183 if (p->Last == NULL)
2184 p->Last = point;
2185 if (p->First != NULL)
2186 p->First->Prev = point;
2187 p->First = point;
2188 return point;
2189 }
2190
2191 GAIAGEO_DECLARE gaiaPointPtr
gaiaPrependPointZMToDynamicLine(gaiaDynamicLinePtr p,double x,double y,double z,double m)2192 gaiaPrependPointZMToDynamicLine (gaiaDynamicLinePtr p, double x, double y,
2193 double z, double m)
2194 {
2195 /* inserts a new POINT to this DYNAMIC LINE before the first one */
2196 gaiaPointPtr point = gaiaAllocPointXYZM (x, y, z, m);
2197 point->Next = p->First;
2198 if (p->Last == NULL)
2199 p->Last = point;
2200 if (p->First != NULL)
2201 p->First->Prev = point;
2202 p->First = point;
2203 return point;
2204 }
2205
2206 GAIAGEO_DECLARE gaiaPointPtr
gaiaDynamicLineInsertAfter(gaiaDynamicLinePtr p,gaiaPointPtr pt,double x,double y)2207 gaiaDynamicLineInsertAfter (gaiaDynamicLinePtr p, gaiaPointPtr pt, double x,
2208 double y)
2209 {
2210 /* inserts a new POINT to this DYNAMIC LINE after the referenced POINT */
2211 gaiaPointPtr point = gaiaAllocPoint (x, y);
2212 point->Prev = pt;
2213 point->Next = pt->Next;
2214 if (pt->Next)
2215 pt->Next->Prev = point;
2216 pt->Next = point;
2217 if (pt == p->Last)
2218 p->Last = point;
2219 return point;
2220 }
2221
2222 GAIAGEO_DECLARE gaiaPointPtr
gaiaDynamicLineInsertBefore(gaiaDynamicLinePtr p,gaiaPointPtr pt,double x,double y)2223 gaiaDynamicLineInsertBefore (gaiaDynamicLinePtr p, gaiaPointPtr pt, double x,
2224 double y)
2225 {
2226 /* inserts a new POINT to this DYNAMIC LINE before the referenced POINT */
2227 gaiaPointPtr point = gaiaAllocPoint (x, y);
2228 point->Next = pt;
2229 point->Prev = pt->Prev;
2230 if (pt->Prev)
2231 pt->Prev->Next = point;
2232 pt->Prev = point;
2233 if (pt == p->First)
2234 p->First = point;
2235 return point;
2236 }
2237
2238 GAIAGEO_DECLARE void
gaiaDynamicLineDeletePoint(gaiaDynamicLinePtr p,gaiaPointPtr pt)2239 gaiaDynamicLineDeletePoint (gaiaDynamicLinePtr p, gaiaPointPtr pt)
2240 {
2241 /* deletes a POINT from this DYNAMIC LINE */
2242 if (pt->Prev)
2243 pt->Prev->Next = pt->Next;
2244 if (pt->Next)
2245 pt->Next->Prev = pt->Prev;
2246 if (pt == p->First)
2247 p->First = pt->Next;
2248 if (pt == p->Last)
2249 p->Last = pt->Prev;
2250 gaiaFreePoint (pt);
2251 }
2252
2253 GAIAGEO_DECLARE gaiaDynamicLinePtr
gaiaCloneDynamicLine(gaiaDynamicLinePtr org)2254 gaiaCloneDynamicLine (gaiaDynamicLinePtr org)
2255 {
2256 /* creates a new line obtained by simply copying the current one */
2257 gaiaPointPtr pt;
2258 gaiaDynamicLinePtr dst = gaiaAllocDynamicLine ();
2259 pt = org->First;
2260 while (pt)
2261 {
2262 gaiaAppendPointToDynamicLine (dst, pt->X, pt->Y);
2263 pt = pt->Next;
2264 }
2265 return dst;
2266 }
2267
2268 GAIAGEO_DECLARE gaiaDynamicLinePtr
gaiaReverseDynamicLine(gaiaDynamicLinePtr org)2269 gaiaReverseDynamicLine (gaiaDynamicLinePtr org)
2270 {
2271 /* creates a new line obtained by inverting the current one */
2272 gaiaPointPtr pt;
2273 gaiaDynamicLinePtr dst = gaiaAllocDynamicLine ();
2274 pt = org->Last;
2275 while (pt)
2276 {
2277 gaiaAppendPointToDynamicLine (dst, pt->X, pt->Y);
2278 pt = pt->Prev;
2279 }
2280 return dst;
2281 }
2282
2283 GAIAGEO_DECLARE gaiaDynamicLinePtr
gaiaDynamicLineSplitBefore(gaiaDynamicLinePtr org,gaiaPointPtr point)2284 gaiaDynamicLineSplitBefore (gaiaDynamicLinePtr org, gaiaPointPtr point)
2285 {
2286 /* creates a new line obtained by cutting the current one in two */
2287 gaiaDynamicLinePtr dst = gaiaAllocDynamicLine ();
2288 dst->First = org->First;
2289 dst->Last = point->Prev;
2290 point->Prev->Next = NULL;
2291 org->First = point;
2292 point->Prev = NULL;
2293 return dst;
2294 }
2295
2296 GAIAGEO_DECLARE gaiaDynamicLinePtr
gaiaDynamicLineSplitAfter(gaiaDynamicLinePtr org,gaiaPointPtr point)2297 gaiaDynamicLineSplitAfter (gaiaDynamicLinePtr org, gaiaPointPtr point)
2298 {
2299 /* creates a new line obtained by cutting the current one in two */
2300 gaiaDynamicLinePtr dst = gaiaAllocDynamicLine ();
2301 dst->First = point->Next;
2302 dst->Last = org->Last;
2303 point->Next->Prev = NULL;
2304 org->Last = point;
2305 point->Next = NULL;
2306 return dst;
2307 }
2308
2309 GAIAGEO_DECLARE gaiaDynamicLinePtr
gaiaDynamicLineJoinAfter(gaiaDynamicLinePtr org,gaiaPointPtr point,gaiaDynamicLinePtr toJoin)2310 gaiaDynamicLineJoinAfter (gaiaDynamicLinePtr org, gaiaPointPtr point,
2311 gaiaDynamicLinePtr toJoin)
2312 {
2313 /* creates a new line obtained by joining the current one with another one */
2314 gaiaPointPtr pt;
2315 gaiaDynamicLinePtr dst = gaiaAllocDynamicLine ();
2316 pt = org->First;
2317 while (pt)
2318 {
2319 /* inserting the first slice since the delimiting POINT included */
2320 gaiaAppendPointToDynamicLine (dst, pt->X, pt->Y);
2321 if (pt == point)
2322 break;
2323 pt = pt->Next;
2324 }
2325 pt = toJoin->First;
2326 while (pt)
2327 {
2328 /* inserting the other line */
2329 gaiaAppendPointToDynamicLine (dst, pt->X, pt->Y);
2330 pt = pt->Next;
2331 }
2332 pt = point->Next;
2333 while (pt)
2334 {
2335 /* inserting the second slice after the delimiting POINT */
2336 gaiaAppendPointToDynamicLine (dst, pt->X, pt->Y);
2337 pt = pt->Next;
2338 }
2339 return dst;
2340 }
2341
2342 GAIAGEO_DECLARE gaiaDynamicLinePtr
gaiaDynamicLineJoinBefore(gaiaDynamicLinePtr org,gaiaPointPtr point,gaiaDynamicLinePtr toJoin)2343 gaiaDynamicLineJoinBefore (gaiaDynamicLinePtr org, gaiaPointPtr point,
2344 gaiaDynamicLinePtr toJoin)
2345 {
2346 /* creates a new line obtained by joining the current one with another one */
2347 gaiaPointPtr pt;
2348 gaiaDynamicLinePtr dst = gaiaAllocDynamicLine ();
2349 pt = org->First;
2350 while (pt)
2351 {
2352 /* inserting the first slice since the delimiting POINT excluded */
2353 if (pt == point)
2354 break;
2355 gaiaAppendPointToDynamicLine (dst, pt->X, pt->Y);
2356 pt = pt->Next;
2357 }
2358 pt = toJoin->First;
2359 while (pt)
2360 {
2361 /* inserting the other line */
2362 gaiaAppendPointToDynamicLine (dst, pt->X, pt->Y);
2363 pt = pt->Next;
2364 }
2365 pt = point;
2366 while (pt)
2367 {
2368 /* inserting the second slice beginning from the delimiting POINT */
2369 gaiaAppendPointToDynamicLine (dst, pt->X, pt->Y);
2370 pt = pt->Next;
2371 }
2372 return dst;
2373 }
2374
2375 GAIAGEO_DECLARE gaiaPointPtr
gaiaDynamicLineFindByCoords(gaiaDynamicLinePtr p,double x,double y)2376 gaiaDynamicLineFindByCoords (gaiaDynamicLinePtr p, double x, double y)
2377 {
2378 /* finds a POINT inside this DYNAMIC LINE */
2379 gaiaPointPtr pP;
2380 pP = p->First;
2381 while (pP != NULL)
2382 {
2383 if (pP->X == x && pP->Y == y)
2384 return pP;
2385 pP = pP->Next;
2386 }
2387 return NULL;
2388 }
2389
2390 GAIAGEO_DECLARE gaiaPointPtr
gaiaDynamicLineFindByPos(gaiaDynamicLinePtr p,int pos)2391 gaiaDynamicLineFindByPos (gaiaDynamicLinePtr p, int pos)
2392 {
2393 /* finds a POINT inside this DYNAMIC LINE */
2394 int n = 0;
2395 gaiaPointPtr pP;
2396 pP = p->First;
2397 while (pP != NULL)
2398 {
2399 if (pos == n)
2400 return pP;
2401 n++;
2402 pP = pP->Next;
2403 }
2404 return NULL;
2405 }
2406
2407 GAIAGEO_DECLARE gaiaDynamicLinePtr
gaiaCreateDynamicLine(double * coords,int points)2408 gaiaCreateDynamicLine (double *coords, int points)
2409 {
2410 /* creates a DynamicLine from an array of coordinates */
2411 int iv;
2412 double x;
2413 double y;
2414 gaiaDynamicLinePtr line = gaiaAllocDynamicLine ();
2415 for (iv = 0; iv < points; iv++)
2416 {
2417 gaiaGetPoint (coords, iv, &x, &y);
2418 gaiaAppendPointToDynamicLine (line, x, y);
2419 }
2420 return line;
2421 }
2422
2423 GAIAGEO_DECLARE void
gaiaMbrLinestring(gaiaLinestringPtr line)2424 gaiaMbrLinestring (gaiaLinestringPtr line)
2425 {
2426 /* computes the MBR for this linestring */
2427 int iv;
2428 double x;
2429 double y;
2430 double z;
2431 double m;
2432 line->MinX = DBL_MAX;
2433 line->MinY = DBL_MAX;
2434 line->MaxX = -DBL_MAX;
2435 line->MaxY = -DBL_MAX;
2436 for (iv = 0; iv < line->Points; iv++)
2437 {
2438 if (line->DimensionModel == GAIA_XY_Z)
2439 {
2440 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
2441 }
2442 else if (line->DimensionModel == GAIA_XY_M)
2443 {
2444 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
2445 }
2446 else if (line->DimensionModel == GAIA_XY_Z_M)
2447 {
2448 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
2449 }
2450 else
2451 {
2452 gaiaGetPoint (line->Coords, iv, &x, &y);
2453 }
2454 if (x < line->MinX)
2455 line->MinX = x;
2456 if (y < line->MinY)
2457 line->MinY = y;
2458 if (x > line->MaxX)
2459 line->MaxX = x;
2460 if (y > line->MaxY)
2461 line->MaxY = y;
2462 }
2463 }
2464
2465 GAIAGEO_DECLARE void
gaiaMbrRing(gaiaRingPtr rng)2466 gaiaMbrRing (gaiaRingPtr rng)
2467 {
2468 /* computes the MBR for this ring */
2469 int iv;
2470 double x;
2471 double y;
2472 double z;
2473 double m;
2474 rng->MinX = DBL_MAX;
2475 rng->MinY = DBL_MAX;
2476 rng->MaxX = -DBL_MAX;
2477 rng->MaxY = -DBL_MAX;
2478 for (iv = 0; iv < rng->Points; iv++)
2479 {
2480 if (rng->DimensionModel == GAIA_XY_Z)
2481 {
2482 gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
2483 }
2484 else if (rng->DimensionModel == GAIA_XY_M)
2485 {
2486 gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
2487 }
2488 else if (rng->DimensionModel == GAIA_XY_Z_M)
2489 {
2490 gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
2491 }
2492 else
2493 {
2494 gaiaGetPoint (rng->Coords, iv, &x, &y);
2495 }
2496 if (x < rng->MinX)
2497 rng->MinX = x;
2498 if (y < rng->MinY)
2499 rng->MinY = y;
2500 if (x > rng->MaxX)
2501 rng->MaxX = x;
2502 if (y > rng->MaxY)
2503 rng->MaxY = y;
2504 }
2505 }
2506
2507 GAIAGEO_DECLARE void
gaiaMbrPolygon(gaiaPolygonPtr polyg)2508 gaiaMbrPolygon (gaiaPolygonPtr polyg)
2509 {
2510 /* computes the MBR for this polygon */
2511 gaiaRingPtr rng;
2512 polyg->MinX = DBL_MAX;
2513 polyg->MinY = DBL_MAX;
2514 polyg->MaxX = -DBL_MAX;
2515 polyg->MaxY = -DBL_MAX;
2516 rng = polyg->Exterior;
2517 gaiaMbrRing (rng);
2518 if (rng->MinX < polyg->MinX)
2519 polyg->MinX = rng->MinX;
2520 if (rng->MinY < polyg->MinY)
2521 polyg->MinY = rng->MinY;
2522 if (rng->MaxX > polyg->MaxX)
2523 polyg->MaxX = rng->MaxX;
2524 if (rng->MaxY > polyg->MaxY)
2525 polyg->MaxY = rng->MaxY;
2526 }
2527
2528 GAIAGEO_DECLARE void
gaiaMbrGeometry(gaiaGeomCollPtr geom)2529 gaiaMbrGeometry (gaiaGeomCollPtr geom)
2530 {
2531 /* computes the MBR for this geometry */
2532 gaiaPointPtr point = NULL;
2533 gaiaLinestringPtr line = NULL;
2534 gaiaPolygonPtr polyg = NULL;
2535 geom->MinX = DBL_MAX;
2536 geom->MinY = DBL_MAX;
2537 geom->MaxX = -DBL_MAX;
2538 geom->MaxY = -DBL_MAX;
2539 point = geom->FirstPoint;
2540 while (point)
2541 {
2542 if (point->X < geom->MinX)
2543 geom->MinX = point->X;
2544 if (point->Y < geom->MinY)
2545 geom->MinY = point->Y;
2546 if (point->X > geom->MaxX)
2547 geom->MaxX = point->X;
2548 if (point->Y > geom->MaxY)
2549 geom->MaxY = point->Y;
2550 point = point->Next;
2551 }
2552 line = geom->FirstLinestring;
2553 while (line)
2554 {
2555 gaiaMbrLinestring (line);
2556 if (line->MinX < geom->MinX)
2557 geom->MinX = line->MinX;
2558 if (line->MinY < geom->MinY)
2559 geom->MinY = line->MinY;
2560 if (line->MaxX > geom->MaxX)
2561 geom->MaxX = line->MaxX;
2562 if (line->MaxY > geom->MaxY)
2563 geom->MaxY = line->MaxY;
2564 line = line->Next;
2565 }
2566 polyg = geom->FirstPolygon;
2567 while (polyg)
2568 {
2569 gaiaMbrPolygon (polyg);
2570 if (polyg->MinX < geom->MinX)
2571 geom->MinX = polyg->MinX;
2572 if (polyg->MinY < geom->MinY)
2573 geom->MinY = polyg->MinY;
2574 if (polyg->MaxX > geom->MaxX)
2575 geom->MaxX = polyg->MaxX;
2576 if (polyg->MaxY > geom->MaxY)
2577 geom->MaxY = polyg->MaxY;
2578 polyg = polyg->Next;
2579 }
2580 }
2581
2582 GAIAGEO_DECLARE void
gaiaMRangeLinestring(gaiaLinestringPtr line,double * min,double * max)2583 gaiaMRangeLinestring (gaiaLinestringPtr line, double *min, double *max)
2584 {
2585 /* computes the M-range [min/max] for this linestring */
2586 int iv;
2587 double x;
2588 double y;
2589 double z;
2590 double m;
2591 *min = DBL_MAX;
2592 *max = -DBL_MAX;
2593 for (iv = 0; iv < line->Points; iv++)
2594 {
2595 m = 0.0;
2596 if (line->DimensionModel == GAIA_XY_Z)
2597 {
2598 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
2599 }
2600 else if (line->DimensionModel == GAIA_XY_M)
2601 {
2602 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
2603 }
2604 else if (line->DimensionModel == GAIA_XY_Z_M)
2605 {
2606 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
2607 }
2608 else
2609 {
2610 gaiaGetPoint (line->Coords, iv, &x, &y);
2611 }
2612 if (m < *min)
2613 *min = m;
2614 if (m > *max)
2615 *max = m;
2616 }
2617 }
2618
2619 GAIAGEO_DECLARE void
gaiaMRangeLinestringEx(gaiaLinestringPtr line,double nodata,double * min,double * max)2620 gaiaMRangeLinestringEx (gaiaLinestringPtr line, double nodata, double *min,
2621 double *max)
2622 {
2623 /* computes the M-range [min/max] for this linestring (NODATA flavor) */
2624 int iv;
2625 double x;
2626 double y;
2627 double z;
2628 double m;
2629 *min = DBL_MAX;
2630 *max = -DBL_MAX;
2631 for (iv = 0; iv < line->Points; iv++)
2632 {
2633 m = 0.0;
2634 if (line->DimensionModel == GAIA_XY_Z)
2635 {
2636 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
2637 }
2638 else if (line->DimensionModel == GAIA_XY_M)
2639 {
2640 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
2641 }
2642 else if (line->DimensionModel == GAIA_XY_Z_M)
2643 {
2644 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
2645 }
2646 else
2647 {
2648 gaiaGetPoint (line->Coords, iv, &x, &y);
2649 }
2650 if (m == nodata)
2651 continue;
2652 if (m < *min)
2653 *min = m;
2654 if (m > *max)
2655 *max = m;
2656 }
2657 }
2658
2659 GAIAGEO_DECLARE void
gaiaMRangeRing(gaiaRingPtr rng,double * min,double * max)2660 gaiaMRangeRing (gaiaRingPtr rng, double *min, double *max)
2661 {
2662 /* computes the M-range [min/max] for this ring */
2663 int iv;
2664 double x;
2665 double y;
2666 double z;
2667 double m;
2668 *min = DBL_MAX;
2669 *max = -DBL_MAX;
2670 for (iv = 0; iv < rng->Points; iv++)
2671 {
2672 m = 0.0;
2673 if (rng->DimensionModel == GAIA_XY_Z)
2674 {
2675 gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
2676 }
2677 else if (rng->DimensionModel == GAIA_XY_M)
2678 {
2679 gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
2680 }
2681 else if (rng->DimensionModel == GAIA_XY_Z_M)
2682 {
2683 gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
2684 }
2685 else
2686 {
2687 gaiaGetPoint (rng->Coords, iv, &x, &y);
2688 }
2689 if (m < *min)
2690 *min = m;
2691 if (m > *max)
2692 *max = m;
2693 }
2694 }
2695
2696 GAIAGEO_DECLARE void
gaiaMRangeRingEx(gaiaRingPtr rng,double nodata,double * min,double * max)2697 gaiaMRangeRingEx (gaiaRingPtr rng, double nodata, double *min, double *max)
2698 {
2699 /* computes the M-range [min/max] for this ring (NODATA flavor) */
2700 int iv;
2701 double x;
2702 double y;
2703 double z;
2704 double m;
2705 *min = DBL_MAX;
2706 *max = -DBL_MAX;
2707 for (iv = 0; iv < rng->Points; iv++)
2708 {
2709 m = 0.0;
2710 if (rng->DimensionModel == GAIA_XY_Z)
2711 {
2712 gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
2713 }
2714 else if (rng->DimensionModel == GAIA_XY_M)
2715 {
2716 gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
2717 }
2718 else if (rng->DimensionModel == GAIA_XY_Z_M)
2719 {
2720 gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
2721 }
2722 else
2723 {
2724 gaiaGetPoint (rng->Coords, iv, &x, &y);
2725 }
2726 if (m == nodata)
2727 continue;
2728 if (m < *min)
2729 *min = m;
2730 if (m > *max)
2731 *max = m;
2732 }
2733 }
2734
2735 GAIAGEO_DECLARE void
gaiaMRangePolygon(gaiaPolygonPtr polyg,double * min,double * max)2736 gaiaMRangePolygon (gaiaPolygonPtr polyg, double *min, double *max)
2737 {
2738 /* computes the M-range [min/max] for this polygon */
2739 gaiaRingPtr rng;
2740 int ib;
2741 double r_min;
2742 double r_max;
2743 *min = DBL_MAX;
2744 *max = -DBL_MAX;
2745 rng = polyg->Exterior;
2746 gaiaMRangeRing (rng, &r_min, &r_max);
2747 if (r_min < *min)
2748 *min = r_min;
2749 if (r_max > *max)
2750 *max = r_max;
2751 for (ib = 0; ib < polyg->NumInteriors; ib++)
2752 {
2753 rng = polyg->Interiors + ib;
2754 gaiaMRangeRing (rng, &r_min, &r_max);
2755 if (r_min < *min)
2756 *min = r_min;
2757 if (r_max > *max)
2758 *max = r_max;
2759 }
2760 }
2761
2762 GAIAGEO_DECLARE void
gaiaMRangePolygonEx(gaiaPolygonPtr polyg,double nodata,double * min,double * max)2763 gaiaMRangePolygonEx (gaiaPolygonPtr polyg, double nodata, double *min,
2764 double *max)
2765 {
2766 /* computes the M-range [min/max] for this polygon (NODATA flavor) */
2767 gaiaRingPtr rng;
2768 int ib;
2769 double r_min;
2770 double r_max;
2771 *min = DBL_MAX;
2772 *max = -DBL_MAX;
2773 rng = polyg->Exterior;
2774 gaiaMRangeRingEx (rng, nodata, &r_min, &r_max);
2775 if (r_min < *min)
2776 *min = r_min;
2777 if (r_max > *max)
2778 *max = r_max;
2779 for (ib = 0; ib < polyg->NumInteriors; ib++)
2780 {
2781 rng = polyg->Interiors + ib;
2782 gaiaMRangeRingEx (rng, nodata, &r_min, &r_max);
2783 if (r_min < *min)
2784 *min = r_min;
2785 if (r_max > *max)
2786 *max = r_max;
2787 }
2788 }
2789
2790 GAIAGEO_DECLARE void
gaiaMRangeGeometry(gaiaGeomCollPtr geom,double * min,double * max)2791 gaiaMRangeGeometry (gaiaGeomCollPtr geom, double *min, double *max)
2792 {
2793 /* computes the M-range [min/max] for this geometry */
2794 gaiaPointPtr point = NULL;
2795 gaiaLinestringPtr line = NULL;
2796 gaiaPolygonPtr polyg = NULL;
2797 double m;
2798 double r_min;
2799 double r_max;
2800 *min = DBL_MAX;
2801 *max = -DBL_MAX;
2802 point = geom->FirstPoint;
2803 while (point)
2804 {
2805 m = 0.0;
2806 if (point->DimensionModel == GAIA_XY_M
2807 || point->DimensionModel == GAIA_XY_Z_M)
2808 m = point->M;
2809 if (m < *min)
2810 *min = m;
2811 if (m > *max)
2812 *max = m;
2813 point = point->Next;
2814 }
2815 line = geom->FirstLinestring;
2816 while (line)
2817 {
2818 gaiaMRangeLinestring (line, &r_min, &r_max);
2819 if (r_min < *min)
2820 *min = r_min;
2821 if (r_max > *max)
2822 *max = r_max;
2823 line = line->Next;
2824 }
2825 polyg = geom->FirstPolygon;
2826 while (polyg)
2827 {
2828 gaiaMRangePolygon (polyg, &r_min, &r_max);
2829 if (r_min < *min)
2830 *min = r_min;
2831 if (r_max > *max)
2832 *max = r_max;
2833 polyg = polyg->Next;
2834 }
2835 }
2836
2837 GAIAGEO_DECLARE void
gaiaMRangeGeometryEx(gaiaGeomCollPtr geom,double nodata,double * min,double * max)2838 gaiaMRangeGeometryEx (gaiaGeomCollPtr geom, double nodata, double *min,
2839 double *max)
2840 {
2841 /* computes the M-range [min/max] for this geometry */
2842 gaiaPointPtr point = NULL;
2843 gaiaLinestringPtr line = NULL;
2844 gaiaPolygonPtr polyg = NULL;
2845 double m;
2846 double r_min;
2847 double r_max;
2848 *min = DBL_MAX;
2849 *max = -DBL_MAX;
2850 point = geom->FirstPoint;
2851 while (point)
2852 {
2853 m = 0.0;
2854 if (point->DimensionModel == GAIA_XY_M
2855 || point->DimensionModel == GAIA_XY_Z_M)
2856 m = point->M;
2857 if (m == nodata)
2858 continue;
2859 if (m < *min)
2860 *min = m;
2861 if (m > *max)
2862 *max = m;
2863 point = point->Next;
2864 }
2865 line = geom->FirstLinestring;
2866 while (line)
2867 {
2868 gaiaMRangeLinestringEx (line, nodata, &r_min, &r_max);
2869 if (r_min < *min)
2870 *min = r_min;
2871 if (r_max > *max)
2872 *max = r_max;
2873 line = line->Next;
2874 }
2875 polyg = geom->FirstPolygon;
2876 while (polyg)
2877 {
2878 gaiaMRangePolygonEx (polyg, nodata, &r_min, &r_max);
2879 if (r_min < *min)
2880 *min = r_min;
2881 if (r_max > *max)
2882 *max = r_max;
2883 polyg = polyg->Next;
2884 }
2885 }
2886
2887 GAIAGEO_DECLARE void
gaiaZRangeLinestring(gaiaLinestringPtr line,double * min,double * max)2888 gaiaZRangeLinestring (gaiaLinestringPtr line, double *min, double *max)
2889 {
2890 /* computes the Z-range [min/max] for this linestring */
2891 int iv;
2892 double x;
2893 double y;
2894 double z;
2895 double m;
2896 *min = DBL_MAX;
2897 *max = -DBL_MAX;
2898 for (iv = 0; iv < line->Points; iv++)
2899 {
2900 z = 0.0;
2901 m = 0.0;
2902 if (line->DimensionModel == GAIA_XY_Z)
2903 {
2904 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
2905 }
2906 else if (line->DimensionModel == GAIA_XY_M)
2907 {
2908 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
2909 }
2910 else if (line->DimensionModel == GAIA_XY_Z_M)
2911 {
2912 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
2913 }
2914 else
2915 {
2916 gaiaGetPoint (line->Coords, iv, &x, &y);
2917 }
2918 if (z < *min)
2919 *min = z;
2920 if (z > *max)
2921 *max = z;
2922 }
2923 }
2924
2925 GAIAGEO_DECLARE void
gaiaZRangeLinestringEx(gaiaLinestringPtr line,double nodata,double * min,double * max)2926 gaiaZRangeLinestringEx (gaiaLinestringPtr line, double nodata, double *min,
2927 double *max)
2928 {
2929 /* computes the Z-range [min/max] for this linestring (NODATA flavor) */
2930 int iv;
2931 double x;
2932 double y;
2933 double z;
2934 double m;
2935 *min = DBL_MAX;
2936 *max = -DBL_MAX;
2937 for (iv = 0; iv < line->Points; iv++)
2938 {
2939 z = 0.0;
2940 m = 0.0;
2941 if (line->DimensionModel == GAIA_XY_Z)
2942 {
2943 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
2944 }
2945 else if (line->DimensionModel == GAIA_XY_M)
2946 {
2947 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
2948 }
2949 else if (line->DimensionModel == GAIA_XY_Z_M)
2950 {
2951 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
2952 }
2953 else
2954 {
2955 gaiaGetPoint (line->Coords, iv, &x, &y);
2956 }
2957 if (z == nodata)
2958 continue;
2959 if (z < *min)
2960 *min = z;
2961 if (z > *max)
2962 *max = z;
2963 }
2964 }
2965
2966 GAIAGEO_DECLARE void
gaiaZRangeRing(gaiaRingPtr rng,double * min,double * max)2967 gaiaZRangeRing (gaiaRingPtr rng, double *min, double *max)
2968 {
2969 /* computes the Z-range [min/max] for this ring */
2970 int iv;
2971 double x;
2972 double y;
2973 double z;
2974 double m;
2975 *min = DBL_MAX;
2976 *max = -DBL_MAX;
2977 for (iv = 0; iv < rng->Points; iv++)
2978 {
2979 z = 0.0;
2980 m = 0.0;
2981 if (rng->DimensionModel == GAIA_XY_Z)
2982 {
2983 gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
2984 }
2985 else if (rng->DimensionModel == GAIA_XY_M)
2986 {
2987 gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
2988 }
2989 else if (rng->DimensionModel == GAIA_XY_Z_M)
2990 {
2991 gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
2992 }
2993 else
2994 {
2995 gaiaGetPoint (rng->Coords, iv, &x, &y);
2996 }
2997 if (z < *min)
2998 *min = z;
2999 if (z > *max)
3000 *max = z;
3001 }
3002 }
3003
3004 GAIAGEO_DECLARE void
gaiaZRangeRingEx(gaiaRingPtr rng,double nodata,double * min,double * max)3005 gaiaZRangeRingEx (gaiaRingPtr rng, double nodata, double *min, double *max)
3006 {
3007 /* computes the Z-range [min/max] for this ring (NODATA flavor) */
3008 int iv;
3009 double x;
3010 double y;
3011 double z;
3012 double m;
3013 *min = DBL_MAX;
3014 *max = -DBL_MAX;
3015 for (iv = 0; iv < rng->Points; iv++)
3016 {
3017 z = 0.0;
3018 m = 0.0;
3019 if (rng->DimensionModel == GAIA_XY_Z)
3020 {
3021 gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
3022 }
3023 else if (rng->DimensionModel == GAIA_XY_M)
3024 {
3025 gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
3026 }
3027 else if (rng->DimensionModel == GAIA_XY_Z_M)
3028 {
3029 gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
3030 }
3031 else
3032 {
3033 gaiaGetPoint (rng->Coords, iv, &x, &y);
3034 }
3035 if (z == nodata)
3036 continue;
3037 if (z < *min)
3038 *min = z;
3039 if (z > *max)
3040 *max = z;
3041 }
3042 }
3043
3044 GAIAGEO_DECLARE void
gaiaZRangePolygon(gaiaPolygonPtr polyg,double * min,double * max)3045 gaiaZRangePolygon (gaiaPolygonPtr polyg, double *min, double *max)
3046 {
3047 /* computes the Z-range [min/max] for this polygon */
3048 gaiaRingPtr rng;
3049 int ib;
3050 double r_min;
3051 double r_max;
3052 *min = DBL_MAX;
3053 *max = -DBL_MAX;
3054 rng = polyg->Exterior;
3055 gaiaZRangeRing (rng, &r_min, &r_max);
3056 if (r_min < *min)
3057 *min = r_min;
3058 if (r_max > *max)
3059 *max = r_max;
3060 for (ib = 0; ib < polyg->NumInteriors; ib++)
3061 {
3062 rng = polyg->Interiors + ib;
3063 gaiaZRangeRing (rng, &r_min, &r_max);
3064 if (r_min < *min)
3065 *min = r_min;
3066 if (r_max > *max)
3067 *max = r_max;
3068 }
3069 }
3070
3071 GAIAGEO_DECLARE void
gaiaZRangePolygonEx(gaiaPolygonPtr polyg,double nodata,double * min,double * max)3072 gaiaZRangePolygonEx (gaiaPolygonPtr polyg, double nodata, double *min,
3073 double *max)
3074 {
3075 /* computes the Z-range [min/max] for this polygon (NODATA flavor) */
3076 gaiaRingPtr rng;
3077 int ib;
3078 double r_min;
3079 double r_max;
3080 *min = DBL_MAX;
3081 *max = -DBL_MAX;
3082 rng = polyg->Exterior;
3083 gaiaZRangeRingEx (rng, nodata, &r_min, &r_max);
3084 if (r_min < *min)
3085 *min = r_min;
3086 if (r_max > *max)
3087 *max = r_max;
3088 for (ib = 0; ib < polyg->NumInteriors; ib++)
3089 {
3090 rng = polyg->Interiors + ib;
3091 gaiaZRangeRingEx (rng, nodata, &r_min, &r_max);
3092 if (r_min < *min)
3093 *min = r_min;
3094 if (r_max > *max)
3095 *max = r_max;
3096 }
3097 }
3098
3099 GAIAGEO_DECLARE void
gaiaZRangeGeometry(gaiaGeomCollPtr geom,double * min,double * max)3100 gaiaZRangeGeometry (gaiaGeomCollPtr geom, double *min, double *max)
3101 {
3102 /* computes the Z-range [min/max] for this geometry */
3103 gaiaPointPtr point = NULL;
3104 gaiaLinestringPtr line = NULL;
3105 gaiaPolygonPtr polyg = NULL;
3106 double z;
3107 double r_min;
3108 double r_max;
3109 *min = DBL_MAX;
3110 *max = -DBL_MAX;
3111 point = geom->FirstPoint;
3112 while (point)
3113 {
3114 z = 0.0;
3115 if (point->DimensionModel == GAIA_XY_Z
3116 || point->DimensionModel == GAIA_XY_Z_M)
3117 z = point->Z;
3118 if (z < *min)
3119 *min = z;
3120 if (z > *max)
3121 *max = z;
3122 point = point->Next;
3123 }
3124 line = geom->FirstLinestring;
3125 while (line)
3126 {
3127 gaiaZRangeLinestring (line, &r_min, &r_max);
3128 if (r_min < *min)
3129 *min = r_min;
3130 if (r_max > *max)
3131 *max = r_max;
3132 line = line->Next;
3133 }
3134 polyg = geom->FirstPolygon;
3135 while (polyg)
3136 {
3137 gaiaZRangePolygon (polyg, &r_min, &r_max);
3138 if (r_min < *min)
3139 *min = r_min;
3140 if (r_max > *max)
3141 *max = r_max;
3142 polyg = polyg->Next;
3143 }
3144 }
3145
3146 GAIAGEO_DECLARE void
gaiaZRangeGeometryEx(gaiaGeomCollPtr geom,double nodata,double * min,double * max)3147 gaiaZRangeGeometryEx (gaiaGeomCollPtr geom, double nodata, double *min,
3148 double *max)
3149 {
3150 /* computes the Z-range [min/max] for this geometry (NODATA flavor) */
3151 gaiaPointPtr point = NULL;
3152 gaiaLinestringPtr line = NULL;
3153 gaiaPolygonPtr polyg = NULL;
3154 double z;
3155 double r_min;
3156 double r_max;
3157 *min = DBL_MAX;
3158 *max = -DBL_MAX;
3159 point = geom->FirstPoint;
3160 while (point)
3161 {
3162 z = 0.0;
3163 if (point->DimensionModel == GAIA_XY_Z
3164 || point->DimensionModel == GAIA_XY_Z_M)
3165 z = point->Z;
3166 if (z == nodata)
3167 continue;
3168 if (z < *min)
3169 *min = z;
3170 if (z > *max)
3171 *max = z;
3172 point = point->Next;
3173 }
3174 line = geom->FirstLinestring;
3175 while (line)
3176 {
3177 gaiaZRangeLinestringEx (line, nodata, &r_min, &r_max);
3178 if (r_min < *min)
3179 *min = r_min;
3180 if (r_max > *max)
3181 *max = r_max;
3182 line = line->Next;
3183 }
3184 polyg = geom->FirstPolygon;
3185 while (polyg)
3186 {
3187 gaiaZRangePolygonEx (polyg, nodata, &r_min, &r_max);
3188 if (r_min < *min)
3189 *min = r_min;
3190 if (r_max > *max)
3191 *max = r_max;
3192 polyg = polyg->Next;
3193 }
3194 }
3195
3196 GAIAGEO_DECLARE int
gaiaDimension(gaiaGeomCollPtr geom)3197 gaiaDimension (gaiaGeomCollPtr geom)
3198 {
3199 /* determines the Dimension for this geometry */
3200 gaiaPointPtr point;
3201 gaiaLinestringPtr line;
3202 gaiaPolygonPtr polyg;
3203 int n_points = 0;
3204 int n_linestrings = 0;
3205 int n_polygons = 0;
3206 if (!geom)
3207 return -1;
3208 point = geom->FirstPoint;
3209 while (point)
3210 {
3211 /* counts how many points are there */
3212 n_points++;
3213 point = point->Next;
3214 }
3215 line = geom->FirstLinestring;
3216 while (line)
3217 {
3218 /* counts how many linestrings are there */
3219 n_linestrings++;
3220 line = line->Next;
3221 }
3222 polyg = geom->FirstPolygon;
3223 while (polyg)
3224 {
3225 /* counts how many polygons are there */
3226 n_polygons++;
3227 polyg = polyg->Next;
3228 }
3229 if (n_points == 0 && n_linestrings == 0 && n_polygons == 0)
3230 return -1;
3231 if (n_points > 0 && n_linestrings == 0 && n_polygons == 0)
3232 return 0;
3233 if (n_linestrings > 0 && n_polygons == 0)
3234 return 1;
3235 return 2;
3236 }
3237
3238 GAIAGEO_DECLARE int
gaiaGeometryType(gaiaGeomCollPtr geom)3239 gaiaGeometryType (gaiaGeomCollPtr geom)
3240 {
3241 /* determines the Class for this geometry */
3242 gaiaPointPtr point;
3243 gaiaLinestringPtr line;
3244 gaiaPolygonPtr polyg;
3245 gaiaRingPtr ring;
3246 int ib;
3247 int n_points = 0;
3248 int n_linestrings = 0;
3249 int n_polygons = 0;
3250 int dm = GAIA_XY;
3251 if (!geom)
3252 return GAIA_UNKNOWN;
3253 point = geom->FirstPoint;
3254 while (point)
3255 {
3256 /* counts how many points are there */
3257 n_points++;
3258 if (point->DimensionModel == GAIA_XY_Z)
3259 {
3260 if (dm == GAIA_XY)
3261 dm = GAIA_XY_Z;
3262 else if (dm == GAIA_XY_M)
3263 dm = GAIA_XY_Z_M;
3264 }
3265 else if (point->DimensionModel == GAIA_XY_M)
3266 {
3267 if (dm == GAIA_XY)
3268 dm = GAIA_XY_M;
3269 else if (dm == GAIA_XY_Z)
3270 dm = GAIA_XY_Z_M;
3271 }
3272 else if (point->DimensionModel == GAIA_XY_Z_M)
3273 dm = GAIA_XY_Z_M;
3274 point = point->Next;
3275 }
3276 line = geom->FirstLinestring;
3277 while (line)
3278 {
3279 /* counts how many linestrings are there */
3280 n_linestrings++;
3281 if (line->DimensionModel == GAIA_XY_Z)
3282 {
3283 if (dm == GAIA_XY)
3284 dm = GAIA_XY_Z;
3285 else if (dm == GAIA_XY_M)
3286 dm = GAIA_XY_Z_M;
3287 }
3288 else if (line->DimensionModel == GAIA_XY_M)
3289 {
3290 if (dm == GAIA_XY)
3291 dm = GAIA_XY_M;
3292 else if (dm == GAIA_XY_Z)
3293 dm = GAIA_XY_Z_M;
3294 }
3295 else if (line->DimensionModel == GAIA_XY_Z_M)
3296 dm = GAIA_XY_Z_M;
3297 line = line->Next;
3298 }
3299 polyg = geom->FirstPolygon;
3300 while (polyg)
3301 {
3302 /* counts how many polygons are there */
3303 n_polygons++;
3304 ring = polyg->Exterior;
3305 if (ring->DimensionModel == GAIA_XY_Z)
3306 {
3307 if (dm == GAIA_XY)
3308 dm = GAIA_XY_Z;
3309 else if (dm == GAIA_XY_M)
3310 dm = GAIA_XY_Z_M;
3311 }
3312 else if (ring->DimensionModel == GAIA_XY_M)
3313 {
3314 if (dm == GAIA_XY)
3315 dm = GAIA_XY_M;
3316 else if (dm == GAIA_XY_Z)
3317 dm = GAIA_XY_Z_M;
3318 }
3319 else if (ring->DimensionModel == GAIA_XY_Z_M)
3320 dm = GAIA_XY_Z_M;
3321 for (ib = 0; ib < polyg->NumInteriors; ib++)
3322 {
3323 ring = polyg->Interiors + ib;
3324 if (ring->DimensionModel == GAIA_XY_Z)
3325 {
3326 if (dm == GAIA_XY)
3327 dm = GAIA_XY_Z;
3328 else if (dm == GAIA_XY_M)
3329 dm = GAIA_XY_Z_M;
3330 }
3331 else if (ring->DimensionModel == GAIA_XY_M)
3332 {
3333 if (dm == GAIA_XY)
3334 dm = GAIA_XY_M;
3335 else if (dm == GAIA_XY_Z)
3336 dm = GAIA_XY_Z_M;
3337 }
3338 else if (ring->DimensionModel == GAIA_XY_Z_M)
3339 dm = GAIA_XY_Z_M;
3340 }
3341 polyg = polyg->Next;
3342 }
3343 if (n_points == 0 && n_linestrings == 0 && n_polygons == 0)
3344 return GAIA_UNKNOWN;
3345 if (n_points == 1 && n_linestrings == 0 && n_polygons == 0)
3346 {
3347 if (geom->DeclaredType == GAIA_MULTIPOINT)
3348 {
3349 if (dm == GAIA_XY_Z)
3350 return GAIA_MULTIPOINTZ;
3351 if (dm == GAIA_XY_M)
3352 return GAIA_MULTIPOINTM;
3353 if (dm == GAIA_XY_Z_M)
3354 return GAIA_MULTIPOINTZM;
3355 else
3356 return GAIA_MULTIPOINT;
3357 }
3358 else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3359 {
3360 if (dm == GAIA_XY_Z)
3361 return GAIA_GEOMETRYCOLLECTIONZ;
3362 if (dm == GAIA_XY_M)
3363 return GAIA_GEOMETRYCOLLECTIONM;
3364 if (dm == GAIA_XY_Z_M)
3365 return GAIA_GEOMETRYCOLLECTIONZM;
3366 else
3367 return GAIA_GEOMETRYCOLLECTION;
3368 }
3369 else
3370 {
3371 if (dm == GAIA_XY_Z)
3372 return GAIA_POINTZ;
3373 if (dm == GAIA_XY_M)
3374 return GAIA_POINTM;
3375 if (dm == GAIA_XY_Z_M)
3376 return GAIA_POINTZM;
3377 else
3378 return GAIA_POINT;
3379 }
3380 }
3381 if (n_points > 0 && n_linestrings == 0 && n_polygons == 0)
3382 {
3383 if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3384 {
3385 if (dm == GAIA_XY_Z)
3386 return GAIA_GEOMETRYCOLLECTIONZ;
3387 if (dm == GAIA_XY_M)
3388 return GAIA_GEOMETRYCOLLECTIONM;
3389 if (dm == GAIA_XY_Z_M)
3390 return GAIA_GEOMETRYCOLLECTIONZM;
3391 else
3392 return GAIA_GEOMETRYCOLLECTION;
3393 }
3394 else
3395 {
3396 if (dm == GAIA_XY_Z)
3397 return GAIA_MULTIPOINTZ;
3398 if (dm == GAIA_XY_M)
3399 return GAIA_MULTIPOINTM;
3400 if (dm == GAIA_XY_Z_M)
3401 return GAIA_MULTIPOINTZM;
3402 else
3403 return GAIA_MULTIPOINT;
3404 }
3405 }
3406 if (n_points == 0 && n_linestrings == 1 && n_polygons == 0)
3407 {
3408 if (geom->DeclaredType == GAIA_MULTILINESTRING)
3409 {
3410 if (dm == GAIA_XY_Z)
3411 return GAIA_MULTILINESTRINGZ;
3412 if (dm == GAIA_XY_M)
3413 return GAIA_MULTILINESTRINGM;
3414 if (dm == GAIA_XY_Z_M)
3415 return GAIA_MULTILINESTRINGZM;
3416 else
3417 return GAIA_MULTILINESTRING;
3418 }
3419 else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3420 {
3421 if (dm == GAIA_XY_Z)
3422 return GAIA_GEOMETRYCOLLECTIONZ;
3423 if (dm == GAIA_XY_M)
3424 return GAIA_GEOMETRYCOLLECTIONM;
3425 if (dm == GAIA_XY_Z_M)
3426 return GAIA_GEOMETRYCOLLECTIONZM;
3427 else
3428 return GAIA_GEOMETRYCOLLECTION;
3429 }
3430 else
3431 {
3432 if (dm == GAIA_XY_Z)
3433 return GAIA_LINESTRINGZ;
3434 if (dm == GAIA_XY_M)
3435 return GAIA_LINESTRINGM;
3436 if (dm == GAIA_XY_Z_M)
3437 return GAIA_LINESTRINGZM;
3438 else
3439 return GAIA_LINESTRING;
3440 }
3441 }
3442 if (n_points == 0 && n_linestrings > 0 && n_polygons == 0)
3443 {
3444 if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3445 {
3446 if (dm == GAIA_XY_Z)
3447 return GAIA_GEOMETRYCOLLECTIONZ;
3448 if (dm == GAIA_XY_M)
3449 return GAIA_GEOMETRYCOLLECTIONM;
3450 if (dm == GAIA_XY_Z_M)
3451 return GAIA_GEOMETRYCOLLECTIONZM;
3452 else
3453 return GAIA_GEOMETRYCOLLECTION;
3454 }
3455 else
3456 {
3457 if (dm == GAIA_XY_Z)
3458 return GAIA_MULTILINESTRINGZ;
3459 if (dm == GAIA_XY_M)
3460 return GAIA_MULTILINESTRINGM;
3461 if (dm == GAIA_XY_Z_M)
3462 return GAIA_MULTILINESTRINGZM;
3463 else
3464 return GAIA_MULTILINESTRING;
3465 }
3466 }
3467 if (n_points == 0 && n_linestrings == 0 && n_polygons == 1)
3468 {
3469 if (geom->DeclaredType == GAIA_MULTIPOLYGON)
3470 {
3471 if (dm == GAIA_XY_Z)
3472 return GAIA_MULTIPOLYGONZ;
3473 if (dm == GAIA_XY_M)
3474 return GAIA_MULTIPOLYGONM;
3475 if (dm == GAIA_XY_Z_M)
3476 return GAIA_MULTIPOLYGONZM;
3477 else
3478 return GAIA_MULTIPOLYGON;
3479 }
3480 else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3481 {
3482 if (dm == GAIA_XY_Z)
3483 return GAIA_GEOMETRYCOLLECTIONZ;
3484 if (dm == GAIA_XY_M)
3485 return GAIA_GEOMETRYCOLLECTIONM;
3486 if (dm == GAIA_XY_Z_M)
3487 return GAIA_GEOMETRYCOLLECTIONZM;
3488 else
3489 return GAIA_GEOMETRYCOLLECTION;
3490 }
3491 else
3492 {
3493 if (dm == GAIA_XY_Z)
3494 return GAIA_POLYGONZ;
3495 if (dm == GAIA_XY_M)
3496 return GAIA_POLYGONM;
3497 if (dm == GAIA_XY_Z_M)
3498 return GAIA_POLYGONZM;
3499 else
3500 return GAIA_POLYGON;
3501 }
3502 }
3503 if (n_points == 0 && n_linestrings == 0 && n_polygons > 0)
3504 {
3505 if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3506 {
3507 if (dm == GAIA_XY_Z)
3508 return GAIA_GEOMETRYCOLLECTIONZ;
3509 if (dm == GAIA_XY_M)
3510 return GAIA_GEOMETRYCOLLECTIONM;
3511 if (dm == GAIA_XY_Z_M)
3512 return GAIA_GEOMETRYCOLLECTIONZM;
3513 else
3514 return GAIA_GEOMETRYCOLLECTION;
3515 }
3516 else
3517 {
3518 if (dm == GAIA_XY_Z)
3519 return GAIA_MULTIPOLYGONZ;
3520 if (dm == GAIA_XY_M)
3521 return GAIA_MULTIPOLYGONM;
3522 if (dm == GAIA_XY_Z_M)
3523 return GAIA_MULTIPOLYGONZM;
3524 else
3525 return GAIA_MULTIPOLYGON;
3526 }
3527 }
3528 if (dm == GAIA_XY_Z)
3529 return GAIA_GEOMETRYCOLLECTIONZ;
3530 if (dm == GAIA_XY_M)
3531 return GAIA_GEOMETRYCOLLECTIONM;
3532 if (dm == GAIA_XY_Z_M)
3533 return GAIA_GEOMETRYCOLLECTIONZM;
3534 else
3535 return GAIA_GEOMETRYCOLLECTION;
3536 }
3537
3538 GAIAGEO_DECLARE int
gaiaGeometryAliasType(gaiaGeomCollPtr geom)3539 gaiaGeometryAliasType (gaiaGeomCollPtr geom)
3540 {
3541 /* determines the AliasClass for this geometry */
3542 gaiaPointPtr point;
3543 gaiaLinestringPtr line;
3544 gaiaPolygonPtr polyg;
3545 int n_points = 0;
3546 int n_linestrings = 0;
3547 int n_polygons = 0;
3548 if (!geom)
3549 return GAIA_UNKNOWN;
3550 point = geom->FirstPoint;
3551 while (point)
3552 {
3553 /* counts how many points are there */
3554 n_points++;
3555 point = point->Next;
3556 }
3557 line = geom->FirstLinestring;
3558 while (line)
3559 {
3560 /* counts how many linestrings are there */
3561 n_linestrings++;
3562 line = line->Next;
3563 }
3564 polyg = geom->FirstPolygon;
3565 while (polyg)
3566 {
3567 /* counts how many polygons are there */
3568 n_polygons++;
3569 polyg = polyg->Next;
3570 }
3571 if (n_points == 0 && n_linestrings == 0 && n_polygons == 0)
3572 return GAIA_UNKNOWN;
3573 if (n_points == 1 && n_linestrings == 0 && n_polygons == 0)
3574 {
3575 if (geom->DeclaredType == GAIA_MULTIPOINT)
3576 return GAIA_MULTIPOINT;
3577 else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3578 return GAIA_GEOMETRYCOLLECTION;
3579 else
3580 return GAIA_POINT;
3581 }
3582 if (n_points >= 1 && n_linestrings == 0 && n_polygons == 0)
3583 {
3584 if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3585 return GAIA_GEOMETRYCOLLECTION;
3586 else
3587 return GAIA_MULTIPOINT;
3588 }
3589 if (n_points == 0 && n_linestrings == 1 && n_polygons == 0)
3590 {
3591 if (geom->DeclaredType == GAIA_MULTILINESTRING)
3592 return GAIA_MULTILINESTRING;
3593 else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3594 return GAIA_GEOMETRYCOLLECTION;
3595 else
3596 return GAIA_LINESTRING;
3597 }
3598 if (n_points == 0 && n_linestrings >= 1 && n_polygons == 0)
3599 {
3600 if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3601 return GAIA_GEOMETRYCOLLECTION;
3602 else
3603 return GAIA_MULTILINESTRING;
3604 }
3605 if (n_points == 0 && n_linestrings == 0 && n_polygons == 1)
3606 {
3607 if (geom->DeclaredType == GAIA_MULTIPOLYGON)
3608 return GAIA_MULTIPOLYGON;
3609 else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3610 return GAIA_GEOMETRYCOLLECTION;
3611 else
3612 return GAIA_POLYGON;
3613 }
3614 if (n_points == 0 && n_linestrings == 0 && n_polygons >= 1)
3615 {
3616 if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3617 return GAIA_GEOMETRYCOLLECTION;
3618 else
3619 return GAIA_MULTIPOLYGON;
3620 }
3621 return GAIA_GEOMETRYCOLLECTION;
3622 }
3623
3624 GAIAGEO_DECLARE int
gaiaIsEmpty(gaiaGeomCollPtr geom)3625 gaiaIsEmpty (gaiaGeomCollPtr geom)
3626 {
3627 /* checks if this GEOMETRYCOLLECTION is an empty one */
3628 if (!geom)
3629 return 1;
3630 if (geom->FirstPoint != NULL)
3631 {
3632 /* there is at least one point */
3633 return 0;
3634 }
3635 if (geom->FirstLinestring != NULL)
3636 {
3637 /* there is at least one linestring */
3638 return 0;
3639 }
3640 if (geom->FirstPolygon != NULL)
3641 {
3642 /* there is at least one polygon */
3643 return 0;
3644 }
3645 return 1;
3646 }
3647
3648 GAIAGEO_DECLARE int
gaiaIsClosed(gaiaLinestringPtr line)3649 gaiaIsClosed (gaiaLinestringPtr line)
3650 {
3651 /* checks if this linestring is a closed one */
3652 double x0;
3653 double y0;
3654 double x1;
3655 double y1;
3656 double z;
3657 double m;
3658 if (!line)
3659 return 0;
3660 if (line->Points < 3)
3661 return 0;
3662 if (line->DimensionModel == GAIA_XY_Z)
3663 {
3664 gaiaGetPointXYZ (line->Coords, 0, &x0, &y0, &z);
3665 }
3666 else if (line->DimensionModel == GAIA_XY_M)
3667 {
3668 gaiaGetPointXYM (line->Coords, 0, &x0, &y0, &m);
3669 }
3670 else if (line->DimensionModel == GAIA_XY_Z_M)
3671 {
3672 gaiaGetPointXYZM (line->Coords, 0, &x0, &y0, &z, &m);
3673 }
3674 else
3675 {
3676 gaiaGetPoint (line->Coords, 0, &x0, &y0);
3677 }
3678 if (line->DimensionModel == GAIA_XY_Z)
3679 {
3680 gaiaGetPointXYZ (line->Coords, (line->Points - 1), &x1, &y1, &z);
3681 }
3682 else if (line->DimensionModel == GAIA_XY_M)
3683 {
3684 gaiaGetPointXYM (line->Coords, (line->Points - 1), &x1, &y1, &m);
3685 }
3686 else if (line->DimensionModel == GAIA_XY_Z_M)
3687 {
3688 gaiaGetPointXYZM (line->Coords, (line->Points - 1), &x1, &y1, &z, &m);
3689 }
3690 else
3691 {
3692 gaiaGetPoint (line->Coords, (line->Points - 1), &x1, &y1);
3693 }
3694 if (x0 == x1 && y0 == y1)
3695 return 1;
3696 return 0;
3697 }
3698
3699 GAIAGEO_DECLARE int
gaiaMbrsEqual(gaiaGeomCollPtr mbr1,gaiaGeomCollPtr mbr2)3700 gaiaMbrsEqual (gaiaGeomCollPtr mbr1, gaiaGeomCollPtr mbr2)
3701 {
3702 /*
3703 / checks if two MBRs are identical
3704 /
3705 / returns 1 if TRUE
3706 / 0 if FALSE
3707 */
3708 if (mbr1->MinX != mbr2->MinX)
3709 return 0;
3710 if (mbr1->MinY != mbr2->MinY)
3711 return 0;
3712 if (mbr1->MaxX != mbr2->MaxX)
3713 return 0;
3714 if (mbr1->MaxY != mbr2->MaxY)
3715 return 0;
3716 return 1;
3717 }
3718
3719 GAIAGEO_DECLARE int
gaiaMbrsDisjoint(gaiaGeomCollPtr mbr1,gaiaGeomCollPtr mbr2)3720 gaiaMbrsDisjoint (gaiaGeomCollPtr mbr1, gaiaGeomCollPtr mbr2)
3721 {
3722 /*
3723 / checks if two MBRs are disjoint
3724 /
3725 / returns 1 if TRUE
3726 / 0 if FALSE
3727 */
3728 if (mbr1->MinX > mbr2->MaxX)
3729 return 1;
3730 if (mbr1->MinY > mbr2->MaxY)
3731 return 1;
3732 if (mbr1->MaxX < mbr2->MinX)
3733 return 1;
3734 if (mbr1->MaxY < mbr2->MinY)
3735 return 1;
3736 if (mbr2->MinX > mbr1->MaxX)
3737 return 1;
3738 if (mbr2->MinY > mbr1->MaxY)
3739 return 1;
3740 if (mbr2->MaxX < mbr1->MinX)
3741 return 1;
3742 if (mbr2->MaxY < mbr1->MinY)
3743 return 1;
3744 return 0;
3745 }
3746
3747 GAIAGEO_DECLARE int
gaiaMbrsTouches(gaiaGeomCollPtr mbr1,gaiaGeomCollPtr mbr2)3748 gaiaMbrsTouches (gaiaGeomCollPtr mbr1, gaiaGeomCollPtr mbr2)
3749 {
3750 /*
3751 / checks if two MBRs touches
3752 /
3753 / returns 1 if TRUE
3754 / 0 if FALSE
3755 */
3756 if (mbr1->MinX == mbr2->MinX)
3757 return 1;
3758 if (mbr1->MinY == mbr2->MinY)
3759 return 1;
3760 if (mbr1->MaxX == mbr2->MaxX)
3761 return 1;
3762 if (mbr1->MaxY == mbr2->MaxY)
3763 return 1;
3764 return 0;
3765 }
3766
3767 GAIAGEO_DECLARE int
gaiaMbrsIntersects(gaiaGeomCollPtr mbr1,gaiaGeomCollPtr mbr2)3768 gaiaMbrsIntersects (gaiaGeomCollPtr mbr1, gaiaGeomCollPtr mbr2)
3769 {
3770 /*
3771 / checks if two MBRs intersect
3772 /
3773 / returns 1 if TRUE
3774 / 0 if FALSE
3775 */
3776 if (gaiaMbrsDisjoint (mbr1, mbr2))
3777 return 0;
3778 return 1;
3779 }
3780
3781 GAIAGEO_DECLARE int
gaiaMbrsOverlaps(gaiaGeomCollPtr mbr1,gaiaGeomCollPtr mbr2)3782 gaiaMbrsOverlaps (gaiaGeomCollPtr mbr1, gaiaGeomCollPtr mbr2)
3783 {
3784 /*
3785 / checks if two MBRs overlap
3786 /
3787 / returns 1 if TRUE
3788 / 0 if FALSE
3789 */
3790 if (gaiaMbrsDisjoint (mbr1, mbr2))
3791 return 0;
3792 if (mbr1->MinX >= mbr2->MinX && mbr1->MinX <= mbr2->MaxX)
3793 return 1;
3794 if (mbr1->MaxX >= mbr2->MinX && mbr1->MaxX <= mbr2->MaxX)
3795 return 1;
3796 if (mbr1->MinY >= mbr2->MinY && mbr1->MinY <= mbr2->MaxY)
3797 return 1;
3798 if (mbr1->MaxY >= mbr2->MinY && mbr1->MaxY <= mbr2->MaxY)
3799 return 1;
3800 return 0;
3801 }
3802
3803 GAIAGEO_DECLARE int
gaiaMbrsContains(gaiaGeomCollPtr mbr1,gaiaGeomCollPtr mbr2)3804 gaiaMbrsContains (gaiaGeomCollPtr mbr1, gaiaGeomCollPtr mbr2)
3805 {
3806 /*
3807 / checks if MBR-1 completely contains MBR-2
3808 /
3809 / returns 1 if TRUE
3810 / 0 if FALSE
3811 */
3812 int ok_1 = 0;
3813 int ok_2 = 0;
3814 int ok_3 = 0;
3815 int ok_4 = 0;
3816 if (mbr2->MinX >= mbr1->MinX && mbr2->MinX <= mbr1->MaxX)
3817 ok_1 = 1;
3818 if (mbr2->MaxX >= mbr1->MinX && mbr2->MaxX <= mbr1->MaxX)
3819 ok_2 = 1;
3820 if (mbr2->MinY >= mbr1->MinY && mbr2->MinY <= mbr1->MaxY)
3821 ok_3 = 1;
3822 if (mbr2->MaxY >= mbr1->MinY && mbr2->MaxY <= mbr1->MaxY)
3823 ok_4 = 1;
3824 if (ok_1 && ok_2 && ok_3 && ok_4)
3825 return 1;
3826 return 0;
3827 }
3828
3829 GAIAGEO_DECLARE int
gaiaMbrsWithin(gaiaGeomCollPtr mbr1,gaiaGeomCollPtr mbr2)3830 gaiaMbrsWithin (gaiaGeomCollPtr mbr1, gaiaGeomCollPtr mbr2)
3831 {
3832 /*
3833 / checks if MBR-2 completely contains MBR-1
3834 /
3835 / returns 1 if TRUE
3836 / 0 if FALSE
3837 */
3838 int ok_1 = 0;
3839 int ok_2 = 0;
3840 int ok_3 = 0;
3841 int ok_4 = 0;
3842 if (mbr1->MinX >= mbr2->MinX && mbr1->MinX <= mbr2->MaxX)
3843 ok_1 = 1;
3844 if (mbr1->MaxX >= mbr2->MinX && mbr1->MaxX <= mbr2->MaxX)
3845 ok_2 = 1;
3846 if (mbr1->MinY >= mbr2->MinY && mbr1->MinY <= mbr2->MaxY)
3847 ok_3 = 1;
3848 if (mbr1->MaxY >= mbr2->MinY && mbr1->MaxY <= mbr2->MaxY)
3849 ok_4 = 1;
3850 if (ok_1 && ok_2 && ok_3 && ok_4)
3851 return 1;
3852 return 0;
3853 }
3854
3855 static void
fatMakePoint(double x,double y,int srid,unsigned char ** result,int * size)3856 fatMakePoint (double x, double y, int srid, unsigned char **result, int *size)
3857 {
3858 /* build a Blob encoded Geometry representing a POINT */
3859 unsigned char *ptr;
3860 int endian_arch = gaiaEndianArch ();
3861 /* computing the Blob size and then allocating it */
3862 *size = 44; /* header size */
3863 *size += (sizeof (double) * 2); /* [x,y] coords */
3864 *result = malloc (*size);
3865 ptr = *result;
3866 /* setting the Blob value */
3867 *ptr = GAIA_MARK_START; /* START signature */
3868 *(ptr + 1) = GAIA_LITTLE_ENDIAN; /* byte ordering */
3869 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
3870 gaiaExport64 (ptr + 6, x, 1, endian_arch); /* MBR - minimum X */
3871 gaiaExport64 (ptr + 14, y, 1, endian_arch); /* MBR - minimum Y */
3872 gaiaExport64 (ptr + 22, x, 1, endian_arch); /* MBR - maximum X */
3873 gaiaExport64 (ptr + 30, y, 1, endian_arch); /* MBR - maximum Y */
3874 *(ptr + 38) = GAIA_MARK_MBR; /* MBR signature */
3875 gaiaExport32 (ptr + 39, GAIA_POINT, 1, endian_arch); /* class POINT */
3876 gaiaExport64 (ptr + 43, x, 1, endian_arch); /* X */
3877 gaiaExport64 (ptr + 51, y, 1, endian_arch); /* Y */
3878 *(ptr + 59) = GAIA_MARK_END; /* END signature */
3879 }
3880
3881 static void
tinyMakePoint(double x,double y,int srid,unsigned char ** result,int * size)3882 tinyMakePoint (double x, double y, int srid, unsigned char **result, int *size)
3883 {
3884 /* build a Blob encoded TinyPoint representing a POINT */
3885 unsigned char *ptr;
3886 int endian_arch = gaiaEndianArch ();
3887 /* allocating the BLOB */
3888 *size = 24;
3889 *result = malloc (*size);
3890 ptr = *result;
3891 /* setting the Blob value */
3892 *ptr = GAIA_MARK_START; /* START signature */
3893 *(ptr + 1) = GAIA_TINYPOINT_LITTLE_ENDIAN; /* byte ordering */
3894 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
3895 *(ptr + 6) = GAIA_TINYPOINT_XY; /* Point Type */
3896 gaiaExport64 (ptr + 7, x, 1, endian_arch); /* X */
3897 gaiaExport64 (ptr + 15, y, 1, endian_arch); /* Y */
3898 *(ptr + 23) = GAIA_MARK_END; /* END signature */
3899 }
3900
3901 GAIAGEO_DECLARE void
gaiaMakePoint(double x,double y,int srid,unsigned char ** result,int * size)3902 gaiaMakePoint (double x, double y, int srid, unsigned char **result, int *size)
3903 {
3904 /* always returns a BLOB-Geometry encoded POINT */
3905 gaiaMakePointEx (0, x, y, srid, result, size);
3906 }
3907
3908 GAIAGEO_DECLARE void
gaiaMakePointEx(int tiny_point,double x,double y,int srid,unsigned char ** result,int * size)3909 gaiaMakePointEx (int tiny_point, double x, double y, int srid,
3910 unsigned char **result, int *size)
3911 {
3912 /* conditionally returns either a BLOB-Geometry or BLOB-TinyPoint encoded POINT */
3913 if (tiny_point)
3914 tinyMakePoint (x, y, srid, result, size);
3915 else
3916 fatMakePoint (x, y, srid, result, size);
3917 }
3918
3919 static void
fatMakePointZ(double x,double y,double z,int srid,unsigned char ** result,int * size)3920 fatMakePointZ (double x, double y, double z, int srid, unsigned char **result,
3921 int *size)
3922 {
3923 /* build a Blob encoded Geometry representing a POINT Z */
3924 unsigned char *ptr;
3925 int endian_arch = gaiaEndianArch ();
3926 /* computing the Blob size and then allocating it */
3927 *size = 44; /* header size */
3928 *size += (sizeof (double) * 3); /* [x,y,z] coords */
3929 *result = malloc (*size);
3930 ptr = *result;
3931 /* setting the Blob value */
3932 *ptr = GAIA_MARK_START; /* START signature */
3933 *(ptr + 1) = GAIA_LITTLE_ENDIAN; /* byte ordering */
3934 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
3935 gaiaExport64 (ptr + 6, x, 1, endian_arch); /* MBR - minimum X */
3936 gaiaExport64 (ptr + 14, y, 1, endian_arch); /* MBR - minimum Y */
3937 gaiaExport64 (ptr + 22, x, 1, endian_arch); /* MBR - maximum X */
3938 gaiaExport64 (ptr + 30, y, 1, endian_arch); /* MBR - maximum Y */
3939 *(ptr + 38) = GAIA_MARK_MBR; /* MBR signature */
3940 gaiaExport32 (ptr + 39, GAIA_POINTZ, 1, endian_arch); /* class POINT */
3941 gaiaExport64 (ptr + 43, x, 1, endian_arch); /* X */
3942 gaiaExport64 (ptr + 51, y, 1, endian_arch); /* Y */
3943 gaiaExport64 (ptr + 59, z, 1, endian_arch); /* Z */
3944 *(ptr + 67) = GAIA_MARK_END; /* END signature */
3945 }
3946
3947 static void
tinyMakePointZ(double x,double y,double z,int srid,unsigned char ** result,int * size)3948 tinyMakePointZ (double x, double y, double z, int srid, unsigned char **result,
3949 int *size)
3950 {
3951 /* build a Blob encoded TinyPoint representing a POINT Z */
3952 unsigned char *ptr;
3953 int endian_arch = gaiaEndianArch ();
3954 /* allocating the BLOB */
3955 *size = 32;
3956 *result = malloc (*size);
3957 ptr = *result;
3958 /* setting the Blob value */
3959 *ptr = GAIA_MARK_START; /* START signature */
3960 *(ptr + 1) = GAIA_TINYPOINT_LITTLE_ENDIAN; /* byte ordering */
3961 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
3962 *(ptr + 6) = GAIA_TINYPOINT_XYZ; /* Point Type */
3963 gaiaExport64 (ptr + 7, x, 1, endian_arch); /* X */
3964 gaiaExport64 (ptr + 15, y, 1, endian_arch); /* Y */
3965 gaiaExport64 (ptr + 23, z, 1, endian_arch); /* Z */
3966 *(ptr + 31) = GAIA_MARK_END; /* END signature */
3967 }
3968
3969 GAIAGEO_DECLARE void
gaiaMakePointZ(double x,double y,double z,int srid,unsigned char ** result,int * size)3970 gaiaMakePointZ (double x, double y, double z, int srid, unsigned char **result,
3971 int *size)
3972 {
3973 /* always returns a BLOB-Geometry encoded POINT Z */
3974 gaiaMakePointZEx (0, x, y, z, srid, result, size);
3975 }
3976
3977 GAIAGEO_DECLARE void
gaiaMakePointZEx(int tiny_point,double x,double y,double z,int srid,unsigned char ** result,int * size)3978 gaiaMakePointZEx (int tiny_point, double x, double y, double z, int srid,
3979 unsigned char **result, int *size)
3980 {
3981 /* conditionally returns either a BLOB-Geometry or BLOB-TinyPoint encoded POINT Z */
3982 if (tiny_point)
3983 tinyMakePointZ (x, y, z, srid, result, size);
3984 else
3985 fatMakePointZ (x, y, z, srid, result, size);
3986 }
3987
3988 static void
fatMakePointM(double x,double y,double m,int srid,unsigned char ** result,int * size)3989 fatMakePointM (double x, double y, double m, int srid, unsigned char **result,
3990 int *size)
3991 {
3992 /* build a Blob encoded Geometry representing a POINT M */
3993 unsigned char *ptr;
3994 int endian_arch = gaiaEndianArch ();
3995 /* computing the Blob size and then allocating it */
3996 *size = 44; /* header size */
3997 *size += (sizeof (double) * 3); /* [x,y,z] coords */
3998 *result = malloc (*size);
3999 ptr = *result;
4000 /* setting the Blob value */
4001 *ptr = GAIA_MARK_START; /* START signature */
4002 *(ptr + 1) = GAIA_LITTLE_ENDIAN; /* byte ordering */
4003 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
4004 gaiaExport64 (ptr + 6, x, 1, endian_arch); /* MBR - minimum X */
4005 gaiaExport64 (ptr + 14, y, 1, endian_arch); /* MBR - minimum Y */
4006 gaiaExport64 (ptr + 22, x, 1, endian_arch); /* MBR - maximum X */
4007 gaiaExport64 (ptr + 30, y, 1, endian_arch); /* MBR - maximum Y */
4008 *(ptr + 38) = GAIA_MARK_MBR; /* MBR signature */
4009 gaiaExport32 (ptr + 39, GAIA_POINTM, 1, endian_arch); /* class POINT */
4010 gaiaExport64 (ptr + 43, x, 1, endian_arch); /* X */
4011 gaiaExport64 (ptr + 51, y, 1, endian_arch); /* Y */
4012 gaiaExport64 (ptr + 59, m, 1, endian_arch); /* M */
4013 *(ptr + 67) = GAIA_MARK_END; /* END signature */
4014 }
4015
4016 static void
tinyMakePointM(double x,double y,double m,int srid,unsigned char ** result,int * size)4017 tinyMakePointM (double x, double y, double m, int srid, unsigned char **result,
4018 int *size)
4019 {
4020 /* build a Blob encoded TinyPoint representing a POINT M */
4021 unsigned char *ptr;
4022 int endian_arch = gaiaEndianArch ();
4023 /* allocating the BLOB */
4024 *size = 32;
4025 *result = malloc (*size);
4026 ptr = *result;
4027 /* setting the Blob value */
4028 *ptr = GAIA_MARK_START; /* START signature */
4029 *(ptr + 1) = GAIA_TINYPOINT_LITTLE_ENDIAN; /* byte ordering */
4030 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
4031 *(ptr + 6) = GAIA_TINYPOINT_XYM; /* Point Type */
4032 gaiaExport64 (ptr + 7, x, 1, endian_arch); /* X */
4033 gaiaExport64 (ptr + 15, y, 1, endian_arch); /* Y */
4034 gaiaExport64 (ptr + 23, m, 1, endian_arch); /* M */
4035 *(ptr + 31) = GAIA_MARK_END; /* END signature */
4036 }
4037
4038 GAIAGEO_DECLARE void
gaiaMakePointM(double x,double y,double m,int srid,unsigned char ** result,int * size)4039 gaiaMakePointM (double x, double y, double m, int srid, unsigned char **result,
4040 int *size)
4041 {
4042 /* always returns a BLOB-Geometry encoded POINT M */
4043 gaiaMakePointMEx (0, x, y, m, srid, result, size);
4044 }
4045
4046 GAIAGEO_DECLARE void
gaiaMakePointMEx(int tiny_point,double x,double y,double m,int srid,unsigned char ** result,int * size)4047 gaiaMakePointMEx (int tiny_point, double x, double y, double m, int srid,
4048 unsigned char **result, int *size)
4049 {
4050 /* conditionally returns either a BLOB-Geometry or BLOB-TinyPoint encoded POINT M */
4051 if (tiny_point)
4052 tinyMakePointM (x, y, m, srid, result, size);
4053 else
4054 fatMakePointM (x, y, m, srid, result, size);
4055 }
4056
4057 static void
fatMakePointZM(double x,double y,double z,double m,int srid,unsigned char ** result,int * size)4058 fatMakePointZM (double x, double y, double z, double m, int srid,
4059 unsigned char **result, int *size)
4060 {
4061 /* build a Blob encoded Geometry representing a POINT ZM */
4062 unsigned char *ptr;
4063 int endian_arch = gaiaEndianArch ();
4064 /* computing the Blob size and then allocating it */
4065 *size = 44; /* header size */
4066 *size += (sizeof (double) * 4); /* [x,y,z,m] coords */
4067 *result = malloc (*size);
4068 ptr = *result;
4069 /* setting the Blob value */
4070 *ptr = GAIA_MARK_START; /* START signature */
4071 *(ptr + 1) = GAIA_LITTLE_ENDIAN; /* byte ordering */
4072 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
4073 gaiaExport64 (ptr + 6, x, 1, endian_arch); /* MBR - minimum X */
4074 gaiaExport64 (ptr + 14, y, 1, endian_arch); /* MBR - minimum Y */
4075 gaiaExport64 (ptr + 22, x, 1, endian_arch); /* MBR - maximum X */
4076 gaiaExport64 (ptr + 30, y, 1, endian_arch); /* MBR - maximum Y */
4077 *(ptr + 38) = GAIA_MARK_MBR; /* MBR signature */
4078 gaiaExport32 (ptr + 39, GAIA_POINTZM, 1, endian_arch); /* class POINT */
4079 gaiaExport64 (ptr + 43, x, 1, endian_arch); /* X */
4080 gaiaExport64 (ptr + 51, y, 1, endian_arch); /* Y */
4081 gaiaExport64 (ptr + 59, z, 1, endian_arch); /* Z */
4082 gaiaExport64 (ptr + 67, m, 1, endian_arch); /* M */
4083 *(ptr + 75) = GAIA_MARK_END; /* END signature */
4084 }
4085
4086 static void
tinyMakePointZM(double x,double y,double z,double m,int srid,unsigned char ** result,int * size)4087 tinyMakePointZM (double x, double y, double z, double m, int srid,
4088 unsigned char **result, int *size)
4089 {
4090 /* build a Blob encoded TinyPoint representing a POINT ZM */
4091 unsigned char *ptr;
4092 int endian_arch = gaiaEndianArch ();
4093 /* allocating the BLOB */
4094 *size = 40;
4095 *result = malloc (*size);
4096 ptr = *result;
4097 /* setting the Blob value */
4098 *ptr = GAIA_MARK_START; /* START signature */
4099 *(ptr + 1) = GAIA_TINYPOINT_LITTLE_ENDIAN; /* byte ordering */
4100 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
4101 *(ptr + 6) = GAIA_TINYPOINT_XYZM; /* Point Type */
4102 gaiaExport64 (ptr + 7, x, 1, endian_arch); /* X */
4103 gaiaExport64 (ptr + 15, y, 1, endian_arch); /* Y */
4104 gaiaExport64 (ptr + 23, z, 1, endian_arch); /* Z */
4105 gaiaExport64 (ptr + 31, m, 1, endian_arch); /* M */
4106 *(ptr + 39) = GAIA_MARK_END; /* END signature */
4107 }
4108
4109 GAIAGEO_DECLARE void
gaiaMakePointZM(double x,double y,double z,double m,int srid,unsigned char ** result,int * size)4110 gaiaMakePointZM (double x, double y, double z, double m, int srid,
4111 unsigned char **result, int *size)
4112 {
4113 /* always returns a BLOB-Geometry encoded POINT ZM */
4114 gaiaMakePointZMEx (0, x, y, z, m, srid, result, size);
4115 }
4116
4117 GAIAGEO_DECLARE void
gaiaMakePointZMEx(int tiny_point,double x,double y,double z,double m,int srid,unsigned char ** result,int * size)4118 gaiaMakePointZMEx (int tiny_point, double x, double y, double z, double m,
4119 int srid, unsigned char **result, int *size)
4120 {
4121 /* conditionally returns either a BLOB-Geometry or BLOB-TinyPoint encoded POINT ZM */
4122 if (tiny_point)
4123 tinyMakePointZM (x, y, z, m, srid, result, size);
4124 else
4125 fatMakePointZM (x, y, z, m, srid, result, size);
4126 }
4127
4128 GAIAGEO_DECLARE void
gaiaMakeLine(gaiaGeomCollPtr geom1,gaiaGeomCollPtr geom2,unsigned char ** result,int * size)4129 gaiaMakeLine (gaiaGeomCollPtr geom1, gaiaGeomCollPtr geom2,
4130 unsigned char **result, int *size)
4131 {
4132 /* build a Blob encoded Geometry representing a LINESTRING (segment) */
4133 int pts;
4134 int lns;
4135 int pgs;
4136 gaiaPointPtr pt;
4137 gaiaLinestringPtr ln;
4138 gaiaPolygonPtr pg;
4139 gaiaGeomCollPtr g;
4140 int dims0 = 0;
4141 int dims1 = 0;
4142 int dims;
4143 double x0 = 0.0;
4144 double y0 = 0.0;
4145 double z0 = 0.0;
4146 double m0 = 0.0;
4147 double x1 = 0.0;
4148 double y1 = 0.0;
4149 double z1 = 0.0;
4150 double m1 = 0.0;
4151
4152 /* checking if GEOM-1 simply is a POINT */
4153 if (geom1 == NULL)
4154 {
4155 *result = NULL;
4156 *size = 0;
4157 return;
4158 }
4159 pts = 0;
4160 lns = 0;
4161 pgs = 0;
4162 pt = geom1->FirstPoint;
4163 while (pt)
4164 {
4165 pts++;
4166 x0 = pt->X;
4167 y0 = pt->Y;
4168 z0 = pt->Z;
4169 m0 = pt->M;
4170 dims0 = pt->DimensionModel;
4171 pt = pt->Next;
4172 }
4173 ln = geom1->FirstLinestring;
4174 while (ln)
4175 {
4176 lns++;
4177 ln = ln->Next;
4178 }
4179 pg = geom1->FirstPolygon;
4180 while (pg)
4181 {
4182 pgs++;
4183 pg = pg->Next;
4184 }
4185 if (pts == 1 && lns == 0 && pgs == 0)
4186 ;
4187 else
4188 {
4189 /* failure: not a simple POINT */
4190 *result = NULL;
4191 *size = 0;
4192 return;
4193 }
4194
4195 /* checking if GEOM-2 simply is a POINT */
4196 if (geom2 == NULL)
4197 {
4198 *result = NULL;
4199 *size = 0;
4200 return;
4201 }
4202 pts = 0;
4203 lns = 0;
4204 pgs = 0;
4205 pt = geom2->FirstPoint;
4206 while (pt)
4207 {
4208 pts++;
4209 x1 = pt->X;
4210 y1 = pt->Y;
4211 z1 = pt->Z;
4212 m1 = pt->M;
4213 dims1 = pt->DimensionModel;
4214 pt = pt->Next;
4215 }
4216 ln = geom2->FirstLinestring;
4217 while (ln)
4218 {
4219 lns++;
4220 ln = ln->Next;
4221 }
4222 pg = geom2->FirstPolygon;
4223 while (pg)
4224 {
4225 pgs++;
4226 pg = pg->Next;
4227 }
4228 if (pts == 1 && lns == 0 && pgs == 0)
4229 ;
4230 else
4231 {
4232 /* failure: not a simple POINT */
4233 *result = NULL;
4234 *size = 0;
4235 return;
4236 }
4237
4238 /* building a new Geometry */
4239 if (dims0 == dims1)
4240 dims = dims0;
4241 else
4242 {
4243 if (dims0 == GAIA_XY_Z_M || dims1 == GAIA_XY_Z_M)
4244 dims = GAIA_XY_Z_M;
4245 else if (dims0 == GAIA_XY_Z && dims1 == GAIA_XY_M)
4246 dims = GAIA_XY_Z_M;
4247 else if (dims0 == GAIA_XY_M && dims1 == GAIA_XY_Z)
4248 dims = GAIA_XY_Z_M;
4249 else if (dims0 == GAIA_XY_Z)
4250 dims = GAIA_XY_Z;
4251 else if (dims1 == GAIA_XY_Z)
4252 dims = GAIA_XY_Z;
4253 else if (dims0 == GAIA_XY_M)
4254 dims = GAIA_XY_M;
4255 else if (dims1 == GAIA_XY_M)
4256 dims = GAIA_XY_M;
4257 else
4258 dims = GAIA_XY;
4259 }
4260 if (dims == GAIA_XY_Z_M)
4261 g = gaiaAllocGeomCollXYZM ();
4262 else if (dims == GAIA_XY_Z)
4263 g = gaiaAllocGeomCollXYZ ();
4264 else if (dims == GAIA_XY_M)
4265 g = gaiaAllocGeomCollXYM ();
4266 else
4267 g = gaiaAllocGeomColl ();
4268 g->Srid = geom1->Srid;
4269 g->DeclaredType = GAIA_LINESTRING;
4270 ln = gaiaAddLinestringToGeomColl (g, 2);
4271 if (dims == GAIA_XY_Z_M)
4272 {
4273 gaiaSetPointXYZM (ln->Coords, 0, x0, y0, z0, m0);
4274 gaiaSetPointXYZM (ln->Coords, 1, x1, y1, z1, m1);
4275 }
4276 else if (dims == GAIA_XY_Z)
4277 {
4278 gaiaSetPointXYZ (ln->Coords, 0, x0, y0, z0);
4279 gaiaSetPointXYZ (ln->Coords, 1, x1, y1, z1);
4280 }
4281 else if (dims == GAIA_XY_M)
4282 {
4283 gaiaSetPointXYM (ln->Coords, 0, x0, y0, m0);
4284 gaiaSetPointXYM (ln->Coords, 1, x1, y1, m1);
4285 }
4286 else
4287 {
4288 gaiaSetPoint (ln->Coords, 0, x0, y0);
4289 gaiaSetPoint (ln->Coords, 1, x1, y1);
4290 }
4291 /* converting to Binary Blob */
4292 gaiaToSpatiaLiteBlobWkb (g, result, size);
4293 gaiaFreeGeomColl (g);
4294 }
4295
4296 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaMergeGeometries(gaiaGeomCollPtr geom1,gaiaGeomCollPtr geom2)4297 gaiaMergeGeometries (gaiaGeomCollPtr geom1, gaiaGeomCollPtr geom2)
4298 {
4299 return gaiaMergeGeometries_r (NULL, geom1, geom2);
4300 }
4301
4302 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaMergeGeometries_r(const void * cache,gaiaGeomCollPtr geom1,gaiaGeomCollPtr geom2)4303 gaiaMergeGeometries_r (const void *cache, gaiaGeomCollPtr geom1,
4304 gaiaGeomCollPtr geom2)
4305 {
4306 /* mergine a second generic Geometries into the first one */
4307 gaiaPointPtr pt;
4308 gaiaLinestringPtr ln;
4309 gaiaLinestringPtr new_ln;
4310 gaiaPolygonPtr pg;
4311 gaiaPolygonPtr new_pg;
4312 gaiaRingPtr rng;
4313 gaiaRingPtr new_rng;
4314 double x;
4315 double y;
4316 double z;
4317 double m;
4318 int iv;
4319 int ib;
4320
4321 if (geom1 == NULL || geom2 == NULL)
4322 return NULL;
4323 if (cache != NULL)
4324 cache = NULL;
4325
4326 pt = geom2->FirstPoint;
4327 while (pt)
4328 {
4329 /* copying POINTs from GEOM-2 */
4330 z = 0.0;
4331 m = 0.0;
4332 if (pt->DimensionModel == GAIA_XY_Z_M)
4333 {
4334 x = pt->X;
4335 y = pt->Y;
4336 z = pt->Z;
4337 m = pt->M;
4338 }
4339 else if (pt->DimensionModel == GAIA_XY_Z)
4340 {
4341 x = pt->X;
4342 y = pt->Y;
4343 z = pt->Z;
4344 }
4345 else if (pt->DimensionModel == GAIA_XY_M)
4346 {
4347 x = pt->X;
4348 y = pt->Y;
4349 m = pt->M;
4350 }
4351 else
4352 {
4353 x = pt->X;
4354 y = pt->Y;
4355 }
4356 if (geom1->DimensionModel == GAIA_XY_Z_M)
4357 {
4358 gaiaAddPointToGeomCollXYZM (geom1, x, y, z, m);
4359 }
4360 else if (geom1->DimensionModel == GAIA_XY_Z)
4361 {
4362 gaiaAddPointToGeomCollXYZ (geom1, x, y, z);
4363 }
4364 else if (geom1->DimensionModel == GAIA_XY_M)
4365 {
4366 gaiaAddPointToGeomCollXYM (geom1, x, y, m);
4367 }
4368 else
4369 {
4370 gaiaAddPointToGeomColl (geom1, x, y);
4371 }
4372 pt = pt->Next;
4373 }
4374
4375 ln = geom2->FirstLinestring;
4376 while (ln)
4377 {
4378 /* copying LINESTRINGs from GEOM-2 */
4379 new_ln = gaiaAddLinestringToGeomColl (geom1, ln->Points);
4380 for (iv = 0; iv < ln->Points; iv++)
4381 {
4382 z = 0.0;
4383 m = 0.0;
4384 if (ln->DimensionModel == GAIA_XY_Z_M)
4385 {
4386 gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
4387 }
4388 else if (ln->DimensionModel == GAIA_XY_Z)
4389 {
4390 gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
4391 }
4392 else if (ln->DimensionModel == GAIA_XY_M)
4393 {
4394 gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
4395 }
4396 else
4397 {
4398 gaiaGetPoint (ln->Coords, iv, &x, &y);
4399 }
4400 if (new_ln->DimensionModel == GAIA_XY_Z_M)
4401 {
4402 gaiaSetPointXYZM (new_ln->Coords, iv, x, y, z, m);
4403 }
4404 else if (new_ln->DimensionModel == GAIA_XY_Z)
4405 {
4406 gaiaSetPointXYZ (new_ln->Coords, iv, x, y, z);
4407 }
4408 else if (new_ln->DimensionModel == GAIA_XY_M)
4409 {
4410 gaiaSetPointXYM (new_ln->Coords, iv, x, y, m);
4411 }
4412 else
4413 {
4414 gaiaSetPoint (new_ln->Coords, iv, x, y);
4415 }
4416 }
4417 ln = ln->Next;
4418 }
4419
4420 pg = geom2->FirstPolygon;
4421 while (pg)
4422 {
4423 /* copying POLYGONs from GEOM-2 */
4424 rng = pg->Exterior;
4425 new_pg =
4426 gaiaAddPolygonToGeomColl (geom1, rng->Points, pg->NumInteriors);
4427 new_rng = new_pg->Exterior;
4428 for (iv = 0; iv < rng->Points; iv++)
4429 {
4430 /* Exterior Ring */
4431 z = 0.0;
4432 m = 0.0;
4433 if (rng->DimensionModel == GAIA_XY_Z_M)
4434 {
4435 gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
4436 }
4437 else if (rng->DimensionModel == GAIA_XY_Z)
4438 {
4439 gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
4440 }
4441 else if (rng->DimensionModel == GAIA_XY_M)
4442 {
4443 gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
4444 }
4445 else
4446 {
4447 gaiaGetPoint (rng->Coords, iv, &x, &y);
4448 }
4449 if (new_rng->DimensionModel == GAIA_XY_Z_M)
4450 {
4451 gaiaSetPointXYZM (new_rng->Coords, iv, x, y, z, m);
4452 }
4453 else if (new_rng->DimensionModel == GAIA_XY_Z)
4454 {
4455 gaiaSetPointXYZ (new_rng->Coords, iv, x, y, z);
4456 }
4457 else if (new_rng->DimensionModel == GAIA_XY_M)
4458 {
4459 gaiaSetPointXYM (new_rng->Coords, iv, x, y, m);
4460 }
4461 else
4462 {
4463 gaiaSetPoint (new_rng->Coords, iv, x, y);
4464 }
4465 }
4466 for (ib = 0; ib < pg->NumInteriors; ib++)
4467 {
4468 /* Interior Rings */
4469 rng = pg->Interiors + ib;
4470 new_rng = gaiaAddInteriorRing (new_pg, ib, rng->Points);
4471 for (iv = 0; iv < rng->Points; iv++)
4472 {
4473 z = 0.0;
4474 m = 0.0;
4475 if (rng->DimensionModel == GAIA_XY_Z_M)
4476 {
4477 gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
4478 }
4479 else if (rng->DimensionModel == GAIA_XY_Z)
4480 {
4481 gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
4482 }
4483 else if (rng->DimensionModel == GAIA_XY_M)
4484 {
4485 gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
4486 }
4487 else
4488 {
4489 gaiaGetPoint (rng->Coords, iv, &x, &y);
4490 }
4491 if (new_rng->DimensionModel == GAIA_XY_Z_M)
4492 {
4493 gaiaSetPointXYZM (new_rng->Coords, iv, x, y, z, m);
4494 }
4495 else if (new_rng->DimensionModel == GAIA_XY_Z)
4496 {
4497 gaiaSetPointXYZ (new_rng->Coords, iv, x, y, z);
4498 }
4499 else if (new_rng->DimensionModel == GAIA_XY_M)
4500 {
4501 gaiaSetPointXYM (new_rng->Coords, iv, x, y, m);
4502 }
4503 else
4504 {
4505 gaiaSetPoint (new_rng->Coords, iv, x, y);
4506 }
4507 }
4508 }
4509 pg = pg->Next;
4510 }
4511
4512 return geom1;
4513 }
4514
4515 GAIAGEO_DECLARE void
gaiaBuildMbr(double x1,double y1,double x2,double y2,int srid,unsigned char ** result,int * size)4516 gaiaBuildMbr (double x1, double y1, double x2, double y2, int srid,
4517 unsigned char **result, int *size)
4518 {
4519 /* build a Blob encoded Geometry representing an MBR */
4520 unsigned char *ptr;
4521 double minx;
4522 double maxx;
4523 double miny;
4524 double maxy;
4525 int endian_arch = gaiaEndianArch ();
4526 /* computing MinMax coords */
4527 if (x1 > x2)
4528 {
4529 maxx = x1;
4530 minx = x2;
4531 }
4532 else
4533 {
4534 minx = x1;
4535 maxx = x2;
4536 }
4537 if (y1 > y2)
4538 {
4539 maxy = y1;
4540 miny = y2;
4541 }
4542 else
4543 {
4544 miny = y1;
4545 maxy = y2;
4546 }
4547 /* computing the Blob size and then allocating it */
4548 *size = 44; /* header size */
4549 *size += (8 + ((sizeof (double) * 2) * 5)); /* # rings + # points + [x.y] array - exterior ring */
4550 *result = malloc (*size);
4551 ptr = *result;
4552 /* setting the Blob value */
4553 *ptr = GAIA_MARK_START; /* START signature */
4554 *(ptr + 1) = GAIA_LITTLE_ENDIAN; /* byte ordering */
4555 gaiaExport32 (ptr + 2, srid, 1, endian_arch); /* the SRID */
4556 gaiaExport64 (ptr + 6, minx, 1, endian_arch); /* MBR - minimum X */
4557 gaiaExport64 (ptr + 14, miny, 1, endian_arch); /* MBR - minimum Y */
4558 gaiaExport64 (ptr + 22, maxx, 1, endian_arch); /* MBR - maximum X */
4559 gaiaExport64 (ptr + 30, maxy, 1, endian_arch); /* MBR - maximum Y */
4560 *(ptr + 38) = GAIA_MARK_MBR; /* MBR signature */
4561 gaiaExport32 (ptr + 39, GAIA_POLYGON, 1, endian_arch); /* class POLYGON */
4562 gaiaExport32 (ptr + 43, 1, 1, endian_arch); /* # rings */
4563 gaiaExport32 (ptr + 47, 5, 1, endian_arch); /* # points - exterior ring */
4564 ptr += 51;
4565 /* setting Envelope points */
4566 gaiaExport64 (ptr, minx, 1, endian_arch);
4567 gaiaExport64 (ptr + 8, miny, 1, endian_arch);
4568 ptr += 16;
4569 gaiaExport64 (ptr, maxx, 1, endian_arch);
4570 gaiaExport64 (ptr + 8, miny, 1, endian_arch);
4571 ptr += 16;
4572 gaiaExport64 (ptr, maxx, 1, endian_arch);
4573 gaiaExport64 (ptr + 8, maxy, 1, endian_arch);
4574 ptr += 16;
4575 gaiaExport64 (ptr, minx, 1, endian_arch);
4576 gaiaExport64 (ptr + 8, maxy, 1, endian_arch);
4577 ptr += 16;
4578 gaiaExport64 (ptr, minx, 1, endian_arch);
4579 gaiaExport64 (ptr + 8, miny, 1, endian_arch);
4580 ptr += 16;
4581 *ptr = GAIA_MARK_END; /* END signature */
4582 }
4583
4584 GAIAGEO_DECLARE void
gaiaBuildCircleMbr(double x,double y,double radius,int srid,unsigned char ** result,int * size)4585 gaiaBuildCircleMbr (double x, double y, double radius, int srid,
4586 unsigned char **result, int *size)
4587 {
4588 /* build a Blob encoded Geometry representing an MBR */
4589 int sz;
4590 unsigned char *res = NULL;
4591 double minx = x - radius;
4592 double maxx = x + radius;
4593 double miny = y - radius;
4594 double maxy = y + radius;
4595 gaiaBuildMbr (minx, miny, maxx, maxy, srid, &res, &sz);
4596 if (!res)
4597 {
4598 *result = NULL;
4599 *size = 0;
4600 }
4601 else
4602 {
4603 *result = res;
4604 *size = sz;
4605 }
4606 }
4607
4608 GAIAGEO_DECLARE void
gaiaBuildFilterMbr(double x1,double y1,double x2,double y2,int mode,unsigned char ** result,int * size)4609 gaiaBuildFilterMbr (double x1, double y1, double x2, double y2, int mode,
4610 unsigned char **result, int *size)
4611 {
4612 /* build a filter for an MBR */
4613 unsigned char *ptr;
4614 double minx;
4615 double maxx;
4616 double miny;
4617 double maxy;
4618 int endian_arch = gaiaEndianArch ();
4619 char filter = GAIA_FILTER_MBR_WITHIN;
4620 if (mode == GAIA_FILTER_MBR_CONTAINS)
4621 filter = GAIA_FILTER_MBR_CONTAINS;
4622 if (mode == GAIA_FILTER_MBR_INTERSECTS)
4623 filter = GAIA_FILTER_MBR_INTERSECTS;
4624 if (mode == GAIA_FILTER_MBR_DECLARE)
4625 filter = GAIA_FILTER_MBR_DECLARE;
4626 /* computing MinMax coords */
4627 if (x1 > x2)
4628 {
4629 maxx = x1;
4630 minx = x2;
4631 }
4632 else
4633 {
4634 minx = x1;
4635 maxx = x2;
4636 }
4637 if (y1 > y2)
4638 {
4639 maxy = y1;
4640 miny = y2;
4641 }
4642 else
4643 {
4644 miny = y1;
4645 maxy = y2;
4646 }
4647 /* computing the Blob size and then allocating it */
4648 *size = 37; /* MBR filter size */
4649 *result = malloc (*size);
4650 ptr = *result;
4651 /* setting the Blob value */
4652 *ptr = filter; /* signature */
4653 ptr++;
4654 gaiaExport64 (ptr, minx, 1, endian_arch); /* MBR - minimum X */
4655 ptr += 8;
4656 *ptr = filter; /* signature */
4657 ptr++;
4658 gaiaExport64 (ptr, miny, 1, endian_arch); /* MBR - minimum Y */
4659 ptr += 8;
4660 *ptr = filter; /* signature */
4661 ptr++;
4662 gaiaExport64 (ptr, maxx, 1, endian_arch); /* MBR - maximum X */
4663 ptr += 8;
4664 *ptr = filter; /* signature */
4665 ptr++;
4666 gaiaExport64 (ptr, maxy, 1, endian_arch); /* MBR - maximum Y */
4667 ptr += 8;
4668 *ptr = filter; /* signature */
4669 }
4670
4671
4672 GAIAGEO_DECLARE int
gaiaParseFilterMbr(unsigned char * ptr,int size,double * minx,double * miny,double * maxx,double * maxy,int * mode)4673 gaiaParseFilterMbr (unsigned char *ptr, int size, double *minx, double *miny,
4674 double *maxx, double *maxy, int *mode)
4675 {
4676 /* parsing a filter for an MBR */
4677 char decl_mode;
4678 int endian_arch = gaiaEndianArch ();
4679 if (size != 37)
4680 return 0; /* cannot be an MBR Filter */
4681 if (!ptr)
4682 return 0; /* cannot be an MBR Filter */
4683 decl_mode = *(ptr + 0);
4684 if (decl_mode == GAIA_FILTER_MBR_WITHIN)
4685 ;
4686 else if (decl_mode == GAIA_FILTER_MBR_CONTAINS)
4687 ;
4688 else if (decl_mode == GAIA_FILTER_MBR_INTERSECTS)
4689 ;
4690 else if (decl_mode == GAIA_FILTER_MBR_DECLARE)
4691 ;
4692 else
4693 return 0; /* cannot be an MBR Filter */
4694 if (*(ptr + 9)
4695 == decl_mode
4696 && *(ptr +
4697 18) ==
4698 decl_mode && *(ptr + 27) == decl_mode && *(ptr + 36) == decl_mode)
4699 ;
4700 else
4701 return 0; /* cannot be an MBR Filter */
4702 *mode = decl_mode;
4703 *minx = gaiaImport64 (ptr + 1, 1, endian_arch);
4704 *miny = gaiaImport64 (ptr + 10, 1, endian_arch);
4705 *maxx = gaiaImport64 (ptr + 19, 1, endian_arch);
4706 *maxy = gaiaImport64 (ptr + 28, 1, endian_arch);
4707 return 1;
4708 }
4709
4710 GAIAGEO_DECLARE int
gaiaGetMbrMinX(const unsigned char * blob,unsigned int size,double * minx)4711 gaiaGetMbrMinX (const unsigned char *blob, unsigned int size, double *minx)
4712 {
4713 /* returns the MinX coordinate value for a Blob encoded Geometry */
4714 int little_endian;
4715 int endian_arch = gaiaEndianArch ();
4716
4717 if (size == 24 || size == 32 || size == 40)
4718 {
4719 /* testing for a possible TinyPoint BLOB */
4720 if (*(blob + 0) == GAIA_MARK_START &&
4721 (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN
4722 || *(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
4723 && *(blob + (size - 1)) == GAIA_MARK_END)
4724 {
4725 if (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN)
4726 little_endian = 1;
4727 else if (*(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
4728 little_endian = 0;
4729 else
4730 return 0; /* unknown encoding; neither little-endian nor big-endian */
4731 *minx = gaiaImport64 (blob + 7, little_endian, endian_arch);
4732 return 1;
4733 }
4734 }
4735
4736 if (size < 45)
4737 return 0; /* cannot be an internal BLOB WKB geometry */
4738 if (*(blob + 0) != GAIA_MARK_START)
4739 return 0; /* failed to recognize START signature */
4740 if (*(blob + (size - 1)) != GAIA_MARK_END)
4741 return 0; /* failed to recognize END signature */
4742 if (*(blob + 38) != GAIA_MARK_MBR)
4743 return 0; /* failed to recognize MBR signature */
4744 if (*(blob + 1) == GAIA_LITTLE_ENDIAN)
4745 little_endian = 1;
4746 else if (*(blob + 1) == GAIA_BIG_ENDIAN)
4747 little_endian = 0;
4748 else
4749 return 0; /* unknown encoding; neither little-endian nor big-endian */
4750 *minx = gaiaImport64 (blob + 6, little_endian, endian_arch);
4751 return 1;
4752 }
4753
4754 GAIAGEO_DECLARE int
gaiaGetMbrMaxX(const unsigned char * blob,unsigned int size,double * maxx)4755 gaiaGetMbrMaxX (const unsigned char *blob, unsigned int size, double *maxx)
4756 {
4757 /* returns the MaxX coordinate value for a Blob encoded Geometry */
4758 int little_endian;
4759 int endian_arch = gaiaEndianArch ();
4760
4761 if (size == 24 || size == 32 || size == 40)
4762 {
4763 /* testing for a possible TinyPoint BLOB */
4764 if (*(blob + 0) == GAIA_MARK_START &&
4765 (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN
4766 || *(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
4767 && *(blob + (size - 1)) == GAIA_MARK_END)
4768 {
4769 if (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN)
4770 little_endian = 1;
4771 else if (*(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
4772 little_endian = 0;
4773 else
4774 return 0; /* unknown encoding; neither little-endian nor big-endian */
4775 *maxx = gaiaImport64 (blob + 7, little_endian, endian_arch);
4776 return 1;
4777 }
4778 }
4779
4780 if (size < 45)
4781 return 0; /* cannot be an internal BLOB WKB geometry */
4782 if (*(blob + 0) != GAIA_MARK_START)
4783 return 0; /* failed to recognize START signature */
4784 if (*(blob + (size - 1)) != GAIA_MARK_END)
4785 return 0; /* failed to recognize END signature */
4786 if (*(blob + 38) != GAIA_MARK_MBR)
4787 return 0; /* failed to recognize MBR signature */
4788 if (*(blob + 1) == GAIA_LITTLE_ENDIAN)
4789 little_endian = 1;
4790 else if (*(blob + 1) == GAIA_BIG_ENDIAN)
4791 little_endian = 0;
4792 else
4793 return 0; /* unknown encoding; neither little-endian nor big-endian */
4794 *maxx = gaiaImport64 (blob + 22, little_endian, endian_arch);
4795 return 1;
4796 }
4797
4798 GAIAGEO_DECLARE int
gaiaGetMbrMinY(const unsigned char * blob,unsigned int size,double * miny)4799 gaiaGetMbrMinY (const unsigned char *blob, unsigned int size, double *miny)
4800 {
4801 /* returns the MinY coordinate value for a Blob encoded Geometry */
4802 int little_endian;
4803 int endian_arch = gaiaEndianArch ();
4804
4805 if (size == 24 || size == 32 || size == 40)
4806 {
4807 /* testing for a possible TinyPoint BLOB */
4808 if (*(blob + 0) == GAIA_MARK_START &&
4809 (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN
4810 || *(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
4811 && *(blob + (size - 1)) == GAIA_MARK_END)
4812 {
4813 if (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN)
4814 little_endian = 1;
4815 else if (*(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
4816 little_endian = 0;
4817 else
4818 return 0; /* unknown encoding; neither little-endian nor big-endian */
4819 *miny = gaiaImport64 (blob + 15, little_endian, endian_arch);
4820 return 1;
4821 }
4822 }
4823
4824 if (size < 45)
4825 return 0; /* cannot be an internal BLOB WKB geometry */
4826 if (*(blob + 0) != GAIA_MARK_START)
4827 return 0; /* failed to recognize START signature */
4828 if (*(blob + (size - 1)) != GAIA_MARK_END)
4829 return 0; /* failed to recognize END signature */
4830 if (*(blob + 38) != GAIA_MARK_MBR)
4831 return 0; /* failed to recognize MBR signature */
4832 if (*(blob + 1) == GAIA_LITTLE_ENDIAN)
4833 little_endian = 1;
4834 else if (*(blob + 1) == GAIA_BIG_ENDIAN)
4835 little_endian = 0;
4836 else
4837 return 0; /* unknown encoding; neither little-endian nor big-endian */
4838 *miny = gaiaImport64 (blob + 14, little_endian, endian_arch);
4839 return 1;
4840 }
4841
4842 GAIAGEO_DECLARE int
gaiaGetMbrMaxY(const unsigned char * blob,unsigned int size,double * maxy)4843 gaiaGetMbrMaxY (const unsigned char *blob, unsigned int size, double *maxy)
4844 {
4845 /* returns the MaxY coordinate value for a Blob encoded Geometry */
4846 int little_endian;
4847 int endian_arch = gaiaEndianArch ();
4848
4849 if (size == 24 || size == 32 || size == 40)
4850 {
4851 /* testing for a possible TinyPoint BLOB */
4852 if (*(blob + 0) == GAIA_MARK_START &&
4853 (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN
4854 || *(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
4855 && *(blob + (size - 1)) == GAIA_MARK_END)
4856 {
4857 if (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN)
4858 little_endian = 1;
4859 else if (*(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
4860 little_endian = 0;
4861 else
4862 return 0; /* unknown encoding; neither little-endian nor big-endian */
4863 *maxy = gaiaImport64 (blob + 15, little_endian, endian_arch);
4864 return 1;
4865 }
4866 }
4867
4868 if (size < 45)
4869 return 0; /* cannot be an internal BLOB WKB geometry */
4870 if (*(blob + 0) != GAIA_MARK_START)
4871 return 0; /* failed to recognize START signature */
4872 if (*(blob + (size - 1)) != GAIA_MARK_END)
4873 return 0; /* failed to recognize END signature */
4874 if (*(blob + 38) != GAIA_MARK_MBR)
4875 return 0; /* failed to recognize MBR signature */
4876 if (*(blob + 1) == GAIA_LITTLE_ENDIAN)
4877 little_endian = 1;
4878 else if (*(blob + 1) == GAIA_BIG_ENDIAN)
4879 little_endian = 0;
4880 else
4881 return 0; /* unknown encoding; neither little-endian nor big-endian */
4882 *maxy = gaiaImport64 (blob + 30, little_endian, endian_arch);
4883 return 1;
4884 }
4885
4886 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaAddMeasure(gaiaGeomCollPtr geom,double m_start,double m_end)4887 gaiaAddMeasure (gaiaGeomCollPtr geom, double m_start, double m_end)
4888 {
4889 /* linearly interpolates M-values between the start and end points. */
4890 double total_length;
4891 double progressive_length;
4892 gaiaGeomCollPtr geo2;
4893 gaiaLinestringPtr pL;
4894 gaiaLinestringPtr pL2;
4895 int iv;
4896 double x;
4897 double y;
4898 double z;
4899 double m;
4900 double x0;
4901 double y0;
4902 double mm;
4903 double percent;
4904 double interval = m_end - m_start;
4905
4906 if (!geom)
4907 return NULL;
4908 /* only Linestring or MultiLinestrings are accepted */
4909 if (geom->FirstPoint != NULL)
4910 return NULL;
4911 if (geom->FirstPolygon != NULL)
4912 return NULL;
4913 if (geom->FirstLinestring == NULL)
4914 return NULL;
4915
4916 /* computing the total length */
4917 total_length = 0.0;
4918 pL = geom->FirstLinestring;
4919 while (pL != NULL)
4920 {
4921 for (iv = 0; iv < pL->Points; iv++)
4922 {
4923 z = 0.0;
4924 m = 0.0;
4925 if (pL->DimensionModel == GAIA_XY_Z)
4926 {
4927 gaiaGetPointXYZ (pL->Coords, iv, &x, &y, &z);
4928 }
4929 else if (pL->DimensionModel == GAIA_XY_M)
4930 {
4931 gaiaGetPointXYM (pL->Coords, iv, &x, &y, &m);
4932 }
4933 else if (pL->DimensionModel == GAIA_XY_Z_M)
4934 {
4935 gaiaGetPointXYZM (pL->Coords, iv, &x, &y, &z, &m);
4936 }
4937 else
4938 {
4939 gaiaGetPoint (pL->Coords, iv, &x, &y);
4940 }
4941
4942 if (iv != 0)
4943 total_length +=
4944 sqrt (((x0 - x) * (x0 - x)) + ((y0 - y) * (y0 - y)));
4945 x0 = x;
4946 y0 = y;
4947 }
4948 pL = pL->Next;
4949 }
4950
4951 /* creating the output geometry */
4952 progressive_length = 0.0;
4953 if (geom->DimensionModel == GAIA_XY_Z)
4954 geo2 = gaiaAllocGeomCollXYZM ();
4955 else if (geom->DimensionModel == GAIA_XY_M)
4956 geo2 = gaiaAllocGeomCollXYM ();
4957 else if (geom->DimensionModel == GAIA_XY_Z_M)
4958 geo2 = gaiaAllocGeomCollXYZM ();
4959 else
4960 geo2 = gaiaAllocGeomCollXYM ();
4961 geo2->Srid = geom->Srid;
4962 pL = geom->FirstLinestring;
4963 while (pL != NULL)
4964 {
4965 pL2 = gaiaAddLinestringToGeomColl (geo2, pL->Points);
4966 for (iv = 0; iv < pL->Points; iv++)
4967 {
4968 z = 0.0;
4969 m = 0.0;
4970 if (pL->DimensionModel == GAIA_XY_Z)
4971 {
4972 gaiaGetPointXYZ (pL->Coords, iv, &x, &y, &z);
4973 }
4974 else if (pL->DimensionModel == GAIA_XY_M)
4975 {
4976 gaiaGetPointXYM (pL->Coords, iv, &x, &y, &m);
4977 }
4978 else if (pL->DimensionModel == GAIA_XY_Z_M)
4979 {
4980 gaiaGetPointXYZM (pL->Coords, iv, &x, &y, &z, &m);
4981 }
4982 else
4983 {
4984 gaiaGetPoint (pL->Coords, iv, &x, &y);
4985 }
4986
4987 if (iv != 0)
4988 progressive_length +=
4989 sqrt (((x0 - x) * (x0 - x)) + ((y0 - y) * (y0 - y)));
4990 x0 = x;
4991 y0 = y;
4992
4993 /* linealy interpolating M-values */
4994 percent = progressive_length / total_length;
4995 mm = m_start + (interval * percent);
4996 if (pL2->DimensionModel == GAIA_XY_M)
4997 {
4998 gaiaSetPointXYM (pL2->Coords, iv, x, y, mm);
4999 }
5000 else
5001 {
5002 gaiaSetPointXYZM (pL2->Coords, iv, x, y, z, mm);
5003 }
5004 }
5005 pL = pL->Next;
5006 }
5007
5008 return geo2;
5009 }
5010
5011 GAIAGEO_DECLARE int
gaiaInterpolatePoint(const void * p_cache,gaiaGeomCollPtr line,gaiaGeomCollPtr point,double * m_value)5012 gaiaInterpolatePoint (const void *p_cache, gaiaGeomCollPtr line,
5013 gaiaGeomCollPtr point, double *m_value)
5014 {
5015 /* Will interpolate the M-value for a LinestringM at the point closest to the given Point */
5016 gaiaLinestringPtr pL;
5017 int iv;
5018 double x;
5019 double y;
5020 double m;
5021 double z;
5022 double fraction;
5023 double x0;
5024 double y0;
5025 double m0;
5026 double progressive_length;
5027 double pl0;
5028 double length;
5029 double normalized_len;
5030
5031 if (!line)
5032 return 0;
5033 if (!point)
5034 return 0;
5035 /* only a Linestring M is accepted as the first geom */
5036 if (line->FirstPoint != NULL)
5037 return 0;
5038 if (line->FirstPolygon != NULL)
5039 return 0;
5040 if (line->FirstLinestring == NULL)
5041 return 0;
5042 if (line->FirstLinestring != line->LastLinestring)
5043 return 0;
5044 if (line->DimensionModel == GAIA_XY_M
5045 || line->DimensionModel == GAIA_XY_Z_M)
5046 ;
5047 else
5048 return 0;
5049 /* only a Point is accepted as the second geom */
5050 if (point->FirstPolygon != NULL)
5051 return 0;
5052 if (point->FirstLinestring != NULL)
5053 return 0;
5054 if (point->FirstPoint == NULL)
5055 return 0;
5056 if (point->FirstPoint != point->LastPoint)
5057 return 0;
5058
5059 #ifndef OMIT_GEOS /* only if GEOS is supported */
5060
5061 /* locating the Point along the Line */
5062 if (p_cache != NULL)
5063 {
5064 if (!gaiaGeomCollLengthOrPerimeter_r (p_cache, line, 0, &length))
5065 return 0;
5066 fraction = gaiaLineLocatePoint_r (p_cache, line, point);
5067 }
5068 else
5069 {
5070 if (!gaiaGeomCollLengthOrPerimeter (line, 0, &length))
5071 return 0;
5072 fraction = gaiaLineLocatePoint (line, point);
5073 }
5074 normalized_len = length * fraction;
5075
5076 pL = line->FirstLinestring;
5077 if (fraction <= 0.0)
5078 {
5079 /* special case: assuming the start point */
5080 z = 0.0;
5081 if (pL->DimensionModel == GAIA_XY_M)
5082 {
5083 gaiaGetPointXYM (pL->Coords, 0, &x, &y, &m);
5084 }
5085 else
5086 {
5087 gaiaGetPointXYZM (pL->Coords, 0, &x, &y, &z, &m);
5088 }
5089 *m_value = m;
5090 return 1;
5091 }
5092 if (fraction >= 1.0)
5093 {
5094 /* special case: assuming the end point */
5095 z = 0.0;
5096 iv = pL->Points - 1;
5097 if (pL->DimensionModel == GAIA_XY_M)
5098 {
5099 gaiaGetPointXYM (pL->Coords, iv, &x, &y, &m);
5100 }
5101 else
5102 {
5103 gaiaGetPointXYZM (pL->Coords, iv, &x, &y, &z, &m);
5104 }
5105 *m_value = m;
5106 return 1;
5107 }
5108
5109 /* computing the progressive length */
5110 progressive_length = 0.0;
5111 for (iv = 0; iv < pL->Points; iv++)
5112 {
5113 z = 0.0;
5114 if (pL->DimensionModel == GAIA_XY_M)
5115 {
5116 gaiaGetPointXYM (pL->Coords, iv, &x, &y, &m);
5117 }
5118 else
5119 {
5120 gaiaGetPointXYZM (pL->Coords, iv, &x, &y, &z, &m);
5121 }
5122
5123 if (iv != 0)
5124 {
5125 double length =
5126 sqrt (((x0 - x) * (x0 - x)) + ((y0 - y) * (y0 - y)));
5127 progressive_length += length;
5128
5129 if (progressive_length == normalized_len)
5130 {
5131 /* special case: exactly intercepting a vertex */
5132 *m_value = m;
5133 return 1;
5134 }
5135 if (progressive_length > normalized_len)
5136 {
5137 /* interpolating the M-Value */
5138 double interval = m - m0;
5139 double diff = normalized_len - pl0;
5140 double ratio = diff / length;
5141 *m_value = m0 + (interval * ratio);
5142 break;
5143 }
5144 }
5145 x0 = x;
5146 y0 = y;
5147 m0 = m;
5148 pl0 = progressive_length;
5149 }
5150 return 1;
5151
5152 #else
5153 return 0;
5154 #endif /* end GEOS conditional */
5155 }
5156
5157 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaLocateBetweenMeasures(gaiaGeomCollPtr geom,double m_start,double m_end)5158 gaiaLocateBetweenMeasures (gaiaGeomCollPtr geom, double m_start, double m_end)
5159 {
5160 /* extracts points/linestrings accordingly to a range of measures */
5161 gaiaPointPtr pt;
5162 gaiaLinestringPtr ln;
5163 gaiaLinestringPtr new_line;
5164 gaiaGeomCollPtr new_geom = NULL;
5165 gaiaDynamicLinePtr dyn = NULL;
5166 int iv;
5167 double x;
5168 double y;
5169 double z;
5170 double m;
5171 if (!geom)
5172 return NULL;
5173 if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
5174 return NULL;
5175 if (geom->FirstPolygon != NULL)
5176 return NULL;
5177 if (geom->DimensionModel == GAIA_XY_M)
5178 new_geom = gaiaAllocGeomCollXYM ();
5179 else if (geom->DimensionModel == GAIA_XY_Z_M)
5180 new_geom = gaiaAllocGeomCollXYZM ();
5181 else
5182 return NULL;
5183 new_geom->Srid = geom->Srid;
5184 new_geom->DeclaredType = geom->DeclaredType;
5185 pt = geom->FirstPoint;
5186 while (pt)
5187 {
5188 /* extracting POINTs */
5189 if (pt->M >= m_start && pt->M <= m_end)
5190 {
5191 if (geom->DimensionModel == GAIA_XY_M)
5192 gaiaAddPointToGeomCollXYM (new_geom, pt->X, pt->Y, pt->M);
5193 else if (geom->DimensionModel == GAIA_XY_Z_M)
5194 gaiaAddPointToGeomCollXYZM (new_geom, pt->X, pt->Y,
5195 pt->Z, pt->M);
5196 }
5197 pt = pt->Next;
5198 }
5199 ln = geom->FirstLinestring;
5200 while (ln)
5201 {
5202 /* extracting LINESTRINGs */
5203 for (iv = 0; iv < ln->Points; iv++)
5204 {
5205 z = 0.0;
5206 if (ln->DimensionModel == GAIA_XY_Z_M)
5207 {
5208 gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
5209 }
5210 else
5211 {
5212 gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
5213 }
5214 if (m >= m_start && m <= m_end)
5215 {
5216 /* found a valid vertex */
5217 if (dyn == NULL)
5218 dyn = gaiaAllocDynamicLine ();
5219 if (ln->DimensionModel == GAIA_XY_Z_M)
5220 gaiaAppendPointZMToDynamicLine (dyn, x, y, z, m);
5221 else
5222 gaiaAppendPointMToDynamicLine (dyn, x, y, m);
5223 }
5224 else
5225 {
5226 if (dyn != NULL)
5227 {
5228 /* evaluting the latest sequence found */
5229 int cnt = 0;
5230 pt = dyn->First;
5231 while (pt)
5232 {
5233 /* counting how many points are there */
5234 cnt++;
5235 pt = pt->Next;
5236 }
5237 if (cnt > 1)
5238 {
5239 /* creating a Linestring */
5240 new_line =
5241 gaiaAddLinestringToGeomColl (new_geom,
5242 cnt);
5243 cnt = 0;
5244 pt = dyn->First;
5245 while (pt)
5246 {
5247
5248 if (new_line->DimensionModel ==
5249 GAIA_XY_Z_M)
5250 {
5251 gaiaSetPointXYZM
5252 (new_line->Coords, cnt, pt->X,
5253 pt->Y, pt->Z, pt->M);
5254 }
5255 else
5256 {
5257 gaiaSetPointXYM (new_line->Coords,
5258 cnt, pt->X,
5259 pt->Y, pt->M);
5260 }
5261 cnt++;
5262 pt = pt->Next;
5263 }
5264 }
5265 else if (cnt == 1)
5266 {
5267 /* creating a Point */
5268 pt = dyn->First;
5269 if (geom->DimensionModel == GAIA_XY_M)
5270 gaiaAddPointToGeomCollXYM (new_geom,
5271 pt->X, pt->Y,
5272 pt->M);
5273 else if (geom->DimensionModel == GAIA_XY_Z_M)
5274 gaiaAddPointToGeomCollXYZM (new_geom,
5275 pt->X, pt->Y,
5276 pt->Z, pt->M);
5277 }
5278 gaiaFreeDynamicLine (dyn);
5279 dyn = NULL;
5280 }
5281 }
5282 }
5283 if (dyn != NULL)
5284 {
5285 /* evaluting the latest sequence found */
5286 int cnt = 0;
5287 pt = dyn->First;
5288 while (pt)
5289 {
5290 /* counting how many points are there */
5291 cnt++;
5292 pt = pt->Next;
5293 }
5294 if (cnt > 1)
5295 {
5296 /* creating a Linestring */
5297 new_line = gaiaAddLinestringToGeomColl (new_geom, cnt);
5298 cnt = 0;
5299 pt = dyn->First;
5300 while (pt)
5301 {
5302
5303 if (new_line->DimensionModel == GAIA_XY_Z_M)
5304 {
5305 gaiaSetPointXYZM (new_line->Coords, cnt,
5306 pt->X, pt->Y, pt->Z, pt->M);
5307 }
5308 else
5309 {
5310 gaiaSetPointXYM (new_line->Coords,
5311 cnt, pt->X, pt->Y, pt->M);
5312 }
5313 cnt++;
5314 pt = pt->Next;
5315 }
5316 }
5317 else if (cnt == 1)
5318 {
5319 /* creating a Point */
5320 pt = dyn->First;
5321 if (geom->DimensionModel == GAIA_XY_M)
5322 gaiaAddPointToGeomCollXYM (new_geom,
5323 pt->X, pt->Y, pt->M);
5324 else if (geom->DimensionModel == GAIA_XY_Z_M)
5325 gaiaAddPointToGeomCollXYZM (new_geom,
5326 pt->X, pt->Y,
5327 pt->Z, pt->M);
5328 }
5329 gaiaFreeDynamicLine (dyn);
5330 dyn = NULL;
5331 }
5332 ln = ln->Next;
5333 }
5334 if (new_geom->FirstPoint == NULL && new_geom->FirstLinestring == NULL)
5335 {
5336 /* empty result: returning NULL */
5337 gaiaFreeGeomColl (new_geom);
5338 return NULL;
5339 }
5340 return new_geom;
5341 }
5342
5343 GAIAGEO_DECLARE int
gaiaIsValidTrajectory(gaiaGeomCollPtr geom)5344 gaiaIsValidTrajectory (gaiaGeomCollPtr geom)
5345 {
5346 /* Checks if a Geometry object is valid Trajectory */
5347 gaiaLinestringPtr ln;
5348 int iv;
5349 double x;
5350 double y;
5351 double z;
5352 double m;
5353 double prev_m;
5354 if (!geom)
5355 return 0;
5356 if (geom->FirstPoint != NULL || geom->FirstLinestring == NULL
5357 || geom->FirstPolygon != NULL)
5358 return 0; /* not a Linestring */
5359 if (geom->FirstLinestring != geom->LastLinestring)
5360 return 0; /* not a simple Linestring */
5361 if (geom->DimensionModel == GAIA_XY_M
5362 || geom->DimensionModel == GAIA_XY_Z_M)
5363 ;
5364 else
5365 return 0; /* not supporting M_values */
5366 ln = geom->FirstLinestring;
5367 for (iv = 0; iv < ln->Points; iv++)
5368 {
5369 z = 0.0;
5370 if (ln->DimensionModel == GAIA_XY_Z_M)
5371 {
5372 gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
5373 }
5374 else
5375 {
5376 gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
5377 }
5378 if (iv != 0)
5379 {
5380 if (m <= prev_m)
5381 return 0;
5382 }
5383 prev_m = m;
5384 }
5385 return 1;
5386 }
5387
5388 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaTrajectoryInterpolatePoint(gaiaGeomCollPtr geom,double m_value)5389 gaiaTrajectoryInterpolatePoint (gaiaGeomCollPtr geom, double m_value)
5390 {
5391 /* attempts to interpolate a Point along a Trajectory accordingly to given M-Value */
5392 gaiaGeomCollPtr point;
5393 gaiaLinestringPtr ln;
5394 int iv;
5395 double x;
5396 double y;
5397 double z;
5398 double m;
5399 double prev_x;
5400 double prev_y;
5401 double prev_z;
5402 double prev_m;
5403 if (!gaiaIsValidTrajectory (geom))
5404 return NULL;
5405
5406 /* creating the Geometry to be returned */
5407 if (geom->DimensionModel == GAIA_XY_M)
5408 point = gaiaAllocGeomCollXYM ();
5409 else if (geom->DimensionModel == GAIA_XY_Z_M)
5410 point = gaiaAllocGeomCollXYZM ();
5411 else
5412 return NULL;
5413 point->Srid = geom->Srid;
5414 point->DeclaredType = GAIA_POINT;
5415
5416 ln = geom->FirstLinestring;
5417 /* testing if m < StartPoint */
5418 if (ln->DimensionModel == GAIA_XY_Z_M)
5419 {
5420 gaiaGetPointXYZM (ln->Coords, 0, &x, &y, &z, &m);
5421 }
5422 else
5423 {
5424 gaiaGetPointXYM (ln->Coords, 0, &x, &y, &m);
5425 }
5426 if (m_value < m)
5427 {
5428 if (ln->DimensionModel == GAIA_XY_Z_M)
5429 gaiaAddPointToGeomCollXYZM (point, x, y, z, m_value);
5430 else
5431 gaiaAddPointToGeomCollXYM (point, x, y, m_value);
5432 return point;
5433 }
5434
5435 /* testing if m > EndPoint */
5436 iv = ln->Points - 1;
5437 if (ln->DimensionModel == GAIA_XY_Z_M)
5438 {
5439 gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
5440 }
5441 else
5442 {
5443 gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
5444 }
5445 if (m_value > m)
5446 {
5447 if (ln->DimensionModel == GAIA_XY_Z_M)
5448 gaiaAddPointToGeomCollXYZM (point, x, y, z, m_value);
5449 else
5450 gaiaAddPointToGeomCollXYM (point, x, y, m_value);
5451 return point;
5452 }
5453
5454 prev_m = 0.0 - DBL_MAX;
5455 ln = geom->FirstLinestring;
5456 for (iv = 0; iv < ln->Points; iv++)
5457 {
5458 z = 0.0;
5459 if (ln->DimensionModel == GAIA_XY_Z_M)
5460 {
5461 gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
5462 }
5463 else
5464 {
5465 gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
5466 }
5467 if (m_value == m)
5468 {
5469 if (ln->DimensionModel == GAIA_XY_Z_M)
5470 gaiaAddPointToGeomCollXYZM (point, x, y, z, m_value);
5471 else
5472 gaiaAddPointToGeomCollXYM (point, x, y, m_value);
5473 return point;
5474 }
5475 if (m_value > prev_m && m_value < m)
5476 {
5477 /* interpolating the Point */
5478 double ix;
5479 double iy;
5480 double iz;
5481 double diff = m - prev_m;
5482 double m_diff = m_value - prev_m;
5483 double ratio = diff / m_diff;
5484 diff = x - prev_x;
5485 ix = prev_x + (diff / ratio);
5486 diff = y - prev_y;
5487 iy = prev_y + (diff / ratio);
5488 diff = z - prev_z;
5489 iz = prev_z + (diff / ratio);
5490 if (ln->DimensionModel == GAIA_XY_Z_M)
5491 gaiaAddPointToGeomCollXYZM (point, ix, iy, iz, m_value);
5492 else
5493 gaiaAddPointToGeomCollXYM (point, ix, iy, m_value);
5494 return point;
5495 }
5496 prev_x = x;
5497 prev_y = y;
5498 prev_z = z;
5499 prev_m = m;
5500 }
5501
5502 gaiaFreeGeomColl (point);
5503 return NULL;
5504 }
5505
5506 static int
check_closed_multi_linestring(gaiaGeomCollPtr geom,int single)5507 check_closed_multi_linestring (gaiaGeomCollPtr geom, int single)
5508 {
5509 /* check if :
5510 / - this geometry is a (multi) Linestring
5511 / - all Linestrings are effectively closed
5512 */
5513 int pts = 0;
5514 int lns = 0;
5515 int pgs = 0;
5516 int closed = 0;
5517 gaiaPointPtr pt;
5518 gaiaLinestringPtr ln;
5519 gaiaPolygonPtr pg;
5520 pt = geom->FirstPoint;
5521 while (pt)
5522 {
5523 pts++;
5524 pt = pt->Next;
5525 }
5526 ln = geom->FirstLinestring;
5527 while (ln)
5528 {
5529 if (gaiaIsClosed (ln))
5530 closed++;
5531 lns++;
5532 ln = ln->Next;
5533 }
5534 pg = geom->FirstPolygon;
5535 while (pg)
5536 {
5537 pgs++;
5538 pg = pg->Next;
5539 }
5540 if (closed != lns)
5541 return 0;
5542 if (single)
5543 {
5544 if (pts == 0 && lns == 1 && pgs == 0)
5545 return lns;
5546 }
5547 else
5548 {
5549 if (pts == 0 && lns >= 1 && pgs == 0)
5550 return lns;
5551 }
5552 return 0;
5553 }
5554
5555 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaMakePolygon(gaiaGeomCollPtr exterior,gaiaGeomCollPtr interiors)5556 gaiaMakePolygon (gaiaGeomCollPtr exterior, gaiaGeomCollPtr interiors)
5557 {
5558 /* reassembling a Polygon from closed Linestrings */
5559 gaiaGeomCollPtr geom;
5560 gaiaPolygonPtr pg;
5561 gaiaRingPtr rng;
5562 gaiaLinestringPtr ln;
5563 int iv;
5564 double x;
5565 double y;
5566 double z;
5567 double m;
5568 int num_interiors = 0;
5569 int ib;
5570
5571 if (exterior == NULL)
5572 return NULL;
5573 if (!check_closed_multi_linestring (exterior, 1))
5574 return NULL;
5575 if (interiors != NULL)
5576 {
5577 num_interiors = check_closed_multi_linestring (interiors, 0);
5578 if (!num_interiors)
5579 return NULL;
5580 }
5581
5582 /* reassembling the Polygon */
5583 if (exterior->DimensionModel == GAIA_XY_Z)
5584 geom = gaiaAllocGeomCollXYZ ();
5585 else if (exterior->DimensionModel == GAIA_XY_M)
5586 geom = gaiaAllocGeomCollXYM ();
5587 else if (exterior->DimensionModel == GAIA_XY_Z_M)
5588 geom = gaiaAllocGeomCollXYZM ();
5589 else
5590 geom = gaiaAllocGeomColl ();
5591 geom->Srid = exterior->Srid;
5592 ln = exterior->FirstLinestring;
5593 pg = gaiaAddPolygonToGeomColl (geom, ln->Points, num_interiors);
5594 rng = pg->Exterior;
5595 for (iv = 0; iv < ln->Points; iv++)
5596 {
5597 /* exterior ring */
5598 m = 0.0;
5599 z = 0.0;
5600 switch (ln->DimensionModel)
5601 {
5602 case GAIA_XY:
5603 gaiaGetPoint (ln->Coords, iv, &x, &y);
5604 break;
5605 case GAIA_XY_Z:
5606 gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
5607 break;
5608 case GAIA_XY_M:
5609 gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
5610 break;
5611 case GAIA_XY_Z_M:
5612 gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
5613 break;
5614 default:
5615 return 0;
5616 };
5617 switch (rng->DimensionModel)
5618 {
5619 case GAIA_XY:
5620 gaiaSetPoint (rng->Coords, iv, x, y);
5621 break;
5622 case GAIA_XY_Z:
5623 gaiaSetPointXYZ (rng->Coords, iv, x, y, z);
5624 break;
5625 case GAIA_XY_M:
5626 gaiaSetPointXYM (rng->Coords, iv, x, y, m);
5627 break;
5628 case GAIA_XY_Z_M:
5629 gaiaSetPointXYZM (rng->Coords, iv, x, y, z, m);
5630 break;
5631 };
5632 }
5633 if (interiors != NULL)
5634 {
5635 /* setting up the interior rings */
5636 ib = 0;
5637 ln = interiors->FirstLinestring;
5638 while (ln)
5639 {
5640 rng = gaiaAddInteriorRing (pg, ib, ln->Points);
5641 for (iv = 0; iv < ln->Points; iv++)
5642 {
5643 m = 0.0;
5644 z = 0.0;
5645 switch (ln->DimensionModel)
5646 {
5647 case GAIA_XY:
5648 gaiaGetPoint (ln->Coords, iv, &x, &y);
5649 break;
5650 case GAIA_XY_Z:
5651 gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
5652 break;
5653 case GAIA_XY_M:
5654 gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
5655 break;
5656 case GAIA_XY_Z_M:
5657 gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
5658 break;
5659 default:
5660 return 0;
5661 };
5662 switch (rng->DimensionModel)
5663 {
5664 case GAIA_XY:
5665 gaiaSetPoint (rng->Coords, iv, x, y);
5666 break;
5667 case GAIA_XY_Z:
5668 gaiaSetPointXYZ (rng->Coords, iv, x, y, z);
5669 break;
5670 case GAIA_XY_M:
5671 gaiaSetPointXYM (rng->Coords, iv, x, y, m);
5672 break;
5673 case GAIA_XY_Z_M:
5674 gaiaSetPointXYZM (rng->Coords, iv, x, y, z, m);
5675 break;
5676 };
5677 }
5678 ib++;
5679 ln = ln->Next;
5680 }
5681 }
5682 return geom;
5683 }
5684