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

5413{
5414 LWGEOM *prj = lwpoint_as_lwgeom(node->geom);
5415 const POINT2D *pt = getPoint2d_cp(lwgeom_as_lwpoint(prj)->point, 0);
5416
5417 LWDEBUGF(1, "Experimental handling of within-tolerance edge %" LWTFMT_ELEMID, edge->edge_id);
5418 LWGEOM *snapE = lwgeom_snap(lwline_as_lwgeom(edge->geom), prj, tol);
5419
5420 /* TODO: check if an endpoint moved */
5421
5422 LWGEOM *splitE = lwgeom_split(snapE, prj);
5423 LWDEBUGG(1, splitE, "Split edge");
5424
5425 LWCOLLECTION *splitC = lwgeom_as_lwcollection(splitE);
5426 if ( splitC->ngeoms != 2 )
5427 {
5428 lwerror("Split of edge resulted in %d components", splitC->ngeoms);
5429 return -1;
5430 }
5431
5432 LWT_NODE_EDGES *firstNodeEdges = lwt_nodeEdges_loadFromDB(topo, edge->start_node, LWT_COL_EDGE_ALL );
5433 if ( ! firstNodeEdges ) {
5434 lwerror("No edges found in DB to be incident to split edge's first node");
5435 return -1;
5436 }
5437 LWT_NODE_EDGES *lastNodeEdges = lwt_nodeEdges_loadFromDB(topo, edge->end_node, LWT_COL_EDGE_ALL );
5438 if ( ! lastNodeEdges ) {
5439 lwerror("No edges found in DB to be incident to split edge's last node");
5440 return -1;
5441 }
5442 LWT_NODE_EDGES *splitNodeEdges = lwt_nodeEdges_loadFromDB(topo, node->node_id, LWT_COL_EDGE_ALL);
5443 if ( ! splitNodeEdges ) {
5444 lwerror("No edges found in DB to be incident to split node");
5445 return -1;
5446 }
5447
5448 /* Update split edge reference as it was possibly changed by previous call */
5449 for ( uint64_t t=0; t<firstNodeEdges->numEdges; t++ )
5450 {
5451 if ( firstNodeEdges->edges[t].edge_id == edge->edge_id )
5452 {
5453 edge = &(firstNodeEdges->edges[t]);
5454 break;
5455 }
5456 }
5457
5458 LWDEBUGF(1, "Split edge %"
5459 LWTFMT_ELEMID " start condition: next_right:%"
5460 LWTFMT_ELEMID ", next_left:%"
5461 LWTFMT_ELEMID ", face_right:%"
5462 LWTFMT_ELEMID ", face_left:%"
5463 LWTFMT_ELEMID ", start_node:%"
5464 LWTFMT_ELEMID ", end_node:%"
5466 edge->edge_id,
5467 edge->next_right,
5468 edge->next_left,
5469 edge->face_right,
5470 edge->face_left,
5471 edge->start_node,
5472 edge->end_node
5473 );
5474
5475 int ret;
5476
5477 uint64_t n;
5478 LWT_ELEMID replacedBy[2];
5479 LWT_ISO_EDGE *existingEdges[2];
5480 //int replacedByForward[2];
5481 edgeend splitNodeEdgeEnds[2];
5482 for ( n=0; n<2; ++n)
5483 {
5484 int forward;
5485 /* TODO: directly get full existing edge rather than just id * */
5486 LWT_ELEMID existingEdgeId = _lwt_GetEqualEdge( topo, lwgeom_as_lwline(splitC->geoms[n]), &forward );
5487 if ( existingEdgeId == -1 )
5488 {
5489 /* probably too late, due to internal lwerror */
5490 return -1;
5491 }
5492 existingEdges[n] = NULL;
5493 if ( existingEdgeId == 0 )
5494 {
5495 LWDEBUGF(1, "Split component %llu is a new edge, computing edgeEndInfo", n);
5496 {
5497 // Compute nextCW and nextCCW of the split edge now
5498 // incident to the split point
5499
5500 POINT2D op; /* other point */
5501 if ( n == 1 ) {
5503 lwgeom_as_lwline(splitC->geoms[1])->points, //const POINTARRAY* pa,
5504 pt, //POINT2D *ref,
5505 0, // int from,
5506 1, // int dir,
5507 &op // POINT2D *op
5508 );
5509 if (!ret)
5510 {
5511 lwerror("No distinct vertices found on second part of split edge");
5512 return -1; /* lwerror should have been raised */
5513 }
5514 } else {
5515 const POINTARRAY *pa = lwgeom_as_lwline(splitC->geoms[0])->points;
5517 pa, //const POINTARRAY* pa,
5518 pt, //POINT2D *ref,
5519 pa->npoints-1, // int from,
5520 -1, // int dir,
5521 &op // POINT2D *op
5522 );
5523 if (!ret)
5524 {
5525 lwerror("No distinct vertices found on first part of split edge");
5526 return -1; /* lwerror should have been raised */
5527 }
5528 }
5529 if ( ! azimuth_pt_pt(pt, &op, &(splitNodeEdgeEnds[n].myaz)) ) {
5530 lwerror("error computing azimuth of split endpoint [%.15g %.15g,%.15g %.15g]",
5531 op.x, op.y,
5532 pt->x, pt->y
5533 );
5534 return -1;
5535 }
5536 LWDEBUGF(1, "Azimuth of split component %llu edgeend [%.15g %.15g,%.15g %.15g] is %.15g",
5537 n, op.x, op.y, pt->x, pt->y, splitNodeEdgeEnds[n].myaz);
5538 ret = _lwt_FindAdjacentEdges( topo, node->node_id, &(splitNodeEdgeEnds[n]), NULL, -1 );
5539 if ( ! ret ) {
5540 lwerror("Unexpected backend return: _lwt_FindAdjacentEdges(%"
5541 LWTFMT_ELEMID ") found no edges when we previously split edge %"
5542 LWTFMT_ELEMID "d on it",
5543 node->node_id, edge->edge_id);
5544 return -1;
5545 }
5546 LWDEBUGF(1, "Component %llu of split edge %" LWTFMT_ELEMID
5547 " next CW is %" LWTFMT_ELEMID ", next CCW is %" LWTFMT_ELEMID,
5548 n, edge->edge_id, splitNodeEdgeEnds[n].nextCW, splitNodeEdgeEnds[n].nextCCW);
5549 }
5550 }
5551 else
5552 {
5553 LWDEBUGF(1, "Split component %llu matches existing edge %" LWTFMT_ELEMID
5554 " (%s)", n, existingEdgeId, forward ? "forward" : "backward" );
5555 /* Get existing edge */
5556 for ( uint64_t t=0; t<splitNodeEdges->numEdges; t++ )
5557 {
5558 if ( splitNodeEdges->edges[t].edge_id == existingEdgeId )
5559 {
5560 existingEdges[n] = &(splitNodeEdges->edges[t]);
5561 break;
5562 }
5563 }
5564 if (existingEdges[n] == NULL)
5565 {
5566 lwerror("could not find edge %" LWTFMT_ELEMID " in database, but _lwt_GetEqualEdges said it was there", existingEdgeId );
5567 return -1;
5568 }
5569 }
5570
5571 replacedBy[n] = existingEdgeId;
5572 }
5573
5574
5575 LWT_ISO_EDGE updatedEdge;
5576 int updateFlags;
5577 LWT_ISO_EDGE selEdge;
5578
5579 if ( ( replacedBy[0] != 0 && replacedBy[1] == 0 ) ||
5580 ( replacedBy[1] != 0 && replacedBy[0] == 0 ) )
5581 {
5582 /* One side of the snapped edge collapsed to an existing edge */
5583
5584 LWT_ISO_EDGE *existingEdge;
5585 edgeend *splitNodeEdgeEndInfo;
5586 LWLINE *newSplitEdgeLine;
5587 int splitNodeNewEdgeOutgoing; // The new split edge goes out of the split node
5588
5589 if ( replacedBy[1] == 0 )
5590 /* First part of edge is the existing edge */
5591 {
5592 existingEdge = existingEdges[0];
5593 newSplitEdgeLine = lwgeom_as_lwline(splitC->geoms[1]);
5594 splitNodeEdgeEndInfo = &(splitNodeEdgeEnds[1]);
5595 splitNodeNewEdgeOutgoing = 1;
5596 }
5597 else
5598 /* Second part of edge is the existing edge */
5599 {
5600 existingEdge = existingEdges[1];
5601 newSplitEdgeLine = lwgeom_as_lwline(splitC->geoms[0]);
5602 splitNodeEdgeEndInfo = &(splitNodeEdgeEnds[0]);
5603 splitNodeNewEdgeOutgoing = 0;
5604 }
5605
5606 _lwt_SnapEdge_checkMotion( topo, splitC, edge, existingEdge, splitNodeEdges );
5607
5608 LWDEBUGF(1, "Existing edge %"
5609 LWTFMT_ELEMID " (post-modEdgeSplit) next_right:%"
5610 LWTFMT_ELEMID ", next_left:%"
5611 LWTFMT_ELEMID ", face_right:%"
5612 LWTFMT_ELEMID ", face_left:%"
5614 existingEdge->edge_id,
5615 existingEdge->next_right,
5616 existingEdge->next_left,
5617 existingEdge->face_right,
5618 existingEdge->face_left
5619 );
5620
5621 /*****
5622 *
5623 * Update edge linking
5624 *
5625 */
5626
5627 /*
5628 * Update next CW / CCW edges on split node
5629 * (fix linking on split node)
5630 */
5631
5632 /* Update next CCW edge */
5633 {
5634 LWT_ELEMID nextEdge, sideFace;
5635 if ( splitNodeNewEdgeOutgoing ) {
5636 nextEdge = edge->edge_id;
5637 sideFace = edge->face_left;
5638 } else {
5639 nextEdge = -edge->edge_id;
5640 sideFace = edge->face_right;
5641 }
5642
5643 LWDEBUGF(1, "Setting nextEdge/sideFace of CCW edge %" LWTFMT_ELEMID
5644 " to %" LWTFMT_ELEMID "/%" LWTFMT_ELEMID,
5645 splitNodeEdgeEndInfo->nextCCW,
5646 nextEdge, sideFace
5647 );
5648
5649 if ( splitNodeEdgeEndInfo->nextCCW > 0 )
5650 {
5651 selEdge.edge_id = splitNodeEdgeEndInfo->nextCCW;
5652 updatedEdge.next_right = nextEdge;
5653 updatedEdge.face_right = sideFace;
5654 updateFlags = LWT_COL_EDGE_NEXT_RIGHT|
5656 LWDEBUGF(1, "Will update next_right/face_right of outgoing CCW edge %" LWTFMT_ELEMID
5657 " to %" LWTFMT_ELEMID "/%" LWTFMT_ELEMID,
5658 selEdge.edge_id,
5659 nextEdge, sideFace
5660 );
5661 }
5662 else
5663 {
5664 selEdge.edge_id = -splitNodeEdgeEndInfo->nextCCW;
5665 updatedEdge.next_left = nextEdge;
5666 updatedEdge.face_left = sideFace;
5667 updateFlags = LWT_COL_EDGE_NEXT_LEFT|
5669 LWDEBUGF(1, "Will update next_left/face_left of incoming CCW edge %" LWTFMT_ELEMID
5670 " to %" LWTFMT_ELEMID "/%" LWTFMT_ELEMID,
5671 selEdge.edge_id,
5672 nextEdge, sideFace
5673 );
5674 }
5675
5676 ret = lwt_be_updateEdges(topo,
5677 &selEdge, LWT_COL_EDGE_EDGE_ID,
5678 &updatedEdge, updateFlags,
5679 NULL, 0);
5680 if ( ret == -1 ) {
5682 return -1;
5683 } else if ( ret == 0 ) {
5684 lwerror("Edge %" LWTFMT_ELEMID " disappeared during operations", selEdge.edge_id);
5685 return -1;
5686 } else if ( ret > 1 ) {
5687 lwerror("More than a single edge found with id %"
5688 LWTFMT_ELEMID " ! (corrupted topology?)", selEdge.edge_id);
5689 return -1;
5690 }
5691 }
5692
5693 /* Update next CW edge on split node */
5694 {
5695 LWT_ELEMID sideFace;
5696 if ( splitNodeNewEdgeOutgoing ) {
5697 sideFace = edge->face_right;
5698 } else {
5699 sideFace = edge->face_left;
5700 }
5701
5702 LWDEBUGF(1, "Setting sideFace of CW edge %" LWTFMT_ELEMID
5703 " to %" LWTFMT_ELEMID,
5704 splitNodeEdgeEndInfo->nextCW, sideFace
5705 );
5706
5707 if ( splitNodeEdgeEndInfo->nextCW > 0 )
5708 {
5709 selEdge.edge_id = splitNodeEdgeEndInfo->nextCW;
5710 updatedEdge.face_left = sideFace;
5711 updateFlags = LWT_COL_EDGE_FACE_LEFT;
5712 LWDEBUGF(1, "Updating left_face of edge %" LWTFMT_ELEMID
5713 ", outgoing next CW of new split edge on split node",
5714 selEdge.edge_id);
5715 }
5716 else
5717 {
5718 selEdge.edge_id = -splitNodeEdgeEndInfo->nextCW;
5719 updatedEdge.face_right = sideFace;
5720 updateFlags = LWT_COL_EDGE_FACE_RIGHT;
5721 LWDEBUGF(1, "Updating right_face of edge %" LWTFMT_ELEMID
5722 ", incoming next CW of new split edge on split node",
5723 selEdge.edge_id);
5724 }
5725
5726 ret = lwt_be_updateEdges(topo,
5727 &selEdge, LWT_COL_EDGE_EDGE_ID,
5728 &updatedEdge, updateFlags,
5729 NULL, 0);
5730 if ( ret == -1 ) {
5732 return -1;
5733 } else if ( ret == 0 ) {
5734 lwerror("Edge %" LWTFMT_ELEMID " disappeared during operations", selEdge.edge_id);
5735 return -1;
5736 } else if ( ret > 1 ) {
5737 lwerror("More than a single edge found with edge_id %"
5738 LWTFMT_ELEMID " ! (corrupted topology?)", selEdge.edge_id);
5739 return -1;
5740 }
5741 }
5742
5743 /*
5744 * Update links to now-disappeared edgeend
5745 * on the node originally in common with
5746 * the existing node
5747 */
5748
5749 LWT_ISO_EDGE *nextCCWEdge = NULL;
5750 int nextCCWEdgeIsIncoming = 0;
5751 int collapsedEdgeIsIncoming;
5752
5753 LWT_ELEMID commonNodeID;
5754
5755 LWT_NODE_EDGES *commonNodeEdges;
5756 if ( replacedBy[0] ) {
5757 commonNodeEdges = firstNodeEdges;
5758 commonNodeID = edge->start_node;
5759 collapsedEdgeIsIncoming = 0;
5760 } else {
5761 commonNodeEdges = lastNodeEdges;
5762 commonNodeID = edge->end_node;
5763 collapsedEdgeIsIncoming = 1;
5764 }
5765
5766
5767 // Update next CCW edge
5768 {
5769 LWT_ELEMID signedCollapsedEdgeID = collapsedEdgeIsIncoming ? -edge->edge_id: edge->edge_id;
5770
5771 LWDEBUGF(1, "Looking for next CCW edge of split edge %"
5772 LWTFMT_ELEMID " on common node %" LWTFMT_ELEMID
5773 " having %llu attached edges",
5774 edge->edge_id,
5775 commonNodeID, commonNodeEdges->numEdges
5776 );
5777
5778 /* Find next CCW edge */
5779 for ( uint64_t t=0; t<commonNodeEdges->numEdges; t++ )
5780 {
5781 LWT_ISO_EDGE *et = &(commonNodeEdges->edges[t]);
5782
5783 LWDEBUGF(1, "common node edge %"
5784 LWTFMT_ELEMID " has next_left:%" LWTFMT_ELEMID
5785 " next_right:%" LWTFMT_ELEMID,
5786 et->edge_id,
5787 et->next_left,
5788 et->next_right
5789 );
5790
5791 if ( et->start_node == commonNodeID )
5792 {
5793 if ( et->next_right == signedCollapsedEdgeID )
5794 {
5795 nextCCWEdge = et;
5796 nextCCWEdgeIsIncoming = 0;
5797 break;
5798 }
5799 }
5800 else if ( et->end_node == commonNodeID )
5801 {
5802 if ( et->next_left == signedCollapsedEdgeID )
5803 {
5804 nextCCWEdge = et;
5805 nextCCWEdgeIsIncoming = 1;
5806 break;
5807 }
5808 }
5809 }
5810 if ( ! nextCCWEdge )
5811 {
5812 lwerror("Could not find nextCCW edge on common node %" LWTFMT_ELEMID,
5813 commonNodeID
5814 );
5815 return -1;
5816 }
5817
5818 LWDEBUGF(1, "Next CCW edge of split edge %"
5819 LWTFMT_ELEMID " on common node %" LWTFMT_ELEMID
5820 " is (%s) %" LWTFMT_ELEMID,
5821 edge->edge_id,
5822 commonNodeID,
5823 nextCCWEdgeIsIncoming ? "incoming" : "outgoing",
5824 nextCCWEdge->edge_id
5825 );
5826
5827 if ( nextCCWEdge->edge_id == existingEdge->edge_id )
5828 {
5829 LWDEBUG(1, "Next CCW edge is existing/collapse edge, will not update here");
5830 }
5831 else
5832 {
5833 /*
5834 * TODO: the nextCCW is only of interest IFF the collapse
5835 * happened clockwise!
5836 *
5837 * just update to the split edge id (positive or negative
5838 * depending on whether it was outgoing or incoming in the
5839 * common node)
5840 */
5841 LWT_ELEMID newNextEdge = existingEdge->start_node == commonNodeID ?
5842 existingEdge->edge_id :
5843 -existingEdge->edge_id;
5844
5845 selEdge.edge_id = nextCCWEdge->edge_id;
5846 if ( nextCCWEdgeIsIncoming ) {
5847 updatedEdge.next_left = newNextEdge;
5848 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
5849 LWDEBUGF(1, "Updating next_left of incoming next CCW edge %"
5851 " to %" LWTFMT_ELEMID,
5852 selEdge.edge_id,
5853 newNextEdge
5854 );
5855 } else {
5856 updatedEdge.next_right = newNextEdge;
5857 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
5858 LWDEBUGF(1, "Updating next_right of outgoing next CCW edge %"
5860 " to %" LWTFMT_ELEMID,
5861 selEdge.edge_id,
5862 newNextEdge
5863 );
5864 }
5865 ret = lwt_be_updateEdges(topo,
5866 &selEdge, LWT_COL_EDGE_EDGE_ID,
5867 &updatedEdge, updateFlags,
5868 NULL, 0);
5869 if ( ret == -1 ) {
5871 return -1;
5872 } else if ( ret == 0 ) {
5873 lwerror("Edge %" LWTFMT_ELEMID " disappeared during operations", selEdge.edge_id);
5874 return -1;
5875 } else if ( ret > 1 ) {
5876 lwerror("More than a single edge found with next_left %"
5877 LWTFMT_ELEMID " ! (corrupted topology?)", selEdge.next_left);
5878 return -1;
5879 }
5880 }
5881 }
5882
5883 /*****
5884 *
5885 * Update the existing edge our split edge collapsed to
5886 *
5887 */
5888
5889 selEdge.edge_id = existingEdge->edge_id;
5890 updateFlags = 0;
5891 if ( existingEdge->next_left == edge->edge_id )
5892 {
5893 updatedEdge.next_left = edge->next_right;
5894 updateFlags |= LWT_COL_EDGE_NEXT_LEFT;
5895 LWDEBUGF(1, "Will update next_left of existing edge %"
5897 selEdge.edge_id,
5898 updatedEdge.next_left
5899 );
5900 }
5901 if ( existingEdge->next_right == edge->edge_id )
5902 {
5903 updatedEdge.next_right = edge->next_right;
5904 updateFlags |= LWT_COL_EDGE_NEXT_RIGHT;
5905 LWDEBUGF(1, "Will update next_right of existing edge %"
5907 selEdge.edge_id,
5908 updatedEdge.next_right
5909 );
5910 }
5911 if ( existingEdge->next_left == -edge->edge_id )
5912 {
5913 updatedEdge.next_left = edge->next_left;
5914 updateFlags |= LWT_COL_EDGE_NEXT_LEFT;
5915 LWDEBUGF(1, "Will update next_left of existing edge %"
5917 selEdge.edge_id,
5918 updatedEdge.next_left
5919 );
5920 }
5921 if ( existingEdge->next_right == -edge->edge_id )
5922 {
5923 updatedEdge.next_right = edge->next_left;
5924 updateFlags |= LWT_COL_EDGE_NEXT_RIGHT;
5925 LWDEBUGF(1, "Will update next_right of existing edge %"
5927 selEdge.edge_id,
5928 updatedEdge.next_right
5929 );
5930 }
5931 if ( updateFlags )
5932 {
5933 ret = lwt_be_updateEdges(topo,
5934 &selEdge, LWT_COL_EDGE_EDGE_ID,
5935 &updatedEdge, updateFlags,
5936 NULL, 0);
5937 if ( ret == -1 ) {
5939 return -1;
5940 } else if ( ret == 0 ) {
5941 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
5942 return -1;
5943 } else if ( ret > 1 ) {
5944 lwerror("More than a single edge found with id %"
5945 LWTFMT_ELEMID " !", selEdge.edge_id);
5946 return -1;
5947 }
5948 }
5949
5950 /*****
5951 *
5952 * Update the split edge
5953 *
5954 */
5955
5956 selEdge.edge_id = edge->edge_id;
5957 updatedEdge.geom = newSplitEdgeLine;
5958 updateFlags = LWT_COL_EDGE_GEOM;
5959 if ( splitNodeNewEdgeOutgoing ) {
5960 updatedEdge.start_node = node->node_id;
5961 updatedEdge.next_right = splitNodeEdgeEndInfo->nextCW;
5962 updateFlags |= LWT_COL_EDGE_START_NODE;
5963 updateFlags |= LWT_COL_EDGE_NEXT_RIGHT;
5964 LWDEBUGF(1, "Updating split edge %" LWTFMT_ELEMID
5965 " start node to %" LWTFMT_ELEMID
5966 " and next_right to %" LWTFMT_ELEMID,
5967 selEdge.edge_id,
5968 updatedEdge.start_node,
5969 updatedEdge.next_right
5970 );
5971 } else {
5972 updatedEdge.end_node = node->node_id;
5973 updatedEdge.next_left = splitNodeEdgeEndInfo->nextCW;
5974 updateFlags |= LWT_COL_EDGE_END_NODE;
5975 updateFlags |= LWT_COL_EDGE_NEXT_LEFT;
5976 LWDEBUGF(1, "Updating split edge %" LWTFMT_ELEMID
5977 " end node to %" LWTFMT_ELEMID
5978 " and next_left to %" LWTFMT_ELEMID
5979 ,
5980 selEdge.edge_id,
5981 updatedEdge.end_node
5982 , updatedEdge.next_left
5983 );
5984 }
5985
5986 ret = lwt_be_updateEdges(topo,
5987 &selEdge, LWT_COL_EDGE_EDGE_ID,
5988 &updatedEdge, updateFlags,
5989 NULL, 0);
5990 if ( ret == -1 ) {
5992 return -1;
5993 } else if ( ret == 0 ) {
5994 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
5995 return -1;
5996 } else if ( ret > 1 ) {
5997 lwerror("More than a single edge found with id %"
5998 LWTFMT_ELEMID " !", selEdge.edge_id);
5999 return -1;
6000 }
6001
6002 /************
6003 *
6004 * Update split-edge collapsed side face MBR, if needed
6005 *
6006 */
6007
6008 if ( edge->face_left != edge->face_right )
6009 {
6010 /* TODO: update a single face ? */
6011 LWT_ISO_FACE updface;
6012 updface.face_id = edge->face_right;
6013 if ( updface.face_id != 0 )
6014 {
6015 /* We only need to update the MBR if the shrunk face is
6016 * not the universe face */
6017 LWGEOM *fg = lwt_GetFaceGeometry(topo, updface.face_id);
6018 if ( ! fg )
6019 {
6020 lwerror("Could not get geometry of face %" LWTFMT_ELEMID, updface.face_id);
6021 return -1;
6022 }
6023 updface.mbr = (GBOX *)lwgeom_get_bbox(fg);
6024 if ( updface.mbr )
6025 {
6026 int ret = lwt_be_updateFacesById( topo, &updface, 1 );
6027 if ( ret == -1 )
6028 {
6030 return -1;
6031 }
6032 lwgeom_free(fg);
6033 }
6034 else
6035 {
6036 lwerror("Programmatic error ? Geometry of face %" LWTFMT_ELEMID " is empty!", updface.face_id);
6037 }
6038 }
6039 updface.face_id = edge->face_left;
6040 if ( updface.face_id != 0 )
6041 {
6042 /* We only need to update the MBR if the shrunk face is
6043 * not the universe face */
6044 LWGEOM *fg = lwt_GetFaceGeometry(topo, updface.face_id);
6045 if ( ! fg )
6046 {
6047 lwerror("Could not get geometry of face %" LWTFMT_ELEMID, updface.face_id);
6048 return -1;
6049 }
6050 updface.mbr = (GBOX *)lwgeom_get_bbox(fg);
6051 if ( updface.mbr )
6052 {
6053 int ret = lwt_be_updateFacesById( topo, &updface, 1 );
6054 if ( ret == -1 )
6055 {
6057 return -1;
6058 }
6059 lwgeom_free(fg);
6060 }
6061 else
6062 {
6063 lwerror("Programmatic error ? Geometry of face %" LWTFMT_ELEMID " is empty!", updface.face_id);
6064 }
6065 }
6066 }
6067
6068 /************
6069 *
6070 * Update TopoGeometries composition
6071 *
6072 */
6073
6074 LWDEBUGF(1, "Updating lineal TopoGeometry composition to add edge %" LWTFMT_ELEMID
6075 " to features composed by edge %" LWTFMT_ELEMID,
6076 existingEdge->edge_id, edge->edge_id
6077 );
6078 ret = lwt_be_updateTopoGeomEdgeSplit(topo, edge->edge_id, existingEdge->edge_id, -1);
6079 if ( ! ret ) {
6081 return -1;
6082 }
6083
6084 return 0;
6085 }
6086 else if ( replacedBy[0] == 0 && replacedBy[1] == 0 )
6087 {
6088
6089 /* Neither sides of the snapped edge collapsed to an existing edge */
6090
6091 /* New edge is the outgoing one, by design */
6092 LWT_ISO_EDGE newEdge;
6093 newEdge.edge_id = lwt_be_getNextEdgeId( topo );
6094 if ( newEdge.edge_id == -1 ) {
6096 return -1;
6097 }
6098 newEdge.geom = lwgeom_as_lwline(splitC->geoms[1]);
6099 newEdge.end_node = edge->end_node;
6100 newEdge.start_node = node->node_id;
6101 newEdge.next_right = -updatedEdge.edge_id; // to be assigned later, if needed
6102 if ( edge->next_left == -edge->edge_id ) {
6103 newEdge.next_left = -newEdge.edge_id;
6104 } else {
6105 newEdge.next_left = edge->next_left; // unchanged
6106 }
6107 newEdge.face_left = edge->face_left; // to be changed later
6108 newEdge.face_right = edge->face_right; // to be changed later
6109
6110 /* Updated edge is the incoming one, by design */
6111 updatedEdge.edge_id = edge->edge_id;
6112 updatedEdge.geom = lwgeom_as_lwline(splitC->geoms[0]);
6113 updatedEdge.end_node = node->node_id;
6114 updatedEdge.next_left = newEdge.edge_id; // to be re-assigned later, if needed
6115
6116
6117 LWT_EDGEEND_STAR *nodeStar = lwt_edgeEndStar_init( node->node_id );
6118 for ( uint64_t t=0; t<splitNodeEdges->numEdges; t++ )
6119 {
6120 lwt_edgeEndStar_addEdge( nodeStar, &(splitNodeEdges->edges[t]) );
6121 }
6122 lwt_edgeEndStar_addEdge( nodeStar, &updatedEdge );
6123 lwt_edgeEndStar_addEdge( nodeStar, &newEdge );
6124
6125 _lwt_SnapEdge_checkMotion( topo, splitC, edge, NULL, splitNodeEdges );
6126
6127 /* There cannot be anything in the middle of the two components,
6128 * so both sides will give the same nextCCW and same nextCW */
6129
6130 lwt_EdgeEndStar_debugPrint( nodeStar );
6131
6132 const LWT_EDGEEND *ee0 = lwt_edgeEndStar_getNextCW( nodeStar, &updatedEdge, 0); // incoming
6133 LWDEBUGF(1, "* NextCW of incoming snap-edge component is %s %" LWTFMT_ELEMID,
6134 ee0->outgoing ? "outgoing" : "incoming", ee0->edge->edge_id);
6135 if ( ee0->outgoing ) {
6136 updatedEdge.next_left = ee0->edge->edge_id;
6137 } else {
6138 updatedEdge.next_left = -ee0->edge->edge_id;
6139 }
6140 int splitFaceOnLeft = 1;
6141 if ( ee0->edge->edge_id == newEdge.edge_id )
6142 {
6143 splitFaceOnLeft = 0;
6144 }
6145
6146 const LWT_EDGEEND *ee1 = lwt_edgeEndStar_getNextCW( nodeStar, &newEdge, 1); // outgoing
6147 LWDEBUGF(1, "* NextCW of outgoing snap-edge component is %s %" LWTFMT_ELEMID,
6148 ee1->outgoing ? "outgoing" : "incoming", ee1->edge->edge_id);
6149 if ( ee1->outgoing ) {
6150 newEdge.next_right = ee1->edge->edge_id;
6151 } else {
6152 newEdge.next_right = -ee1->edge->edge_id;
6153 }
6154
6155 int ret = lwt_be_insertEdges(topo, &newEdge, 1);
6156 if (ret != 1)
6157 {
6159 return -1;
6160 }
6161
6162 /* Updating the first portion of the edge */
6163 selEdge.edge_id = edge->edge_id;
6164 ret = lwt_be_updateEdges(topo,
6165 &selEdge, LWT_COL_EDGE_EDGE_ID,
6167 NULL, 0);
6168 if ( ret == -1 ) {
6170 return -1;
6171 } else if ( ret == 0 ) {
6172 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6173 return -1;
6174 } else if ( ret > 1 ) {
6175 lwerror("More than a single edge found with id %"
6176 LWTFMT_ELEMID " !", selEdge.edge_id);
6177 return -1;
6178 }
6179
6180 /* Update CCW edges if needed */
6181 ee0 = lwt_edgeEndStar_getNextCCW( nodeStar, &updatedEdge, 0); // incoming
6182 LWDEBUGF(1, "* NextCCW of incoming snap-edge component is %s %" LWTFMT_ELEMID,
6183 ee0->outgoing ? "outgoing" : "incoming", ee0->edge->edge_id);
6184 if ( ee0->edge->edge_id != newEdge.edge_id )
6185 {
6186 selEdge.edge_id = ee0->edge->edge_id;
6187 if ( ee0->outgoing ) {
6188 updatedEdge.next_right = -edge->edge_id;
6189 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6190 } else {
6191 updatedEdge.next_left = -edge->edge_id;
6192 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6193 }
6194
6195 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of incoming snap-edge",
6196 selEdge.edge_id, ee0->outgoing ? "outgoing" : "incoming");
6197 ret = lwt_be_updateEdges(topo,
6198 &selEdge, LWT_COL_EDGE_EDGE_ID,
6199 &updatedEdge, updateFlags,
6200 NULL, 0);
6201 if ( ret == -1 ) {
6203 return -1;
6204 } else if ( ret == 0 ) {
6205 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6206 return -1;
6207 } else if ( ret > 1 ) {
6208 lwerror("More than a single edge found with id %"
6209 LWTFMT_ELEMID " !", selEdge.edge_id);
6210 return -1;
6211 }
6212 }
6213
6214 /* Update CCW edge of outgoing portion if needed */
6215 ee1 = lwt_edgeEndStar_getNextCCW( nodeStar, &newEdge, 1); // outgoing
6216 LWDEBUGF(1, "* NextCCW of outgoing snap-edge component is %s %" LWTFMT_ELEMID,
6217 ee1->outgoing ? "outgoing" : "incoming", ee1->edge->edge_id);
6218 if ( ee1->edge->edge_id != edge->edge_id )
6219 {
6220 selEdge.edge_id = ee1->edge->edge_id;
6221 if ( ee1->outgoing ) {
6222 updatedEdge.next_right = newEdge.edge_id;
6223 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6224 } else {
6225 updatedEdge.next_left = newEdge.edge_id;
6226 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6227 }
6228
6229 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of outgoing snap-edge",
6230 selEdge.edge_id, ee1->outgoing ? "outgoing" : "incoming");
6231 ret = lwt_be_updateEdges(topo,
6232 &selEdge, LWT_COL_EDGE_EDGE_ID,
6233 &updatedEdge, updateFlags,
6234 NULL, 0);
6235 if ( ret == -1 ) {
6237 return -1;
6238 } else if ( ret == 0 ) {
6239 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6240 return -1;
6241 } else if ( ret > 1 ) {
6242 lwerror("More than a single edge found with id %"
6243 LWTFMT_ELEMID " !", selEdge.edge_id);
6244 return -1;
6245 }
6246 }
6247
6248 /* If any edge was connected to the end node of the split edge, we
6249 * need to update its link to us */
6250 updateFlags = 0;
6251 for ( uint64_t t=0; t<lastNodeEdges->numEdges; t++ )
6252 {
6253 const LWT_ISO_EDGE *in = &(lastNodeEdges->edges[t]);
6254 if ( in->next_right == -edge->edge_id )
6255 {
6256 if ( in->edge_id != edge->edge_id ) {
6257 selEdge.edge_id = in->edge_id;
6258 updatedEdge.next_right = -newEdge.edge_id;
6259 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6260 }
6261 break;
6262 }
6263 if ( in->next_left == -edge->edge_id )
6264 {
6265 if ( in->edge_id != edge->edge_id ) {
6266 selEdge.edge_id = in->edge_id;
6267 updatedEdge.next_left = -newEdge.edge_id;
6268 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6269 }
6270 break;
6271 }
6272 }
6273 if ( updateFlags != 0 )
6274 {
6275 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of outgoing snap-edge",
6276 selEdge.edge_id,
6277 updateFlags & LWT_COL_EDGE_NEXT_LEFT ? "incoming" : "outgoing");
6278 ret = lwt_be_updateEdges(topo,
6279 &selEdge, LWT_COL_EDGE_EDGE_ID,
6280 &updatedEdge, updateFlags,
6281 NULL, 0);
6282 if ( ret == -1 ) {
6284 return -1;
6285 } else if ( ret == 0 ) {
6286 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6287 return -1;
6288 } else if ( ret > 1 ) {
6289 lwerror("More than a single edge found with id %"
6290 LWTFMT_ELEMID " !", selEdge.edge_id);
6291 return -1;
6292 }
6293 }
6294
6295 /* Handle face split */
6296 LWT_ELEMID newFaceId1 = 0;
6297 LWT_ELEMID newFaceId2 = 0;
6298 LWT_ELEMID oldFaceId;
6299 if ( splitFaceOnLeft ) {
6300
6301 oldFaceId = edge->face_left;
6302
6303 LWDEBUGF(1, "Adding face split for left side of new edge %" LWTFMT_ELEMID, newEdge.edge_id);
6304 newFaceId1 = _lwt_AddFaceSplit( topo, newEdge.edge_id, oldFaceId, 0 );
6305 LWDEBUGF(1, "_lwt_AddFaceSplit(%" LWTFMT_ELEMID ") returned %" LWTFMT_ELEMID,
6306 newEdge.edge_id, newFaceId1);
6307
6308 // TODO: retain oldFaceID rather than creating a new one, if a
6309 // new one was already created for the new edge ring !
6310 LWDEBUGF(1, "Adding face split for left side of updated edge %" LWTFMT_ELEMID, edge->edge_id);
6311 newFaceId2 = _lwt_AddFaceSplit( topo, edge->edge_id, oldFaceId, 0 );
6312 LWDEBUGF(1, "_lwt_AddFaceSplit(%" LWTFMT_ELEMID ") returned %" LWTFMT_ELEMID,
6313 edge->edge_id, newFaceId2);
6314
6315
6316 } else {
6317
6318 oldFaceId = edge->face_right;
6319
6320 LWDEBUGF(1, "Adding face split for right side of new edge %" LWTFMT_ELEMID, newEdge.edge_id);
6321 newFaceId1 = _lwt_AddFaceSplit( topo, -newEdge.edge_id, oldFaceId, 0 );
6322 LWDEBUGF(1, "_lwt_AddFaceSplit(%" LWTFMT_ELEMID ") returned %" LWTFMT_ELEMID,
6323 -newEdge.edge_id, newFaceId1);
6324
6325 // TODO: retain oldFaceID rather than creating a new one, if a
6326 // new one was already created on the new edge ring !
6327 LWDEBUGF(1, "Adding face split for right side of updated edge %" LWTFMT_ELEMID, edge->edge_id);
6328 newFaceId2 = _lwt_AddFaceSplit( topo, -edge->edge_id, oldFaceId, 0 );
6329 LWDEBUGF(1, "_lwt_AddFaceSplit(%" LWTFMT_ELEMID ") returned %" LWTFMT_ELEMID,
6330 -edge->edge_id, newFaceId2);
6331
6332 }
6333
6334 /************
6335 *
6336 * Update TopoGeometries composition
6337 *
6338 */
6339
6340 ret = lwt_be_updateTopoGeomEdgeSplit(topo, edge->edge_id, newEdge.edge_id, -1);
6341 if ( ! ret ) {
6343 return -1;
6344 }
6345
6346 LWDEBUGF(1, "New faces %" LWTFMT_ELEMID " and %" LWTFMT_ELEMID
6347 "split from from old face %" LWTFMT_ELEMID,
6348 newFaceId1, newFaceId2, oldFaceId);
6349 if ( newFaceId1 || newFaceId2 )
6350 {
6352 topo, oldFaceId,
6353 newFaceId1 ? newFaceId1 : oldFaceId,
6354 newFaceId2 ? newFaceId2 : oldFaceId
6355 );
6356 if ( ! ret ) {
6358 return -1;
6359 }
6360
6361 if ( newFaceId1 && newFaceId2 )
6362 {
6363 LWDEBUGF(1, "Deleting fully replaced face %" LWTFMT_ELEMID, oldFaceId);
6364 int nids = 1;
6365 ret = lwt_be_deleteFacesById(topo, &oldFaceId, nids);
6366 if ( ret == -1 ) {
6368 return -1;
6369 }
6370 }
6371 }
6372
6373 return 0;
6374 }
6375 else if ( replacedBy[0] != 0 && replacedBy[1] != 0 )
6376 {
6377 // Edge was replaced with two existing edges
6378
6379 // Sanity check
6380 if ( edge->face_right == edge->face_left )
6381 {
6382 lwerror("Unexpectedly, dangling edge %" LWTFMT_ELEMID " was replaced by "
6383 "edges %" LWTFMT_ELEMID " and %" LWTFMT_ELEMID
6384 " when snap to node %" LWTFMT_ELEMID,
6385 edge->edge_id, replacedBy[0], replacedBy[1], node->node_id);
6386 return -1;
6387 }
6388
6389 LWT_ELEMID collapsedFace = 0;
6390 LWT_ELEMID replacingFace = 0;
6391
6392 if ( FP_ABS(edge->next_right) == replacedBy[0] ) {
6393 /* Face on the right of the removed edge disappeared */
6394 // We need to update nextCW on first node and nextCCW on last node
6395 collapsedFace = edge->face_right;
6396 replacingFace = edge->face_left;
6397 } else {
6398 /* Face on the left of the removed edge disappeared */
6399 // We need to update nextCCW on first node and nextCW on last node
6400 collapsedFace = edge->face_left;
6401 replacingFace = edge->face_right;
6402 }
6403
6404 //const LWT_ISO_EDGE *sp_nextCCW = 0;
6405 //const LWT_ISO_EDGE *ep_nextCCW = 0;
6406
6407 // Update CCW edge on first node
6408 updateFlags = 0;
6409 for ( uint64_t t=0; t<firstNodeEdges->numEdges; t++ )
6410 {
6411 const LWT_ISO_EDGE *in = &(firstNodeEdges->edges[t]);
6412 if ( in->edge_id == edge->edge_id ) continue;
6413 if ( in->next_right == edge->edge_id )
6414 {
6415 selEdge.edge_id = in->edge_id;
6416 updatedEdge.next_right = edge->next_right;
6417 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6418 if ( in->face_right == collapsedFace ) {
6419 updatedEdge.face_right = replacingFace;
6420 updateFlags |= LWT_COL_EDGE_FACE_RIGHT;
6421 }
6422 //sp_nextCCW = in;
6423 break;
6424 }
6425 if ( in->next_left == edge->edge_id )
6426 {
6427 selEdge.edge_id = in->edge_id;
6428 updatedEdge.next_left = edge->next_right;
6429 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6430 if ( in->face_left == collapsedFace ) {
6431 updatedEdge.face_left = replacingFace;
6432 updateFlags |= LWT_COL_EDGE_FACE_LEFT;
6433 }
6434 //sp_nextCCW = in;
6435 break;
6436 }
6437 }
6438 if ( updateFlags != 0 )
6439 {
6440 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of outgoing snap-edge",
6441 selEdge.edge_id,
6442 updateFlags & LWT_COL_EDGE_NEXT_LEFT ? "incoming" : "outgoing");
6443 ret = lwt_be_updateEdges(topo,
6444 &selEdge, LWT_COL_EDGE_EDGE_ID,
6445 &updatedEdge, updateFlags,
6446 NULL, 0);
6447 if ( ret == -1 ) {
6449 return -1;
6450 } else if ( ret == 0 ) {
6451 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6452 return -1;
6453 } else if ( ret > 1 ) {
6454 lwerror("More than a single edge found with id %"
6455 LWTFMT_ELEMID " !", selEdge.edge_id);
6456 return -1;
6457 }
6458 }
6459
6460 // Update CCW edge on last node
6461 updateFlags = 0;
6462 for ( uint64_t t=0; t<lastNodeEdges->numEdges; t++ )
6463 {
6464 const LWT_ISO_EDGE *in = &(lastNodeEdges->edges[t]);
6465 if ( in->edge_id == edge->edge_id ) continue;
6466 if ( in->next_right == -edge->edge_id )
6467 {
6468 selEdge.edge_id = in->edge_id;
6469 updatedEdge.next_right = edge->next_left;
6470 updateFlags = LWT_COL_EDGE_NEXT_RIGHT;
6471 if ( in->face_right == collapsedFace ) {
6472 updatedEdge.face_right = replacingFace;
6473 updateFlags |= LWT_COL_EDGE_FACE_RIGHT;
6474 }
6475 break;
6476 }
6477 if ( in->next_left == -edge->edge_id )
6478 {
6479 selEdge.edge_id = in->edge_id;
6480 updatedEdge.next_left = edge->next_left;
6481 updateFlags = LWT_COL_EDGE_NEXT_LEFT;
6482 if ( in->face_left == collapsedFace ) {
6483 updatedEdge.face_left = replacingFace;
6484 updateFlags |= LWT_COL_EDGE_FACE_LEFT;
6485 }
6486 break;
6487 }
6488 }
6489 if ( updateFlags != 0 )
6490 {
6491 LWDEBUGF(1, "Updating edge %" LWTFMT_ELEMID ", %s nextCCW of incoming snap-edge",
6492 selEdge.edge_id,
6493 updateFlags & LWT_COL_EDGE_NEXT_LEFT ? "incoming" : "outgoing");
6494 ret = lwt_be_updateEdges(topo,
6495 &selEdge, LWT_COL_EDGE_EDGE_ID,
6496 &updatedEdge, updateFlags,
6497 NULL, 0);
6498 if ( ret == -1 ) {
6500 return -1;
6501 } else if ( ret == 0 ) {
6502 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6503 return -1;
6504 } else if ( ret > 1 ) {
6505 lwerror("More than a single edge found with id %"
6506 LWTFMT_ELEMID " !", selEdge.edge_id);
6507 return -1;
6508 }
6509 }
6510
6511 if ( collapsedFace == edge->face_right )
6512 {
6513 // We need to update side face of nextCW on first node and nextCCW on last node
6514 // nextCCW on last node was done already, supposedly so we need to do nextCW
6515 // on first
6516 if ( edge->next_right < 0 ) {
6517 selEdge.edge_id = -edge->next_right;
6518 updatedEdge.face_right = replacingFace;
6519 updateFlags = LWT_COL_EDGE_FACE_RIGHT;
6520 } else {
6521 selEdge.edge_id = edge->next_right;
6522 updatedEdge.face_left = replacingFace;
6523 updateFlags = LWT_COL_EDGE_FACE_LEFT;
6524 }
6525 LWDEBUGF(1, "Updating %s face of edge %" LWTFMT_ELEMID ", %s nextCW of outgoing snap-edge",
6526 updateFlags & LWT_COL_EDGE_FACE_LEFT ? "left" : "right",
6527 selEdge.edge_id,
6528 updateFlags & LWT_COL_EDGE_FACE_RIGHT ? "incoming" : "outgoing");
6529 ret = lwt_be_updateEdges(topo,
6530 &selEdge, LWT_COL_EDGE_EDGE_ID,
6531 &updatedEdge, updateFlags,
6532 NULL, 0);
6533 if ( ret == -1 ) {
6535 return -1;
6536 } else if ( ret == 0 ) {
6537 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6538 return -1;
6539 } else if ( ret > 1 ) {
6540 lwerror("More than a single edge found with id %"
6541 LWTFMT_ELEMID " !", selEdge.edge_id);
6542 return -1;
6543 }
6544 }
6545 else
6546 {
6547 // We need to update side face of nextCCW on first node and nextCW on last node
6548 // nextCCW on first node was done already, supposedly so we need to do nextCW
6549 // on last
6550 if ( edge->next_left < 0 ) {
6551 selEdge.edge_id = -edge->next_left;
6552 updatedEdge.face_right = replacingFace;
6553 updateFlags = LWT_COL_EDGE_FACE_RIGHT;
6554 } else {
6555 selEdge.edge_id = edge->next_left;
6556 updatedEdge.face_left = replacingFace;
6557 updateFlags = LWT_COL_EDGE_FACE_LEFT;
6558 }
6559 LWDEBUGF(1, "Updating %s face of edge %" LWTFMT_ELEMID ", %s nextCW of incoming snap-edge",
6560 updateFlags & LWT_COL_EDGE_FACE_LEFT ? "left" : "right",
6561 selEdge.edge_id,
6562 updateFlags & LWT_COL_EDGE_FACE_RIGHT ? "incoming" : "outgoing");
6563 ret = lwt_be_updateEdges(topo,
6564 &selEdge, LWT_COL_EDGE_EDGE_ID,
6565 &updatedEdge, updateFlags,
6566 NULL, 0);
6567 if ( ret == -1 ) {
6569 return -1;
6570 } else if ( ret == 0 ) {
6571 lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", selEdge.edge_id);
6572 return -1;
6573 } else if ( ret > 1 ) {
6574 lwerror("More than a single edge found with id %"
6575 LWTFMT_ELEMID " !", selEdge.edge_id);
6576 return -1;
6577 }
6578 }
6579
6580 /* Delete the old edge */
6581 selEdge.edge_id = edge->edge_id;
6582 LWDEBUGF(1, "Deleting edge %" LWTFMT_ELEMID, selEdge.edge_id);
6583 ret = lwt_be_deleteEdges(topo, &selEdge, LWT_COL_EDGE_EDGE_ID);
6584 if ( ret == -1 ) {
6586 return -1;
6587 }
6588
6589 /* Delete collapsed face */
6590 LWDEBUGF(1, "Deleting collapsed face %" LWTFMT_ELEMID, collapsedFace);
6591 int nids = 1;
6592 ret = lwt_be_deleteFacesById(topo, &collapsedFace, nids);
6593 if ( ret == -1 ) {
6595 return -1;
6596 }
6597
6598 /* Delete the collapsed face from composition of TopoGeometries */
6599 if ( ! lwt_be_updateTopoGeomFaceHeal( topo, collapsedFace, -1, -1) )
6600 {
6602 return -1;
6603 }
6604
6605 return 0;
6606 }
6607
6608 //LWDEBUGF(1, "Not handling within-tolerance edge %" LWTFMT_ELEMID, edge->edge_id);
6609 lwerror("Don't know how to deal with edge %" LWTFMT_ELEMID
6610 " replaced by edges %" LWTFMT_ELEMID
6611 " and %" LWTFMT_ELEMID, edge->edge_id, replacedBy[0], replacedBy[1]);
6612
6613 return -1;
6614}
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
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:1246
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition lwgeom.c:261
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:367
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:207
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:771
#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: