PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ lwt_AddIsoEdge()

LWT_ELEMID lwt_AddIsoEdge ( LWT_TOPOLOGY topo,
LWT_ELEMID  startNode,
LWT_ELEMID  endNode,
const LWLINE geom 
)

Add an isolated edge connecting two existing isolated nodes.

For ST_AddIsoEdge

Parameters
topothe topology to operate on
start_nodeidentifier of the starting node
end_nodeidentifier of the ending node
geomthe edge geometry
Returns
ID of the newly added edge, or -1 on error (liblwgeom error handler will be invoked with error message)

Definition at line 918 of file lwgeom_topo.c.

920{
921 uint64_t num_nodes;
922 uint64_t i;
923 LWT_ISO_EDGE newedge;
924 LWT_ISO_NODE *endpoints;
925 LWT_ELEMID containing_face = -1;
926 LWT_ELEMID node_ids[2];
927 LWT_ISO_NODE updated_nodes[2];
928 int skipISOChecks = 0;
929 POINT2D p1, p2;
930
931 /* NOT IN THE SPECS:
932 * A closed edge is never isolated (as it forms a face)
933 */
934 if (startNode == endNode)
935 {
936 lwerror("Closed edges would not be isolated, try lwt_AddEdgeNewFaces");
937 return -1;
938 }
939
940 if ( ! skipISOChecks )
941 {
942 /* Acurve must be simple */
943 if ( ! lwgeom_is_simple(lwline_as_lwgeom(geom)) )
944 {
945 lwerror("SQL/MM Spatial exception - curve not simple");
946 return -1;
947 }
948 }
949
950 /*
951 * Check for:
952 * existence of nodes
953 * nodes faces match
954 * Extract:
955 * nodes face id
956 * nodes geoms
957 */
958 num_nodes = 2;
959 node_ids[0] = startNode;
960 node_ids[1] = endNode;
961 endpoints = lwt_be_getNodeById( topo, node_ids, &num_nodes,
963 if (num_nodes == UINT64_MAX)
964 {
966 return -1;
967 }
968 else if ( num_nodes < 2 )
969 {
970 if ( num_nodes ) _lwt_release_nodes(endpoints, num_nodes);
971 lwerror("SQL/MM Spatial exception - non-existent node");
972 return -1;
973 }
974 for ( i=0; i<num_nodes; ++i )
975 {
976 const LWT_ISO_NODE *n = &(endpoints[i]);
977 if ( n->containing_face == -1 )
978 {
979 _lwt_release_nodes(endpoints, num_nodes);
980 lwerror("SQL/MM Spatial exception - not isolated node");
981 return -1;
982 }
983 if ( containing_face == -1 ) containing_face = n->containing_face;
984 else if ( containing_face != n->containing_face )
985 {
986 _lwt_release_nodes(endpoints, num_nodes);
987 lwerror("SQL/MM Spatial exception - nodes in different faces");
988 return -1;
989 }
990
991 if ( ! skipISOChecks )
992 {
993 if ( n->node_id == startNode )
994 {
995 /* l) Check that start point of acurve match start node geoms. */
996 getPoint2d_p(geom->points, 0, &p1);
997 getPoint2d_p(n->geom->point, 0, &p2);
998 if ( ! P2D_SAME_STRICT(&p1, &p2) )
999 {
1000 _lwt_release_nodes(endpoints, num_nodes);
1001 lwerror("SQL/MM Spatial exception - "
1002 "start node not geometry start point.");
1003 return -1;
1004 }
1005 }
1006 else
1007 {
1008 /* m) Check that end point of acurve match end node geoms. */
1009 getPoint2d_p(geom->points, geom->points->npoints-1, &p1);
1010 getPoint2d_p(n->geom->point, 0, &p2);
1011 if ( ! P2D_SAME_STRICT(&p1, &p2) )
1012 {
1013 _lwt_release_nodes(endpoints, num_nodes);
1014 lwerror("SQL/MM Spatial exception - "
1015 "end node not geometry end point.");
1016 return -1;
1017 }
1018 }
1019 }
1020 }
1021
1022 if ( num_nodes ) _lwt_release_nodes(endpoints, num_nodes);
1023
1024 if ( ! skipISOChecks )
1025 {
1026 if ( _lwt_CheckEdgeCrossing( topo, startNode, endNode, geom, 0 ) )
1027 {
1028 /* would have called lwerror already, leaking :( */
1029 return -1;
1030 }
1031 }
1032
1033 /*
1034 * All checks passed, time to prepare the new edge
1035 */
1036
1037 newedge.edge_id = lwt_be_getNextEdgeId( topo );
1038 if ( newedge.edge_id == -1 ) {
1040 return -1;
1041 }
1042
1043 /* TODO: this should likely be an exception instead ! */
1044 if ( containing_face == -1 ) containing_face = 0;
1045
1046 newedge.start_node = startNode;
1047 newedge.end_node = endNode;
1048 newedge.face_left = newedge.face_right = containing_face;
1049 newedge.next_left = -newedge.edge_id;
1050 newedge.next_right = newedge.edge_id;
1051 newedge.geom = (LWLINE *)geom; /* const cast.. */
1052
1053 int ret = lwt_be_insertEdges(topo, &newedge, 1);
1054 if ( ret == -1 ) {
1056 return -1;
1057 } else if ( ret == 0 ) {
1058 lwerror("Insertion of split edge failed (no reason)");
1059 return -1;
1060 }
1061
1062 /*
1063 * Update Node containing_face values
1064 *
1065 * the nodes anode and anothernode are no more isolated
1066 * because now there is an edge connecting them
1067 */
1068 updated_nodes[0].node_id = startNode;
1069 updated_nodes[0].containing_face = -1;
1070 updated_nodes[1].node_id = endNode;
1071 updated_nodes[1].containing_face = -1;
1072 ret = lwt_be_updateNodesById(topo, updated_nodes, 2,
1074 if ( ret == -1 ) {
1076 return -1;
1077 }
1078
1079 return newedge.edge_id;
1080}
int lwgeom_is_simple(const LWGEOM *lwgeom)
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition lwgeom_api.c:342
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
#define P2D_SAME_STRICT(a, b)
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_NODE_CONTAINING_FACE
#define LWT_COL_NODE_ALL
#define PGTOPO_BE_ERROR()
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
LWT_ELEMID lwt_be_getNextEdgeId(LWT_TOPOLOGY *topo)
static int lwt_be_updateNodesById(LWT_TOPOLOGY *topo, const LWT_ISO_NODE *nodes, int numnodes, int upd_fields)
static int _lwt_CheckEdgeCrossing(LWT_TOPOLOGY *topo, LWT_ELEMID start_node, LWT_ELEMID end_node, const LWLINE *geom, LWT_ELEMID myself)
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
int lwt_be_insertEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edge, uint64_t numelems)
LWT_ISO_NODE * lwt_be_getNodeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
POINTARRAY * points
Definition liblwgeom.h:483
POINTARRAY * point
Definition liblwgeom.h:471
LWT_ELEMID face_right
LWT_ELEMID next_right
LWT_ELEMID end_node
LWT_ELEMID face_left
LWT_ELEMID next_left
LWT_ELEMID edge_id
LWT_ELEMID start_node
LWT_ELEMID node_id
LWT_ELEMID containing_face
LWPOINT * geom
uint32_t npoints
Definition liblwgeom.h:427

References _lwt_CheckEdgeCrossing(), _lwt_release_nodes(), LWT_ISO_NODE::containing_face, LWT_ISO_EDGE::edge_id, LWT_ISO_EDGE::end_node, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, LWT_ISO_NODE::geom, LWT_ISO_EDGE::geom, getPoint2d_p(), lwerror(), lwgeom_is_simple(), lwline_as_lwgeom(), lwt_be_getNextEdgeId(), lwt_be_getNodeById(), lwt_be_insertEdges(), lwt_be_updateNodesById(), LWT_COL_NODE_ALL, LWT_COL_NODE_CONTAINING_FACE, LWT_ISO_EDGE::next_left, LWT_ISO_EDGE::next_right, LWT_ISO_NODE::node_id, POINTARRAY::npoints, P2D_SAME_STRICT, PGTOPO_BE_ERROR, LWPOINT::point, LWLINE::points, and LWT_ISO_EDGE::start_node.

Here is the call graph for this function: