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

◆ _lwt_SnapEdgeToExistingNode()

static int _lwt_SnapEdgeToExistingNode ( LWT_TOPOLOGY topo,
LWT_ISO_NODE node,
LWT_ISO_EDGE edge,
double  tol 
)
static

Definition at line 5290 of file lwgeom_topo.c.

5296{
5297 LWGEOM *prj = lwpoint_as_lwgeom(node->geom);
5298 const POINT2D *pt = getPoint2d_cp(lwgeom_as_lwpoint(prj)->point, 0);
5299
5300 LWDEBUGF(1, "Experimental handling of within-tolerance edge %" LWTFMT_ELEMID, edge->edge_id);
5301 LWGEOM *snapE = lwgeom_snap(lwline_as_lwgeom(edge->geom), prj, tol);
5302
5303 /* TODO: check if an endpoint moved */
5304
5305 LWGEOM *splitE = lwgeom_split(snapE, prj);
5306 LWDEBUGG(1, splitE, "Split edge");
5307
5308 LWCOLLECTION *splitC = lwgeom_as_lwcollection(splitE);
5309 if ( splitC->ngeoms != 2 )
5310 {
5311 lwerror("Split of edge resulted in %d components", splitC->ngeoms);
5312 return -1;
5313 }
5314
5315 LWT_NODE_EDGES *firstNodeEdges = lwt_nodeEdges_loadFromDB(topo, edge->start_node, LWT_COL_EDGE_ALL );
5316 if ( ! firstNodeEdges ) {
5317 lwerror("No edges found in DB to be incident to split edge's first node");
5318 return -1;
5319 }
5320 LWT_NODE_EDGES *lastNodeEdges = lwt_nodeEdges_loadFromDB(topo, edge->end_node, LWT_COL_EDGE_ALL );
5321 if ( ! lastNodeEdges ) {
5322 lwerror("No edges found in DB to be incident to split edge's last node");
5323 return -1;
5324 }
5325 LWT_NODE_EDGES *splitNodeEdges = lwt_nodeEdges_loadFromDB(topo, node->node_id, LWT_COL_EDGE_ALL);
5326 if ( ! splitNodeEdges ) {
5327 lwerror("No edges found in DB to be incident to split node");
5328 return -1;
5329 }
5330
5331 /* Update split edge reference as it was possibly changed by previous call */
5332 for ( uint64_t t=0; t<firstNodeEdges->numEdges; t++ )
5333 {
5334 if ( firstNodeEdges->edges[t].edge_id == edge->edge_id )
5335 {
5336 edge = &(firstNodeEdges->edges[t]);
5337 break;
5338 }
5339 }
5340
5341 LWDEBUGF(1, "Split edge %"
5342 LWTFMT_ELEMID " start condition: next_right:%"
5343 LWTFMT_ELEMID ", next_left:%"
5344 LWTFMT_ELEMID ", face_right:%"
5345 LWTFMT_ELEMID ", face_left:%"
5346 LWTFMT_ELEMID ", start_node:%"
5347 LWTFMT_ELEMID ", end_node:%"
5349 edge->edge_id,
5350 edge->next_right,
5351 edge->next_left,
5352 edge->face_right,
5353 edge->face_left,
5354 edge->start_node,
5355 edge->end_node
5356 );
5357
5358 int ret;
5359
5360 uint64_t n;
5361 LWT_ELEMID replacedBy[2];
5362 LWT_ISO_EDGE *existingEdges[2];
5363 //int replacedByForward[2];
5364 edgeend splitNodeEdgeEnds[2];
5365 for ( n=0; n<2; ++n)
5366 {
5367 int forward;
5368 /* TODO: directly get full existing edge rather than just id * */
5369 LWT_ELEMID existingEdgeId = _lwt_GetEqualEdge( topo, lwgeom_as_lwline(splitC->geoms[n]), &forward );
5370 if ( existingEdgeId == -1 )
5371 {
5372 /* probably too late, due to internal lwerror */
5373 return -1;
5374 }
5375 existingEdges[n] = NULL;
5376 if ( existingEdgeId == 0 )
5377 {
5378 LWDEBUGF(1, "Split component %llu is a new edge, computing edgeEndInfo", n);
5379 {
5380 // Compute nextCW and nextCCW of the split edge now
5381 // incident to the split point
5382
5383 POINT2D op; /* other point */
5384 if ( n == 1 ) {
5386 lwgeom_as_lwline(splitC->geoms[1])->points, //const POINTARRAY* pa,
5387 pt, //POINT2D *ref,
5388 0, // int from,
5389 1, // int dir,
5390 &op // POINT2D *op
5391 );
5392 if (!ret)
5393 {
5394 lwerror("No distinct vertices found on second part of split edge");
5395 return -1; /* lwerror should have been raised */
5396 }
5397 } else {
5398 const POINTARRAY *pa = lwgeom_as_lwline(splitC->geoms[0])->points;
5400 pa, //const POINTARRAY* pa,
5401 pt, //POINT2D *ref,
5402 pa->npoints-1, // int from,
5403 -1, // int dir,
5404 &op // POINT2D *op
5405 );
5406 if (!ret)
5407 {
5408 lwerror("No distinct vertices found on first part of split edge");
5409 return -1; /* lwerror should have been raised */
5410 }
5411 }
5412 if ( ! azimuth_pt_pt(pt, &op, &(splitNodeEdgeEnds[n].myaz)) ) {
5413 lwerror("error computing azimuth of split endpoint [%.15g %.15g,%.15g %.15g]",
5414 op.x, op.y,
5415 pt->x, pt->y
5416 );
5417 return -1;
5418 }
5419 LWDEBUGF(1, "Azimuth of split component %llu edgeend [%.15g %.15g,%.15g %.15g] is %.15g",
5420 n, op.x, op.y, pt->x, pt->y, splitNodeEdgeEnds[n].myaz);
5421 ret = _lwt_FindAdjacentEdges( topo, node->node_id, &(splitNodeEdgeEnds[n]), NULL, -1 );
5422 if ( ! ret ) {
5423 lwerror("Unexpected backend return: _lwt_FindAdjacentEdges(%"
5424 LWTFMT_ELEMID ") found no edges when we previously split edge %"
5425 LWTFMT_ELEMID "d on it",
5426 node->node_id, edge->edge_id);
5427 return -1;
5428 }
5429 LWDEBUGF(1, "Component %llu of split edge %" LWTFMT_ELEMID
5430 " next CW is %" LWTFMT_ELEMID ", next CCW is %" LWTFMT_ELEMID,
5431 n, edge->edge_id, splitNodeEdgeEnds[n].nextCW, splitNodeEdgeEnds[n].nextCCW);
5432 }
5433 }
5434 else
5435 {
5436 LWDEBUGF(1, "Split component %llu matches existing edge %" LWTFMT_ELEMID
5437 " (%s)", n, existingEdgeId, forward ? "forward" : "backward" );
5438 /* Get existing edge */
5439 for ( uint64_t t=0; t<splitNodeEdges->numEdges; t++ )
5440 {
5441 if ( splitNodeEdges->edges[t].edge_id == existingEdgeId )
5442 {
5443 existingEdges[n] = &(splitNodeEdges->edges[t]);
5444 break;
5445 }
5446 }
5447 if (existingEdges[n] == NULL)
5448 {
5449 lwerror("could not find edge %" LWTFMT_ELEMID " in database, but _lwt_GetEqualEdges said it was there", existingEdgeId );
5450 return -1;
5451 }
5452 }
5453
5454 replacedBy[n] = existingEdgeId;
5455 }
5456
5457
5458 LWT_ISO_EDGE updatedEdge;
5459 int updateFlags;
5460 LWT_ISO_EDGE selEdge;
5461
5462 if ( ( replacedBy[0] != 0 && replacedBy[1] == 0 ) ||
5463 ( replacedBy[1] != 0 && replacedBy[0] == 0 ) )
5464 {
5465 /* One side of the snapped edge collapsed to an existing edge */
5466
5467 LWT_ISO_EDGE *existingEdge;
5468 edgeend *splitNodeEdgeEndInfo;
5469 LWLINE *newSplitEdgeLine;
5470 int splitNodeNewEdgeOutgoing; // The new split edge goes out of the split node
5471
5472 if ( replacedBy[1] == 0 )
5473 /* First part of edge is the existing edge */
5474 {
5475 existingEdge = existingEdges[0];
5476 newSplitEdgeLine = lwgeom_as_lwline(splitC->geoms[1]);
5477 splitNodeEdgeEndInfo = &(splitNodeEdgeEnds[1]);
5478 splitNodeNewEdgeOutgoing = 1;
5479 }
5480 else
5481 /* Second part of edge is the existing edge */
5482 {
5483 existingEdge = existingEdges[1];
5484 newSplitEdgeLine = lwgeom_as_lwline(splitC->geoms[0]);
5485 splitNodeEdgeEndInfo = &(splitNodeEdgeEnds[0]);
5486 splitNodeNewEdgeOutgoing = 0;
5487 }
5488
5489 _lwt_SnapEdge_checkMotion( topo, splitC, edge, existingEdge, splitNodeEdges );
5490
5491 LWDEBUGF(1, "Existing edge %"
5492 LWTFMT_ELEMID " (post-modEdgeSplit) next_right:%"
5493 LWTFMT_ELEMID ", next_left:%"
5494 LWTFMT_ELEMID ", face_right:%"
5495 LWTFMT_ELEMID ", face_left:%"
5497 existingEdge->edge_id,
5498 existingEdge->next_right,
5499 existingEdge->next_left,
5500 existingEdge->face_right,
5501 existingEdge->face_left
5502 );
5503
5504 /*****
5505 *
5506 * Update edge linking
5507 *
5508 */
5509
5510 /*
5511 * Update next CW / CCW edges on split node
5512 * (fix linking on split node)
5513 */
5514
5515 /* Update next CCW edge */
5516 {
5517 LWT_ELEMID nextEdge, sideFace;
5518 if ( splitNodeNewEdgeOutgoing ) {
5519 nextEdge = edge->edge_id;
5520 sideFace = edge->face_left;
5521 } else {
5522 nextEdge = -edge->edge_id;
5523 sideFace = edge->face_right;
5524 }
5525
5526 LWDEBUGF(1, "Setting nextEdge/sideFace of CCW edge %" LWTFMT_ELEMID
5527 " to %" LWTFMT_ELEMID "/%" LWTFMT_ELEMID,
5528 splitNodeEdgeEndInfo->nextCCW,
5529 nextEdge, sideFace
5530 );
5531
5532 if ( splitNodeEdgeEndInfo->nextCCW > 0 )
5533 {
5534 selEdge.edge_id = splitNodeEdgeEndInfo->nextCCW;
5535 updatedEdge.next_right = nextEdge;
5536 updatedEdge.face_right = sideFace;
5537 updateFlags = LWT_COL_EDGE_NEXT_RIGHT|
5539 LWDEBUGF(1, "Will update next_right/face_right of outgoing CCW edge %" LWTFMT_ELEMID
5540 " to %" LWTFMT_ELEMID "/%" LWTFMT_ELEMID,
5541 selEdge.edge_id,
5542 nextEdge, sideFace
5543 );
5544 }
5545 else
5546 {
5547 selEdge.edge_id = -splitNodeEdgeEndInfo->nextCCW;
5548 updatedEdge.next_left = nextEdge;
5549 updatedEdge.face_left = sideFace;
5550 updateFlags = LWT_COL_EDGE_NEXT_LEFT|
5552 LWDEBUGF(1, "Will update next_left/face_left of incoming CCW edge %" LWTFMT_ELEMID
5553 " to %" LWTFMT_ELEMID "/%" LWTFMT_ELEMID,
5554 selEdge.edge_id,
5555 nextEdge, sideFace
5556 );
5557 }
5558
5559 ret = lwt_be_updateEdges(topo,
5560 &selEdge, LWT_COL_EDGE_EDGE_ID,
5561 &updatedEdge, updateFlags,
5562 NULL, 0);
5563 if ( ret == -1 ) {
5565 return -1;
5566 } else if ( ret == 0 ) {
5567 lwerror("Edge %" LWTFMT_ELEMID " disappeared during operations", selEdge.edge_id);
5568 return -1;
5569 } else if ( ret > 1 ) {
5570 lwerror("More than a single edge found with id %"
5571 LWTFMT_ELEMID " ! (corrupted topology?)", selEdge.edge_id);
5572 return -1;
5573 }
5574 }
5575
5576 /* Update next CW edge on split node */
5577 {
5578 LWT_ELEMID sideFace;
5579 if ( splitNodeNewEdgeOutgoing ) {
5580 sideFace = edge->face_right;
5581 } else {
5582 sideFace = edge->face_left;
5583 }
5584
5585 LWDEBUGF(1, "Setting sideFace of CW edge %" LWTFMT_ELEMID
5586 " to %" LWTFMT_ELEMID,
5587 splitNodeEdgeEndInfo->nextCW, sideFace
5588 );
5589
5590 if ( splitNodeEdgeEndInfo->nextCW > 0 )
5591 {
5592 selEdge.edge_id = splitNodeEdgeEndInfo->nextCW;
5593 updatedEdge.face_left = sideFace;
5594 updateFlags = LWT_COL_EDGE_FACE_LEFT;
5595 LWDEBUGF(1, "Updating left_face of edge %" LWTFMT_ELEMID
5596 ", outgoing next CW of new split edge on split node",
5597 selEdge.edge_id);
5598 }
5599 else
5600 {
5601 selEdge.edge_id = -splitNodeEdgeEndInfo->nextCW;
5602 updatedEdge.face_right = sideFace;
5603 updateFlags = LWT_COL_EDGE_FACE_RIGHT;
5604 LWDEBUGF(1, "Updating right_face of edge %" LWTFMT_ELEMID
5605 ", incoming next CW of new split edge on split node",
5606 selEdge.edge_id);
5607 }
5608
5609 ret = lwt_be_updateEdges(topo,
5610 &selEdge, LWT_COL_EDGE_EDGE_ID,
5611 &updatedEdge, updateFlags,
5612 NULL, 0);
5613 if ( ret == -1 ) {
5615 return -1;
5616 } else if ( ret == 0 ) {
5617 lwerror("Edge %" LWTFMT_ELEMID " disappeared during operations", selEdge.edge_id);
5618 return -1;
5619 } else if ( ret > 1 ) {
5620 lwerror("More than a single edge found with edge_id %"
5621 LWTFMT_ELEMID " ! (corrupted topology?)", selEdge.edge_id);
5622 return -1;
5623 }
5624 }
5625
5626 /*
5627 * Update links to now-disappeared edgeend
5628 * on the node originally in common with
5629 * the existing node
5630 */
5631
5632 LWT_ISO_EDGE *nextCCWEdge = NULL;
5633 int nextCCWEdgeIsIncoming = 0;
5634 int collapsedEdgeIsIncoming;
5635
5636 LWT_ELEMID commonNodeID;
5637
5638 LWT_NODE_EDGES *commonNodeEdges;
5639 if ( replacedBy[0] ) {
5640 commonNodeEdges = firstNodeEdges;
5641 commonNodeID = edge->start_node;
5642 collapsedEdgeIsIncoming = 0;
5643 } else {
5644 commonNodeEdges = lastNodeEdges;
5645 commonNodeID = edge->end_node;
5646 collapsedEdgeIsIncoming = 1;
5647 }
5648
5649
5650 // Update next CCW edge
5651 {
5652 LWT_ELEMID signedCollapsedEdgeID = collapsedEdgeIsIncoming ? -edge->edge_id: edge->edge_id;
5653
5654 LWDEBUGF(1, "Looking for next CCW edge of split edge %"
5655 LWTFMT_ELEMID " on common node %" LWTFMT_ELEMID
5656 " having %llu attached edges",
5657 edge->edge_id,
5658 commonNodeID, commonNodeEdges->numEdges
5659 );
5660
5661 /* Find next CCW edge */
5662 for ( uint64_t t=0; t<commonNodeEdges->numEdges; t++ )
5663 {
5664 LWT_ISO_EDGE *et = &(commonNodeEdges->edges[t]);
5665
5666 LWDEBUGF(1, "common node edge %"
5667 LWTFMT_ELEMID " has next_left:%" LWTFMT_ELEMID
5668 " next_right:%" LWTFMT_ELEMID,
5669 et->edge_id,
5670 et->next_left,
5671 et->next_right
5672 );
5673
5674 if ( et->start_node == commonNodeID )
5675 {
5676 if ( et->next_right == signedCollapsedEdgeID )
5677 {
5678 nextCCWEdge = et;
5679 nextCCWEdgeIsIncoming = 0;
5680 break;
5681 }
5682 }
5683 else if ( et->end_node == commonNodeID )
5684 {
5685 if ( et->next_left == signedCollapsedEdgeID )
5686 {
5687 nextCCWEdge = et;
5688 nextCCWEdgeIsIncoming = 1;
5689 break;
5690 }
5691 }
5692 }
5693 if ( ! nextCCWEdge )
5694 {
5695 lwerror("Could not find nextCCW edge on common node %" LWTFMT_ELEMID,
5696 commonNodeID
5697 );
5698 return -1;
5699 }
5700
5701 LWDEBUGF(1, "Next CCW edge of split edge %"
5702 LWTFMT_ELEMID " on common node %" LWTFMT_ELEMID
5703 " is (%s) %" LWTFMT_ELEMID,
5704 edge->edge_id,
5705 commonNodeID,
5706 nextCCWEdgeIsIncoming ? "incoming" : "outgoing",
5707 nextCCWEdge->edge_id
5708 );
5709
5710 if ( nextCCWEdge->edge_id == existingEdge->edge_id )
5711 {
5712 LWDEBUG(1, "Next CCW edge is existing/collapse edge, will not update here");
5713 }
5714 else
5715 {
5716 /*
5717 * TODO: the nextCCW is only of interest IFF the collapse
5718 * happened clockwise!
5719 *
5720 * just update to the split edge id (positive or negative
5721 * depending on whether it was outgoing or incoming in the
5722 * common node)
5723 */
5724 LWT_ELEMID newNextEdge = existingEdge->start_node == commonNodeID ?
5725 existingEdge->edge_id :
5726 -existingEdge->edge_id;
5727
5728 selEdge.edge_id = nextCCWEdge->edge_id;
5729 if ( nextCCWEdgeIsIncoming ) {
5730 updatedEdge.next_left = newNextEdge;
5731 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
5732 LWDEBUGF(1, "Updating next_left of incoming next CCW edge %"
5734 " to %" LWTFMT_ELEMID,
5735 selEdge.edge_id,
5736 newNextEdge
5737 );
5738 } else {
5739 updatedEdge.next_right = newNextEdge;
5740 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
5741 LWDEBUGF(1, "Updating next_right of outgoing next CCW edge %"
5743 " to %" LWTFMT_ELEMID,
5744 selEdge.edge_id,
5745 newNextEdge
5746 );
5747 }
5748 ret = lwt_be_updateEdges(topo,
5749 &selEdge, LWT_COL_EDGE_EDGE_ID,
5750 &updatedEdge, updateFlags,
5751 NULL, 0);
5752 if ( ret == -1 ) {
5754 return -1;
5755 } else if ( ret == 0 ) {
5756 lwerror("Edge %" LWTFMT_ELEMID " disappeared during operations", selEdge.edge_id);
5757 return -1;
5758 } else if ( ret > 1 ) {
5759 lwerror("More than a single edge found with next_left %"
5760 LWTFMT_ELEMID " ! (corrupted topology?)", selEdge.next_left);
5761 return -1;
5762 }
5763 }
5764 }
5765
5766 /*****
5767 *
5768 * Update the existing edge our split edge collapsed to
5769 *
5770 */
5771
5772 selEdge.edge_id = existingEdge->edge_id;
5773 updateFlags = 0;
5774 if ( existingEdge->next_left == edge->edge_id )
5775 {
5776 updatedEdge.next_left = edge->next_right;
5777 updateFlags |= LWT_COL_EDGE_NEXT_LEFT;
5778 LWDEBUGF(1, "Will update next_left of existing edge %"
5780 selEdge.edge_id,
5781 updatedEdge.next_left
5782 );
5783 }
5784 if ( existingEdge->next_right == edge->edge_id )
5785 {
5786 updatedEdge.next_right = edge->next_right;
5787 updateFlags |= LWT_COL_EDGE_NEXT_RIGHT;
5788 LWDEBUGF(1, "Will update next_right of existing edge %"
5790 selEdge.edge_id,
5791 updatedEdge.next_right
5792 );
5793 }
5794 if ( existingEdge->next_left == -edge->edge_id )
5795 {
5796 updatedEdge.next_left = edge->next_left;
5797 updateFlags |= LWT_COL_EDGE_NEXT_LEFT;
5798 LWDEBUGF(1, "Will update next_left of existing edge %"
5800 selEdge.edge_id,
5801 updatedEdge.next_left
5802 );
5803 }
5804 if ( existingEdge->next_right == -edge->edge_id )
5805 {
5806 updatedEdge.next_right = edge->next_left;
5807 updateFlags |= LWT_COL_EDGE_NEXT_RIGHT;
5808 LWDEBUGF(1, "Will update next_right of existing edge %"
5810 selEdge.edge_id,
5811 updatedEdge.next_right
5812 );
5813 }
5814 if ( updateFlags )
5815 {
5816 ret = lwt_be_updateEdges(topo,
5817 &selEdge, LWT_COL_EDGE_EDGE_ID,
5818 &updatedEdge, updateFlags,
5819 NULL, 0);
5820 if ( ret == -1 ) {
5822 return -1;
5823 } else if ( ret == 0 ) {
5824 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
5825 return -1;
5826 } else if ( ret > 1 ) {
5827 lwerror("More than a single edge found with id %"
5828 LWTFMT_ELEMID " !", selEdge.edge_id);
5829 return -1;
5830 }
5831 }
5832
5833 /*****
5834 *
5835 * Update the split edge
5836 *
5837 */
5838
5839 selEdge.edge_id = edge->edge_id;
5840 updatedEdge.geom = newSplitEdgeLine;
5841 updateFlags = LWT_COL_EDGE_GEOM;
5842 if ( splitNodeNewEdgeOutgoing ) {
5843 updatedEdge.start_node = node->node_id;
5844 updatedEdge.next_right = splitNodeEdgeEndInfo->nextCW;
5845 updateFlags |= LWT_COL_EDGE_START_NODE;
5846 updateFlags |= LWT_COL_EDGE_NEXT_RIGHT;
5847 LWDEBUGF(1, "Updating split edge %" LWTFMT_ELEMID
5848 " start node to %" LWTFMT_ELEMID
5849 " and next_right to %" LWTFMT_ELEMID,
5850 selEdge.edge_id,
5851 updatedEdge.start_node,
5852 updatedEdge.next_right
5853 );
5854 } else {
5855 updatedEdge.end_node = node->node_id;
5856 updatedEdge.next_left = splitNodeEdgeEndInfo->nextCW;
5857 updateFlags |= LWT_COL_EDGE_END_NODE;
5858 updateFlags |= LWT_COL_EDGE_NEXT_LEFT;
5859 LWDEBUGF(1, "Updating split edge %" LWTFMT_ELEMID
5860 " end node to %" LWTFMT_ELEMID
5861 " and next_left to %" LWTFMT_ELEMID
5862 ,
5863 selEdge.edge_id,
5864 updatedEdge.end_node
5865 , updatedEdge.next_left
5866 );
5867 }
5868
5869 ret = lwt_be_updateEdges(topo,
5870 &selEdge, LWT_COL_EDGE_EDGE_ID,
5871 &updatedEdge, updateFlags,
5872 NULL, 0);
5873 if ( ret == -1 ) {
5875 return -1;
5876 } else if ( ret == 0 ) {
5877 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
5878 return -1;
5879 } else if ( ret > 1 ) {
5880 lwerror("More than a single edge found with id %"
5881 LWTFMT_ELEMID " !", selEdge.edge_id);
5882 return -1;
5883 }
5884
5885 /************
5886 *
5887 * Update split-edge collapsed side face MBR, if needed
5888 *
5889 */
5890
5891 if ( edge->face_left != edge->face_right )
5892 {
5893 /* TODO: update a single face ? */
5894 LWT_ISO_FACE updface;
5895 updface.face_id = edge->face_right;
5896 if ( updface.face_id != 0 )
5897 {
5898 /* We only need to update the MBR if the shrunk face is
5899 * not the universe face */
5900 LWGEOM *fg = lwt_GetFaceGeometry(topo, updface.face_id);
5901 if ( ! fg )
5902 {
5903 lwerror("Could not get geometry of face %" LWTFMT_ELEMID, updface.face_id);
5904 return -1;
5905 }
5906 updface.mbr = (GBOX *)lwgeom_get_bbox(fg);
5907 if ( updface.mbr )
5908 {
5909 int ret = lwt_be_updateFacesById( topo, &updface, 1 );
5910 if ( ret == -1 )
5911 {
5913 return -1;
5914 }
5915 lwgeom_free(fg);
5916 }
5917 else
5918 {
5919 lwerror("Programmatic error ? Geometry of face %" LWTFMT_ELEMID " is empty!", updface.face_id);
5920 }
5921 }
5922 updface.face_id = edge->face_left;
5923 if ( updface.face_id != 0 )
5924 {
5925 /* We only need to update the MBR if the shrunk face is
5926 * not the universe face */
5927 LWGEOM *fg = lwt_GetFaceGeometry(topo, updface.face_id);
5928 if ( ! fg )
5929 {
5930 lwerror("Could not get geometry of face %" LWTFMT_ELEMID, updface.face_id);
5931 return -1;
5932 }
5933 updface.mbr = (GBOX *)lwgeom_get_bbox(fg);
5934 if ( updface.mbr )
5935 {
5936 int ret = lwt_be_updateFacesById( topo, &updface, 1 );
5937 if ( ret == -1 )
5938 {
5940 return -1;
5941 }
5942 lwgeom_free(fg);
5943 }
5944 else
5945 {
5946 lwerror("Programmatic error ? Geometry of face %" LWTFMT_ELEMID " is empty!", updface.face_id);
5947 }
5948 }
5949 }
5950
5951 /************
5952 *
5953 * Update TopoGeometries composition
5954 *
5955 */
5956
5957 LWDEBUGF(1, "Updating lineal TopoGeometry composition to add edge %" LWTFMT_ELEMID
5958 " to features composed by edge %" LWTFMT_ELEMID,
5959 existingEdge->edge_id, edge->edge_id
5960 );
5961 ret = lwt_be_updateTopoGeomEdgeSplit(topo, edge->edge_id, existingEdge->edge_id, -1);
5962 if ( ! ret ) {
5964 return -1;
5965 }
5966
5967 return 0;
5968 }
5969 else if ( replacedBy[0] == 0 && replacedBy[1] == 0 )
5970 {
5971
5972 /* Neither sides of the snapped edge collapsed to an existing edge */
5973
5974 /* New edge is the outgoing one, by design */
5975 LWT_ISO_EDGE newEdge;
5976 newEdge.edge_id = lwt_be_getNextEdgeId( topo );
5977 if ( newEdge.edge_id == -1 ) {
5979 return -1;
5980 }
5981 newEdge.geom = lwgeom_as_lwline(splitC->geoms[1]);
5982 newEdge.end_node = edge->end_node;
5983 newEdge.start_node = node->node_id;
5984 newEdge.next_right = -updatedEdge.edge_id; // to be assigned later, if needed
5985 if ( edge->next_left == -edge->edge_id ) {
5986 newEdge.next_left = -newEdge.edge_id;
5987 } else {
5988 newEdge.next_left = edge->next_left; // unchanged
5989 }
5990 newEdge.face_left = edge->face_left; // to be changed later
5991 newEdge.face_right = edge->face_right; // to be changed later
5992
5993 /* Updated edge is the incoming one, by design */
5994 updatedEdge.edge_id = edge->edge_id;
5995 updatedEdge.geom = lwgeom_as_lwline(splitC->geoms[0]);
5996 updatedEdge.end_node = node->node_id;
5997 updatedEdge.next_left = newEdge.edge_id; // to be re-assigned later, if needed
5998
5999
6000 LWT_EDGEEND_STAR *nodeStar = lwt_edgeEndStar_init( node->node_id );
6001 for ( uint64_t t=0; t<splitNodeEdges->numEdges; t++ )
6002 {
6003 lwt_edgeEndStar_addEdge( nodeStar, &(splitNodeEdges->edges[t]) );
6004 }
6005 lwt_edgeEndStar_addEdge( nodeStar, &updatedEdge );
6006 lwt_edgeEndStar_addEdge( nodeStar, &newEdge );
6007
6008 _lwt_SnapEdge_checkMotion( topo, splitC, edge, NULL, splitNodeEdges );
6009
6010 /* There cannot be anything in the middle of the two components,
6011 * so both sides will give the same nextCCW and same nextCW */
6012
6013 lwt_EdgeEndStar_debugPrint( nodeStar );
6014
6015 const LWT_EDGEEND *ee0 = lwt_edgeEndStar_getNextCW( nodeStar, &updatedEdge, 0); // incoming
6016 LWDEBUGF(1, "* NextCW of incoming snap-edge component is %s %" LWTFMT_ELEMID,
6017 ee0->outgoing ? "outgoing" : "incoming", ee0->edge->edge_id);
6018 if ( ee0->outgoing ) {
6019 updatedEdge.next_left = ee0->edge->edge_id;
6020 } else {
6021 updatedEdge.next_left = -ee0->edge->edge_id;
6022 }
6023 int splitFaceOnLeft = 1;
6024 if ( ee0->edge->edge_id == newEdge.edge_id )
6025 {
6026 splitFaceOnLeft = 0;
6027 }
6028
6029 const LWT_EDGEEND *ee1 = lwt_edgeEndStar_getNextCW( nodeStar, &newEdge, 1); // outgoing
6030 LWDEBUGF(1, "* NextCW of outgoing snap-edge component is %s %" LWTFMT_ELEMID,
6031 ee1->outgoing ? "outgoing" : "incoming", ee1->edge->edge_id);
6032 if ( ee1->outgoing ) {
6033 newEdge.next_right = ee1->edge->edge_id;
6034 } else {
6035 newEdge.next_right = -ee1->edge->edge_id;
6036 }
6037
6038 int ret = lwt_be_insertEdges(topo, &newEdge, 1);
6039 if (ret != 1)
6040 {
6042 return -1;
6043 }
6044
6045 /* Updating the first portion of the edge */
6046 selEdge.edge_id = edge->edge_id;
6047 ret = lwt_be_updateEdges(topo,
6048 &selEdge, LWT_COL_EDGE_EDGE_ID,
6050 NULL, 0);
6051 if ( ret == -1 ) {
6053 return -1;
6054 } else if ( ret == 0 ) {
6055 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6056 return -1;
6057 } else if ( ret > 1 ) {
6058 lwerror("More than a single edge found with id %"
6059 LWTFMT_ELEMID " !", selEdge.edge_id);
6060 return -1;
6061 }
6062
6063 /* Update CCW edges if needed */
6064 ee0 = lwt_edgeEndStar_getNextCCW( nodeStar, &updatedEdge, 0); // incoming
6065 LWDEBUGF(1, "* NextCCW of incoming snap-edge component is %s %" LWTFMT_ELEMID,
6066 ee0->outgoing ? "outgoing" : "incoming", ee0->edge->edge_id);
6067 if ( ee0->edge->edge_id != newEdge.edge_id )
6068 {
6069 selEdge.edge_id = ee0->edge->edge_id;
6070 if ( ee0->outgoing ) {
6071 updatedEdge.next_right = -edge->edge_id;
6072 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6073 } else {
6074 updatedEdge.next_left = -edge->edge_id;
6075 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6076 }
6077
6078 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of incoming snap-edge",
6079 selEdge.edge_id, ee0->outgoing ? "outgoing" : "incoming");
6080 ret = lwt_be_updateEdges(topo,
6081 &selEdge, LWT_COL_EDGE_EDGE_ID,
6082 &updatedEdge, updateFlags,
6083 NULL, 0);
6084 if ( ret == -1 ) {
6086 return -1;
6087 } else if ( ret == 0 ) {
6088 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6089 return -1;
6090 } else if ( ret > 1 ) {
6091 lwerror("More than a single edge found with id %"
6092 LWTFMT_ELEMID " !", selEdge.edge_id);
6093 return -1;
6094 }
6095 }
6096
6097 /* Update CCW edge of outgoing portion if needed */
6098 ee1 = lwt_edgeEndStar_getNextCCW( nodeStar, &newEdge, 1); // outgoing
6099 LWDEBUGF(1, "* NextCCW of outgoing snap-edge component is %s %" LWTFMT_ELEMID,
6100 ee1->outgoing ? "outgoing" : "incoming", ee1->edge->edge_id);
6101 if ( ee1->edge->edge_id != edge->edge_id )
6102 {
6103 selEdge.edge_id = ee1->edge->edge_id;
6104 if ( ee1->outgoing ) {
6105 updatedEdge.next_right = newEdge.edge_id;
6106 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6107 } else {
6108 updatedEdge.next_left = newEdge.edge_id;
6109 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6110 }
6111
6112 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of outgoing snap-edge",
6113 selEdge.edge_id, ee1->outgoing ? "outgoing" : "incoming");
6114 ret = lwt_be_updateEdges(topo,
6115 &selEdge, LWT_COL_EDGE_EDGE_ID,
6116 &updatedEdge, updateFlags,
6117 NULL, 0);
6118 if ( ret == -1 ) {
6120 return -1;
6121 } else if ( ret == 0 ) {
6122 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6123 return -1;
6124 } else if ( ret > 1 ) {
6125 lwerror("More than a single edge found with id %"
6126 LWTFMT_ELEMID " !", selEdge.edge_id);
6127 return -1;
6128 }
6129 }
6130
6131 /* If any edge was connected to the end node of the split edge, we
6132 * need to update its link to us */
6133 updateFlags = 0;
6134 for ( uint64_t t=0; t<lastNodeEdges->numEdges; t++ )
6135 {
6136 const LWT_ISO_EDGE *in = &(lastNodeEdges->edges[t]);
6137 if ( in->next_right == -edge->edge_id )
6138 {
6139 if ( in->edge_id != edge->edge_id ) {
6140 selEdge.edge_id = in->edge_id;
6141 updatedEdge.next_right = -newEdge.edge_id;
6142 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6143 }
6144 break;
6145 }
6146 if ( in->next_left == -edge->edge_id )
6147 {
6148 if ( in->edge_id != edge->edge_id ) {
6149 selEdge.edge_id = in->edge_id;
6150 updatedEdge.next_left = -newEdge.edge_id;
6151 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6152 }
6153 break;
6154 }
6155 }
6156 if ( updateFlags != 0 )
6157 {
6158 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of outgoing snap-edge",
6159 selEdge.edge_id,
6160 updateFlags & LWT_COL_EDGE_NEXT_LEFT ? "incoming" : "outgoing");
6161 ret = lwt_be_updateEdges(topo,
6162 &selEdge, LWT_COL_EDGE_EDGE_ID,
6163 &updatedEdge, updateFlags,
6164 NULL, 0);
6165 if ( ret == -1 ) {
6167 return -1;
6168 } else if ( ret == 0 ) {
6169 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6170 return -1;
6171 } else if ( ret > 1 ) {
6172 lwerror("More than a single edge found with id %"
6173 LWTFMT_ELEMID " !", selEdge.edge_id);
6174 return -1;
6175 }
6176 }
6177
6178 /* Handle face split */
6179 LWT_ELEMID newFaceId1 = 0;
6180 LWT_ELEMID newFaceId2 = 0;
6181 LWT_ELEMID oldFaceId;
6182 if ( splitFaceOnLeft ) {
6183
6184 oldFaceId = edge->face_left;
6185
6186 LWDEBUGF(1, "Adding face split for left side of new edge %" LWTFMT_ELEMID, newEdge.edge_id);
6187 newFaceId1 = _lwt_AddFaceSplit( topo, newEdge.edge_id, oldFaceId, 0 );
6188 LWDEBUGF(1, "_lwt_AddFaceSplit(%" LWTFMT_ELEMID ") returned %" LWTFMT_ELEMID,
6189 newEdge.edge_id, newFaceId1);
6190
6191 // TODO: retain oldFaceID rather than creating a new one, if a
6192 // new one was already created for the new edge ring !
6193 LWDEBUGF(1, "Adding face split for left side of updated edge %" LWTFMT_ELEMID, edge->edge_id);
6194 newFaceId2 = _lwt_AddFaceSplit( topo, edge->edge_id, oldFaceId, 0 );
6195 LWDEBUGF(1, "_lwt_AddFaceSplit(%" LWTFMT_ELEMID ") returned %" LWTFMT_ELEMID,
6196 edge->edge_id, newFaceId2);
6197
6198
6199 } else {
6200
6201 oldFaceId = edge->face_right;
6202
6203 LWDEBUGF(1, "Adding face split for right side of new edge %" LWTFMT_ELEMID, newEdge.edge_id);
6204 newFaceId1 = _lwt_AddFaceSplit( topo, -newEdge.edge_id, oldFaceId, 0 );
6205 LWDEBUGF(1, "_lwt_AddFaceSplit(%" LWTFMT_ELEMID ") returned %" LWTFMT_ELEMID,
6206 -newEdge.edge_id, newFaceId1);
6207
6208 // TODO: retain oldFaceID rather than creating a new one, if a
6209 // new one was already created on the new edge ring !
6210 LWDEBUGF(1, "Adding face split for right side of updated edge %" LWTFMT_ELEMID, edge->edge_id);
6211 newFaceId2 = _lwt_AddFaceSplit( topo, -edge->edge_id, oldFaceId, 0 );
6212 LWDEBUGF(1, "_lwt_AddFaceSplit(%" LWTFMT_ELEMID ") returned %" LWTFMT_ELEMID,
6213 -edge->edge_id, newFaceId2);
6214
6215 }
6216
6217 /************
6218 *
6219 * Update TopoGeometries composition
6220 *
6221 */
6222
6223 ret = lwt_be_updateTopoGeomEdgeSplit(topo, edge->edge_id, newEdge.edge_id, -1);
6224 if ( ! ret ) {
6226 return -1;
6227 }
6228
6229 LWDEBUGF(1, "New faces %" LWTFMT_ELEMID " and %" LWTFMT_ELEMID
6230 "split from from old face %" LWTFMT_ELEMID,
6231 newFaceId1, newFaceId2, oldFaceId);
6232 if ( newFaceId1 || newFaceId2 )
6233 {
6235 topo, oldFaceId,
6236 newFaceId1 ? newFaceId1 : oldFaceId,
6237 newFaceId2 ? newFaceId2 : oldFaceId
6238 );
6239 if ( ! ret ) {
6241 return -1;
6242 }
6243
6244 if ( newFaceId1 && newFaceId2 )
6245 {
6246 LWDEBUGF(1, "Deleting fully replaced face %" LWTFMT_ELEMID, oldFaceId);
6247 int nids = 1;
6248 ret = lwt_be_deleteFacesById(topo, &oldFaceId, nids);
6249 if ( ret == -1 ) {
6251 return -1;
6252 }
6253 }
6254 }
6255
6256 return 0;
6257 }
6258 else if ( replacedBy[0] != 0 && replacedBy[1] != 0 )
6259 {
6260 // Edge was replaced with two existing edges
6261
6262 // Sanity check
6263 if ( edge->face_right == edge->face_left )
6264 {
6265 lwerror("Unexpectedly, dangling edge %" LWTFMT_ELEMID " was replaced by "
6266 "edges %" LWTFMT_ELEMID " and %" LWTFMT_ELEMID
6267 " when snap to node %" LWTFMT_ELEMID,
6268 edge->edge_id, replacedBy[0], replacedBy[1], node->node_id);
6269 return -1;
6270 }
6271
6272 LWT_ELEMID collapsedFace = 0;
6273 LWT_ELEMID replacingFace = 0;
6274
6275 if ( FP_ABS(edge->next_right) == replacedBy[0] ) {
6276 /* Face on the right of the removed edge disappeared */
6277 // We need to update nextCW on first node and nextCCW on last node
6278 collapsedFace = edge->face_right;
6279 replacingFace = edge->face_left;
6280 } else {
6281 /* Face on the left of the removed edge disappeared */
6282 // We need to update nextCCW on first node and nextCW on last node
6283 collapsedFace = edge->face_left;
6284 replacingFace = edge->face_right;
6285 }
6286
6287 //const LWT_ISO_EDGE *sp_nextCCW = 0;
6288 //const LWT_ISO_EDGE *ep_nextCCW = 0;
6289
6290 // Update CCW edge on first node
6291 updateFlags = 0;
6292 for ( uint64_t t=0; t<firstNodeEdges->numEdges; t++ )
6293 {
6294 const LWT_ISO_EDGE *in = &(firstNodeEdges->edges[t]);
6295 if ( in->edge_id == edge->edge_id ) continue;
6296 if ( in->next_right == edge->edge_id )
6297 {
6298 selEdge.edge_id = in->edge_id;
6299 updatedEdge.next_right = edge->next_right;
6300 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6301 if ( in->face_right == collapsedFace ) {
6302 updatedEdge.face_right = replacingFace;
6303 updateFlags |= LWT_COL_EDGE_FACE_RIGHT;
6304 }
6305 //sp_nextCCW = in;
6306 break;
6307 }
6308 if ( in->next_left == edge->edge_id )
6309 {
6310 selEdge.edge_id = in->edge_id;
6311 updatedEdge.next_left = edge->next_right;
6312 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6313 if ( in->face_left == collapsedFace ) {
6314 updatedEdge.face_left = replacingFace;
6315 updateFlags |= LWT_COL_EDGE_FACE_LEFT;
6316 }
6317 //sp_nextCCW = in;
6318 break;
6319 }
6320 }
6321 if ( updateFlags != 0 )
6322 {
6323 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of outgoing snap-edge",
6324 selEdge.edge_id,
6325 updateFlags & LWT_COL_EDGE_NEXT_LEFT ? "incoming" : "outgoing");
6326 ret = lwt_be_updateEdges(topo,
6327 &selEdge, LWT_COL_EDGE_EDGE_ID,
6328 &updatedEdge, updateFlags,
6329 NULL, 0);
6330 if ( ret == -1 ) {
6332 return -1;
6333 } else if ( ret == 0 ) {
6334 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6335 return -1;
6336 } else if ( ret > 1 ) {
6337 lwerror("More than a single edge found with id %"
6338 LWTFMT_ELEMID " !", selEdge.edge_id);
6339 return -1;
6340 }
6341 }
6342
6343 // Update CCW edge on last node
6344 updateFlags = 0;
6345 for ( uint64_t t=0; t<lastNodeEdges->numEdges; t++ )
6346 {
6347 const LWT_ISO_EDGE *in = &(lastNodeEdges->edges[t]);
6348 if ( in->edge_id == edge->edge_id ) continue;
6349 if ( in->next_right == -edge->edge_id )
6350 {
6351 selEdge.edge_id = in->edge_id;
6352 updatedEdge.next_right = edge->next_left;
6353 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6354 if ( in->face_right == collapsedFace ) {
6355 updatedEdge.face_right = replacingFace;
6356 updateFlags |= LWT_COL_EDGE_FACE_RIGHT;
6357 }
6358 break;
6359 }
6360 if ( in->next_left == -edge->edge_id )
6361 {
6362 selEdge.edge_id = in->edge_id;
6363 updatedEdge.next_left = edge->next_left;
6364 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6365 if ( in->face_left == collapsedFace ) {
6366 updatedEdge.face_left = replacingFace;
6367 updateFlags |= LWT_COL_EDGE_FACE_LEFT;
6368 }
6369 break;
6370 }
6371 }
6372 if ( updateFlags != 0 )
6373 {
6374 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of incoming snap-edge",
6375 selEdge.edge_id,
6376 updateFlags & LWT_COL_EDGE_NEXT_LEFT ? "incoming" : "outgoing");
6377 ret = lwt_be_updateEdges(topo,
6378 &selEdge, LWT_COL_EDGE_EDGE_ID,
6379 &updatedEdge, updateFlags,
6380 NULL, 0);
6381 if ( ret == -1 ) {
6383 return -1;
6384 } else if ( ret == 0 ) {
6385 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6386 return -1;
6387 } else if ( ret > 1 ) {
6388 lwerror("More than a single edge found with id %"
6389 LWTFMT_ELEMID " !", selEdge.edge_id);
6390 return -1;
6391 }
6392 }
6393
6394 if ( collapsedFace == edge->face_right )
6395 {
6396 // We need to update side face of nextCW on first node and nextCCW on last node
6397 // nextCCW on last node was done already, supposedly so we need to do nextCW
6398 // on first
6399 if ( edge->next_right < 0 ) {
6400 selEdge.edge_id = -edge->next_right;
6401 updatedEdge.face_right = replacingFace;
6402 updateFlags = LWT_COL_EDGE_FACE_RIGHT;
6403 } else {
6404 selEdge.edge_id = edge->next_right;
6405 updatedEdge.face_left = replacingFace;
6406 updateFlags = LWT_COL_EDGE_FACE_LEFT;
6407 }
6408 LWDEBUGF(1, "Updating %s face of edge %" LWTFMT_ELEMID ", %s nextCW of outgoing snap-edge",
6409 updateFlags & LWT_COL_EDGE_FACE_LEFT ? "left" : "right",
6410 selEdge.edge_id,
6411 updateFlags & LWT_COL_EDGE_FACE_RIGHT ? "incoming" : "outgoing");
6412 ret = lwt_be_updateEdges(topo,
6413 &selEdge, LWT_COL_EDGE_EDGE_ID,
6414 &updatedEdge, updateFlags,
6415 NULL, 0);
6416 if ( ret == -1 ) {
6418 return -1;
6419 } else if ( ret == 0 ) {
6420 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6421 return -1;
6422 } else if ( ret > 1 ) {
6423 lwerror("More than a single edge found with id %"
6424 LWTFMT_ELEMID " !", selEdge.edge_id);
6425 return -1;
6426 }
6427 }
6428 else
6429 {
6430 // We need to update side face of nextCCW on first node and nextCW on last node
6431 // nextCCW on first node was done already, supposedly so we need to do nextCW
6432 // on last
6433 if ( edge->next_left < 0 ) {
6434 selEdge.edge_id = -edge->next_left;
6435 updatedEdge.face_right = replacingFace;
6436 updateFlags = LWT_COL_EDGE_FACE_RIGHT;
6437 } else {
6438 selEdge.edge_id = edge->next_left;
6439 updatedEdge.face_left = replacingFace;
6440 updateFlags = LWT_COL_EDGE_FACE_LEFT;
6441 }
6442 LWDEBUGF(1, "Updating %s face of edge %" LWTFMT_ELEMID ", %s nextCW of incoming snap-edge",
6443 updateFlags & LWT_COL_EDGE_FACE_LEFT ? "left" : "right",
6444 selEdge.edge_id,
6445 updateFlags & LWT_COL_EDGE_FACE_RIGHT ? "incoming" : "outgoing");
6446 ret = lwt_be_updateEdges(topo,
6447 &selEdge, LWT_COL_EDGE_EDGE_ID,
6448 &updatedEdge, updateFlags,
6449 NULL, 0);
6450 if ( ret == -1 ) {
6452 return -1;
6453 } else if ( ret == 0 ) {
6454 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6455 return -1;
6456 } else if ( ret > 1 ) {
6457 lwerror("More than a single edge found with id %"
6458 LWTFMT_ELEMID " !", selEdge.edge_id);
6459 return -1;
6460 }
6461 }
6462
6463 /* Delete the old edge */
6464 selEdge.edge_id = edge->edge_id;
6465 LWDEBUGF(1, "Deleting edge %" LWTFMT_ELEMID, selEdge.edge_id);
6466 ret = lwt_be_deleteEdges(topo, &selEdge, LWT_COL_EDGE_EDGE_ID);
6467 if ( ret == -1 ) {
6469 return -1;
6470 }
6471
6472 /* Delete collapsed face */
6473 LWDEBUGF(1, "Deleting collapsed face %" LWTFMT_ELEMID, collapsedFace);
6474 int nids = 1;
6475 ret = lwt_be_deleteFacesById(topo, &collapsedFace, nids);
6476 if ( ret == -1 ) {
6478 return -1;
6479 }
6480
6481 /* Delete the collapsed face from composition of TopoGeometries */
6482 if ( ! lwt_be_updateTopoGeomFaceHeal( topo, collapsedFace, -1, -1) )
6483 {
6485 return -1;
6486 }
6487
6488 return 0;
6489 }
6490
6491 //LWDEBUGF(1, "Not handling within-tolerance edge %" LWTFMT_ELEMID, edge->edge_id);
6492 lwerror("Don't know how to deal with edge %" LWTFMT_ELEMID
6493 " replaced by edges %" LWTFMT_ELEMID
6494 " and %" LWTFMT_ELEMID, edge->edge_id, replacedBy[0], replacedBy[1]);
6495
6496 return -1;
6497}
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:344
LWGEOM * lwgeom_split(const LWGEOM *lwgeom_in, const LWGEOM *blade_in)
int azimuth_pt_pt(const POINT2D *p1, const POINT2D *p2, double *ret)
Compute the azimuth of segment AB in radians.
Definition measures.c:2408
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1218
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition lwgeom.c:233
LWGEOM * lwgeom_snap(const LWGEOM *geom1, const LWGEOM *geom2, double tolerance)
Snap vertices and segments of a geometry to another using a given tolerance.
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:339
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:179
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
Definition lwgeom.c:743
#define FP_ABS(a)
#define LWT_COL_EDGE_FACE_RIGHT
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_START_NODE
#define LWT_COL_EDGE_FACE_LEFT
#define LWT_COL_EDGE_NEXT_RIGHT
#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 LWT_COL_EDGE_GEOM
#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.
#define LWDEBUGG(level, geom, msg)
Definition lwgeom_log.h:111
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_SnapEdge_checkMotion(LWT_TOPOLOGY *topo, const LWCOLLECTION *splitC, const LWT_ISO_EDGE *edge, LWT_ISO_EDGE *existingEdge, const LWT_NODE_EDGES *splitNodeEdges)
Check the motion of a snapped edge, invoke lwerror if the movement hits any other edge or node.
LWT_ELEMID lwt_be_getNextEdgeId(LWT_TOPOLOGY *topo)
static int lwt_be_updateTopoGeomFaceSplit(LWT_TOPOLOGY *topo, LWT_ELEMID split_face, LWT_ELEMID new_face1, LWT_ELEMID new_face2)
static int lwt_be_updateTopoGeomFaceHeal(LWT_TOPOLOGY *topo, LWT_ELEMID face1, LWT_ELEMID face2, LWT_ELEMID newface)
int lwt_be_updateTopoGeomEdgeSplit(LWT_TOPOLOGY *topo, LWT_ELEMID split_edge, LWT_ELEMID new_edge1, LWT_ELEMID new_edge2)
int lwt_be_updateEdges(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *sel_edge, int sel_fields, const LWT_ISO_EDGE *upd_edge, int upd_fields, const LWT_ISO_EDGE *exc_edge, int exc_fields)
static LWT_ELEMID _lwt_GetEqualEdge(LWT_TOPOLOGY *topo, LWLINE *edge, int *forward)
int lwt_be_deleteEdges(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *sel_edge, int sel_fields)
static LWT_ELEMID _lwt_AddFaceSplit(LWT_TOPOLOGY *topo, LWT_ELEMID sedge, LWT_ELEMID face, int mbr_only)
int lwt_be_insertEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edge, uint64_t numelems)
static int _lwt_FirstDistinctVertex2D(const POINTARRAY *pa, const POINT2D *ref, int from, int dir, POINT2D *op)
LWGEOM * lwt_GetFaceGeometry(LWT_TOPOLOGY *topo, LWT_ELEMID faceid)
Return the geometry of a face.
static int _lwt_FindAdjacentEdges(LWT_TOPOLOGY *topo, LWT_ELEMID node, edgeend *data, edgeend *other, LWT_ELEMID myedge_id)
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition lwinline.h:127
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition lwinline.h:97
const LWT_EDGEEND * lwt_edgeEndStar_getNextCW(LWT_EDGEEND_STAR *star, LWT_ISO_EDGE *edge, int outgoing)
LWT_EDGEEND_STAR * lwt_edgeEndStar_init(LWT_ELEMID nodeID)
const LWT_EDGEEND * lwt_edgeEndStar_getNextCCW(LWT_EDGEEND_STAR *star, LWT_ISO_EDGE *edge, int outgoing)
void lwt_EdgeEndStar_debugPrint(const LWT_EDGEEND_STAR *star)
void lwt_edgeEndStar_addEdge(LWT_EDGEEND_STAR *star, const LWT_ISO_EDGE *edge)
LWT_NODE_EDGES * lwt_nodeEdges_loadFromDB(LWT_TOPOLOGY *topo, LWT_ELEMID node_id, int fields)
uint32_t ngeoms
Definition liblwgeom.h:580
LWGEOM ** geoms
Definition liblwgeom.h:575
POINTARRAY * points
Definition liblwgeom.h:483
const LWT_ISO_EDGE * edge
Definition lwt_edgeend.h:33
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
LWPOINT * geom
LWT_ISO_EDGE * edges
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
uint32_t npoints
Definition liblwgeom.h:427
LWT_ELEMID nextCCW
LWT_ELEMID nextCW

References _lwt_AddFaceSplit(), _lwt_FindAdjacentEdges(), _lwt_FirstDistinctVertex2D(), _lwt_GetEqualEdge(), _lwt_SnapEdge_checkMotion(), azimuth_pt_pt(), LWT_EDGEEND_t::edge, LWT_ISO_EDGE::edge_id, LWT_NODE_EDGES_t::edges, LWT_ISO_EDGE::end_node, LWT_ISO_FACE::face_id, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, FP_ABS, LWT_ISO_NODE::geom, LWT_ISO_EDGE::geom, LWCOLLECTION::geoms, getPoint2d_cp(), LWDEBUG, LWDEBUGF, LWDEBUGG, lwerror(), lwgeom_as_lwcollection(), lwgeom_as_lwline(), lwgeom_as_lwpoint(), lwgeom_free(), lwgeom_get_bbox(), lwgeom_snap(), lwgeom_split(), lwline_as_lwgeom(), lwpoint_as_lwgeom(), lwt_be_deleteEdges(), lwt_be_deleteFacesById(), lwt_be_getNextEdgeId(), lwt_be_insertEdges(), lwt_be_updateEdges(), lwt_be_updateFacesById(), lwt_be_updateTopoGeomEdgeSplit(), lwt_be_updateTopoGeomFaceHeal(), lwt_be_updateTopoGeomFaceSplit(), LWT_COL_EDGE_ALL, LWT_COL_EDGE_EDGE_ID, LWT_COL_EDGE_END_NODE, LWT_COL_EDGE_FACE_LEFT, LWT_COL_EDGE_FACE_RIGHT, LWT_COL_EDGE_GEOM, LWT_COL_EDGE_NEXT_LEFT, LWT_COL_EDGE_NEXT_RIGHT, LWT_COL_EDGE_START_NODE, lwt_edgeEndStar_addEdge(), lwt_EdgeEndStar_debugPrint(), lwt_edgeEndStar_getNextCCW(), lwt_edgeEndStar_getNextCW(), lwt_edgeEndStar_init(), lwt_GetFaceGeometry(), lwt_nodeEdges_loadFromDB(), LWTFMT_ELEMID, LWT_ISO_FACE::mbr, edgeend_t::myaz, LWT_ISO_EDGE::next_left, LWT_ISO_EDGE::next_right, edgeend_t::nextCCW, edgeend_t::nextCW, LWCOLLECTION::ngeoms, LWT_ISO_NODE::node_id, POINTARRAY::npoints, LWT_NODE_EDGES_t::numEdges, LWT_EDGEEND_t::outgoing, PGTOPO_BE_ERROR, LWLINE::points, LWT_ISO_EDGE::start_node, POINT2D::x, and POINT2D::y.

Referenced by _lwt_SplitAllEdgesToNewNode().

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