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