5413{
5416
5419
5420
5421
5424
5426 if ( splitC->
ngeoms != 2 )
5427 {
5428 lwerror(
"Split of edge resulted in %d components", splitC->
ngeoms);
5429 return -1;
5430 }
5431
5433 if ( ! firstNodeEdges ) {
5434 lwerror(
"No edges found in DB to be incident to split edge's first node");
5435 return -1;
5436 }
5438 if ( ! lastNodeEdges ) {
5439 lwerror(
"No edges found in DB to be incident to split edge's last node");
5440 return -1;
5441 }
5443 if ( ! splitNodeEdges ) {
5444 lwerror(
"No edges found in DB to be incident to split node");
5445 return -1;
5446 }
5447
5448
5449 for ( uint64_t t=0; t<firstNodeEdges->
numEdges; t++ )
5450 {
5452 {
5453 edge = &(firstNodeEdges->
edges[t]);
5454 break;
5455 }
5456 }
5457
5473 );
5474
5475 int ret;
5476
5477 uint64_t n;
5480
5482 for ( n=0; n<2; ++n)
5483 {
5484 int forward;
5485
5487 if ( existingEdgeId == -1 )
5488 {
5489
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
5498
5499
5501 if ( n == 1 ) {
5504 pt,
5505 0,
5506 1,
5507 &op
5508 );
5509 if (!ret)
5510 {
5511 lwerror(
"No distinct vertices found on second part of split edge");
5512 return -1;
5513 }
5514 } else {
5517 pa,
5518 pt,
5520 -1,
5521 &op
5522 );
5523 if (!ret)
5524 {
5525 lwerror(
"No distinct vertices found on first part of split edge");
5526 return -1;
5527 }
5528 }
5529 if ( !
azimuth_pt_pt(pt, &op, &(splitNodeEdgeEnds[n].myaz)) ) {
5530 lwerror(
"error computing azimuth of split endpoint [%.15g %.15g,%.15g %.15g]",
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);
5539 if ( ! ret ) {
5540 lwerror(
"Unexpected backend return: _lwt_FindAdjacentEdges(%"
5541 LWTFMT_ELEMID ") found no edges when we previously split edge %"
5544 return -1;
5545 }
5548 n, edge->
edge_id, splitNodeEdgeEnds[n].nextCW, splitNodeEdgeEnds[n].nextCCW);
5549 }
5550 }
5551 else
5552 {
5554 " (%s)", n, existingEdgeId, forward ? "forward" : "backward" );
5555
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
5576 int updateFlags;
5578
5579 if ( ( replacedBy[0] != 0 && replacedBy[1] == 0 ) ||
5580 ( replacedBy[1] != 0 && replacedBy[0] == 0 ) )
5581 {
5582
5583
5585 edgeend *splitNodeEdgeEndInfo;
5586 LWLINE *newSplitEdgeLine;
5587 int splitNodeNewEdgeOutgoing;
5588
5589 if ( replacedBy[1] == 0 )
5590
5591 {
5592 existingEdge = existingEdges[0];
5594 splitNodeEdgeEndInfo = &(splitNodeEdgeEnds[1]);
5595 splitNodeNewEdgeOutgoing = 1;
5596 }
5597 else
5598
5599 {
5600 existingEdge = existingEdges[1];
5602 splitNodeEdgeEndInfo = &(splitNodeEdgeEnds[0]);
5603 splitNodeNewEdgeOutgoing = 0;
5604 }
5605
5607
5619 );
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633 {
5635 if ( splitNodeNewEdgeOutgoing ) {
5638 } else {
5641 }
5642
5645 splitNodeEdgeEndInfo->
nextCCW,
5646 nextEdge, sideFace
5647 );
5648
5649 if ( splitNodeEdgeEndInfo->
nextCCW > 0 )
5650 {
5659 nextEdge, sideFace
5660 );
5661 }
5662 else
5663 {
5672 nextEdge, sideFace
5673 );
5674 }
5675
5678 &updatedEdge, updateFlags,
5679 NULL, 0);
5680 if ( ret == -1 ) {
5682 return -1;
5683 } else if ( ret == 0 ) {
5685 return -1;
5686 } else if ( ret > 1 ) {
5687 lwerror(
"More than a single edge found with id %"
5689 return -1;
5690 }
5691 }
5692
5693
5694 {
5696 if ( splitNodeNewEdgeOutgoing ) {
5698 } else {
5700 }
5701
5704 splitNodeEdgeEndInfo->
nextCW, sideFace
5705 );
5706
5707 if ( splitNodeEdgeEndInfo->
nextCW > 0 )
5708 {
5713 ", outgoing next CW of new split edge on split node",
5715 }
5716 else
5717 {
5722 ", incoming next CW of new split edge on split node",
5724 }
5725
5728 &updatedEdge, updateFlags,
5729 NULL, 0);
5730 if ( ret == -1 ) {
5732 return -1;
5733 } else if ( ret == 0 ) {
5735 return -1;
5736 } else if ( ret > 1 ) {
5737 lwerror(
"More than a single edge found with edge_id %"
5739 return -1;
5740 }
5741 }
5742
5743
5744
5745
5746
5747
5748
5750 int nextCCWEdgeIsIncoming = 0;
5751 int collapsedEdgeIsIncoming;
5752
5754
5756 if ( replacedBy[0] ) {
5757 commonNodeEdges = firstNodeEdges;
5759 collapsedEdgeIsIncoming = 0;
5760 } else {
5761 commonNodeEdges = lastNodeEdges;
5763 collapsedEdgeIsIncoming = 1;
5764 }
5765
5766
5767
5768 {
5770
5771 LWDEBUGF(1,
"Looking for next CCW edge of split edge %"
5773 " having %llu attached edges",
5775 commonNodeID, commonNodeEdges->
numEdges
5776 );
5777
5778
5779 for ( uint64_t t=0; t<commonNodeEdges->
numEdges; t++ )
5780 {
5782
5789 );
5790
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 {
5813 commonNodeID
5814 );
5815 return -1;
5816 }
5817
5818 LWDEBUGF(1,
"Next CCW edge of split edge %"
5822 commonNodeID,
5823 nextCCWEdgeIsIncoming ? "incoming" : "outgoing",
5824 nextCCWEdge->edge_id
5825 );
5826
5828 {
5829 LWDEBUG(1,
"Next CCW edge is existing/collapse edge, will not update here");
5830 }
5831 else
5832 {
5833
5834
5835
5836
5837
5838
5839
5840
5844
5846 if ( nextCCWEdgeIsIncoming ) {
5849 LWDEBUGF(1,
"Updating next_left of incoming next CCW edge %"
5853 newNextEdge
5854 );
5855 } else {
5858 LWDEBUGF(1,
"Updating next_right of outgoing next CCW edge %"
5862 newNextEdge
5863 );
5864 }
5867 &updatedEdge, updateFlags,
5868 NULL, 0);
5869 if ( ret == -1 ) {
5871 return -1;
5872 } else if ( ret == 0 ) {
5874 return -1;
5875 } else if ( ret > 1 ) {
5876 lwerror(
"More than a single edge found with next_left %"
5878 return -1;
5879 }
5880 }
5881 }
5882
5883
5884
5885
5886
5887
5888
5890 updateFlags = 0;
5892 {
5895 LWDEBUGF(1,
"Will update next_left of existing edge %"
5899 );
5900 }
5902 {
5905 LWDEBUGF(1,
"Will update next_right of existing edge %"
5909 );
5910 }
5912 {
5915 LWDEBUGF(1,
"Will update next_left of existing edge %"
5919 );
5920 }
5922 {
5925 LWDEBUGF(1,
"Will update next_right of existing edge %"
5929 );
5930 }
5931 if ( updateFlags )
5932 {
5935 &updatedEdge, updateFlags,
5936 NULL, 0);
5937 if ( ret == -1 ) {
5939 return -1;
5940 } else if ( ret == 0 ) {
5942 return -1;
5943 } else if ( ret > 1 ) {
5944 lwerror(
"More than a single edge found with id %"
5946 return -1;
5947 }
5948 }
5949
5950
5951
5952
5953
5954
5955
5957 updatedEdge.
geom = newSplitEdgeLine;
5959 if ( splitNodeNewEdgeOutgoing ) {
5970 );
5971 } else {
5979 ,
5983 );
5984 }
5985
5988 &updatedEdge, updateFlags,
5989 NULL, 0);
5990 if ( ret == -1 ) {
5992 return -1;
5993 } else if ( ret == 0 ) {
5995 return -1;
5996 } else if ( ret > 1 ) {
5997 lwerror(
"More than a single edge found with id %"
5999 return -1;
6000 }
6001
6002
6003
6004
6005
6006
6007
6009 {
6010
6014 {
6015
6016
6018 if ( ! fg )
6019 {
6021 return -1;
6022 }
6025 {
6027 if ( ret == -1 )
6028 {
6030 return -1;
6031 }
6033 }
6034 else
6035 {
6037 }
6038 }
6041 {
6042
6043
6045 if ( ! fg )
6046 {
6048 return -1;
6049 }
6052 {
6054 if ( ret == -1 )
6055 {
6057 return -1;
6058 }
6060 }
6061 else
6062 {
6064 }
6065 }
6066 }
6067
6068
6069
6070
6071
6072
6073
6077 );
6079 if ( ! ret ) {
6081 return -1;
6082 }
6083
6084 return 0;
6085 }
6086 else if ( replacedBy[0] == 0 && replacedBy[1] == 0 )
6087 {
6088
6089
6090
6091
6094 if ( newEdge.
edge_id == -1 ) {
6096 return -1;
6097 }
6104 } else {
6106 }
6109
6110
6115
6116
6118 for ( uint64_t t=0; t<splitNodeEdges->
numEdges; t++ )
6119 {
6121 }
6124
6126
6127
6128
6129
6131
6134 ee0->
outgoing ?
"outgoing" :
"incoming", ee0->edge->edge_id);
6137 } else {
6139 }
6140 int splitFaceOnLeft = 1;
6142 {
6143 splitFaceOnLeft = 0;
6144 }
6145
6148 ee1->
outgoing ?
"outgoing" :
"incoming", ee1->edge->edge_id);
6151 } else {
6153 }
6154
6156 if (ret != 1)
6157 {
6159 return -1;
6160 }
6161
6162
6167 NULL, 0);
6168 if ( ret == -1 ) {
6170 return -1;
6171 } else if ( ret == 0 ) {
6173 return -1;
6174 } else if ( ret > 1 ) {
6175 lwerror(
"More than a single edge found with id %"
6177 return -1;
6178 }
6179
6180
6183 ee0->
outgoing ?
"outgoing" :
"incoming", ee0->edge->edge_id);
6185 {
6190 } else {
6193 }
6194
6199 &updatedEdge, updateFlags,
6200 NULL, 0);
6201 if ( ret == -1 ) {
6203 return -1;
6204 } else if ( ret == 0 ) {
6206 return -1;
6207 } else if ( ret > 1 ) {
6208 lwerror(
"More than a single edge found with id %"
6210 return -1;
6211 }
6212 }
6213
6214
6217 ee1->
outgoing ?
"outgoing" :
"incoming", ee1->edge->edge_id);
6219 {
6224 } else {
6227 }
6228
6233 &updatedEdge, updateFlags,
6234 NULL, 0);
6235 if ( ret == -1 ) {
6237 return -1;
6238 } else if ( ret == 0 ) {
6240 return -1;
6241 } else if ( ret > 1 ) {
6242 lwerror(
"More than a single edge found with id %"
6244 return -1;
6245 }
6246 }
6247
6248
6249
6250 updateFlags = 0;
6251 for ( uint64_t t=0; t<lastNodeEdges->
numEdges; t++ )
6252 {
6255 {
6260 }
6261 break;
6262 }
6264 {
6269 }
6270 break;
6271 }
6272 }
6273 if ( updateFlags != 0 )
6274 {
6280 &updatedEdge, updateFlags,
6281 NULL, 0);
6282 if ( ret == -1 ) {
6284 return -1;
6285 } else if ( ret == 0 ) {
6287 return -1;
6288 } else if ( ret > 1 ) {
6289 lwerror(
"More than a single edge found with id %"
6291 return -1;
6292 }
6293 }
6294
6295
6299 if ( splitFaceOnLeft ) {
6300
6302
6307
6308
6309
6314
6315
6316 } else {
6317
6319
6323 -newEdge.
edge_id, newFaceId1);
6324
6325
6326
6331
6332 }
6333
6334
6335
6336
6337
6338
6339
6341 if ( ! ret ) {
6343 return -1;
6344 }
6345
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 {
6364 int nids = 1;
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
6378
6379
6381 {
6386 return -1;
6387 }
6388
6391
6393
6394
6397 } else {
6398
6399
6402 }
6403
6404
6405
6406
6407
6408 updateFlags = 0;
6409 for ( uint64_t t=0; t<firstNodeEdges->
numEdges; t++ )
6410 {
6414 {
6421 }
6422
6423 break;
6424 }
6426 {
6433 }
6434
6435 break;
6436 }
6437 }
6438 if ( updateFlags != 0 )
6439 {
6445 &updatedEdge, updateFlags,
6446 NULL, 0);
6447 if ( ret == -1 ) {
6449 return -1;
6450 } else if ( ret == 0 ) {
6452 return -1;
6453 } else if ( ret > 1 ) {
6454 lwerror(
"More than a single edge found with id %"
6456 return -1;
6457 }
6458 }
6459
6460
6461 updateFlags = 0;
6462 for ( uint64_t t=0; t<lastNodeEdges->
numEdges; t++ )
6463 {
6467 {
6474 }
6475 break;
6476 }
6478 {
6485 }
6486 break;
6487 }
6488 }
6489 if ( updateFlags != 0 )
6490 {
6496 &updatedEdge, updateFlags,
6497 NULL, 0);
6498 if ( ret == -1 ) {
6500 return -1;
6501 } else if ( ret == 0 ) {
6503 return -1;
6504 } else if ( ret > 1 ) {
6505 lwerror(
"More than a single edge found with id %"
6507 return -1;
6508 }
6509 }
6510
6512 {
6513
6514
6515
6520 } else {
6524 }
6527 selEdge.edge_id,
6531 &updatedEdge, updateFlags,
6532 NULL, 0);
6533 if ( ret == -1 ) {
6535 return -1;
6536 } else if ( ret == 0 ) {
6538 return -1;
6539 } else if ( ret > 1 ) {
6540 lwerror(
"More than a single edge found with id %"
6542 return -1;
6543 }
6544 }
6545 else
6546 {
6547
6548
6549
6554 } else {
6558 }
6561 selEdge.edge_id,
6565 &updatedEdge, updateFlags,
6566 NULL, 0);
6567 if ( ret == -1 ) {
6569 return -1;
6570 } else if ( ret == 0 ) {
6572 return -1;
6573 } else if ( ret > 1 ) {
6574 lwerror(
"More than a single edge found with id %"
6576 return -1;
6577 }
6578 }
6579
6580
6584 if ( ret == -1 ) {
6586 return -1;
6587 }
6588
6589
6591 int nids = 1;
6593 if ( ret == -1 ) {
6595 return -1;
6596 }
6597
6598
6600 {
6602 return -1;
6603 }
6604
6605 return 0;
6606 }
6607
6608
6612
6613 return -1;
6614}
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
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.
void lwgeom_free(LWGEOM *geom)
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
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)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
#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_END_NODE
#define LWT_COL_EDGE_NEXT_LEFT
#define LWT_COL_EDGE_GEOM
#define PGTOPO_BE_ERROR()
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
#define LWDEBUGG(level, geom, msg)
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)
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
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)
const LWT_ISO_EDGE * edge