Changes the shape of an edge without affecting the topology structure.
3261{
3265 uint64_t i;
3266 int isclosed = 0;
3267 int leftRingIsCCW = -1;
3268
3269
3271 {
3272 lwerror(
"SQL/MM Spatial exception - curve not simple");
3273 return -1;
3274 }
3275
3276 i = 1;
3278 if ( ! oldedge )
3279 {
3281 "lwt_be_getEdgeById returned NULL and set i=%llu", i);
3282 if (i == UINT64_MAX)
3283 {
3285 return -1;
3286 }
3287 else if ( i == 0 )
3288 {
3289 lwerror(
"SQL/MM Spatial exception - non-existent edge %"
3291 return -1;
3292 }
3293 else
3294 {
3295 lwerror(
"Backend coding error: getEdgeById callback returned NULL "
3296 "but numelements output parameter has value %" PRIu64 " "
3297 "(expected 0 or 1)", i);
3298 return -1;
3299 }
3300 }
3301
3303 "old edge has %d points, new edge has %d points",
3305
3306
3307
3308
3312 {
3314 lwerror(
"SQL/MM Spatial exception - "
3315 "start node not geometry start point.");
3316 return -1;
3317 }
3318
3319
3320
3321
3323 {
3326 " has less than 2 vertices", oldedge->
edge_id);
3327 return -1;
3328 }
3331 {
3333 lwerror(
"Invalid edge: less than 2 vertices");
3334 return -1;
3335 }
3338 {
3340 lwerror(
"SQL/MM Spatial exception - "
3341 "end node not geometry end point.");
3342 return -1;
3343 }
3344
3345
3346
3347
3348
3350 {
3351 isclosed = 1;
3352#if 1
3353
3355 {
3357 lwerror(
"Invalid edge (no two distinct vertices exist)");
3358 return -1;
3359 }
3360#endif
3361
3364 {
3366 lwerror(
"Edge twist at node POINT(%g %g)", p1.
x, p1.
y);
3367 return -1;
3368 }
3369 }
3370
3372 oldedge->
end_node, geom, edge_id ) )
3373 {
3374
3376 return -1;
3377 }
3378
3379 LWDEBUG(1,
"lwt_ChangeEdgeGeom: "
3380 "edge crossing check passed ");
3381
3382
3383
3384
3385
3386
3387
3388
3393
3395 uint64_t numnodes;
3398 LWDEBUGF(1,
"lwt_be_getNodeWithinBox2D returned %llu nodes", numnodes);
3399 if (numnodes == UINT64_MAX)
3400 {
3403 return -1;
3404 }
3405
3406 if ( numnodes > ( 1 + isclosed ? 0 : 1 ) )
3407 {{
3408
3409 for (i=0; i<numnodes; ++i)
3410 {
3417 if (ocont != ncont)
3418 {
3419 size_t sz;
3422 lwerror(
"Edge motion collision at %s", wkt);
3424 return -1;
3425 }
3426 }
3427 }}
3429
3430 LWDEBUG(1,
"nodes containment check passed");
3431
3432
3433
3434
3435
3436
3438
3440 if (res)
3441 return -1;
3443 isclosed ? &epan_pre : NULL, edge_id );
3445 isclosed ? &span_pre : NULL, edge_id );
3446
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463 if ( ! isclosed &&
3467 {{
3468 uint64_t num_signed_edge_ids;
3471
3472 LWDEBUG(1,
"Twist check before");
3474
3475 if (!signed_edge_ids)
3476 {
3477
3479 return -1;
3480 }
3481 LWDEBUGF(1,
"getRingEdges returned %llu edges", num_signed_edge_ids);
3482
3484 if ( ! shell ) {
3485 lwfree( signed_edge_ids );
3486
3488 return -1;
3489 }
3490
3493 {
3495 lwfree( signed_edge_ids );
3497 " is geometrically not-closed", edge_id);
3498 return -1;
3499 }
3500
3503 lwfree( signed_edge_ids );
3504
3505 LWDEBUGF(1,
"Ring of edge %" LWTFMT_ELEMID " is %sclockwise", edge_id, leftRingIsCCW ?
"counter" :
"");
3506 }}
3507
3508
3509
3511 newedge.
geom = geom;
3513 if (res == -1)
3514 {
3517 return -1;
3518 }
3519 if (!res)
3520 {
3522 lwerror(
"Unexpected error: %" PRIu64
" edges updated when expecting 1", i);
3523 return -1;
3524 }
3525
3526
3527
3528
3530
3532 if (res)
3533 return -1;
3535 isclosed ? &epan_post : NULL, edge_id );
3537 isclosed ? &span_post : NULL, edge_id );
3538
3544
3545
3546
3549 {{
3552 lwerror(
"Edge changed disposition around start node %"
3554 return -1;
3555 }}
3556
3557
3560 {{
3563 lwerror(
"Edge changed disposition around end node %"
3565 return -1;
3566 }}
3567
3568
3569 if ( leftRingIsCCW != -1 )
3570 {{
3571 uint64_t num_signed_edge_ids;
3574 int isCCW;
3575
3576 LWDEBUG(1,
"Twist check after");
3578
3579 if (!signed_edge_ids)
3580 {
3581
3583 return -1;
3584 }
3585 LWDEBUGF(1,
"getRingEdges returned %llu edges", num_signed_edge_ids);
3586
3588 if ( ! shell ) {
3589 lwfree( signed_edge_ids );
3590
3592 return -1;
3593 }
3594
3597 {
3599 lwfree( signed_edge_ids );
3601 " is geometrically not-closed", edge_id);
3602 return -1;
3603 }
3604
3607 lwfree( signed_edge_ids );
3608
3609 if ( isCCW != leftRingIsCCW )
3610 {
3612 lwerror(
"Edge ring changes winding");
3613 return -1;
3614 }
3615 }}
3616
3617
3618
3619
3620
3621
3622
3623
3624
3632 {
3634 uint64_t facestoupdate = 0;
3637 {
3639 if ( ! updatedBox )
3640 {
3644 return -1;
3645 }
3647
3648 faces[facestoupdate++].
mbr = updatedBox;
3649 }
3651
3653 {
3655 if ( ! updatedBox )
3656 {
3657 lwerror(
"Corrupted topology: face %"
3660 return -1;
3661 }
3663
3664 faces[facestoupdate++].
mbr = updatedBox;
3665 }
3666 LWDEBUGF(1,
"%llu faces to update", facestoupdate);
3667 if ( facestoupdate )
3668 {
3670 if (updatedFaces != facestoupdate)
3671 {
3672 while ( facestoupdate-- )
lwfree(faces[facestoupdate].mbr);
3674 if (updatedFaces == UINT64_MAX)
3676 else
3677 lwerror(
"Unexpected error: %" PRIu64
" faces updated when expecting 1", updatedFaces);
3678 return -1;
3679 }
3680 }
3681 while ( facestoupdate-- )
lwfree(faces[facestoupdate].mbr);
3682 }
3683 else
3684 {
3685 LWDEBUG(1,
"BBOX of changed edge did not change");
3686 }
3687
3688 LWDEBUG(1,
"all done, cleaning up edges");
3689
3691 return 0;
3692}
int gbox_same(const GBOX *g1, const GBOX *g2)
Check if 2 given Gbox are the same.
int gbox_union(const GBOX *g1, const GBOX *g2, GBOX *gout)
Update the output GBOX to be large enough to include both inputs.
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
int lwgeom_is_simple(const LWGEOM *lwgeom)
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
int ptarray_is_closed_2d(const POINTARRAY *pa)
void lwpoly_free(LWPOLY *poly)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
#define LW_INSIDE
Constants for point-in-polygon return values.
int ptarray_isccw(const POINTARRAY *pa)
#define P2D_SAME_STRICT(a, b)
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#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.
static GBOX * lwt_be_computeFaceMBR(const LWT_TOPOLOGY *topo, LWT_ELEMID face)
static uint64_t lwt_be_updateFacesById(LWT_TOPOLOGY *topo, const LWT_ISO_FACE *faces, uint64_t numfaces)
static int _lwt_InitEdgeEndByLine(edgeend *fee, edgeend *lee, LWLINE *edge, POINT2D *fp, POINT2D *lp)
static int _lwt_GetInteriorEdgePoint(const LWLINE *edge, POINT2D *ip)
LWT_ISO_EDGE * lwt_be_getEdgeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
static int _lwt_CheckEdgeCrossing(LWT_TOPOLOGY *topo, LWT_ELEMID start_node, LWT_ELEMID end_node, const LWLINE *geom, LWT_ELEMID myself)
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
static LWT_ELEMID * lwt_be_getRingEdges(LWT_TOPOLOGY *topo, LWT_ELEMID edge, uint64_t *numedges, uint64_t limit)
void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
static LWPOLY * _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num_signed_edge_ids)
int lwt_be_updateEdgesById(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *edges, int numedges, int upd_fields)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
static LWT_ISO_NODE * lwt_be_getNodeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
static int _lwt_FindAdjacentEdges(LWT_TOPOLOGY *topo, LWT_ELEMID node, edgeend *data, edgeend *other, LWT_ELEMID myedge_id)
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_BE_IFACE * be_iface