7255{
7258 uint32_t ngeoms;
7264 uint64_t num, numedges = 0, numnodes = 0;
7265 int num_new_edges = 0;
7266 uint64_t i;
7268 int forward;
7269 int input_was_closed = 0;
7271
7273 {
7274 *nedges = 0;
7275 return NULL;
7276 }
7277
7279 {
7280 input_was_closed = 1;
7282 LWDEBUGF(1,
"Input line is closed, original point is %g,%g", originalStartPoint.
x, originalStartPoint.
y);
7283 }
7284
7285 *nedges = -1;
7286
7287
7289 LWDEBUGF(1,
"Working tolerance:%.15g", tol);
7291
7292
7293 if ( tol )
7294 {{
7297 LWDEBUGG(1, tmp,
"Repeated-point removed");
7298 }}
else tmp=(
LWGEOM*)line;
7299
7300
7303 if ( ! noded ) return NULL;
7305
7310 LWDEBUGF(1,
"BOX expanded by %g is %.15g %.15g, %.15g %.15g",
7312
7314 int nearbyindex = 0;
7315 int nearbycount = 0;
7316
7317
7319 if (numedges == UINT64_MAX)
7320 {
7323 return NULL;
7324 }
7325 LWDEBUGF(1,
"Line has %u points, its bbox intersects %llu edges bboxes",
7326 line->points->npoints, numedges);
7327 if ( numedges )
7328 {{
7329
7331
7332 nearbycount += numedges;
7334 for (i=0; i<numedges; ++i)
7335 {{
7341 double dist;
7342 if ( 0 == GEOSDistanceIndexed(edge_g, noded_g, &dist) ) {
7343 GEOSGeom_destroy(edge_g);
7344 GEOSGeom_destroy(noded_g);
7347 return NULL;
7348 }
7349 GEOSGeom_destroy(edge_g);
7350 if ( dist && dist >= tol ) continue;
7351 nearby[nearbyindex++] = g;
7352 }}
7353 LWDEBUGF(1,
"Found %d edges closer than tolerance (%g)", nearbyindex, tol);
7354 GEOSGeom_destroy(noded_g);
7355 }}
7356 int nearbyedgecount = nearbyindex;
7357
7358
7359
7360
7361
7363 if (numnodes == UINT64_MAX)
7364 {
7367 return NULL;
7368 }
7369 LWDEBUGF(1,
"Line bbox intersects %llu nodes bboxes", numnodes);
7370 if ( numnodes )
7371 {{
7372
7373 nearbycount = nearbyedgecount + numnodes;
7374 nearby = nearby ?
7376 :
7378 ;
7379 int nn = 0;
7380 for (i=0; i<numnodes; ++i)
7381 {
7386
7387 if ( dist && dist >= tol )
7388 {
7390 continue;
7391 }
7392 nearby[nearbyindex++] = g;
7393 nn = nn + 1;
7394 }
7395 LWDEBUGF(1,
"Found %d isolated nodes closer than tolerance (%g)", nn, tol);
7396 }}
7397 int nearbynodecount = nearbyindex - nearbyedgecount;
7398 nearbycount = nearbyindex;
7399
7400 LWDEBUGF(1,
"Number of nearby elements is %d", nearbycount);
7401
7402
7403 if ( nearbycount )
7404 {{
7407
7409 NULL, nearbycount, nearby);
7411
7412 LWDEBUGG(1, elems,
"Collected nearby elements");
7413
7416 noded = tmp;
7417 LWDEBUGG(1, noded,
"Elements-snapped");
7418 if ( input_was_closed )
7419 {{
7420
7422 if (scrolled)
7423 {
7425 LWDEBUGF(1,
"Closed input line start point after snap %g,%g", originalStartPoint.
x, originalStartPoint.
y);
7426 }
7427 }}
7428
7429
7431
7432
7433
7434
7435
7436
7439 noded = tmp;
7440 LWDEBUGG(1, noded,
"Unary-unioned");
7441 }}
7442
7443
7444 if ( nearbyedgecount )
7445 {{
7449
7450 LWDEBUGF(1,
"Line intersects %d edges", nearbyedgecount);
7451
7453 NULL, nearbyedgecount, nearby);
7455 LWDEBUGG(1, iedges,
"Collected edges");
7456
7457 LWDEBUGF(1,
"Diffing noded, with srid=%d "
7458 "and intersecting edges, with srid=%d",
7462
7463 LWDEBUGF(1,
"Intersecting noded, with srid=%d "
7464 "and intersecting edges, with srid=%d",
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484 LWDEBUG(1,
"Linemerging intersection");
7488 xset = tmp;
7489
7490
7491
7492
7493
7494 LWDEBUG(1,
"Unioning difference and (linemerged) intersection");
7496 LWDEBUGG(1, noded,
"Diff-Xset Unioned");
7499
7500
7502
7503 if ( input_was_closed )
7504 {{
7506 if (scrolled) {
7509 }
7510 else {
7512 }
7513 }
7514 else {
7515 LWDEBUGG(1, noded,
"Diff-Xset Unioned cannot be scrolled");
7516 }
7517 }}
7518
7519
7520 }}
7521
7522
7523
7524
7525
7526
7527
7528 if ( nearbyedgecount )
7529 {
7530 nearbycount += nearbyedgecount * 2;
7532 for (int i=0; i<nearbyedgecount; i++)
7533 {
7537
7539 nearbynodecount++;
7541 nearbynodecount++;
7542 }
7543 }
7544 if ( nearbynodecount )
7545 {
7547 NULL, nearbynodecount,
7548 nearby + nearbyedgecount);
7550
7553 noded = tmp;
7555
7557 }
7558
7559
7560 LWDEBUG(1,
"Freeing up nearby elements");
7561
7562
7563 if ( nearby )
lwfree(nearby);
7566
7567 LWDEBUGG(2, noded,
"Finally-noded");
7568
7569
7571 if ( col )
7572 {
7573 LWDEBUG(1,
"Noded line was a collection");
7576 }
7577 else
7578 {
7579 LWDEBUG(1,
"Noded line was a single geom");
7580 geomsbuf[0] = noded;
7581 geoms = geomsbuf;
7582 ngeoms = 1;
7583 }
7584
7585 LWDEBUGF(1,
"Line was split into %d edges", ngeoms);
7586
7587
7588
7589
7590
7592 num = 0;
7593 for ( i=0; i<ngeoms; ++i )
7594 {
7595 int edgeNewEdges;
7599
7600#if POSTGIS_DEBUG_LEVEL > 0
7601 {
7602 size_t sz;
7604 LWDEBUGF(1,
"Component %llu of split line is: %s", i, wkt1);
7606 }
7607#endif
7608
7609 forward = -1;
7611 num_new_edges += edgeNewEdges;
7612
7613 if ( forward == -1 )
7614 {
7615 ++num_new_edges;
7616 }
7617
7619 " (forward ? %d), reported to create %d new edges (total new edges: %d)",
7620 id, forward, edgeNewEdges, num_new_edges);
7621 if ( id < 0 )
7622 {
7625 return NULL;
7626 }
7627
7628 if ( maxNewEdges >= 0 && num_new_edges > maxNewEdges )
7629 {
7632 lwerror(
"Adding line to topology requires creating more edges than the requested limit of %d", maxNewEdges);
7633 return NULL;
7634 }
7635
7636 if ( ! id )
7637 {
7638 LWDEBUGF(1,
"Component %llu of split line collapsed", i);
7639 continue;
7640 }
7641
7643 i, forward ? "forward" : "backward", id);
7644 ids[num++] = forward ? id : -id;
7645 }
7646
7647 LWDEBUGG(2, noded,
"Noded before free");
7649
7650
7651
7652 *nedges = num;
7653 return ids;
7654}
void gbox_expand(GBOX *g, double d)
Move the box minimums down and the maximums up by the distance provided.
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
LWGEOM * lwgeom_unaryunion(const LWGEOM *geom1)
void * lwrealloc(void *mem, size_t size)
LWGEOM * lwgeom_node(const LWGEOM *lwgeom_in)
LWGEOM * lwgeom_linemerge(const LWGEOM *geom1)
void lwgeom_free(LWGEOM *geom)
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
void * lwalloc(size_t size)
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2)
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
LWGEOM * lwgeom_difference(const LWGEOM *geom1, const LWGEOM *geom2)
void lwcollection_release(LWCOLLECTION *lwcollection)
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initializing min distance calculation.
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
LWGEOM * lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
LWGEOM * lwline_remove_repeated_points(const LWLINE *in, double tolerance)
int lwline_is_empty(const LWLINE *line)
#define LW_ON_INTERRUPT(x)
int lwline_is_closed(const LWLINE *line)
int ptarray_scroll_in_place(POINTARRAY *pa, const POINT4D *newbase)
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#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.
#define LWDEBUGG(level, geom, msg)
static LWGEOM * _lwt_toposnap(LWGEOM *src, LWGEOM *tgt, double tol)
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
static LWGEOM * _lwt_split_by_nodes(const LWGEOM *g, const LWGEOM *nodes)
void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
#define _LWT_MINTOLERANCE(topo, geom)
static LWT_ISO_NODE * lwt_be_getNodeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
static LWT_ELEMID _lwt_AddLineEdge(LWT_TOPOLOGY *topo, LWLINE *edge, double tol, int handleFaceSplit, int *forward, int *numNewEdges)
LWT_ISO_EDGE * lwt_be_getEdgeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
LWT_ELEMID containing_face