PostGIS 3.6.2dev-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 5205 of file lwgeom_topo.c.

5206{
5207 // build the motion range shape: splitC->geoms[0] + splitC->geoms[1] - edge->geom
5208 POINTARRAY *motionRange = ptarray_clone_deep(lwgeom_as_lwline(splitC->geoms[0])->points);
5209 ptarray_append_ptarray(motionRange, lwgeom_as_lwline(splitC->geoms[1])->points, 0);
5210 POINTARRAY *reverseNewLine = ptarray_clone_deep(edge->geom->points);
5211 ptarray_reverse_in_place(reverseNewLine);
5212 ptarray_append_ptarray(motionRange, reverseNewLine, 0);
5213 ptarray_free(reverseNewLine);
5214
5215 // motionBounds takes ownership of motionRange
5216 LWLINE *motionBounds = lwline_construct(topo->srid, NULL, motionRange);
5217
5218 // motionPolyBare takes ownership of motionBounds
5219 LWGEOM *motionPolyBare = (LWGEOM *)lwpoly_from_lwlines(motionBounds, 0, NULL);
5220 LWGEOM *motionPoly = lwgeom_make_valid(motionPolyBare);
5221 lwgeom_free(motionPolyBare);
5222
5223 LWDEBUGG(1, motionPoly, "Motion range");
5224
5225 // check the Motion range doesn't cover any of
5226 // the edges incident to the split node other
5227 // than the existing edge
5228 GEOSGeometry *motionPolyG = NULL;
5229 for ( uint64_t t=0; t<splitNodeEdges->numEdges; t++ )
5230 {
5231 LWT_ISO_EDGE *e = &(splitNodeEdges->edges[t]);
5232 GEOSGeometry *eg;
5233 if ( e == existingEdge ) continue;
5234 if ( e == edge ) continue;
5235 if ( ! motionPolyG ) {
5236 motionPolyG = LWGEOM2GEOS( motionPoly, 0 );
5237 if ( ! motionPolyG )
5238 {
5239 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
5240 return -1;
5241 }
5242 }
5243 eg = LWGEOM2GEOS( lwline_as_lwgeom(e->geom), 0 );
5244 if ( ! eg )
5245 {
5246 GEOSGeom_destroy(motionPolyG);
5247 lwgeom_free(motionPoly);
5248 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
5249 return -1;
5250 }
5251
5252 char *relate = GEOSRelate( motionPolyG, eg );
5253 GEOSGeom_destroy(eg);
5254 if ( ! relate )
5255 {
5256 GEOSGeom_destroy(motionPolyG);
5257 lwgeom_free(motionPoly);
5258 lwerror("Relate error: %s", lwgeom_geos_errmsg);
5259 return -1;
5260 }
5261
5262 int match = GEOSRelatePatternMatch(relate, "FF*F*****");
5263 GEOSFree( relate );
5264 if (match == 2)
5265 {
5266 GEOSGeom_destroy(motionPolyG);
5267 lwgeom_free(motionPoly);
5268 lwerror("RelateMatch error: %s", lwgeom_geos_errmsg);
5269 return -1;
5270 }
5271 if ( ! match )
5272 {
5273 GEOSGeom_destroy(motionPolyG);
5274 lwgeom_free(motionPoly);
5275 lwerror("snapping edge %" LWTFMT_ELEMID
5276 " to new node moves it past edge %" LWTFMT_ELEMID,
5277 edge->edge_id, e->edge_id
5278 );
5279 return -1;
5280 }
5281 }
5282 if ( motionPolyG ) GEOSGeom_destroy(motionPolyG);
5283
5284 lwgeom_free(motionPoly);
5285
5286 return 0;
5287}
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:1218
LWPOLY * lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes)
Definition lwpoly.c:360
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:339
void ptarray_free(POINTARRAY *pa)
Definition ptarray.c:327
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:179
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: