PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ _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)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:179
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
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
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
Definition: ptarray.c:643
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:327
LWPOLY * lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes)
Definition: lwpoly.c:360
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
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
LWLINE * geom
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: