7117{
7120 uint32_t ngeoms;
7126 uint64_t num, numedges = 0, numnodes = 0;
7127 uint64_t i;
7129 int forward;
7130 int input_was_closed = 0;
7132
7134 {
7135 *nedges = 0;
7136 return NULL;
7137 }
7138
7140 {
7141 input_was_closed = 1;
7143 LWDEBUGF(1,
"Input line is closed, original point is %g,%g", originalStartPoint.
x, originalStartPoint.
y);
7144 }
7145
7146 *nedges = -1;
7147
7148
7150 LWDEBUGF(1,
"Working tolerance:%.15g", tol);
7152
7153
7154 if ( tol )
7155 {{
7158 LWDEBUGG(1, tmp,
"Repeated-point removed");
7159 }}
else tmp=(
LWGEOM*)line;
7160
7161
7164 if ( ! noded ) return NULL;
7166
7171 LWDEBUGF(1,
"BOX expanded by %g is %.15g %.15g, %.15g %.15g",
7173
7175 int nearbyindex = 0;
7176 int nearbycount = 0;
7177
7178
7180 if (numedges == UINT64_MAX)
7181 {
7184 return NULL;
7185 }
7186 LWDEBUGF(1,
"Line has %u points, its bbox intersects %llu edges bboxes",
7187 line->points->npoints, numedges);
7188 if ( numedges )
7189 {{
7190
7192
7193 nearbycount += numedges;
7195 for (i=0; i<numedges; ++i)
7196 {{
7202 double dist;
7203 if ( 0 == GEOSDistanceIndexed(edge_g, noded_g, &dist) ) {
7204 GEOSGeom_destroy(edge_g);
7205 GEOSGeom_destroy(noded_g);
7208 return NULL;
7209 }
7210 GEOSGeom_destroy(edge_g);
7211 if ( dist && dist >= tol ) continue;
7212 nearby[nearbyindex++] = g;
7213 }}
7214 LWDEBUGF(1,
"Found %d edges closer than tolerance (%g)", nearbyindex, tol);
7215 GEOSGeom_destroy(noded_g);
7216 }}
7217 int nearbyedgecount = nearbyindex;
7218
7219
7220
7221
7222
7224 if (numnodes == UINT64_MAX)
7225 {
7228 return NULL;
7229 }
7230 LWDEBUGF(1,
"Line bbox intersects %llu nodes bboxes", numnodes);
7231 if ( numnodes )
7232 {{
7233
7234 nearbycount = nearbyedgecount + numnodes;
7235 nearby = nearby ?
7237 :
7239 ;
7240 int nn = 0;
7241 for (i=0; i<numnodes; ++i)
7242 {
7247
7248 if ( dist && dist >= tol )
7249 {
7251 continue;
7252 }
7253 nearby[nearbyindex++] = g;
7254 nn = nn + 1;
7255 }
7256 LWDEBUGF(1,
"Found %d isolated nodes closer than tolerance (%g)", nn, tol);
7257 }}
7258 int nearbynodecount = nearbyindex - nearbyedgecount;
7259 nearbycount = nearbyindex;
7260
7261 LWDEBUGF(1,
"Number of nearby elements is %d", nearbycount);
7262
7263
7264 if ( nearbycount )
7265 {{
7268
7270 NULL, nearbycount, nearby);
7272
7273 LWDEBUGG(1, elems,
"Collected nearby elements");
7274
7277 noded = tmp;
7278 LWDEBUGG(1, noded,
"Elements-snapped");
7279 if ( input_was_closed )
7280 {{
7281
7283 if (scrolled)
7284 {
7286 LWDEBUGF(1,
"Closed input line start point after snap %g,%g", originalStartPoint.
x, originalStartPoint.
y);
7287 }
7288 }}
7289
7290
7292
7293
7294
7295
7296
7297
7300 noded = tmp;
7301 LWDEBUGG(1, noded,
"Unary-unioned");
7302 }}
7303
7304
7305 if ( nearbyedgecount )
7306 {{
7310
7311 LWDEBUGF(1,
"Line intersects %d edges", nearbyedgecount);
7312
7314 NULL, nearbyedgecount, nearby);
7316 LWDEBUGG(1, iedges,
"Collected edges");
7317
7318 LWDEBUGF(1,
"Diffing noded, with srid=%d "
7319 "and intersecting edges, with srid=%d",
7323
7324 LWDEBUGF(1,
"Intersecting noded, with srid=%d "
7325 "and intersecting edges, with srid=%d",
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345 LWDEBUG(1,
"Linemerging intersection");
7349 xset = tmp;
7350
7351
7352
7353
7354
7355 LWDEBUG(1,
"Unioning difference and (linemerged) intersection");
7357 LWDEBUGG(1, noded,
"Diff-Xset Unioned");
7360
7361
7363
7364 if ( input_was_closed )
7365 {{
7367 if (scrolled) {
7370 }
7371 else {
7373 }
7374 }
7375 else {
7376 LWDEBUGG(1, noded,
"Diff-Xset Unioned cannot be scrolled");
7377 }
7378 }}
7379
7380
7381 }}
7382
7383
7384
7385
7386
7387
7388
7389 if ( nearbyedgecount )
7390 {
7391 nearbycount += nearbyedgecount * 2;
7393 for (int i=0; i<nearbyedgecount; i++)
7394 {
7398
7400 nearbynodecount++;
7402 nearbynodecount++;
7403 }
7404 }
7405 if ( nearbynodecount )
7406 {
7408 NULL, nearbynodecount,
7409 nearby + nearbyedgecount);
7411
7414 noded = tmp;
7416
7418 }
7419
7420
7421 LWDEBUG(1,
"Freeing up nearby elements");
7422
7423
7424 if ( nearby )
lwfree(nearby);
7427
7428 LWDEBUGG(2, noded,
"Finally-noded");
7429
7430
7432 if ( col )
7433 {
7434 LWDEBUG(1,
"Noded line was a collection");
7437 }
7438 else
7439 {
7440 LWDEBUG(1,
"Noded line was a single geom");
7441 geomsbuf[0] = noded;
7442 geoms = geomsbuf;
7443 ngeoms = 1;
7444 }
7445
7446 LWDEBUGF(1,
"Line was split into %d edges", ngeoms);
7447
7448
7449
7450
7451
7453 num = 0;
7454 for ( i=0; i<ngeoms; ++i )
7455 {
7459
7460#if POSTGIS_DEBUG_LEVEL > 0
7461 {
7462 size_t sz;
7464 LWDEBUGF(1,
"Component %llu of split line is: %s", i, wkt1);
7466 }
7467#endif
7468
7471 if ( id < 0 )
7472 {
7475 return NULL;
7476 }
7477 if ( ! id )
7478 {
7479 LWDEBUGF(1,
"Component %llu of split line collapsed", i);
7480 continue;
7481 }
7482
7484 i, forward ? "forward" : "backward", id);
7485 ids[num++] = forward ? id : -id;
7486 }
7487
7488 LWDEBUGG(2, noded,
"Noded before free");
7490
7491
7492
7493 *nedges = num;
7494 return ids;
7495}
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_ELEMID _lwt_AddLineEdge(LWT_TOPOLOGY *topo, LWLINE *edge, double tol, int handleFaceSplit, int *forward)
static LWT_ISO_NODE * lwt_be_getNodeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
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