PostGIS 3.7.0dev-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 4093 of file lwgeom_topo.c.

4094{
4095 uint64_t i, nedges, nfaces, fields;
4096 LWT_ISO_EDGE *edge = NULL;
4097 LWT_ISO_EDGE *upd_edge = NULL;
4098 LWT_ISO_EDGE upd_edge_left[2];
4099 int nedge_left = 0;
4100 LWT_ISO_EDGE upd_edge_right[2];
4101 int nedge_right = 0;
4102 LWT_ISO_NODE upd_node[2];
4103 int nnode = 0;
4104 LWT_ISO_FACE *faces = NULL;
4105 LWT_ISO_FACE newface;
4106 LWT_ELEMID node_ids[2];
4107 LWT_ELEMID face_ids[2];
4108 int fnode_edges = 0; /* number of edges on the first node (excluded
4109 * the one being removed ) */
4110 int lnode_edges = 0; /* number of edges on the last node (excluded
4111 * the one being removed ) */
4112
4113
4114 newface.face_id = 0;
4115
4116 i = 1;
4117 edge = lwt_be_getEdgeById(topo, &edge_id, &i, LWT_COL_EDGE_ALL);
4118 if (!edge)
4119 {
4120 LWDEBUGF(1, "lwt_be_getEdgeById returned NULL and set i=%llu", i);
4121 if (i == UINT64_MAX)
4122 {
4124 return -1;
4125 }
4126 else if (i == 0)
4127 {
4128 lwerror("SQL/MM Spatial exception - non-existent edge %" LWTFMT_ELEMID, edge_id);
4129 return -1;
4130 }
4131 else
4132 {
4133 lwerror(
4134 "Backend coding error: getEdgeById callback returned NULL "
4135 "but numelements output parameter has value %" PRIu64 " "
4136 "(expected 0 or 1)",
4137 i);
4138 return -1;
4139 }
4140 }
4141
4142 if ( ! lwt_be_checkTopoGeomRemEdge(topo, edge_id,
4143 edge->face_left, edge->face_right) )
4144 {
4146 return -1;
4147 }
4148
4149 LWDEBUG(1, "Updating next_{right,left}_face of ring edges...");
4150
4151 /* Update edge linking */
4152
4153 nedges = 0;
4154 node_ids[nedges++] = edge->start_node;
4155 if ( edge->end_node != edge->start_node )
4156 {
4157 node_ids[nedges++] = edge->end_node;
4158 }
4162 upd_edge = lwt_be_getEdgeByNode( topo, &(node_ids[0]), &nedges, fields );
4163 if (nedges == UINT64_MAX)
4164 {
4166 return -1;
4167 }
4168 nedge_left = nedge_right = 0;
4169 for ( i=0; i<nedges; ++i )
4170 {
4171 LWT_ISO_EDGE *e = &(upd_edge[i]);
4172 if ( e->edge_id == edge_id ) continue;
4173 if ( e->start_node == edge->start_node || e->end_node == edge->start_node )
4174 {
4175 ++fnode_edges;
4176 }
4177 if ( e->start_node == edge->end_node || e->end_node == edge->end_node )
4178 {
4179 ++lnode_edges;
4180 }
4181 if ( e->next_left == -edge_id )
4182 {
4183 upd_edge_left[nedge_left].edge_id = e->edge_id;
4184 upd_edge_left[nedge_left++].next_left =
4185 edge->next_left != edge_id ? edge->next_left : edge->next_right;
4186 }
4187 else if ( e->next_left == edge_id )
4188 {
4189 upd_edge_left[nedge_left].edge_id = e->edge_id;
4190 upd_edge_left[nedge_left++].next_left =
4191 edge->next_right != -edge_id ? edge->next_right : edge->next_left;
4192 }
4193
4194 if ( e->next_right == -edge_id )
4195 {
4196 upd_edge_right[nedge_right].edge_id = e->edge_id;
4197 upd_edge_right[nedge_right++].next_right =
4198 edge->next_left != edge_id ? edge->next_left : edge->next_right;
4199 }
4200 else if ( e->next_right == edge_id )
4201 {
4202 upd_edge_right[nedge_right].edge_id = e->edge_id;
4203 upd_edge_right[nedge_right++].next_right =
4204 edge->next_right != -edge_id ? edge->next_right : edge->next_left;
4205 }
4206 }
4207
4208 if ( nedge_left )
4209 {
4210 LWDEBUGF(1, "updating %d 'next_left' edges", nedge_left);
4211 /* update edges in upd_edge_left set next_left */
4212 int result = lwt_be_updateEdgesById(topo, &(upd_edge_left[0]), nedge_left, LWT_COL_EDGE_NEXT_LEFT);
4213 if (result == -1)
4214 {
4215 _lwt_release_edges(edge, 1);
4216 lwfree(upd_edge);
4218 return -1;
4219 }
4220 }
4221 if ( nedge_right )
4222 {
4223 LWDEBUGF(1, "updating %d 'next_right' edges", nedge_right);
4224 /* update edges in upd_edge_right set next_right */
4225 int result = lwt_be_updateEdgesById(topo, &(upd_edge_right[0]), nedge_right, LWT_COL_EDGE_NEXT_RIGHT);
4226 if (result == -1)
4227 {
4228 _lwt_release_edges(edge, 1);
4229 lwfree(upd_edge);
4231 return -1;
4232 }
4233 }
4234 LWDEBUGF(1, "releasing %llu updateable edges in %p", nedges, upd_edge);
4235 lwfree(upd_edge);
4236
4237 /* Id of face that will take up all the space previously
4238 * taken by left and right faces of the edge */
4239 LWT_ELEMID floodface;
4240
4241 /* Find floodface, and update its mbr if != 0 */
4242 if ( edge->face_left == edge->face_right )
4243 {
4244 floodface = edge->face_right;
4245 }
4246 else
4247 {
4248 /* Two faces healed */
4249 if ( edge->face_left == 0 || edge->face_right == 0 )
4250 {
4251 floodface = 0;
4252 LWDEBUG(1, "floodface is universe");
4253 }
4254 else
4255 {
4256 /* we choose right face as the face that will remain
4257 * to be symmetric with ST_AddEdgeModFace */
4258 floodface = edge->face_right;
4259 LWDEBUGF(1, "floodface is %" LWTFMT_ELEMID, floodface);
4260 /* update mbr of floodface as union of mbr of both faces */
4261 face_ids[0] = edge->face_left;
4262 face_ids[1] = edge->face_right;
4263 nfaces = 2;
4264 fields = LWT_COL_FACE_ALL;
4265 faces = lwt_be_getFaceById(topo, face_ids, &nfaces, fields);
4266 if (nfaces == UINT64_MAX)
4267 {
4269 return -1;
4270 }
4271 GBOX *box1=NULL;
4272 GBOX *box2=NULL;
4273 for ( i=0; i<nfaces; ++i )
4274 {
4275 if ( faces[i].face_id == edge->face_left )
4276 {
4277 if ( ! box1 ) box1 = faces[i].mbr;
4278 else
4279 {
4280 i = edge->face_left;
4281 _lwt_release_edges(edge, 1);
4282 _lwt_release_faces(faces, nfaces);
4283 lwerror("corrupted topology: more than 1 face have face_id=%"
4284 LWTFMT_ELEMID, i);
4285 return -1;
4286 }
4287 }
4288 else if ( faces[i].face_id == edge->face_right )
4289 {
4290 if ( ! box2 ) box2 = faces[i].mbr;
4291 else
4292 {
4293 i = edge->face_right;
4294 _lwt_release_edges(edge, 1);
4295 _lwt_release_faces(faces, nfaces);
4296 lwerror("corrupted topology: more than 1 face have face_id=%"
4297 LWTFMT_ELEMID, i);
4298 return -1;
4299 }
4300 }
4301 else
4302 {
4303 i = faces[i].face_id;
4304 _lwt_release_edges(edge, 1);
4305 _lwt_release_faces(faces, nfaces);
4306 lwerror("Backend coding error: getFaceById returned face "
4307 "with non-requested id %" LWTFMT_ELEMID, i);
4308 return -1;
4309 }
4310 }
4311 if ( ! box1 ) {
4312 i = edge->face_left;
4313 _lwt_release_edges(edge, 1);
4314 if ( nfaces ) _lwt_release_faces(faces, nfaces);
4315 lwerror("corrupted topology: no face have face_id=%"
4316 LWTFMT_ELEMID " (left face for edge %"
4317 LWTFMT_ELEMID ")", i, edge_id);
4318 return -1;
4319 }
4320 if ( ! box2 ) {
4321 i = edge->face_right;
4322 _lwt_release_edges(edge, 1);
4323 if ( nfaces ) _lwt_release_faces(faces, nfaces);
4324 lwerror("corrupted topology: no face have face_id=%"
4325 LWTFMT_ELEMID " (right face for edge %"
4326 LWTFMT_ELEMID ")", i, edge_id);
4327 return -1;
4328 }
4329 gbox_merge(box2, box1); /* box1 is now the union of the two */
4330 newface.mbr = box1;
4331 if ( modFace )
4332 {
4333 newface.face_id = floodface;
4334 int result = lwt_be_updateFacesById(topo, &newface, 1);
4335 _lwt_release_faces(faces, 2);
4336 if (result == -1)
4337 {
4338 _lwt_release_edges(edge, 1);
4340 return -1;
4341 }
4342 if (result != 1)
4343 {
4344 _lwt_release_edges(edge, 1);
4345 lwerror("Unexpected error: %" PRIu64 " faces updated when expecting 1", i);
4346 return -1;
4347 }
4348 }
4349 else
4350 {
4351 /* New face replaces the old two faces */
4352 newface.face_id = -1;
4353 int result = lwt_be_insertFaces(topo, &newface, 1);
4354 _lwt_release_faces(faces, 2);
4355 if (result == -1)
4356 {
4357 _lwt_release_edges(edge, 1);
4359 return -1;
4360 }
4361 if (result != 1)
4362 {
4363 _lwt_release_edges(edge, 1);
4364 lwerror("Unexpected error: %d faces inserted when expecting 1", result);
4365 return -1;
4366 }
4367 floodface = newface.face_id;
4368 }
4369 }
4370
4371 /* Update face references for edges and nodes still referencing
4372 * the removed face(s) */
4373
4374 if ( edge->face_left != floodface )
4375 {
4376 if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_left, floodface) )
4377 {
4378 _lwt_release_edges(edge, 1);
4380 return -1;
4381 }
4382 if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_left, floodface) )
4383 {
4384 _lwt_release_edges(edge, 1);
4386 return -1;
4387 }
4388 }
4389
4390 if ( edge->face_right != floodface )
4391 {
4392 if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_right, floodface) )
4393 {
4394 _lwt_release_edges(edge, 1);
4396 return -1;
4397 }
4398 if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_right, floodface) )
4399 {
4400 _lwt_release_edges(edge, 1);
4402 return -1;
4403 }
4404 }
4405
4406 /* Update topogeoms on heal */
4408 edge->face_right, edge->face_left,
4409 floodface) )
4410 {
4411 _lwt_release_edges(edge, 1);
4413 return -1;
4414 }
4415 } /* two faces healed */
4416
4417 /* Delete the edge */
4419 if (result == -1)
4420 {
4421 _lwt_release_edges(edge, 1);
4423 return -1;
4424 }
4425
4426 /* If any of the edge nodes remained isolated, set
4427 * containing_face = floodface
4428 */
4429 if ( ! fnode_edges )
4430 {
4431 upd_node[nnode].node_id = edge->start_node;
4432 upd_node[nnode].containing_face = floodface;
4433 ++nnode;
4434 }
4435 if ( edge->end_node != edge->start_node && ! lnode_edges )
4436 {
4437 upd_node[nnode].node_id = edge->end_node;
4438 upd_node[nnode].containing_face = floodface;
4439 ++nnode;
4440 }
4441 if ( nnode )
4442 {
4443 int result = lwt_be_updateNodesById(topo, upd_node, nnode, LWT_COL_NODE_CONTAINING_FACE);
4444 if (result == -1)
4445 {
4446 _lwt_release_edges(edge, 1);
4448 return -1;
4449 }
4450 }
4451
4452 if ( edge->face_left != edge->face_right )
4453 /* or there'd be no face to remove */
4454 {
4455 LWT_ELEMID ids[2];
4456 int nids = 0;
4457 if ( edge->face_right != floodface )
4458 ids[nids++] = edge->face_right;
4459 if ( edge->face_left != floodface )
4460 ids[nids++] = edge->face_left;
4461 int result = lwt_be_deleteFacesById(topo, ids, nids);
4462 if (result == -1)
4463 {
4464 _lwt_release_edges(edge, 1);
4466 return -1;
4467 }
4468 }
4469
4470 _lwt_release_edges(edge, 1);
4471 return modFace ? floodface : newface.face_id;
4472}
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: