PostGIS 3.0.6dev-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 767 of file lwgeom_topo.c.

769{
770 uint64_t num_nodes;
771 uint64_t i;
772 LWT_ISO_EDGE newedge;
773 LWT_ISO_NODE *endpoints;
774 LWT_ELEMID containing_face = -1;
775 LWT_ELEMID node_ids[2];
776 LWT_ISO_NODE updated_nodes[2];
777 int skipISOChecks = 0;
778 POINT2D p1, p2;
779
780 /* NOT IN THE SPECS:
781 * A closed edge is never isolated (as it forms a face)
782 */
783 if (startNode == endNode)
784 {
785 lwerror("Closed edges would not be isolated, try lwt_AddEdgeNewFaces");
786 return -1;
787 }
788
789 if ( ! skipISOChecks )
790 {
791 /* Acurve must be simple */
792 if ( ! lwgeom_is_simple(lwline_as_lwgeom(geom)) )
793 {
794 lwerror("SQL/MM Spatial exception - curve not simple");
795 return -1;
796 }
797 }
798
799 /*
800 * Check for:
801 * existence of nodes
802 * nodes faces match
803 * Extract:
804 * nodes face id
805 * nodes geoms
806 */
807 num_nodes = 2;
808 node_ids[0] = startNode;
809 node_ids[1] = endNode;
810 endpoints = lwt_be_getNodeById( topo, node_ids, &num_nodes,
812 if (num_nodes == UINT64_MAX)
813 {
814 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
815 return -1;
816 }
817 else if ( num_nodes < 2 )
818 {
819 if ( num_nodes ) _lwt_release_nodes(endpoints, num_nodes);
820 lwerror("SQL/MM Spatial exception - non-existent node");
821 return -1;
822 }
823 for ( i=0; i<num_nodes; ++i )
824 {
825 const LWT_ISO_NODE *n = &(endpoints[i]);
826 if ( n->containing_face == -1 )
827 {
828 _lwt_release_nodes(endpoints, num_nodes);
829 lwerror("SQL/MM Spatial exception - not isolated node");
830 return -1;
831 }
832 if ( containing_face == -1 ) containing_face = n->containing_face;
833 else if ( containing_face != n->containing_face )
834 {
835 _lwt_release_nodes(endpoints, num_nodes);
836 lwerror("SQL/MM Spatial exception - nodes in different faces");
837 return -1;
838 }
839
840 if ( ! skipISOChecks )
841 {
842 if ( n->node_id == startNode )
843 {
844 /* l) Check that start point of acurve match start node geoms. */
845 getPoint2d_p(geom->points, 0, &p1);
846 getPoint2d_p(n->geom->point, 0, &p2);
847 if ( ! p2d_same(&p1, &p2) )
848 {
849 _lwt_release_nodes(endpoints, num_nodes);
850 lwerror("SQL/MM Spatial exception - "
851 "start node not geometry start point.");
852 return -1;
853 }
854 }
855 else
856 {
857 /* m) Check that end point of acurve match end node geoms. */
858 getPoint2d_p(geom->points, geom->points->npoints-1, &p1);
859 getPoint2d_p(n->geom->point, 0, &p2);
860 if ( ! p2d_same(&p1, &p2) )
861 {
862 _lwt_release_nodes(endpoints, num_nodes);
863 lwerror("SQL/MM Spatial exception - "
864 "end node not geometry end point.");
865 return -1;
866 }
867 }
868 }
869 }
870
871 if ( num_nodes ) _lwt_release_nodes(endpoints, num_nodes);
872
873 if ( ! skipISOChecks )
874 {
875 if ( _lwt_CheckEdgeCrossing( topo, startNode, endNode, geom, 0 ) )
876 {
877 /* would have called lwerror already, leaking :( */
878 return -1;
879 }
880 }
881
882 /*
883 * All checks passed, time to prepare the new edge
884 */
885
886 newedge.edge_id = lwt_be_getNextEdgeId( topo );
887 if ( newedge.edge_id == -1 ) {
888 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
889 return -1;
890 }
891
892 /* TODO: this should likely be an exception instead ! */
893 if ( containing_face == -1 ) containing_face = 0;
894
895 newedge.start_node = startNode;
896 newedge.end_node = endNode;
897 newedge.face_left = newedge.face_right = containing_face;
898 newedge.next_left = -newedge.edge_id;
899 newedge.next_right = newedge.edge_id;
900 newedge.geom = (LWLINE *)geom; /* const cast.. */
901
902 int ret = lwt_be_insertEdges(topo, &newedge, 1);
903 if ( ret == -1 ) {
904 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
905 return -1;
906 } else if ( ret == 0 ) {
907 lwerror("Insertion of split edge failed (no reason)");
908 return -1;
909 }
910
911 /*
912 * Update Node containing_face values
913 *
914 * the nodes anode and anothernode are no more isolated
915 * because now there is an edge connecting them
916 */
917 updated_nodes[0].node_id = startNode;
918 updated_nodes[0].containing_face = -1;
919 updated_nodes[1].node_id = endNode;
920 updated_nodes[1].containing_face = -1;
921 ret = lwt_be_updateNodesById(topo, updated_nodes, 2,
923 if ( ret == -1 ) {
924 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
925 return -1;
926 }
927
928 return newedge.edge_id;
929}
int lwgeom_is_simple(const LWGEOM *lwgeom)
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition lwgeom_api.c:349
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:321
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition lwalgorithm.c:50
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_NODE_CONTAINING_FACE
#define LWT_COL_NODE_ALL
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
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)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
LWT_ISO_NODE * lwt_be_getNodeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
POINTARRAY * points
Definition liblwgeom.h:469
POINTARRAY * point
Definition liblwgeom.h:457
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
const LWT_BE_IFACE * be_iface
uint32_t npoints
Definition liblwgeom.h:413

References _lwt_CheckEdgeCrossing(), _lwt_release_nodes(), LWT_TOPOLOGY_T::be_iface, 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_lastErrorMessage(), 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(), LWPOINT::point, LWLINE::points, and LWT_ISO_EDGE::start_node.

Here is the call graph for this function: