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

◆ _lwt_RemEdge()

static LWT_ELEMID _lwt_RemEdge ( LWT_TOPOLOGY topo,
LWT_ELEMID  edge_id,
int  modFace 
)
static

Definition at line 3810 of file lwgeom_topo.c.

3811{
3812 uint64_t i, nedges, nfaces, fields;
3813 LWT_ISO_EDGE *edge = NULL;
3814 LWT_ISO_EDGE *upd_edge = NULL;
3815 LWT_ISO_EDGE upd_edge_left[2];
3816 int nedge_left = 0;
3817 LWT_ISO_EDGE upd_edge_right[2];
3818 int nedge_right = 0;
3819 LWT_ISO_NODE upd_node[2];
3820 int nnode = 0;
3821 LWT_ISO_FACE *faces = NULL;
3822 LWT_ISO_FACE newface;
3823 LWT_ELEMID node_ids[2];
3824 LWT_ELEMID face_ids[2];
3825 int fnode_edges = 0; /* number of edges on the first node (excluded
3826 * the one being removed ) */
3827 int lnode_edges = 0; /* number of edges on the last node (excluded
3828 * the one being removed ) */
3829
3830 newface.face_id = 0;
3831
3832 i = 1;
3833 edge = lwt_be_getEdgeById(topo, &edge_id, &i, LWT_COL_EDGE_ALL);
3834 if (!edge)
3835 {
3836 LWDEBUGF(1, "lwt_be_getEdgeById returned NULL and set i=%d", i);
3837 if (i == UINT64_MAX)
3838 {
3839 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3840 return -1;
3841 }
3842 else if (i == 0)
3843 {
3844 lwerror("SQL/MM Spatial exception - non-existent edge %" LWTFMT_ELEMID, edge_id);
3845 return -1;
3846 }
3847 else
3848 {
3849 lwerror(
3850 "Backend coding error: getEdgeById callback returned NULL "
3851 "but numelements output parameter has value %d "
3852 "(expected 0 or 1)",
3853 i);
3854 return -1;
3855 }
3856 }
3857
3858 if ( ! lwt_be_checkTopoGeomRemEdge(topo, edge_id,
3859 edge->face_left, edge->face_right) )
3860 {
3862 return -1;
3863 }
3864
3865 LWDEBUG(1, "Updating next_{right,left}_face of ring edges...");
3866
3867 /* Update edge linking */
3868
3869 nedges = 0;
3870 node_ids[nedges++] = edge->start_node;
3871 if ( edge->end_node != edge->start_node )
3872 {
3873 node_ids[nedges++] = edge->end_node;
3874 }
3878 upd_edge = lwt_be_getEdgeByNode( topo, &(node_ids[0]), &nedges, fields );
3879 if (nedges == UINT64_MAX)
3880 {
3881 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3882 return -1;
3883 }
3884 nedge_left = nedge_right = 0;
3885 for ( i=0; i<nedges; ++i )
3886 {
3887 LWT_ISO_EDGE *e = &(upd_edge[i]);
3888 if ( e->edge_id == edge_id ) continue;
3889 if ( e->start_node == edge->start_node || e->end_node == edge->start_node )
3890 {
3891 ++fnode_edges;
3892 }
3893 if ( e->start_node == edge->end_node || e->end_node == edge->end_node )
3894 {
3895 ++lnode_edges;
3896 }
3897 if ( e->next_left == -edge_id )
3898 {
3899 upd_edge_left[nedge_left].edge_id = e->edge_id;
3900 upd_edge_left[nedge_left++].next_left =
3901 edge->next_left != edge_id ? edge->next_left : edge->next_right;
3902 }
3903 else if ( e->next_left == edge_id )
3904 {
3905 upd_edge_left[nedge_left].edge_id = e->edge_id;
3906 upd_edge_left[nedge_left++].next_left =
3907 edge->next_right != -edge_id ? edge->next_right : edge->next_left;
3908 }
3909
3910 if ( e->next_right == -edge_id )
3911 {
3912 upd_edge_right[nedge_right].edge_id = e->edge_id;
3913 upd_edge_right[nedge_right++].next_right =
3914 edge->next_left != edge_id ? edge->next_left : edge->next_right;
3915 }
3916 else if ( e->next_right == edge_id )
3917 {
3918 upd_edge_right[nedge_right].edge_id = e->edge_id;
3919 upd_edge_right[nedge_right++].next_right =
3920 edge->next_right != -edge_id ? edge->next_right : edge->next_left;
3921 }
3922 }
3923
3924 if ( nedge_left )
3925 {
3926 LWDEBUGF(1, "updating %d 'next_left' edges", nedge_left);
3927 /* update edges in upd_edge_left set next_left */
3928 int result = lwt_be_updateEdgesById(topo, &(upd_edge_left[0]), nedge_left, LWT_COL_EDGE_NEXT_LEFT);
3929 if (result == -1)
3930 {
3931 _lwt_release_edges(edge, 1);
3932 lwfree(upd_edge);
3933 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3934 return -1;
3935 }
3936 }
3937 if ( nedge_right )
3938 {
3939 LWDEBUGF(1, "updating %d 'next_right' edges", nedge_right);
3940 /* update edges in upd_edge_right set next_right */
3941 int result = lwt_be_updateEdgesById(topo, &(upd_edge_right[0]), nedge_right, LWT_COL_EDGE_NEXT_RIGHT);
3942 if (result == -1)
3943 {
3944 _lwt_release_edges(edge, 1);
3945 lwfree(upd_edge);
3946 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3947 return -1;
3948 }
3949 }
3950 LWDEBUGF(1, "releasing %d updateable edges in %p", nedges, upd_edge);
3951 lwfree(upd_edge);
3952
3953 /* Id of face that will take up all the space previously
3954 * taken by left and right faces of the edge */
3955 LWT_ELEMID floodface;
3956
3957 /* Find floodface, and update its mbr if != 0 */
3958 if ( edge->face_left == edge->face_right )
3959 {
3960 floodface = edge->face_right;
3961 }
3962 else
3963 {
3964 /* Two faces healed */
3965 if ( edge->face_left == 0 || edge->face_right == 0 )
3966 {
3967 floodface = 0;
3968 LWDEBUG(1, "floodface is universe");
3969 }
3970 else
3971 {
3972 /* we choose right face as the face that will remain
3973 * to be symmetric with ST_AddEdgeModFace */
3974 floodface = edge->face_right;
3975 LWDEBUGF(1, "floodface is %" LWTFMT_ELEMID, floodface);
3976 /* update mbr of floodface as union of mbr of both faces */
3977 face_ids[0] = edge->face_left;
3978 face_ids[1] = edge->face_right;
3979 nfaces = 2;
3980 fields = LWT_COL_FACE_ALL;
3981 faces = lwt_be_getFaceById(topo, face_ids, &nfaces, fields);
3982 if (nfaces == UINT64_MAX)
3983 {
3984 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3985 return -1;
3986 }
3987 GBOX *box1=NULL;
3988 GBOX *box2=NULL;
3989 for ( i=0; i<nfaces; ++i )
3990 {
3991 if ( faces[i].face_id == edge->face_left )
3992 {
3993 if ( ! box1 ) box1 = faces[i].mbr;
3994 else
3995 {
3996 i = edge->face_left;
3997 _lwt_release_edges(edge, 1);
3998 _lwt_release_faces(faces, nfaces);
3999 lwerror("corrupted topology: more than 1 face have face_id=%"
4000 LWTFMT_ELEMID, i);
4001 return -1;
4002 }
4003 }
4004 else if ( faces[i].face_id == edge->face_right )
4005 {
4006 if ( ! box2 ) box2 = faces[i].mbr;
4007 else
4008 {
4009 i = edge->face_right;
4010 _lwt_release_edges(edge, 1);
4011 _lwt_release_faces(faces, nfaces);
4012 lwerror("corrupted topology: more than 1 face have face_id=%"
4013 LWTFMT_ELEMID, i);
4014 return -1;
4015 }
4016 }
4017 else
4018 {
4019 i = faces[i].face_id;
4020 _lwt_release_edges(edge, 1);
4021 _lwt_release_faces(faces, nfaces);
4022 lwerror("Backend coding error: getFaceById returned face "
4023 "with non-requested id %" LWTFMT_ELEMID, i);
4024 return -1;
4025 }
4026 }
4027 if ( ! box1 ) {
4028 i = edge->face_left;
4029 _lwt_release_edges(edge, 1);
4030 _lwt_release_faces(faces, nfaces);
4031 lwerror("corrupted topology: no face have face_id=%"
4032 LWTFMT_ELEMID " (left face for edge %"
4033 LWTFMT_ELEMID ")", i, edge_id);
4034 return -1;
4035 }
4036 if ( ! box2 ) {
4037 i = edge->face_right;
4038 _lwt_release_edges(edge, 1);
4039 _lwt_release_faces(faces, nfaces);
4040 lwerror("corrupted topology: no face have face_id=%"
4041 LWTFMT_ELEMID " (right face for edge %"
4042 LWTFMT_ELEMID ")", i, edge_id);
4043 return -1;
4044 }
4045 gbox_merge(box2, box1); /* box1 is now the union of the two */
4046 newface.mbr = box1;
4047 if ( modFace )
4048 {
4049 newface.face_id = floodface;
4050 int result = lwt_be_updateFacesById(topo, &newface, 1);
4051 _lwt_release_faces(faces, 2);
4052 if (result == -1)
4053 {
4054 _lwt_release_edges(edge, 1);
4055 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4056 return -1;
4057 }
4058 if (result != 1)
4059 {
4060 _lwt_release_edges(edge, 1);
4061 lwerror("Unexpected error: %d faces updated when expecting 1", i);
4062 return -1;
4063 }
4064 }
4065 else
4066 {
4067 /* New face replaces the old two faces */
4068 newface.face_id = -1;
4069 int result = lwt_be_insertFaces(topo, &newface, 1);
4070 _lwt_release_faces(faces, 2);
4071 if (result == -1)
4072 {
4073 _lwt_release_edges(edge, 1);
4074 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4075 return -1;
4076 }
4077 if (result != 1)
4078 {
4079 _lwt_release_edges(edge, 1);
4080 lwerror("Unexpected error: %d faces inserted when expecting 1", result);
4081 return -1;
4082 }
4083 floodface = newface.face_id;
4084 }
4085 }
4086
4087 /* Update face references for edges and nodes still referencing
4088 * the removed face(s) */
4089
4090 if ( edge->face_left != floodface )
4091 {
4092 if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_left, floodface) )
4093 {
4094 _lwt_release_edges(edge, 1);
4095 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4096 return -1;
4097 }
4098 if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_left, floodface) )
4099 {
4100 _lwt_release_edges(edge, 1);
4101 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4102 return -1;
4103 }
4104 }
4105
4106 if ( edge->face_right != floodface )
4107 {
4108 if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_right, floodface) )
4109 {
4110 _lwt_release_edges(edge, 1);
4111 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4112 return -1;
4113 }
4114 if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_right, floodface) )
4115 {
4116 _lwt_release_edges(edge, 1);
4117 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4118 return -1;
4119 }
4120 }
4121
4122 /* Update topogeoms on heal */
4124 edge->face_right, edge->face_left,
4125 floodface) )
4126 {
4127 _lwt_release_edges(edge, 1);
4129 return -1;
4130 }
4131 } /* two faces healed */
4132
4133 /* Delete the edge */
4134 int result = lwt_be_deleteEdges(topo, edge, LWT_COL_EDGE_EDGE_ID);
4135 if (result == -1)
4136 {
4137 _lwt_release_edges(edge, 1);
4138 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4139 return -1;
4140 }
4141
4142 /* If any of the edge nodes remained isolated, set
4143 * containing_face = floodface
4144 */
4145 if ( ! fnode_edges )
4146 {
4147 upd_node[nnode].node_id = edge->start_node;
4148 upd_node[nnode].containing_face = floodface;
4149 ++nnode;
4150 }
4151 if ( edge->end_node != edge->start_node && ! lnode_edges )
4152 {
4153 upd_node[nnode].node_id = edge->end_node;
4154 upd_node[nnode].containing_face = floodface;
4155 ++nnode;
4156 }
4157 if ( nnode )
4158 {
4159 int result = lwt_be_updateNodesById(topo, upd_node, nnode, LWT_COL_NODE_CONTAINING_FACE);
4160 if (result == -1)
4161 {
4162 _lwt_release_edges(edge, 1);
4163 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4164 return -1;
4165 }
4166 }
4167
4168 if ( edge->face_left != edge->face_right )
4169 /* or there'd be no face to remove */
4170 {
4171 LWT_ELEMID ids[2];
4172 int nids = 0;
4173 if ( edge->face_right != floodface )
4174 ids[nids++] = edge->face_right;
4175 if ( edge->face_left != floodface )
4176 ids[nids++] = edge->face_left;
4177 int result = lwt_be_deleteFacesById(topo, ids, nids);
4178 if (result == -1)
4179 {
4180 _lwt_release_edges(edge, 1);
4181 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4182 return -1;
4183 }
4184 }
4185
4186 _lwt_release_edges(edge, 1);
4187 return modFace ? floodface : newface.face_id;
4188}
int gbox_merge(const GBOX *new_box, GBOX *merge_box)
Update the merged GBOX to be large enough to include itself and the new box.
Definition gbox.c:257
void lwfree(void *mem)
Definition lwutil.c:242
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_FACE_ALL
#define LWT_COL_EDGE_START_NODE
#define LWT_COL_EDGE_NEXT_RIGHT
#define LWT_COL_NODE_CONTAINING_FACE
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
#define LWT_COL_EDGE_ALL
#define LWT_COL_EDGE_END_NODE
#define LWT_COL_EDGE_NEXT_LEFT
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
static LWT_ISO_EDGE * lwt_be_getEdgeByNode(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
static uint64_t lwt_be_updateFacesById(LWT_TOPOLOGY *topo, const LWT_ISO_FACE *faces, uint64_t numfaces)
static int lwt_be_deleteFacesById(const LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t numelems)
static int lwt_be_checkTopoGeomRemEdge(LWT_TOPOLOGY *topo, LWT_ELEMID edge_id, LWT_ELEMID face_left, LWT_ELEMID face_right)
static int _lwt_UpdateEdgeFaceRef(LWT_TOPOLOGY *topo, LWT_ELEMID of, LWT_ELEMID nf)
LWT_ISO_EDGE * lwt_be_getEdgeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
static int lwt_be_updateNodesById(LWT_TOPOLOGY *topo, const LWT_ISO_NODE *nodes, int numnodes, int upd_fields)
static int lwt_be_updateTopoGeomFaceHeal(LWT_TOPOLOGY *topo, LWT_ELEMID face1, LWT_ELEMID face2, LWT_ELEMID newface)
static int lwt_be_insertFaces(LWT_TOPOLOGY *topo, LWT_ISO_FACE *face, uint64_t numelems)
static LWT_ISO_FACE * lwt_be_getFaceById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
int lwt_be_deleteEdges(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *sel_edge, int sel_fields)
static int _lwt_UpdateNodeFaceRef(LWT_TOPOLOGY *topo, LWT_ELEMID of, LWT_ELEMID nf)
static void _lwt_release_faces(LWT_ISO_FACE *faces, int num_faces)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
#define LWTFMT_ELEMID
Definition lwgeom_topo.c:43
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
static int lwt_be_updateEdgesById(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *edges, int numedges, int upd_fields)
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 face_id
LWT_ELEMID node_id
LWT_ELEMID containing_face
const LWT_BE_IFACE * be_iface

References _lwt_release_edges(), _lwt_release_faces(), _lwt_UpdateEdgeFaceRef(), _lwt_UpdateNodeFaceRef(), LWT_TOPOLOGY_T::be_iface, LWT_ISO_NODE::containing_face, LWT_ISO_EDGE::edge_id, LWT_ISO_EDGE::end_node, LWT_ISO_FACE::face_id, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, gbox_merge(), LWDEBUG, LWDEBUGF, lwerror(), lwfree(), lwt_be_checkTopoGeomRemEdge(), lwt_be_deleteEdges(), lwt_be_deleteFacesById(), lwt_be_getEdgeById(), lwt_be_getEdgeByNode(), lwt_be_getFaceById(), lwt_be_insertFaces(), lwt_be_lastErrorMessage(), lwt_be_updateEdgesById(), lwt_be_updateFacesById(), lwt_be_updateNodesById(), lwt_be_updateTopoGeomFaceHeal(), LWT_COL_EDGE_ALL, LWT_COL_EDGE_EDGE_ID, LWT_COL_EDGE_END_NODE, LWT_COL_EDGE_NEXT_LEFT, LWT_COL_EDGE_NEXT_RIGHT, LWT_COL_EDGE_START_NODE, LWT_COL_FACE_ALL, LWT_COL_NODE_CONTAINING_FACE, LWTFMT_ELEMID, LWT_ISO_FACE::mbr, LWT_ISO_EDGE::next_left, LWT_ISO_EDGE::next_right, LWT_ISO_NODE::node_id, and LWT_ISO_EDGE::start_node.

Referenced by lwt_RemEdgeModFace(), and lwt_RemEdgeNewFace().

Here is the call graph for this function:
Here is the caller graph for this function: