PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ _lwt_SnapEdge_checkMotion()

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 
)
static

Check the motion of a snapped edge, invoke lwerror if the movement hits any other edge or node.

Parameters
topothe Topology we are working on
splitCthe result of the edge being split
edgethe edge before the split/snap
existingEdgean edge on which one component of the split edge collapsed, or null if no collapse happened.
splitNodeEdgesall edges attached to the split node

TODO: check that newSplitEdgeLine retains its position in the edge end star (see ticket #5786) TODO: check that the motion range does not contain any node

Definition at line 5322 of file lwgeom_topo.c.

5323{
5324 // build the motion range shape: splitC->geoms[0] + splitC->geoms[1] - edge->geom
5325 POINTARRAY *motionRange = ptarray_clone_deep(lwgeom_as_lwline(splitC->geoms[0])->points);
5326 ptarray_append_ptarray(motionRange, lwgeom_as_lwline(splitC->geoms[1])->points, 0);
5327 POINTARRAY *reverseNewLine = ptarray_clone_deep(edge->geom->points);
5328 ptarray_reverse_in_place(reverseNewLine);
5329 ptarray_append_ptarray(motionRange, reverseNewLine, 0);
5330 ptarray_free(reverseNewLine);
5331
5332 // motionBounds takes ownership of motionRange
5333 LWLINE *motionBounds = lwline_construct(topo->srid, NULL, motionRange);
5334
5335 // motionPolyBare takes ownership of motionBounds
5336 LWGEOM *motionPolyBare = (LWGEOM *)lwpoly_from_lwlines(motionBounds, 0, NULL);
5337 LWGEOM *motionPoly = lwgeom_make_valid(motionPolyBare);
5338 lwgeom_free(motionPolyBare);
5339
5340 LWDEBUGG(1, motionPoly, "Motion range");
5341
5342 // check the Motion range doesn't cover any of
5343 // the edges incident to the split node other
5344 // than the existing edge
5345 GEOSGeometry *motionPolyG = NULL;
5346 for ( uint64_t t=0; t<splitNodeEdges->numEdges; t++ )
5347 {
5348 LWT_ISO_EDGE *e = &(splitNodeEdges->edges[t]);
5349 GEOSGeometry *eg;
5350 if ( e == existingEdge ) continue;
5351 if ( e == edge ) continue;
5352 if ( ! motionPolyG ) {
5353 motionPolyG = LWGEOM2GEOS( motionPoly, 0 );
5354 if ( ! motionPolyG )
5355 {
5356 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
5357 return -1;
5358 }
5359 }
5360 eg = LWGEOM2GEOS( lwline_as_lwgeom(e->geom), 0 );
5361 if ( ! eg )
5362 {
5363 GEOSGeom_destroy(motionPolyG);
5364 lwgeom_free(motionPoly);
5365 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
5366 return -1;
5367 }
5368
5369 char *relate = GEOSRelate( motionPolyG, eg );
5370 GEOSGeom_destroy(eg);
5371 if ( ! relate )
5372 {
5373 GEOSGeom_destroy(motionPolyG);
5374 lwgeom_free(motionPoly);
5375 lwerror("Relate error: %s", lwgeom_geos_errmsg);
5376 return -1;
5377 }
5378
5379 int match = GEOSRelatePatternMatch(relate, "FF*F*****");
5380 GEOSFree( relate );
5381 if (match == 2)
5382 {
5383 GEOSGeom_destroy(motionPolyG);
5384 lwgeom_free(motionPoly);
5385 lwerror("RelateMatch error: %s", lwgeom_geos_errmsg);
5386 return -1;
5387 }
5388 if ( ! match )
5389 {
5390 GEOSGeom_destroy(motionPolyG);
5391 lwgeom_free(motionPoly);
5392 lwerror("snapping edge %" LWTFMT_ELEMID
5393 " to new node moves it past edge %" LWTFMT_ELEMID,
5394 edge->edge_id, e->edge_id
5395 );
5396 return -1;
5397 }
5398 }
5399 if ( motionPolyG ) GEOSGeom_destroy(motionPolyG);
5400
5401 lwgeom_free(motionPoly);
5402
5403 return 0;
5404}
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
int ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance)
Append a POINTARRAY, pa2 to the end of an existing POINTARRAY, pa1.
Definition ptarray.c:177
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
LWPOLY * lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes)
Definition lwpoly.c:359
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
void ptarray_free(POINTARRAY *pa)
Definition ptarray.c:327
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:207
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
Definition ptarray.c:643
void ptarray_reverse_in_place(POINTARRAY *pa)
Definition ptarray.c:339
#define LWTFMT_ELEMID
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
LWGEOM ** geoms
Definition liblwgeom.h:575
POINTARRAY * points
Definition liblwgeom.h:483
LWT_ELEMID edge_id
LWT_ISO_EDGE * edges

References LWT_ISO_EDGE::edge_id, LWT_NODE_EDGES_t::edges, LWT_ISO_EDGE::geom, LWCOLLECTION::geoms, LWDEBUGG, lwerror(), LWGEOM2GEOS(), lwgeom_as_lwline(), lwgeom_free(), lwgeom_geos_errmsg, lwgeom_make_valid(), lwline_as_lwgeom(), lwline_construct(), lwpoly_from_lwlines(), LWTFMT_ELEMID, LWT_NODE_EDGES_t::numEdges, LWLINE::points, ptarray_append_ptarray(), ptarray_clone_deep(), ptarray_free(), ptarray_reverse_in_place(), and LWT_TOPOLOGY_T::srid.

Referenced by _lwt_SnapEdgeToExistingNode().

Here is the call graph for this function:
Here is the caller graph for this function: