5296{
5299
5302
5303
5304
5307
5309 if ( splitC->
ngeoms != 2 )
5310 {
5311 lwerror(
"Split of edge resulted in %d components", splitC->
ngeoms);
5312 return -1;
5313 }
5314
5316 if ( ! firstNodeEdges ) {
5317 lwerror(
"No edges found in DB to be incident to split edge's first node");
5318 return -1;
5319 }
5321 if ( ! lastNodeEdges ) {
5322 lwerror(
"No edges found in DB to be incident to split edge's last node");
5323 return -1;
5324 }
5326 if ( ! splitNodeEdges ) {
5327 lwerror(
"No edges found in DB to be incident to split node");
5328 return -1;
5329 }
5330
5331
5332 for ( uint64_t t=0; t<firstNodeEdges->
numEdges; t++ )
5333 {
5335 {
5336 edge = &(firstNodeEdges->
edges[t]);
5337 break;
5338 }
5339 }
5340
5356 );
5357
5358 int ret;
5359
5360 uint64_t n;
5363
5365 for ( n=0; n<2; ++n)
5366 {
5367 int forward;
5368
5370 if ( existingEdgeId == -1 )
5371 {
5372
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
5381
5382
5384 if ( n == 1 ) {
5387 pt,
5388 0,
5389 1,
5390 &op
5391 );
5392 if (!ret)
5393 {
5394 lwerror(
"No distinct vertices found on second part of split edge");
5395 return -1;
5396 }
5397 } else {
5400 pa,
5401 pt,
5403 -1,
5404 &op
5405 );
5406 if (!ret)
5407 {
5408 lwerror(
"No distinct vertices found on first part of split edge");
5409 return -1;
5410 }
5411 }
5412 if ( !
azimuth_pt_pt(pt, &op, &(splitNodeEdgeEnds[n].myaz)) ) {
5413 lwerror(
"error computing azimuth of split endpoint [%.15g %.15g,%.15g %.15g]",
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);
5422 if ( ! ret ) {
5423 lwerror(
"Unexpected backend return: _lwt_FindAdjacentEdges(%"
5424 LWTFMT_ELEMID ") found no edges when we previously split edge %"
5427 return -1;
5428 }
5431 n, edge->
edge_id, splitNodeEdgeEnds[n].nextCW, splitNodeEdgeEnds[n].nextCCW);
5432 }
5433 }
5434 else
5435 {
5437 " (%s)", n, existingEdgeId, forward ? "forward" : "backward" );
5438
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
5459 int updateFlags;
5461
5462 if ( ( replacedBy[0] != 0 && replacedBy[1] == 0 ) ||
5463 ( replacedBy[1] != 0 && replacedBy[0] == 0 ) )
5464 {
5465
5466
5468 edgeend *splitNodeEdgeEndInfo;
5469 LWLINE *newSplitEdgeLine;
5470 int splitNodeNewEdgeOutgoing;
5471
5472 if ( replacedBy[1] == 0 )
5473
5474 {
5475 existingEdge = existingEdges[0];
5477 splitNodeEdgeEndInfo = &(splitNodeEdgeEnds[1]);
5478 splitNodeNewEdgeOutgoing = 1;
5479 }
5480 else
5481
5482 {
5483 existingEdge = existingEdges[1];
5485 splitNodeEdgeEndInfo = &(splitNodeEdgeEnds[0]);
5486 splitNodeNewEdgeOutgoing = 0;
5487 }
5488
5490
5502 );
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516 {
5518 if ( splitNodeNewEdgeOutgoing ) {
5521 } else {
5524 }
5525
5528 splitNodeEdgeEndInfo->
nextCCW,
5529 nextEdge, sideFace
5530 );
5531
5532 if ( splitNodeEdgeEndInfo->
nextCCW > 0 )
5533 {
5542 nextEdge, sideFace
5543 );
5544 }
5545 else
5546 {
5555 nextEdge, sideFace
5556 );
5557 }
5558
5561 &updatedEdge, updateFlags,
5562 NULL, 0);
5563 if ( ret == -1 ) {
5565 return -1;
5566 } else if ( ret == 0 ) {
5568 return -1;
5569 } else if ( ret > 1 ) {
5570 lwerror(
"More than a single edge found with id %"
5572 return -1;
5573 }
5574 }
5575
5576
5577 {
5579 if ( splitNodeNewEdgeOutgoing ) {
5581 } else {
5583 }
5584
5587 splitNodeEdgeEndInfo->
nextCW, sideFace
5588 );
5589
5590 if ( splitNodeEdgeEndInfo->
nextCW > 0 )
5591 {
5596 ", outgoing next CW of new split edge on split node",
5598 }
5599 else
5600 {
5605 ", incoming next CW of new split edge on split node",
5607 }
5608
5611 &updatedEdge, updateFlags,
5612 NULL, 0);
5613 if ( ret == -1 ) {
5615 return -1;
5616 } else if ( ret == 0 ) {
5618 return -1;
5619 } else if ( ret > 1 ) {
5620 lwerror(
"More than a single edge found with edge_id %"
5622 return -1;
5623 }
5624 }
5625
5626
5627
5628
5629
5630
5631
5633 int nextCCWEdgeIsIncoming = 0;
5634 int collapsedEdgeIsIncoming;
5635
5637
5639 if ( replacedBy[0] ) {
5640 commonNodeEdges = firstNodeEdges;
5642 collapsedEdgeIsIncoming = 0;
5643 } else {
5644 commonNodeEdges = lastNodeEdges;
5646 collapsedEdgeIsIncoming = 1;
5647 }
5648
5649
5650
5651 {
5653
5654 LWDEBUGF(1,
"Looking for next CCW edge of split edge %"
5656 " having %llu attached edges",
5658 commonNodeID, commonNodeEdges->
numEdges
5659 );
5660
5661
5662 for ( uint64_t t=0; t<commonNodeEdges->
numEdges; t++ )
5663 {
5665
5672 );
5673
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 {
5696 commonNodeID
5697 );
5698 return -1;
5699 }
5700
5701 LWDEBUGF(1,
"Next CCW edge of split edge %"
5705 commonNodeID,
5706 nextCCWEdgeIsIncoming ? "incoming" : "outgoing",
5707 nextCCWEdge->edge_id
5708 );
5709
5711 {
5712 LWDEBUG(1,
"Next CCW edge is existing/collapse edge, will not update here");
5713 }
5714 else
5715 {
5716
5717
5718
5719
5720
5721
5722
5723
5727
5729 if ( nextCCWEdgeIsIncoming ) {
5732 LWDEBUGF(1,
"Updating next_left of incoming next CCW edge %"
5736 newNextEdge
5737 );
5738 } else {
5741 LWDEBUGF(1,
"Updating next_right of outgoing next CCW edge %"
5745 newNextEdge
5746 );
5747 }
5750 &updatedEdge, updateFlags,
5751 NULL, 0);
5752 if ( ret == -1 ) {
5754 return -1;
5755 } else if ( ret == 0 ) {
5757 return -1;
5758 } else if ( ret > 1 ) {
5759 lwerror(
"More than a single edge found with next_left %"
5761 return -1;
5762 }
5763 }
5764 }
5765
5766
5767
5768
5769
5770
5771
5773 updateFlags = 0;
5775 {
5778 LWDEBUGF(1,
"Will update next_left of existing edge %"
5782 );
5783 }
5785 {
5788 LWDEBUGF(1,
"Will update next_right of existing edge %"
5792 );
5793 }
5795 {
5798 LWDEBUGF(1,
"Will update next_left of existing edge %"
5802 );
5803 }
5805 {
5808 LWDEBUGF(1,
"Will update next_right of existing edge %"
5812 );
5813 }
5814 if ( updateFlags )
5815 {
5818 &updatedEdge, updateFlags,
5819 NULL, 0);
5820 if ( ret == -1 ) {
5822 return -1;
5823 } else if ( ret == 0 ) {
5825 return -1;
5826 } else if ( ret > 1 ) {
5827 lwerror(
"More than a single edge found with id %"
5829 return -1;
5830 }
5831 }
5832
5833
5834
5835
5836
5837
5838
5840 updatedEdge.
geom = newSplitEdgeLine;
5842 if ( splitNodeNewEdgeOutgoing ) {
5853 );
5854 } else {
5862 ,
5866 );
5867 }
5868
5871 &updatedEdge, updateFlags,
5872 NULL, 0);
5873 if ( ret == -1 ) {
5875 return -1;
5876 } else if ( ret == 0 ) {
5878 return -1;
5879 } else if ( ret > 1 ) {
5880 lwerror(
"More than a single edge found with id %"
5882 return -1;
5883 }
5884
5885
5886
5887
5888
5889
5890
5892 {
5893
5897 {
5898
5899
5901 if ( ! fg )
5902 {
5904 return -1;
5905 }
5908 {
5910 if ( ret == -1 )
5911 {
5913 return -1;
5914 }
5916 }
5917 else
5918 {
5920 }
5921 }
5924 {
5925
5926
5928 if ( ! fg )
5929 {
5931 return -1;
5932 }
5935 {
5937 if ( ret == -1 )
5938 {
5940 return -1;
5941 }
5943 }
5944 else
5945 {
5947 }
5948 }
5949 }
5950
5951
5952
5953
5954
5955
5956
5960 );
5962 if ( ! ret ) {
5964 return -1;
5965 }
5966
5967 return 0;
5968 }
5969 else if ( replacedBy[0] == 0 && replacedBy[1] == 0 )
5970 {
5971
5972
5973
5974
5977 if ( newEdge.
edge_id == -1 ) {
5979 return -1;
5980 }
5987 } else {
5989 }
5992
5993
5998
5999
6001 for ( uint64_t t=0; t<splitNodeEdges->
numEdges; t++ )
6002 {
6004 }
6007
6009
6010
6011
6012
6014
6017 ee0->
outgoing ?
"outgoing" :
"incoming", ee0->edge->edge_id);
6020 } else {
6022 }
6023 int splitFaceOnLeft = 1;
6025 {
6026 splitFaceOnLeft = 0;
6027 }
6028
6031 ee1->
outgoing ?
"outgoing" :
"incoming", ee1->edge->edge_id);
6034 } else {
6036 }
6037
6039 if (ret != 1)
6040 {
6042 return -1;
6043 }
6044
6045
6050 NULL, 0);
6051 if ( ret == -1 ) {
6053 return -1;
6054 } else if ( ret == 0 ) {
6056 return -1;
6057 } else if ( ret > 1 ) {
6058 lwerror(
"More than a single edge found with id %"
6060 return -1;
6061 }
6062
6063
6066 ee0->
outgoing ?
"outgoing" :
"incoming", ee0->edge->edge_id);
6068 {
6073 } else {
6076 }
6077
6082 &updatedEdge, updateFlags,
6083 NULL, 0);
6084 if ( ret == -1 ) {
6086 return -1;
6087 } else if ( ret == 0 ) {
6089 return -1;
6090 } else if ( ret > 1 ) {
6091 lwerror(
"More than a single edge found with id %"
6093 return -1;
6094 }
6095 }
6096
6097
6100 ee1->
outgoing ?
"outgoing" :
"incoming", ee1->edge->edge_id);
6102 {
6107 } else {
6110 }
6111
6116 &updatedEdge, updateFlags,
6117 NULL, 0);
6118 if ( ret == -1 ) {
6120 return -1;
6121 } else if ( ret == 0 ) {
6123 return -1;
6124 } else if ( ret > 1 ) {
6125 lwerror(
"More than a single edge found with id %"
6127 return -1;
6128 }
6129 }
6130
6131
6132
6133 updateFlags = 0;
6134 for ( uint64_t t=0; t<lastNodeEdges->
numEdges; t++ )
6135 {
6138 {
6143 }
6144 break;
6145 }
6147 {
6152 }
6153 break;
6154 }
6155 }
6156 if ( updateFlags != 0 )
6157 {
6163 &updatedEdge, updateFlags,
6164 NULL, 0);
6165 if ( ret == -1 ) {
6167 return -1;
6168 } else if ( ret == 0 ) {
6170 return -1;
6171 } else if ( ret > 1 ) {
6172 lwerror(
"More than a single edge found with id %"
6174 return -1;
6175 }
6176 }
6177
6178
6182 if ( splitFaceOnLeft ) {
6183
6185
6190
6191
6192
6197
6198
6199 } else {
6200
6202
6206 -newEdge.
edge_id, newFaceId1);
6207
6208
6209
6214
6215 }
6216
6217
6218
6219
6220
6221
6222
6224 if ( ! ret ) {
6226 return -1;
6227 }
6228
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 {
6247 int nids = 1;
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
6261
6262
6264 {
6269 return -1;
6270 }
6271
6274
6276
6277
6280 } else {
6281
6282
6285 }
6286
6287
6288
6289
6290
6291 updateFlags = 0;
6292 for ( uint64_t t=0; t<firstNodeEdges->
numEdges; t++ )
6293 {
6297 {
6304 }
6305
6306 break;
6307 }
6309 {
6316 }
6317
6318 break;
6319 }
6320 }
6321 if ( updateFlags != 0 )
6322 {
6328 &updatedEdge, updateFlags,
6329 NULL, 0);
6330 if ( ret == -1 ) {
6332 return -1;
6333 } else if ( ret == 0 ) {
6335 return -1;
6336 } else if ( ret > 1 ) {
6337 lwerror(
"More than a single edge found with id %"
6339 return -1;
6340 }
6341 }
6342
6343
6344 updateFlags = 0;
6345 for ( uint64_t t=0; t<lastNodeEdges->
numEdges; t++ )
6346 {
6350 {
6357 }
6358 break;
6359 }
6361 {
6368 }
6369 break;
6370 }
6371 }
6372 if ( updateFlags != 0 )
6373 {
6379 &updatedEdge, updateFlags,
6380 NULL, 0);
6381 if ( ret == -1 ) {
6383 return -1;
6384 } else if ( ret == 0 ) {
6386 return -1;
6387 } else if ( ret > 1 ) {
6388 lwerror(
"More than a single edge found with id %"
6390 return -1;
6391 }
6392 }
6393
6395 {
6396
6397
6398
6403 } else {
6407 }
6410 selEdge.edge_id,
6414 &updatedEdge, updateFlags,
6415 NULL, 0);
6416 if ( ret == -1 ) {
6418 return -1;
6419 } else if ( ret == 0 ) {
6421 return -1;
6422 } else if ( ret > 1 ) {
6423 lwerror(
"More than a single edge found with id %"
6425 return -1;
6426 }
6427 }
6428 else
6429 {
6430
6431
6432
6437 } else {
6441 }
6444 selEdge.edge_id,
6448 &updatedEdge, updateFlags,
6449 NULL, 0);
6450 if ( ret == -1 ) {
6452 return -1;
6453 } else if ( ret == 0 ) {
6455 return -1;
6456 } else if ( ret > 1 ) {
6457 lwerror(
"More than a single edge found with id %"
6459 return -1;
6460 }
6461 }
6462
6463
6467 if ( ret == -1 ) {
6469 return -1;
6470 }
6471
6472
6474 int nids = 1;
6476 if ( ret == -1 ) {
6478 return -1;
6479 }
6480
6481
6483 {
6485 return -1;
6486 }
6487
6488 return 0;
6489 }
6490
6491
6495
6496 return -1;
6497}
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