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