Changes the shape of an edge without affecting the topology structure.
3378{
3382 uint64_t i;
3383 int isclosed = 0;
3384 int leftRingIsCCW = -1;
3385
3386
3388 {
3389 lwerror(
"SQL/MM Spatial exception - curve not simple");
3390 return -1;
3391 }
3392
3393 i = 1;
3395 if ( ! oldedge )
3396 {
3398 "lwt_be_getEdgeById returned NULL and set i=%llu", i);
3399 if (i == UINT64_MAX)
3400 {
3402 return -1;
3403 }
3404 else if ( i == 0 )
3405 {
3406 lwerror(
"SQL/MM Spatial exception - non-existent edge %"
3408 return -1;
3409 }
3410 else
3411 {
3412 lwerror(
"Backend coding error: getEdgeById callback returned NULL "
3413 "but numelements output parameter has value %" PRIu64 " "
3414 "(expected 0 or 1)", i);
3415 return -1;
3416 }
3417 }
3418
3420 "old edge has %d points, new edge has %d points",
3422
3423
3424
3425
3429 {
3431 lwerror(
"SQL/MM Spatial exception - "
3432 "start node not geometry start point.");
3433 return -1;
3434 }
3435
3436
3437
3438
3440 {
3443 " has less than 2 vertices", oldedge->
edge_id);
3444 return -1;
3445 }
3448 {
3450 lwerror(
"Invalid edge: less than 2 vertices");
3451 return -1;
3452 }
3455 {
3457 lwerror(
"SQL/MM Spatial exception - "
3458 "end node not geometry end point.");
3459 return -1;
3460 }
3461
3462
3463
3464
3465
3467 {
3468 isclosed = 1;
3469#if 1
3470
3472 {
3474 lwerror(
"Invalid edge (no two distinct vertices exist)");
3475 return -1;
3476 }
3477#endif
3478
3481 {
3483 lwerror(
"Edge twist at node POINT(%g %g)", p1.
x, p1.
y);
3484 return -1;
3485 }
3486 }
3487
3489 oldedge->
end_node, geom, edge_id ) )
3490 {
3491
3493 return -1;
3494 }
3495
3496 LWDEBUG(1,
"lwt_ChangeEdgeGeom: "
3497 "edge crossing check passed ");
3498
3499
3500
3501
3502
3503
3504
3505
3510
3512 uint64_t numnodes;
3515 LWDEBUGF(1,
"lwt_be_getNodeWithinBox2D returned %llu nodes", numnodes);
3516 if (numnodes == UINT64_MAX)
3517 {
3520 return -1;
3521 }
3522
3523 if ( numnodes > ( 1 + isclosed ? 0 : 1 ) )
3524 {{
3525
3526 for (i=0; i<numnodes; ++i)
3527 {
3534 if (ocont != ncont)
3535 {
3536 size_t sz;
3539 lwerror(
"Edge motion collision at %s", wkt);
3541 return -1;
3542 }
3543 }
3544 }}
3546
3547 LWDEBUG(1,
"nodes containment check passed");
3548
3549
3550
3551
3552
3553
3555
3557 if (res)
3558 return -1;
3560 isclosed ? &epan_pre : NULL, edge_id );
3562 isclosed ? &span_pre : NULL, edge_id );
3563
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580 if ( ! isclosed &&
3584 {{
3585 uint64_t num_signed_edge_ids;
3588
3589 LWDEBUG(1,
"Twist check before");
3591
3592 if (!signed_edge_ids)
3593 {
3594
3596 return -1;
3597 }
3598 LWDEBUGF(1,
"getRingEdges returned %llu edges", num_signed_edge_ids);
3599
3601 if ( ! shell ) {
3602 lwfree( signed_edge_ids );
3603
3605 return -1;
3606 }
3607
3610 {
3612 lwfree( signed_edge_ids );
3614 " is geometrically not-closed", edge_id);
3615 return -1;
3616 }
3617
3620 lwfree( signed_edge_ids );
3621
3622 LWDEBUGF(1,
"Ring of edge %" LWTFMT_ELEMID " is %sclockwise", edge_id, leftRingIsCCW ?
"counter" :
"");
3623 }}
3624
3625
3626
3628 newedge.
geom = geom;
3630 if (res == -1)
3631 {
3634 return -1;
3635 }
3636 if (!res)
3637 {
3639 lwerror(
"Unexpected error: %" PRIu64
" edges updated when expecting 1", i);
3640 return -1;
3641 }
3642
3643
3644
3645
3647
3649 if (res)
3650 return -1;
3652 isclosed ? &epan_post : NULL, edge_id );
3654 isclosed ? &span_post : NULL, edge_id );
3655
3661
3662
3663
3666 {{
3669 lwerror(
"Edge changed disposition around start node %"
3671 return -1;
3672 }}
3673
3674
3677 {{
3680 lwerror(
"Edge changed disposition around end node %"
3682 return -1;
3683 }}
3684
3685
3686 if ( leftRingIsCCW != -1 )
3687 {{
3688 uint64_t num_signed_edge_ids;
3691 int isCCW;
3692
3693 LWDEBUG(1,
"Twist check after");
3695
3696 if (!signed_edge_ids)
3697 {
3698
3700 return -1;
3701 }
3702 LWDEBUGF(1,
"getRingEdges returned %llu edges", num_signed_edge_ids);
3703
3705 if ( ! shell ) {
3706 lwfree( signed_edge_ids );
3707
3709 return -1;
3710 }
3711
3714 {
3716 lwfree( signed_edge_ids );
3718 " is geometrically not-closed", edge_id);
3719 return -1;
3720 }
3721
3724 lwfree( signed_edge_ids );
3725
3726 if ( isCCW != leftRingIsCCW )
3727 {
3729 lwerror(
"Edge ring changes winding");
3730 return -1;
3731 }
3732 }}
3733
3734
3735
3736
3737
3738
3739
3740
3741
3749 {
3751 uint64_t facestoupdate = 0;
3754 {
3756 if ( ! updatedBox )
3757 {
3761 return -1;
3762 }
3764
3765 faces[facestoupdate++].
mbr = updatedBox;
3766 }
3768
3770 {
3772 if ( ! updatedBox )
3773 {
3774 lwerror(
"Corrupted topology: face %"
3777 return -1;
3778 }
3780
3781 faces[facestoupdate++].
mbr = updatedBox;
3782 }
3783 LWDEBUGF(1,
"%llu faces to update", facestoupdate);
3784 if ( facestoupdate )
3785 {
3787 if (updatedFaces != facestoupdate)
3788 {
3789 while ( facestoupdate-- )
lwfree(faces[facestoupdate].mbr);
3791 if (updatedFaces == UINT64_MAX)
3793 else
3794 lwerror(
"Unexpected error: %" PRIu64
" faces updated when expecting 1", updatedFaces);
3795 return -1;
3796 }
3797 }
3798 while ( facestoupdate-- )
lwfree(faces[facestoupdate].mbr);
3799 }
3800 else
3801 {
3802 LWDEBUG(1,
"BBOX of changed edge did not change");
3803 }
3804
3805 LWDEBUG(1,
"all done, cleaning up edges");
3806
3808 return 0;
3809}
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