1 /**********************************************************************
2  *
3  * rttopo - topology library
4  * http://git.osgeo.org/gitea/rttopo/librttopo
5  *
6  * rttopo is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * rttopo is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with rttopo.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2015 Sandro Santilli <strk@kbt.io>
22  *
23  **********************************************************************/
24 
25 
26 
27 #ifndef LIBRTGEOM_TOPO_H
28 #define LIBRTGEOM_TOPO_H 1
29 
30 #include "librttopo_geom.h"
31 
32 /* INT64 */
33 typedef int64_t RTT_INT64;
34 
35 /** Identifier of topology element */
36 typedef RTT_INT64 RTT_ELEMID;
37 
38 /*
39  * ISO primitive elements
40  */
41 
42 /** NODE */
43 typedef struct
44 {
45   RTT_ELEMID node_id;
46   RTT_ELEMID containing_face; /* -1 if not isolated */
47   RTPOINT *geom;
48 }
49 RTT_ISO_NODE;
50 
51 void rtt_iso_node_release(RTT_ISO_NODE* node);
52 
53 /** Node fields */
54 #define RTT_COL_NODE_NODE_ID         1<<0
55 #define RTT_COL_NODE_CONTAINING_FACE 1<<1
56 #define RTT_COL_NODE_GEOM            1<<2
57 #define RTT_COL_NODE_ALL            (1<<3)-1
58 
59 /** EDGE */
60 typedef struct
61 {
62   RTT_ELEMID edge_id;
63   RTT_ELEMID start_node;
64   RTT_ELEMID end_node;
65   RTT_ELEMID face_left;
66   RTT_ELEMID face_right;
67   RTT_ELEMID next_left;
68   RTT_ELEMID next_right;
69   RTLINE *geom;
70 }
71 RTT_ISO_EDGE;
72 
73 /** Edge fields */
74 #define RTT_COL_EDGE_EDGE_ID         1<<0
75 #define RTT_COL_EDGE_START_NODE      1<<1
76 #define RTT_COL_EDGE_END_NODE        1<<2
77 #define RTT_COL_EDGE_FACE_LEFT       1<<3
78 #define RTT_COL_EDGE_FACE_RIGHT      1<<4
79 #define RTT_COL_EDGE_NEXT_LEFT       1<<5
80 #define RTT_COL_EDGE_NEXT_RIGHT      1<<6
81 #define RTT_COL_EDGE_GEOM            1<<7
82 #define RTT_COL_EDGE_ALL            (1<<8)-1
83 
84 /** FACE */
85 typedef struct
86 {
87   RTT_ELEMID face_id;
88   RTGBOX *mbr;
89 }
90 RTT_ISO_FACE;
91 
92 /** Face fields */
93 #define RTT_COL_FACE_FACE_ID         1<<0
94 #define RTT_COL_FACE_MBR             1<<1
95 #define RTT_COL_FACE_ALL            (1<<2)-1
96 
97 typedef enum RTT_SPATIALTYPE_T {
98   RTT_PUNTAL = 0,
99   RTT_LINEAL = 1,
100   RTT_AREAL = 2,
101   RTT_COLLECTION = 3
102 } RTT_SPATIALTYPE;
103 
104 /*
105  * Backend handling functions
106  */
107 
108 /* opaque pointers referencing native backend objects */
109 
110 /**
111  * Backend private data pointer
112  *
113  * Only the backend handler needs to know what it really is.
114  * It will be passed to all registered callback functions.
115  */
116 typedef struct RTT_BE_DATA_T RTT_BE_DATA;
117 
118 /**
119  * Backend interface handler
120  *
121  * Embeds all registered backend callbacks and private data pointer.
122  * Will need to be passed (directly or indirectly) to al public facing
123  * APIs of this library.
124  */
125 typedef struct RTT_BE_IFACE_T RTT_BE_IFACE;
126 
127 /**
128  * Topology handler.
129  *
130  * Embeds backend interface handler.
131  * Will need to be passed to all topology manipulation APIs
132  * of this library.
133  */
134 typedef struct RTT_BE_TOPOLOGY_T RTT_BE_TOPOLOGY;
135 
136 /**
137  * Structure containing base backend callbacks
138  *
139  * Used for registering into the backend iface
140  */
141 typedef struct RTT_BE_CALLBACKS_T {
142 
143   /**
144    * Read last error message from backend
145    *
146    * @return NULL-terminated error string
147    */
148   const char* (*lastErrorMessage) (const RTT_BE_DATA* be);
149 
150   /**
151    * Create a new topology in the backend
152    *
153    * @param name the topology name
154    * @param srid the topology SRID
155    * @param precision the topology precision/tolerance
156    * @param hasZ non-zero if topology primitives should have a Z ordinate
157    * @return a topology handler, which embeds the backend data/params
158    *         or NULL on error (@see lastErrorMessage)
159    */
160   RTT_BE_TOPOLOGY* (*createTopology) (
161     const RTT_BE_DATA* be,
162     const char* name, int srid, double precision, int hasZ
163   );
164 
165   /**
166    * Load a topology from the backend
167    *
168    * @param name the topology name
169    * @return a topology handler, which embeds the backend data/params
170    *         or NULL on error (@see lastErrorMessage)
171    */
172   RTT_BE_TOPOLOGY* (*loadTopologyByName) (
173     const RTT_BE_DATA* be,
174     const char* name
175   );
176 
177   /**
178    * Release memory associated to a backend topology
179    *
180    * @param topo the backend topology handler
181    * @return 1 on success, 0 on error (@see lastErrorMessage)
182    */
183   int (*freeTopology) (RTT_BE_TOPOLOGY* topo);
184 
185   /**
186    * Get nodes by id
187    *
188    * @param topo the topology to act upon
189    * @param ids an array of element identifiers
190    * @param numelems input/output parameter, pass number of node identifiers
191    *                 in the input array, gets number of node in output array.
192    * @param fields fields to be filled in the returned structure, see
193    *               RTT_COL_NODE_* macros
194    *
195    * @return an array of nodes
196    *         or NULL in the following cases:
197    *         - no edge found ("numelems" is set to 0)
198    *         - error ("numelems" is set to -1)
199    *           (@see lastErrorMessage)
200    *
201    */
202   RTT_ISO_NODE* (*getNodeById) (
203       const RTT_BE_TOPOLOGY* topo,
204       const RTT_ELEMID* ids, int* numelems, int fields
205   );
206 
207   /**
208    * Get nodes within distance by point
209    *
210    * @param topo the topology to act upon
211    * @param pt the query point
212    * @param dist the distance
213    * @param numelems output parameter, gets number of elements found
214    *                 if the return is not null, otherwise see @return
215    *                 section for semantic.
216    * @param fields fields to be filled in the returned structure, see
217    *               RTT_COL_NODE_* macros
218    * @param limit max number of nodes to return, 0 for no limit, -1
219    *              to only check for existance if a matching row.
220    *
221    * @return an array of nodes or null in the following cases:
222    *         - limit=-1 ("numelems" is set to 1 if found, 0 otherwise)
223    *         - limit>0 and no records found ("numelems" is set to 0)
224    *         - error ("numelems" is set to -1)
225    *
226    */
227   RTT_ISO_NODE* (*getNodeWithinDistance2D) (
228       const RTT_BE_TOPOLOGY* topo,
229       const RTPOINT* pt, double dist, int* numelems,
230       int fields, int limit
231   );
232 
233   /**
234    * Insert nodes
235    *
236    * Insert node primitives in the topology, performing no
237    * consistency checks.
238    *
239    * @param topo the topology to act upon
240    * @param nodes the nodes to insert. Those with a node_id set to -1
241    *              it will be replaced to an automatically assigned identifier
242    * @param nelems number of elements in the nodes array
243    *
244    * @return 1 on success, 0 on error (@see lastErrorMessage)
245    */
246   int (*insertNodes) (
247       const RTT_BE_TOPOLOGY* topo,
248       RTT_ISO_NODE* nodes,
249       int numelems
250   );
251 
252   /**
253    * Get edge by id
254    *
255    * @param topo the topology to act upon
256    * @param ids an array of element identifiers
257    * @param numelems input/output parameter, pass number of edge identifiers
258    *                 in the input array, gets number of edges in output array
259    *                 if the return is not null, otherwise see @return
260    *                 section for semantic.
261    * @param fields fields to be filled in the returned structure, see
262    *               RTT_COL_EDGE_* macros
263    *
264    * @return an array of edges or NULL in the following cases:
265    *         - none found ("numelems" is set to 0)
266    *         - error ("numelems" is set to -1)
267    */
268   RTT_ISO_EDGE* (*getEdgeById) (
269       const RTT_BE_TOPOLOGY* topo,
270       const RTT_ELEMID* ids, int* numelems, int fields
271   );
272 
273   /**
274    * Get edges within distance by point
275    *
276    * @param topo the topology to act upon
277    * @param pt the query point
278    * @param dist the distance
279    * @param numelems output parameter, gets number of elements found
280    *                 if the return is not null, otherwise see @return
281    *                 section for semantic.
282    * @param fields fields to be filled in the returned structure, see
283    *               RTT_COL_EDGE_* macros
284    * @param limit max number of edges to return, 0 for no limit, -1
285    *              to only check for existance if a matching row.
286    *
287    * @return an array of edges or null in the following cases:
288    *         - limit=-1 ("numelems" is set to 1 if found, 0 otherwise)
289    *         - limit>0 and no records found ("numelems" is set to 0)
290    *         - error ("numelems" is set to -1)
291    *
292    */
293   RTT_ISO_EDGE* (*getEdgeWithinDistance2D) (
294       const RTT_BE_TOPOLOGY* topo,
295       const RTPOINT* pt, double dist, int* numelems,
296       int fields, int limit
297   );
298 
299   /**
300    * Get next available edge identifier
301    *
302    * Identifiers returned by this function should not be considered
303    * available anymore.
304    *
305    * @param topo the topology to act upon
306    *
307    * @return next available edge identifier or -1 on error
308    */
309   RTT_ELEMID (*getNextEdgeId) (
310       const RTT_BE_TOPOLOGY* topo
311   );
312 
313   /**
314    * Insert edges
315    *
316    * Insert edge primitives in the topology, performing no
317    * consistency checks.
318    *
319    * @param topo the topology to act upon
320    * @param edges the edges to insert. Those with a edge_id set to -1
321    *              it will be replaced to an automatically assigned identifier
322    * @param nelems number of elements in the edges array
323    *
324    * @return number of inserted edges, or -1 (@see lastErrorMessage)
325    */
326   int (*insertEdges) (
327       const RTT_BE_TOPOLOGY* topo,
328       RTT_ISO_EDGE* edges,
329       int numelems
330   );
331 
332   /**
333    * Update edges selected by fields match/mismatch
334    *
335    * @param topo the topology to act upon
336    * @param sel_edge an RTT_ISO_EDGE object with selecting fields set.
337    * @param sel_fields fields used to select edges to be updated,
338    *                   see RTT_COL_EDGE_* macros
339    * @param upd_edge an RTT_ISO_EDGE object with updated fields set.
340    * @param upd_fields fields to be updated for the selected edges,
341    *                   see RTT_COL_EDGE_* macros
342    * @param exc_edge an RTT_ISO_EDGE object with exclusion fields set,
343    *                 can be NULL if no exlusion condition exists.
344    * @param exc_fields fields used for excluding edges from the update,
345    *                   see RTT_COL_EDGE_* macros
346    *
347    * @return number of edges being updated or -1 on error
348    *         (@see lastErroMessage)
349    */
350   int (*updateEdges) (
351       const RTT_BE_TOPOLOGY* topo,
352       const RTT_ISO_EDGE* sel_edge, int sel_fields,
353       const RTT_ISO_EDGE* upd_edge, int upd_fields,
354       const RTT_ISO_EDGE* exc_edge, int exc_fields
355   );
356 
357   /**
358    * Get faces by id
359    *
360    * @param topo the topology to act upon
361    * @param ids an array of element identifiers
362    * @param numelems input/output parameter, pass number of edge identifiers
363    *                 in the input array, gets number of node in output array
364    *                 if the return is not null, otherwise see @return
365    *                 section for semantic.
366    * @param fields fields to be filled in the returned structure, see
367    *               RTT_COL_FACE_* macros
368    *
369    * @return an array of faces or NULL in the following cases:
370    *         - none found ("numelems" is set to 0)
371    *         - error ("numelems" is set to -1)
372    */
373   RTT_ISO_FACE* (*getFaceById) (
374       const RTT_BE_TOPOLOGY* topo,
375       const RTT_ELEMID* ids, int* numelems, int fields
376   );
377 
378   /**
379    * Get face containing point
380    *
381    * @param topo the topology to act upon
382    * @param pt the query point
383    *
384    * @return a face identifier, -1 if no face contains the point
385    *         (could be in universe face or on an edge)
386    *         or -2 on error (@see lastErrorMessage)
387    */
388   RTT_ELEMID (*getFaceContainingPoint) (
389       const RTT_BE_TOPOLOGY* topo,
390       const RTPOINT* pt
391   );
392 
393   /**
394    * Update TopoGeometry objects after an edge split event
395    *
396    * @param topo the topology to act upon
397    * @param split_edge identifier of the edge that was split.
398    * @param new_edge1 identifier of the first new edge that was created
399    *        as a result of edge splitting.
400    * @param new_edge2 identifier of the second new edge that was created
401    *        as a result of edge splitting, or -1 if the old edge was
402    *        modified rather than replaced.
403    *
404    * @return 1 on success, 0 on error
405    *
406    * @note on splitting an edge, the new edges both have the
407    *       same direction as the original one. If a second new edge was
408    *       created, its start node will be equal to the first new edge
409    *       end node.
410    */
411   int (*updateTopoGeomEdgeSplit) (
412       const RTT_BE_TOPOLOGY* topo,
413       RTT_ELEMID split_edge, RTT_ELEMID new_edge1, RTT_ELEMID new_edge2
414   );
415 
416   /**
417    * Delete edges
418    *
419    * @param topo the topology to act upon
420    * @param sel_edge an RTT_ISO_EDGE object with selecting fields set.
421    * @param sel_fields fields used to select edges to be deleted,
422    *                   see RTT_COL_EDGE_* macros
423    *
424    * @return number of edges being deleted or -1 on error
425    *         (@see lastErroMessage)
426    */
427   int (*deleteEdges) (
428       const RTT_BE_TOPOLOGY* topo,
429       const RTT_ISO_EDGE* sel_edge, int sel_fields
430   );
431 
432   /**
433    * Get edges whose bounding box overlaps a given 2D bounding box
434    *
435    * @param topo the topology to act upon
436    * @param box the query box
437    * @param numelems output parameter, gets number of elements found
438    *                 if the return is not null, otherwise see @return
439    *                 section for semantic.
440    * @param fields fields to be filled in the returned structure, see
441    *               RTT_COL_NODE_* macros
442    * @param limit max number of nodes to return, 0 for no limit, -1
443    *              to only check for existance if a matching row.
444    *
445    * @return an array of nodes or null in the following cases:
446    *         - limit=-1 ("numelems" is set to 1 if found, 0 otherwise)
447    *         - limit>0 and no records found ("numelems" is set to 0)
448    *         - error ("numelems" is set to -1)
449    *
450    */
451   RTT_ISO_NODE* (*getNodeWithinBox2D) (
452       const RTT_BE_TOPOLOGY* topo,
453       const RTGBOX* box,
454       int* numelems, int fields, int limit
455   );
456 
457   /**
458    * Get edges whose bounding box overlaps a given 2D bounding box
459    *
460    * @param topo the topology to act upon
461    * @param box the query box, to be considered infinite if NULL
462    * @param numelems output parameter, gets number of elements found
463    *                 if the return is not null, otherwise see @return
464    *                 section for semantic.
465    * @param fields fields to be filled in the returned structure, see
466    *               RTT_COL_EDGE_* macros
467    * @param limit max number of edges to return, 0 for no limit, -1
468    *              to only check for existance if a matching row.
469    *
470    * @return an array of edges or null in the following cases:
471    *         - limit=-1 ("numelems" is set to 1 if found, 0 otherwise)
472    *         - limit>0 and no records found ("numelems" is set to 0)
473    *         - error ("numelems" is set to -1)
474    *
475    */
476   RTT_ISO_EDGE* (*getEdgeWithinBox2D) (
477       const RTT_BE_TOPOLOGY* topo,
478       const RTGBOX* box,
479       int* numelems, int fields, int limit
480   );
481 
482   /**
483    * Get edges that start or end on any of the given node identifiers
484    *
485    * @param topo the topology to act upon
486    * @param ids an array of node identifiers
487    * @param numelems input/output parameter, pass number of node identifiers
488    *                 in the input array, gets number of edges in output array
489    *                 if the return is not null, otherwise see @return
490    *                 section for semantic.
491    * @param fields fields to be filled in the returned structure, see
492    *               RTT_COL_EDGE_* macros
493    *
494    * @return an array of edges that are incident to a node
495    *         or NULL in the following cases:
496    *         - no edge found ("numelems" is set to 0)
497    *         - error ("numelems" is set to -1)
498    *           (@see lastErrorMessage)
499    */
500   RTT_ISO_EDGE* (*getEdgeByNode) (
501       const RTT_BE_TOPOLOGY* topo,
502       const RTT_ELEMID* ids, int* numelems, int fields
503   );
504 
505   /**
506    * Update nodes selected by fields match/mismatch
507    *
508    * @param topo the topology to act upon
509    * @param sel_node an RTT_ISO_NODE object with selecting fields set.
510    * @param sel_fields fields used to select nodes to be updated,
511    *                   see RTT_COL_NODE_* macros
512    * @param upd_node an RTT_ISO_NODE object with updated fields set.
513    * @param upd_fields fields to be updated for the selected nodes,
514    *                   see RTT_COL_NODE_* macros
515    * @param exc_node an RTT_ISO_NODE object with exclusion fields set,
516    *                 can be NULL if no exlusion condition exists.
517    * @param exc_fields fields used for excluding nodes from the update,
518    *                   see RTT_COL_NODE_* macros
519    *
520    * @return number of nodes being updated or -1 on error
521    *         (@see lastErroMessage)
522    */
523   int (*updateNodes) (
524       const RTT_BE_TOPOLOGY* topo,
525       const RTT_ISO_NODE* sel_node, int sel_fields,
526       const RTT_ISO_NODE* upd_node, int upd_fields,
527       const RTT_ISO_NODE* exc_node, int exc_fields
528   );
529 
530   /**
531    * Update TopoGeometry objects after a face split event
532    *
533    * @param topo the topology to act upon
534    * @param split_face identifier of the face that was split.
535    * @param new_face1 identifier of the first new face that was created
536    *        as a result of face splitting.
537    * @param new_face2 identifier of the second new face that was created
538    *        as a result of face splitting, or -1 if the old face was
539    *        modified rather than replaced.
540    *
541    * @return 1 on success, 0 on error (@see lastErroMessage)
542    *
543    */
544   int (*updateTopoGeomFaceSplit) (
545       const RTT_BE_TOPOLOGY* topo,
546       RTT_ELEMID split_face, RTT_ELEMID new_face1, RTT_ELEMID new_face2
547   );
548 
549   /**
550    * Insert faces
551    *
552    * Insert face primitives in the topology, performing no
553    * consistency checks.
554    *
555    * @param topo the topology to act upon
556    * @param faces the faces to insert. Those with a node_id set to -1
557    *              it will be replaced to an automatically assigned identifier
558    * @param nelems number of elements in the faces array
559    *
560    * @return number of inserted faces, or -1 (@see lastErrorMessage)
561    */
562   int (*insertFaces) (
563       const RTT_BE_TOPOLOGY* topo,
564       RTT_ISO_FACE* faces,
565       int numelems
566   );
567 
568   /**
569    * Update faces by id
570    *
571    * @param topo the topology to act upon
572    * @param faces an array of RTT_ISO_FACE object with selecting id
573    *              and setting mbr.
574    * @param numfaces number of faces in the "faces" array
575    *
576    * @return number of faces being updated or -1 on error
577    *         (@see lastErroMessage)
578    */
579   int (*updateFacesById) (
580       const RTT_BE_TOPOLOGY* topo,
581       const RTT_ISO_FACE* faces, int numfaces
582   );
583 
584   /*
585    * Get the ordered list edge visited by a side walk
586    *
587    * The walk starts from the side of an edge and stops when
588    * either the max number of visited edges OR the starting
589    * position is reached. The output list never includes a
590    * duplicated signed edge identifier.
591    *
592    * It is expected that the walk uses the "next_left" and "next_right"
593    * attributes of ISO edges to perform the walk (rather than recomputing
594    * the turns at each node).
595    *
596    * @param topo the topology to operate on
597    * @param edge walk start position and direction:
598    *             abs value identifies the edge, sign expresses
599    *             side (left if positive, right if negative)
600    *             and direction (forward if positive, backward if negative).
601    * @param numedges output parameter, gets the number of edges visited
602    * @param limit max edges to return (to avoid an infinite loop in case
603    *              of a corrupted topology). 0 is for unlimited.
604    *              The function is expected to error out if the limit is hit.
605    *
606    * @return an array of signed edge identifiers (positive edges being
607    *         walked in their direction, negative ones in opposite) or
608    *         NULL on error (@see lastErroMessage)
609    */
610   RTT_ELEMID* (*getRingEdges) (
611       const RTT_BE_TOPOLOGY* topo,
612       RTT_ELEMID edge, int *numedges, int limit
613   );
614 
615   /**
616    * Update edges by id
617    *
618    * @param topo the topology to act upon
619    * @param edges an array of RTT_ISO_EDGE object with selecting id
620    *              and updating fields.
621    * @param numedges number of edges in the "edges" array
622    * @param upd_fields fields to be updated for the selected edges,
623    *                   see RTT_COL_EDGE_* macros
624    *
625    * @return number of edges being updated or -1 on error
626    *         (@see lastErroMessage)
627    */
628   int (*updateEdgesById) (
629       const RTT_BE_TOPOLOGY* topo,
630       const RTT_ISO_EDGE* edges, int numedges,
631       int upd_fields
632   );
633 
634   /**
635    * \brief
636    * Get edges that have any of the given faces on the left or right side
637    * and optionally whose bounding box overlaps the given one.
638    *
639    * @param topo the topology to act upon
640    * @param ids an array of face identifiers
641    * @param numelems input/output parameter, pass number of face identifiers
642    *                 in the input array, gets number of edges in output array
643    *                 if the return is not null, otherwise see @return
644    *                 section for semantic.
645    * @param fields fields to be filled in the returned structure, see
646    *               RTT_COL_EDGE_* macros
647    * @param box optional bounding box to further restrict matches, use
648    *            NULL for no further restriction.
649    *
650    * @return an array of edges identifiers or NULL in the following cases:
651    *         - no edge found ("numelems" is set to 0)
652    *         - error ("numelems" is set to -1)
653    */
654   RTT_ISO_EDGE* (*getEdgeByFace) (
655       const RTT_BE_TOPOLOGY* topo,
656       const RTT_ELEMID* ids, int* numelems, int fields,
657       const RTGBOX *box
658   );
659 
660   /**
661    * Get isolated nodes contained in any of the given faces
662    *
663    * @param topo the topology to act upon
664    * @param faces an array of face identifiers
665    * @param numelems input/output parameter, pass number of face
666    *                 identifiers in the input array, gets number of
667    *                 nodes in output array if the return is not null,
668    *                 otherwise see @return section for semantic.
669    * @param fields fields to be filled in the returned structure, see
670    *               RTT_COL_NODE_* macros
671    * @param box optional bounding box to further restrict matches, use
672    *            NULL for no further restriction.
673    *
674    * @return an array of nodes or NULL in the following cases:
675    *         - no nod found ("numelems" is set to 0)
676    *         - error ("numelems" is set to -1, @see lastErrorMessage)
677    */
678   RTT_ISO_NODE* (*getNodeByFace) (
679       const RTT_BE_TOPOLOGY* topo,
680       const RTT_ELEMID* faces, int* numelems, int fields,
681       const RTGBOX *box
682   );
683 
684   /**
685    * Update nodes by id
686    *
687    * @param topo the topology to act upon
688    * @param nodes an array of RTT_ISO_EDGE objects with selecting id
689    *              and updating fields.
690    * @param numnodes number of nodes in the "nodes" array
691    * @param upd_fields fields to be updated for the selected edges,
692    *                   see RTT_COL_NODE_* macros
693    *
694    * @return number of nodes being updated or -1 on error
695    *         (@see lastErroMessage)
696    */
697   int (*updateNodesById) (
698       const RTT_BE_TOPOLOGY* topo,
699       const RTT_ISO_NODE* nodes, int numnodes,
700       int upd_fields
701   );
702 
703   /**
704    * Delete faces by id
705    *
706    * @param topo the topology to act upon
707    * @param ids an array of face identifiers
708    * @param numelems number of face identifiers in the ids array
709    *
710    * @return number of faces being deleted or -1 on error
711    *         (@see lastErroMessage)
712    */
713   int (*deleteFacesById) (
714       const RTT_BE_TOPOLOGY* topo,
715       const RTT_ELEMID* ids,
716       int numelems
717   );
718 
719   /**
720    * Get topology SRID
721    * @return 0 for unknown
722    */
723   int (*topoGetSRID) (
724       const RTT_BE_TOPOLOGY* topo
725   );
726 
727   /**
728    * Get topology precision
729    */
730   double (*topoGetPrecision) (
731       const RTT_BE_TOPOLOGY* topo
732   );
733 
734   /**
735    * Get topology Z flag
736    * @return 1 if topology elements do have Z value, 0 otherwise
737    */
738   int (*topoHasZ) (
739       const RTT_BE_TOPOLOGY* topo
740   );
741 
742   /**
743    * Delete nodes by id
744    *
745    * @param topo the topology to act upon
746    * @param ids an array of node identifiers
747    * @param numelems number of node identifiers in the ids array
748    *
749    * @return number of nodes being deleted or -1 on error
750    *         (@see lastErroMessage)
751    */
752   int (*deleteNodesById) (
753       const RTT_BE_TOPOLOGY* topo,
754       const RTT_ELEMID* ids,
755       int numelems
756   );
757 
758   /**
759    * Check TopoGeometry objects before an edge removal event
760    *
761    * @param topo the topology to act upon
762    * @param rem_edge identifier of the edge that's been removed
763    * @param face_left identifier of the face on the edge's left side
764    * @param face_right identifier of the face on the edge's right side
765    *
766    * @return 1 to allow, 0 to forbid the operation
767    *         (reporting reason via lastErrorMessage)
768    *
769    */
770   int (*checkTopoGeomRemEdge) (
771       const RTT_BE_TOPOLOGY* topo,
772       RTT_ELEMID rem_edge,
773       RTT_ELEMID face_left,
774       RTT_ELEMID face_right
775   );
776 
777   /**
778    * Update TopoGeometry objects after healing two faces
779    *
780    * @param topo the topology to act upon
781    * @param face1 identifier of the first face
782    * @param face2 identifier of the second face
783    * @param newface identifier of the new face
784    *
785    * @note that newface may or may not be equal to face1 or face2,
786    *       while face1 should never be the same as face2.
787    *
788    * @return 1 on success, 0 on error (@see lastErrorMessage)
789    *
790    */
791   int (*updateTopoGeomFaceHeal) (
792       const RTT_BE_TOPOLOGY* topo,
793       RTT_ELEMID face1, RTT_ELEMID face2, RTT_ELEMID newface
794   );
795 
796   /**
797    * Check TopoGeometry objects before a node removal event
798    *
799    * @param topo the topology to act upon
800    * @param rem_node identifier of the node that's been removed
801    * @param e1 identifier of the first connected edge
802    * @param e2 identifier of the second connected edge
803    *
804    * The operation should be forbidden if any TopoGeometry object
805    * exists which contains only one of the two healed edges.
806    *
807    * The operation should also be forbidden if the removed node
808    * takes part in the definition of a TopoGeometry, although
809    * this wasn't the case yet as of PostGIS version 2.1.8:
810    * https://trac.osgeo.org/postgis/ticket/3239
811    *
812    * @return 1 to allow, 0 to forbid the operation
813    *         (reporting reason via lastErrorMessage)
814    *
815    */
816   int (*checkTopoGeomRemNode) (
817       const RTT_BE_TOPOLOGY* topo,
818       RTT_ELEMID rem_node,
819       RTT_ELEMID e1,
820       RTT_ELEMID e2
821   );
822 
823   /**
824    * Update TopoGeometry objects after healing two edges
825    *
826    * @param topo the topology to act upon
827    * @param edge1 identifier of the first edge
828    * @param edge2 identifier of the second edge
829    * @param newedge identifier of the new edge, taking the space
830    *                previously occupied by both original edges
831    *
832    * @note that newedge may or may not be equal to edge1 or edge2,
833    *       while edge1 should never be the same as edge2.
834    *
835    * @return 1 on success, 0 on error (@see lastErrorMessage)
836    *
837    */
838   int (*updateTopoGeomEdgeHeal) (
839       const RTT_BE_TOPOLOGY* topo,
840       RTT_ELEMID edge1, RTT_ELEMID edge2, RTT_ELEMID newedge
841   );
842 
843   /**
844    * Get faces whose bounding box overlaps a given 2D bounding box
845    *
846    * @param topo the topology to act upon
847    * @param box the query box
848    * @param numelems output parameter, gets number of elements found
849    *                 if the return is not null, otherwise see @return
850    *                 section for semantic.
851    * @param fields fields to be filled in the returned structure, see
852    *               RTT_COL_FACE_* macros
853    * @param limit max number of faces to return, 0 for no limit, -1
854    *              to only check for existance if a matching row.
855    *
856    * @return an array of faces or null in the following cases:
857    *         - limit=-1 ("numelems" is set to 1 if found, 0 otherwise)
858    *         - limit>0 and no records found ("numelems" is set to 0)
859    *         - error ("numelems" is set to -1)
860    *
861    */
862   RTT_ISO_FACE* (*getFaceWithinBox2D) (
863       const RTT_BE_TOPOLOGY* topo,
864       const RTGBOX* box,
865       int* numelems, int fields, int limit
866   );
867 
868 } RTT_BE_CALLBACKS;
869 
870 
871 /**
872  * Create a new backend interface
873  *
874  * Ownership to caller delete with rtt_FreeBackendIface
875  *
876  * @param ctx librtgeom context, create with rtgeom_init
877  * @param data Backend data, passed as first parameter
878  *             to all callback functions
879  */
880 RTT_BE_IFACE* rtt_CreateBackendIface(const RTCTX* ctx,
881                                      const RTT_BE_DATA* data);
882 
883 /**
884  * Register backend callbacks into the opaque iface handler
885  *
886  * @param iface the backend interface handler (see rtt_CreateBackendIface)
887  * @param cb a pointer to the callbacks structure; ownership left to caller.
888  */
889 void rtt_BackendIfaceRegisterCallbacks(RTT_BE_IFACE* iface,
890                                        const RTT_BE_CALLBACKS* cb);
891 
892 /** Release memory associated with an RTT_BE_IFACE */
893 void rtt_FreeBackendIface(RTT_BE_IFACE* iface);
894 
895 /********************************************************************
896  *
897  * End of BE interface
898  *
899  *******************************************************************/
900 
901 /**
902  * Topology errors type
903  */
904 typedef enum RTT_TOPOERR_TYPE_T {
905   RTT_TOPOERR_EDGE_CROSSES_NODE,
906   RTT_TOPOERR_EDGE_INVALID,
907   RTT_TOPOERR_EDGE_NOT_SIMPLE,
908   RTT_TOPOERR_EDGE_CROSSES_EDGE,
909   RTT_TOPOERR_EDGE_STARTNODE_MISMATCH,
910   RTT_TOPOERR_EDGE_ENDNODE_MISMATCH,
911   RTT_TOPOERR_FACE_WITHOUT_EDGES,
912   RTT_TOPOERR_FACE_HAS_NO_RINGS,
913   RTT_TOPOERR_FACE_OVERLAPS_FACE,
914   RTT_TOPOERR_FACE_WITHIN_FACE
915 } RTT_TOPOERR_TYPE;
916 
917 /** Topology error */
918 typedef struct RTT_TOPOERR_T {
919   /** Type of error */
920   RTT_TOPOERR_TYPE err;
921   /** Identifier of first affected element */
922   RTT_ELEMID elem1;
923   /** Identifier of second affected element (0 if inapplicable) */
924   RTT_ELEMID elem2;
925 } RTT_TOPOERR;
926 
927 /*
928  * Topology functions
929  */
930 
931 /** Opaque topology structure
932  *
933  * Embeds backend interface and topology
934  */
935 typedef struct RTT_TOPOLOGY_T RTT_TOPOLOGY;
936 
937 
938 /*******************************************************************
939  *
940  * Non-ISO signatures here
941  *
942  *******************************************************************/
943 
944 /**
945  * Initializes a new topology
946  *
947  * @param iface the backend interface handler (see rtt_CreateBackendIface)
948  * @param name name of the new topology
949  * @param srid the topology SRID
950  * @param prec the topology precision/tolerance
951  * @param hasz non-zero if topology primitives should have a Z ordinate
952  *
953  * @return the handler of the topology, or NULL on error
954  *         (librtgeom error handler will be invoked with error message)
955  */
956 RTT_TOPOLOGY *rtt_CreateTopology(RTT_BE_IFACE *iface, const char *name,
957                         int srid, double prec, int hasz);
958 
959 /**
960  * Loads an existing topology by name from the database
961  *
962  * @param iface the backend interface handler (see rtt_CreateBackendIface)
963  * @param name name of the topology to load
964  *
965  * @return the handler of the topology, or NULL on error
966  *         (librtgeom error handler will be invoked with error message)
967  */
968 RTT_TOPOLOGY *rtt_LoadTopology(RTT_BE_IFACE *iface, const char *name);
969 
970 /**
971  * Drop a topology and all its associated objects from the database
972  *
973  * @param topo the topology to drop
974  */
975 void rtt_DropTopology(RTT_TOPOLOGY* topo);
976 
977 /** Release memory associated with an RTT_TOPOLOGY
978  *
979  * @param topo the topology to release (it's not removed from db)
980  */
981 void rtt_FreeTopology(RTT_TOPOLOGY* topo);
982 
983 /**
984  * Retrieve the id of a node at a point location
985  *
986  * @param topo the topology to operate on
987  * @param point the point to use for query
988  * @param tol max distance around the given point to look for a node
989  * @return a node identifier if one is found, 0 if none is found, -1
990  *         on error (multiple nodes within distance).
991  *         The librtgeom error handler will be invoked in case of error.
992  */
993 RTT_ELEMID rtt_GetNodeByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol);
994 
995 /**
996  * Find the edge-id of an edge that intersects a given point
997  *
998  * @param topo the topology to operate on
999  * @param point the point to use for query
1000  * @param tol max distance around the given point to look for an
1001  *            intersecting edge
1002  * @return an edge identifier if one is found, 0 if none is found, -1
1003  *         on error (multiple edges within distance).
1004  *         The librtgeom error handler will be invoked in case of error.
1005  */
1006 RTT_ELEMID rtt_GetEdgeByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol);
1007 
1008 /**
1009  * Find the face-id of a face containing a given point
1010  *
1011  * @param topo the topology to operate on
1012  * @param point the point to use for query
1013  * @param tol max distance around the given point to look for a
1014  *            containing face
1015  * @return a face identifier if one is found (0 if universe), -1
1016  *         on error (multiple faces within distance or point on node
1017  *         or edge).
1018  *         The librtgeom error handler will be invoked in case of error.
1019  */
1020 RTT_ELEMID rtt_GetFaceByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol);
1021 
1022 
1023 /*******************************************************************
1024  *
1025  * Topology population (non-ISO)
1026  *
1027  *******************************************************************/
1028 
1029 /**
1030  * Adds a point to the topology
1031  *
1032  * The given point will snap to existing nodes or edges within given
1033  * tolerance. An existing edge may be split by the point.
1034  *
1035  * @param topo the topology to operate on
1036  * @param point the point to add
1037  * @param tol snap tolerance, the topology tolerance will be used if -1
1038  *
1039  * @return identifier of added (or pre-existing) node or -1 on error
1040  *         (librtgeom error handler will be invoked with error message)
1041  */
1042 RTT_ELEMID rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol);
1043 
1044 /**
1045  * Adds a linestring to the topology
1046  *
1047  * The given line will snap to existing nodes or edges within given
1048  * tolerance. Existing edges or faces may be split by the line.
1049  *
1050  * @param topo the topology to operate on
1051  * @param line the line to add
1052  * @param tol snap tolerance, the topology tolerance will be used if -1
1053  * @param nedges output parameter, will be set to number of edges the
1054  *               line was split into, or -1 on error
1055  *               (librtgeom error handler will be invoked with error message)
1056  *
1057  * @return an array of <nedges> edge identifiers that sewed togheter
1058  *         will build up the input linestring (after snapping). Caller
1059  *         will need to free the array using rtfree(const RTCTX *ctx),
1060  *         if not null.
1061  */
1062 RTT_ELEMID* rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol,
1063                         int* nedges);
1064 
1065 /**
1066  * Adds a linestring to the topology without determining generated faces
1067  *
1068  * The given line will snap to existing nodes or edges within given
1069  * tolerance. Existing edges or faces may be split by the line.
1070  * Side faces for the new edges will not be determined and no new
1071  * faces will be created, effectively leaving the topology in an
1072  * invalid state (WARNING!)
1073  *
1074  * @param topo the topology to operate on
1075  * @param line the line to add
1076  * @param tol snap tolerance, the topology tolerance will be used if -1
1077  * @param nedges output parameter, will be set to number of edges the
1078  *               line was split into, or -1 on error
1079  *               (librtgeom error handler will be invoked with error message)
1080  *
1081  * @return an array of <nedges> edge identifiers that sewed togheter
1082  *         will build up the input linestring (after snapping). Caller
1083  *         will need to free the array using rtfree(const RTCTX *ctx),
1084  *         if not null.
1085  */
1086 RTT_ELEMID* rtt_AddLineNoFace(RTT_TOPOLOGY* topo, RTLINE* line, double tol,
1087                         int* nedges);
1088 
1089 /**
1090  * Determine and register all topology faces:
1091  *
1092  *  - Determines which faces are generated by existing
1093  *    edges.
1094  *  - Creates face records with correct mbr
1095  *  - Update edge left/right face attributes
1096  *
1097  *  Precondition:
1098  *     - the topology edges are correctly linked
1099  *
1100  *  Postconditions:
1101  *     - all left/right face attributes of edges
1102  *       reference faces with correct mbr.
1103  *
1104  *  Notes:
1105  *     - does not attempt to assign isolated nodes to their
1106  *       containing faces
1107  *     - does not remove existing face records
1108  *     - loads in memory all the topology edges
1109  *
1110  * @param topo the topology to operate on
1111  *
1112  * @return 0 on success, -1 on error
1113  *         (librtgeom error handler will be invoked with error message)
1114  */
1115 int rtt_Polygonize(RTT_TOPOLOGY* topo);
1116 
1117 /**
1118  * Adds a polygon to the topology
1119  *
1120  * The boundary of the given polygon will snap to existing nodes or
1121  * edges within given tolerance.
1122  * Existing edges or faces may be split by the boundary of the polygon.
1123  *
1124  * @param topo the topology to operate on
1125  * @param poly the polygon to add
1126  * @param tol snap tolerance, the topology tolerance will be used if -1
1127  * @param nfaces output parameter, will be set to number of faces the
1128  *               polygon was split into, or -1 on error
1129  *               (librtgeom error handler will be invoked with error message)
1130  *
1131  * @return an array of <nfaces> face identifiers that sewed togheter
1132  *         will build up the input polygon (after snapping). Caller
1133  *         will need to free the array using rtfree(const RTCTX *ctx),
1134  *         if not null.
1135  */
1136 RTT_ELEMID* rtt_AddPolygon(RTT_TOPOLOGY* topo, RTPOLY* poly, double tol,
1137                         int* nfaces);
1138 
1139 /*******************************************************************
1140  *
1141  * ISO signatures here
1142  *
1143  *******************************************************************/
1144 
1145 /**
1146  * Populate an empty topology with data from a simple geometry
1147  *
1148  * For ST_CreateTopoGeo
1149  *
1150  * @param topo the topology to operate on
1151  * @param geom the geometry to import
1152  *
1153  */
1154 void rtt_CreateTopoGeo(RTT_TOPOLOGY* topo, RTGEOM *geom);
1155 
1156 /**
1157  * Add an isolated node
1158  *
1159  * For ST_AddIsoNode
1160  *
1161  * @param topo the topology to operate on
1162  * @param face the identifier of containing face or -1 for "unknown"
1163  * @param pt the node position
1164  * @param skipChecks if non-zero skips consistency checks
1165  *                   (coincident nodes, crossing edges,
1166  *                    actual face containement)
1167  *
1168  * @return ID of the newly added node, or -1 on error
1169  *         (librtgeom error handler will be invoked with error message)
1170  *
1171  */
1172 RTT_ELEMID rtt_AddIsoNode(RTT_TOPOLOGY* topo, RTT_ELEMID face,
1173                           RTPOINT* pt, int skipChecks);
1174 
1175 /**
1176  * Move an isolated node
1177  *
1178  * For ST_MoveIsoNode
1179  *
1180  * @param topo the topology to operate on
1181  * @param node the identifier of the nod to be moved
1182  * @param pt the new node position
1183  * @return 0 on success, -1 on error
1184  *         (librtgeom error handler will be invoked with error message)
1185  *
1186  */
1187 int rtt_MoveIsoNode(RTT_TOPOLOGY* topo,
1188                     RTT_ELEMID node, RTPOINT* pt);
1189 
1190 /**
1191  * Remove an isolated node
1192  *
1193  * For ST_RemoveIsoNode
1194  *
1195  * @param topo the topology to operate on
1196  * @param node the identifier of the node to be moved
1197  * @return 0 on success, -1 on error
1198  *         (librtgeom error handler will be invoked with error message)
1199  *
1200  */
1201 int rtt_RemoveIsoNode(RTT_TOPOLOGY* topo, RTT_ELEMID node);
1202 
1203 /**
1204  * Remove an isolated edge
1205  *
1206  * For ST_RemIsoEdge
1207  *
1208  * @param topo the topology to operate on
1209  * @param edge the identifier of the edge to be moved
1210  * @return 0 on success, -1 on error
1211  *         (librtgeom error handler will be invoked with error message)
1212  *
1213  */
1214 int rtt_RemIsoEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge);
1215 
1216 /**
1217  * Add an isolated edge connecting two existing isolated nodes
1218  *
1219  * For ST_AddIsoEdge
1220  *
1221  * @param topo the topology to operate on
1222  * @param start_node identifier of the starting node
1223  * @param end_node identifier of the ending node
1224  * @param geom the edge geometry
1225  * @return ID of the newly added edge, or -1 on error
1226  *         (librtgeom error handler will be invoked with error message)
1227  *
1228  */
1229 RTT_ELEMID rtt_AddIsoEdge(RTT_TOPOLOGY* topo,
1230                           RTT_ELEMID startNode, RTT_ELEMID endNode,
1231                           const RTLINE *geom);
1232 
1233 /**
1234  * Add a new edge possibly splitting a face (modifying it)
1235  *
1236  * For ST_AddEdgeModFace
1237  *
1238  * If the new edge splits a face, the face is shrinked and a new one
1239  * is created. Unless the face being split is the Universal Face, the
1240  * new face will be on the right side of the newly added edge.
1241  *
1242  * @param topo the topology to operate on
1243  * @param start_node identifier of the starting node
1244  * @param end_node identifier of the ending node
1245  * @param geom the edge geometry
1246  * @param skipChecks if non-zero skips consistency checks
1247  *                   (curve being simple and valid, start/end nodes
1248  *                    consistency actual face containement)
1249  *
1250  * @return ID of the newly added edge or null on error
1251  *         (librtgeom error handler will be invoked with error message)
1252  *
1253  */
1254 RTT_ELEMID rtt_AddEdgeModFace(RTT_TOPOLOGY* topo,
1255                               RTT_ELEMID start_node, RTT_ELEMID end_node,
1256                               RTLINE *geom, int skipChecks);
1257 
1258 /**
1259  * Add a new edge possibly splitting a face (replacing with two new faces)
1260  *
1261  * For ST_AddEdgeNewFaces
1262  *
1263  * If the new edge splits a face, the face is replaced by two new faces.
1264  *
1265  * @param topo the topology to operate on
1266  * @param start_node identifier of the starting node
1267  * @param end_node identifier of the ending node
1268  * @param geom the edge geometry
1269  * @param skipChecks if non-zero skips consistency checks
1270  *                   (curve being simple and valid, start/end nodes
1271  *                    consistency actual face containement)
1272  * @return ID of the newly added edge
1273  *
1274  */
1275 RTT_ELEMID rtt_AddEdgeNewFaces(RTT_TOPOLOGY* topo,
1276                               RTT_ELEMID start_node, RTT_ELEMID end_node,
1277                               RTLINE *geom, int skipChecks);
1278 
1279 /**
1280  * Remove an edge, possibly merging two faces (replacing both with a new one)
1281  *
1282  * For ST_RemEdgeNewFace
1283  *
1284  * @param topo the topology to operate on
1285  * @param edge identifier of the edge to be removed
1286  * @return the id of newly created face, 0 if no new face was created
1287  *         or -1 on error
1288  *
1289  */
1290 RTT_ELEMID rtt_RemEdgeNewFace(RTT_TOPOLOGY* topo, RTT_ELEMID edge);
1291 
1292 /**
1293  * Remove an edge, possibly merging two faces (replacing one with the other)
1294  *
1295  * For ST_RemEdgeModFace
1296  *
1297  * Preferentially keep the face on the right, to be symmetric with
1298  * rtt_AddEdgeModFace.
1299  *
1300  * @param topo the topology to operate on
1301  * @param edge identifier of the edge to be removed
1302  * @return the id of the face that takes the space previously occupied
1303  *         by the removed edge, or -1 on error
1304  *         (librtgeom error handler will be invoked with error message)
1305  *
1306  */
1307 RTT_ELEMID rtt_RemEdgeModFace(RTT_TOPOLOGY* topo, RTT_ELEMID edge);
1308 
1309 /**
1310  * Changes the shape of an edge without affecting the topology structure.
1311  *
1312  * For ST_ChangeEdgeGeom
1313  *
1314  * @param topo the topology to operate on
1315  * @param curve the edge geometry
1316  * @return 0 on success, -1 on error
1317  *         (librtgeom error handler will be invoked with error message)
1318  *
1319  */
1320 int rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge, RTLINE* curve);
1321 
1322 /**
1323  * Split an edge by a node, modifying the original edge and adding a new one.
1324  *
1325  * For ST_ModEdgeSplit
1326  *
1327  * @param topo the topology to operate on
1328  * @param edge identifier of the edge to be split
1329  * @param pt geometry of the new node
1330  * @param skipChecks if non-zero skips consistency checks
1331  *                   (coincident node, point not on edge...)
1332  * @return the id of newly created node, or -1 on error
1333  *         (librtgeom error handler will be invoked with error message)
1334  *
1335  */
1336 RTT_ELEMID rtt_ModEdgeSplit(RTT_TOPOLOGY* topo, RTT_ELEMID edge,
1337                             RTPOINT* pt, int skipChecks);
1338 
1339 /**
1340  * Split an edge by a node, replacing it with two new edges
1341  *
1342  * For ST_NewEdgesSplit
1343  *
1344  * @param topo the topology to operate on
1345  * @param edge identifier of the edge to be split
1346  * @param pt geometry of the new node
1347  * @param skipChecks if non-zero skips consistency checks
1348  *                   (coincident node, point not on edge...)
1349  * @return the id of newly created node
1350  *
1351  */
1352 RTT_ELEMID rtt_NewEdgesSplit(RTT_TOPOLOGY* topo, RTT_ELEMID edge,
1353                              RTPOINT* pt, int skipChecks);
1354 
1355 /**
1356  * Merge two edges, modifying the first and deleting the second
1357  *
1358  * For ST_ModEdgeHeal
1359  *
1360  * @param topo the topology to operate on
1361  * @param e1 identifier of first edge
1362  * @param e2 identifier of second edge
1363  * @return the id of the removed node or -1 on error
1364  *         (librtgeom error handler will be invoked with error message)
1365  *
1366  */
1367 RTT_ELEMID rtt_ModEdgeHeal(RTT_TOPOLOGY* topo, RTT_ELEMID e1, RTT_ELEMID e2);
1368 
1369 /**
1370  * Merge two edges, replacing both with a new one
1371  *
1372  * For ST_NewEdgeHeal
1373  *
1374  * @param topo the topology to operate on
1375  * @param e1 identifier of first edge
1376  * @param e2 identifier of second edge
1377  * @return the id of the new edge or -1 on error
1378  *         (librtgeom error handler will be invoked with error message)
1379  *
1380  */
1381 RTT_ELEMID rtt_NewEdgeHeal(RTT_TOPOLOGY* topo, RTT_ELEMID e1, RTT_ELEMID e2);
1382 
1383 /**
1384  * Return the list of directed edges bounding a face
1385  *
1386  * For ST_GetFaceEdges
1387  *
1388  * @param topo the topology to operate on
1389  * @param face identifier of the face
1390  * @param edges will be set to an array of signed edge identifiers, will
1391  *              need to be released with rtfree
1392  * @return the number of edges in the edges array, or -1 on error
1393  *         (librtgeom error handler will be invoked with error message)
1394  *
1395  */
1396 int rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face, RTT_ELEMID **edges);
1397 
1398 /**
1399  * Return the geometry of a face
1400  *
1401  * For ST_GetFaceGeometry
1402  *
1403  * @param topo the topology to operate on
1404  * @param face identifier of the face
1405  * @return a polygon geometry representing the face, ownership to caller,
1406  *         to be released with rtgeom_release, or NULL on error
1407  *         (librtgeom error handler will be invoked with error message)
1408  */
1409 RTGEOM* rtt_GetFaceGeometry(RTT_TOPOLOGY* topo, RTT_ELEMID face);
1410 
1411 /*******************************************************************
1412  *
1413  * Utility functions
1414  *
1415  *******************************************************************/
1416 
1417 
1418 /*
1419  * rtt_tpsnap - snap geometry to topology
1420  *
1421  * Uses Trevisani-Peri algorithm version 13 as reported here:
1422  * https://git.osgeo.org/gitea/rttopo/librttopo/wiki/SnapToTopo-algorithm
1423  *
1424  * @param topo the reference topology
1425  * @param gin the input geometry
1426  * @param tolerance_snap snap tolerance
1427  * @param tolerance_removal removal tolerance (use -1 to skip removal phase)
1428  * @param iterate if non zero, allows snapping to more than a single vertex,
1429  *                iteratively
1430  *
1431  * @return a new geometry, or NULL on error
1432  *
1433  */
1434 RTGEOM* rtt_tpsnap(RTT_TOPOLOGY *topo, const RTGEOM *gin,
1435                    double tolerance_snap,
1436                    double tolerance_removal,
1437                    int iterate);
1438 
1439 #endif /* LIBRTGEOM_TOPO_H */
1440