PostGIS 3.6.2dev-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 3976 of file lwgeom_topo.c.

3977{
3978 uint64_t i, nedges, nfaces, fields;
3979 LWT_ISO_EDGE *edge = NULL;
3980 LWT_ISO_EDGE *upd_edge = NULL;
3981 LWT_ISO_EDGE upd_edge_left[2];
3982 int nedge_left = 0;
3983 LWT_ISO_EDGE upd_edge_right[2];
3984 int nedge_right = 0;
3985 LWT_ISO_NODE upd_node[2];
3986 int nnode = 0;
3987 LWT_ISO_FACE *faces = NULL;
3988 LWT_ISO_FACE newface;
3989 LWT_ELEMID node_ids[2];
3990 LWT_ELEMID face_ids[2];
3991 int fnode_edges = 0; /* number of edges on the first node (excluded
3992 * the one being removed ) */
3993 int lnode_edges = 0; /* number of edges on the last node (excluded
3994 * the one being removed ) */
3995
3996
3997 newface.face_id = 0;
3998
3999 i = 1;
4000 edge = lwt_be_getEdgeById(topo, &edge_id, &i, LWT_COL_EDGE_ALL);
4001 if (!edge)
4002 {
4003 LWDEBUGF(1, "lwt_be_getEdgeById returned NULL and set i=%llu", i);
4004 if (i == UINT64_MAX)
4005 {
4007 return -1;
4008 }
4009 else if (i == 0)
4010 {
4011 lwerror("SQL/MM Spatial exception - non-existent edge %" LWTFMT_ELEMID, edge_id);
4012 return -1;
4013 }
4014 else
4015 {
4016 lwerror(
4017 "Backend coding error: getEdgeById callback returned NULL "
4018 "but numelements output parameter has value %" PRIu64 " "
4019 "(expected 0 or 1)",
4020 i);
4021 return -1;
4022 }
4023 }
4024
4025 if ( ! lwt_be_checkTopoGeomRemEdge(topo, edge_id,
4026 edge->face_left, edge->face_right) )
4027 {
4029 return -1;
4030 }
4031
4032 LWDEBUG(1, "Updating next_{right,left}_face of ring edges...");
4033
4034 /* Update edge linking */
4035
4036 nedges = 0;
4037 node_ids[nedges++] = edge->start_node;
4038 if ( edge->end_node != edge->start_node )
4039 {
4040 node_ids[nedges++] = edge->end_node;
4041 }
4045 upd_edge = lwt_be_getEdgeByNode( topo, &(node_ids[0]), &nedges, fields );
4046 if (nedges == UINT64_MAX)
4047 {
4049 return -1;
4050 }
4051 nedge_left = nedge_right = 0;
4052 for ( i=0; i<nedges; ++i )
4053 {
4054 LWT_ISO_EDGE *e = &(upd_edge[i]);
4055 if ( e->edge_id == edge_id ) continue;
4056 if ( e->start_node == edge->start_node || e->end_node == edge->start_node )
4057 {
4058 ++fnode_edges;
4059 }
4060 if ( e->start_node == edge->end_node || e->end_node == edge->end_node )
4061 {
4062 ++lnode_edges;
4063 }
4064 if ( e->next_left == -edge_id )
4065 {
4066 upd_edge_left[nedge_left].edge_id = e->edge_id;
4067 upd_edge_left[nedge_left++].next_left =
4068 edge->next_left != edge_id ? edge->next_left : edge->next_right;
4069 }
4070 else if ( e->next_left == edge_id )
4071 {
4072 upd_edge_left[nedge_left].edge_id = e->edge_id;
4073 upd_edge_left[nedge_left++].next_left =
4074 edge->next_right != -edge_id ? edge->next_right : edge->next_left;
4075 }
4076
4077 if ( e->next_right == -edge_id )
4078 {
4079 upd_edge_right[nedge_right].edge_id = e->edge_id;
4080 upd_edge_right[nedge_right++].next_right =
4081 edge->next_left != edge_id ? edge->next_left : edge->next_right;
4082 }
4083 else if ( e->next_right == edge_id )
4084 {
4085 upd_edge_right[nedge_right].edge_id = e->edge_id;
4086 upd_edge_right[nedge_right++].next_right =
4087 edge->next_right != -edge_id ? edge->next_right : edge->next_left;
4088 }
4089 }
4090
4091 if ( nedge_left )
4092 {
4093 LWDEBUGF(1, "updating %d 'next_left' edges", nedge_left);
4094 /* update edges in upd_edge_left set next_left */
4095 int result = lwt_be_updateEdgesById(topo, &(upd_edge_left[0]), nedge_left, LWT_COL_EDGE_NEXT_LEFT);
4096 if (result == -1)
4097 {
4098 _lwt_release_edges(edge, 1);
4099 lwfree(upd_edge);
4101 return -1;
4102 }
4103 }
4104 if ( nedge_right )
4105 {
4106 LWDEBUGF(1, "updating %d 'next_right' edges", nedge_right);
4107 /* update edges in upd_edge_right set next_right */
4108 int result = lwt_be_updateEdgesById(topo, &(upd_edge_right[0]), nedge_right, LWT_COL_EDGE_NEXT_RIGHT);
4109 if (result == -1)
4110 {
4111 _lwt_release_edges(edge, 1);
4112 lwfree(upd_edge);
4114 return -1;
4115 }
4116 }
4117 LWDEBUGF(1, "releasing %llu updateable edges in %p", nedges, upd_edge);
4118 lwfree(upd_edge);
4119
4120 /* Id of face that will take up all the space previously
4121 * taken by left and right faces of the edge */
4122 LWT_ELEMID floodface;
4123
4124 /* Find floodface, and update its mbr if != 0 */
4125 if ( edge->face_left == edge->face_right )
4126 {
4127 floodface = edge->face_right;
4128 }
4129 else
4130 {
4131 /* Two faces healed */
4132 if ( edge->face_left == 0 || edge->face_right == 0 )
4133 {
4134 floodface = 0;
4135 LWDEBUG(1, "floodface is universe");
4136 }
4137 else
4138 {
4139 /* we choose right face as the face that will remain
4140 * to be symmetric with ST_AddEdgeModFace */
4141 floodface = edge->face_right;
4142 LWDEBUGF(1, "floodface is %" LWTFMT_ELEMID, floodface);
4143 /* update mbr of floodface as union of mbr of both faces */
4144 face_ids[0] = edge->face_left;
4145 face_ids[1] = edge->face_right;
4146 nfaces = 2;
4147 fields = LWT_COL_FACE_ALL;
4148 faces = lwt_be_getFaceById(topo, face_ids, &nfaces, fields);
4149 if (nfaces == UINT64_MAX)
4150 {
4152 return -1;
4153 }
4154 GBOX *box1=NULL;
4155 GBOX *box2=NULL;
4156 for ( i=0; i<nfaces; ++i )
4157 {
4158 if ( faces[i].face_id == edge->face_left )
4159 {
4160 if ( ! box1 ) box1 = faces[i].mbr;
4161 else
4162 {
4163 i = edge->face_left;
4164 _lwt_release_edges(edge, 1);
4165 _lwt_release_faces(faces, nfaces);
4166 lwerror("corrupted topology: more than 1 face have face_id=%"
4167 LWTFMT_ELEMID, i);
4168 return -1;
4169 }
4170 }
4171 else if ( faces[i].face_id == edge->face_right )
4172 {
4173 if ( ! box2 ) box2 = faces[i].mbr;
4174 else
4175 {
4176 i = edge->face_right;
4177 _lwt_release_edges(edge, 1);
4178 _lwt_release_faces(faces, nfaces);
4179 lwerror("corrupted topology: more than 1 face have face_id=%"
4180 LWTFMT_ELEMID, i);
4181 return -1;
4182 }
4183 }
4184 else
4185 {
4186 i = faces[i].face_id;
4187 _lwt_release_edges(edge, 1);
4188 _lwt_release_faces(faces, nfaces);
4189 lwerror("Backend coding error: getFaceById returned face "
4190 "with non-requested id %" LWTFMT_ELEMID, i);
4191 return -1;
4192 }
4193 }
4194 if ( ! box1 ) {
4195 i = edge->face_left;
4196 _lwt_release_edges(edge, 1);
4197 if ( nfaces ) _lwt_release_faces(faces, nfaces);
4198 lwerror("corrupted topology: no face have face_id=%"
4199 LWTFMT_ELEMID " (left face for edge %"
4200 LWTFMT_ELEMID ")", i, edge_id);
4201 return -1;
4202 }
4203 if ( ! box2 ) {
4204 i = edge->face_right;
4205 _lwt_release_edges(edge, 1);
4206 if ( nfaces ) _lwt_release_faces(faces, nfaces);
4207 lwerror("corrupted topology: no face have face_id=%"
4208 LWTFMT_ELEMID " (right face for edge %"
4209 LWTFMT_ELEMID ")", i, edge_id);
4210 return -1;
4211 }
4212 gbox_merge(box2, box1); /* box1 is now the union of the two */
4213 newface.mbr = box1;
4214 if ( modFace )
4215 {
4216 newface.face_id = floodface;
4217 int result = lwt_be_updateFacesById(topo, &newface, 1);
4218 _lwt_release_faces(faces, 2);
4219 if (result == -1)
4220 {
4221 _lwt_release_edges(edge, 1);
4223 return -1;
4224 }
4225 if (result != 1)
4226 {
4227 _lwt_release_edges(edge, 1);
4228 lwerror("Unexpected error: %" PRIu64 " faces updated when expecting 1", i);
4229 return -1;
4230 }
4231 }
4232 else
4233 {
4234 /* New face replaces the old two faces */
4235 newface.face_id = -1;
4236 int result = lwt_be_insertFaces(topo, &newface, 1);
4237 _lwt_release_faces(faces, 2);
4238 if (result == -1)
4239 {
4240 _lwt_release_edges(edge, 1);
4242 return -1;
4243 }
4244 if (result != 1)
4245 {
4246 _lwt_release_edges(edge, 1);
4247 lwerror("Unexpected error: %d faces inserted when expecting 1", result);
4248 return -1;
4249 }
4250 floodface = newface.face_id;
4251 }
4252 }
4253
4254 /* Update face references for edges and nodes still referencing
4255 * the removed face(s) */
4256
4257 if ( edge->face_left != floodface )
4258 {
4259 if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_left, floodface) )
4260 {
4261 _lwt_release_edges(edge, 1);
4263 return -1;
4264 }
4265 if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_left, floodface) )
4266 {
4267 _lwt_release_edges(edge, 1);
4269 return -1;
4270 }
4271 }
4272
4273 if ( edge->face_right != floodface )
4274 {
4275 if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_right, floodface) )
4276 {
4277 _lwt_release_edges(edge, 1);
4279 return -1;
4280 }
4281 if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_right, floodface) )
4282 {
4283 _lwt_release_edges(edge, 1);
4285 return -1;
4286 }
4287 }
4288
4289 /* Update topogeoms on heal */
4291 edge->face_right, edge->face_left,
4292 floodface) )
4293 {
4294 _lwt_release_edges(edge, 1);
4296 return -1;
4297 }
4298 } /* two faces healed */
4299
4300 /* Delete the edge */
4302 if (result == -1)
4303 {
4304 _lwt_release_edges(edge, 1);
4306 return -1;
4307 }
4308
4309 /* If any of the edge nodes remained isolated, set
4310 * containing_face = floodface
4311 */
4312 if ( ! fnode_edges )
4313 {
4314 upd_node[nnode].node_id = edge->start_node;
4315 upd_node[nnode].containing_face = floodface;
4316 ++nnode;
4317 }
4318 if ( edge->end_node != edge->start_node && ! lnode_edges )
4319 {
4320 upd_node[nnode].node_id = edge->end_node;
4321 upd_node[nnode].containing_face = floodface;
4322 ++nnode;
4323 }
4324 if ( nnode )
4325 {
4326 int result = lwt_be_updateNodesById(topo, upd_node, nnode, LWT_COL_NODE_CONTAINING_FACE);
4327 if (result == -1)
4328 {
4329 _lwt_release_edges(edge, 1);
4331 return -1;
4332 }
4333 }
4334
4335 if ( edge->face_left != edge->face_right )
4336 /* or there'd be no face to remove */
4337 {
4338 LWT_ELEMID ids[2];
4339 int nids = 0;
4340 if ( edge->face_right != floodface )
4341 ids[nids++] = edge->face_right;
4342 if ( edge->face_left != floodface )
4343 ids[nids++] = edge->face_left;
4344 int result = lwt_be_deleteFacesById(topo, ids, nids);
4345 if (result == -1)
4346 {
4347 _lwt_release_edges(edge, 1);
4349 return -1;
4350 }
4351 }
4352
4353 _lwt_release_edges(edge, 1);
4354 return modFace ? floodface : newface.face_id;
4355}
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
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:248
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 PGTOPO_BE_ERROR()
#define LWTFMT_ELEMID
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
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)
void _lwt_release_faces(LWT_ISO_FACE *faces, int num_faces)
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 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)
void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
int lwt_be_updateEdgesById(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *edges, int numedges, int upd_fields)
LWT_ISO_EDGE * lwt_be_getEdgeByNode(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
int lwt_be_insertFaces(LWT_TOPOLOGY *topo, LWT_ISO_FACE *face, uint64_t numelems)
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, PGTOPO_BE_ERROR, result, 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: