LWGEOM* lwgeom_sharedpaths(const LWGEOM* geom1, const LWGEOM* geom2) { #if POSTGIS_GEOS_VERSION < 33 lwerror("The GEOS version this postgis binary " "was compiled against (%d) doesn't support " "'SharedPaths' function (3.3.0+ required)", POSTGIS_GEOS_VERSION); return NULL; #else /* POSTGIS_GEOS_VERSION >= 33 */ GEOSGeometry *g1, *g2, *g3; LWGEOM *out; int is3d, srid; srid = geom1->srid; error_if_srid_mismatch(srid, (int)(geom2->srid)); is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ; initGEOS(lwnotice, lwgeom_geos_error); g1 = (GEOSGeometry *)LWGEOM2GEOS(geom1); if ( 0 == g1 ) /* exception thrown at construction */ { lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } g2 = (GEOSGeometry *)LWGEOM2GEOS(geom2); if ( 0 == g2 ) /* exception thrown at construction */ { lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); GEOSGeom_destroy(g1); return NULL; } g3 = GEOSSharedPaths(g1,g2); GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); if (g3 == NULL) { lwerror("GEOSSharedPaths: %s", lwgeom_geos_errmsg); return NULL; } GEOSSetSRID(g3, srid); out = GEOS2LWGEOM(g3, is3d); GEOSGeom_destroy(g3); if (out == NULL) { lwerror("GEOS2LWGEOM threw an error"); return NULL; } return out; #endif /* POSTGIS_GEOS_VERSION >= 33 */ }
test_capioffsetcurve_data() : geom1_(0), geom2_(0), wkt_(0) { initGEOS(notice, notice); wktw_ = GEOSWKTWriter_create(); GEOSWKTWriter_setTrim(wktw_, 1); }
void object::test<1> () { numcalls = 0; initGEOS(notice, notice); GEOS_interruptRegisterCallback(countCalls); ensure_equals(numcalls, 0); GEOSGeometry* geom1 = GEOSGeomFromWKT("LINESTRING(0 0, 1 0)"); ensure("GEOSGeomFromWKT failed", nullptr != geom1); GEOSGeometry* geom2 = GEOSBuffer(geom1, 1, 8); ensure("GEOSBufferWithStyle failed", nullptr != geom2); ensure("interrupt callback never called", numcalls > 0); GEOSGeom_destroy(geom1); GEOSGeom_destroy(geom2); GEOS_interruptRegisterCallback(nullptr); /* unregister */ finishGEOS(); }
test_capigeosnode_data() : geom1_(0), geom2_(0), w_(0) { initGEOS(notice, notice); w_ = GEOSWKTWriter_create(); GEOSWKTWriter_setTrim(w_, 1); }
test_capigeosdistance_data() : geom1_(nullptr), geom2_(nullptr), geom3_(nullptr), w_(nullptr) { initGEOS(notice, notice); w_ = GEOSWKTWriter_create(); GEOSWKTWriter_setTrim(w_, 1); }
void object::test<2> () { numcalls = 0; initGEOS(notice, notice); GEOS_interruptRegisterCallback(countCalls); ensure_equals(numcalls, 0); GEOSGeometry* geom1 = GEOSGeomFromWKT("LINESTRING(0 0, 1 1, 2 2, 4 4)"); GEOSGeometry* geom2 = GEOSGeomFromWKT("LINESTRING(0 0, 1 1.01, 4 4.001)"); ensure("GEOSGeomFromWKT failed", nullptr != geom1); GEOSGeometry* geom3 = GEOSSnap(geom1, geom2, 0.1); ensure("GEOSSnap failed", nullptr != geom3); ensure("interrupt callback never called", numcalls > 0); GEOSGeom_destroy(geom1); GEOSGeom_destroy(geom2); GEOSGeom_destroy(geom3); GEOS_interruptRegisterCallback(nullptr); /* unregister */ finishGEOS(); }
test_capigeosminimumrectangle_data() : input_(nullptr), wkt_(nullptr) { initGEOS(notice, notice); wktw_ = GEOSWKTWriter_create(); GEOSWKTWriter_setTrim(wktw_, 1); GEOSWKTWriter_setRoundingPrecision(wktw_, 8); }
test_capiunaryunion_data() : geom1_(0), geom2_(0) { initGEOS(notice, notice); wktw_ = GEOSWKTWriter_create(); GEOSWKTWriter_setTrim(wktw_, 1); GEOSWKTWriter_setOutputDimension(wktw_, 3); }
test_capigeosclipbyrect_data() : geom1_(0), geom2_(0), geom3_(0), w_(0) { initGEOS(notice, notice); w_ = GEOSWKTWriter_create(); GEOSWKTWriter_setTrim(w_, 1); GEOSWKTWriter_setRoundingPrecision(w_, 8); }
LWGEOM* lwgeom_buildarea(const LWGEOM *geom) { GEOSGeometry* geos_in; GEOSGeometry* geos_out; LWGEOM* geom_out; int SRID = (int)(geom->srid); int is3d = FLAGS_GET_Z(geom->flags); /* Can't build an area from an empty! */ if ( lwgeom_is_empty(geom) ) { return (LWGEOM*)lwpoly_construct_empty(SRID, is3d, 0); } LWDEBUG(3, "buildarea called"); LWDEBUGF(3, "ST_BuildArea got geom @ %p", geom); initGEOS(lwnotice, lwgeom_geos_error); geos_in = LWGEOM2GEOS(geom); if ( 0 == geos_in ) /* exception thrown at construction */ { lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } geos_out = LWGEOM_GEOS_buildArea(geos_in); GEOSGeom_destroy(geos_in); if ( ! geos_out ) /* exception thrown.. */ { lwerror("LWGEOM_GEOS_buildArea: %s", lwgeom_geos_errmsg); return NULL; } /* If no geometries are in result collection, return NULL */ if ( GEOSGetNumGeometries(geos_out) == 0 ) { GEOSGeom_destroy(geos_out); return NULL; } geom_out = GEOS2LWGEOM(geos_out, is3d); GEOSGeom_destroy(geos_out); #if PARANOIA_LEVEL > 0 if ( geom_out == NULL ) { lwerror("serialization error"); return NULL; } #endif return geom_out; }
/* From https://github.com/iamaleksey/iconverl/blob/master/c_src/iconverl.c */ static int load(ErlNifEnv *env, void **priv, ERL_NIF_TERM load_info) { initGEOS(notice_handler, error_handler); GEOSGEOM_RESOURCE = enif_open_resource_type( env, NULL, "geosgeom_resource", &geom_destroy, ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL); return 0; }
LWGEOM* lwgeom_offsetcurve(const LWLINE *lwline, double size, int quadsegs, int joinStyle, double mitreLimit) { #if POSTGIS_GEOS_VERSION < 32 lwerror("lwgeom_offsetcurve: GEOS 3.2 or higher required"); #else GEOSGeometry *g1, *g3; LWGEOM *lwgeom_result; LWGEOM *lwgeom_in = lwline_as_lwgeom(lwline); initGEOS(lwnotice, lwgeom_geos_error); g1 = (GEOSGeometry *)LWGEOM2GEOS(lwgeom_in); if ( ! g1 ) { lwerror("lwgeom_offsetcurve: Geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } #if POSTGIS_GEOS_VERSION < 33 /* Size is always positive for GEOSSingleSidedBuffer, and a flag determines left/right */ g3 = GEOSSingleSidedBuffer(g1, size < 0 ? -size : size, quadsegs, joinStyle, mitreLimit, size < 0 ? 0 : 1); #else g3 = GEOSOffsetCurve(g1, size, quadsegs, joinStyle, mitreLimit); #endif /* Don't need input geometry anymore */ GEOSGeom_destroy(g1); if (g3 == NULL) { GEOSGeom_destroy(g1); lwerror("GEOSOffsetCurve: %s", lwgeom_geos_errmsg); return NULL; } LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3)); GEOSSetSRID(g3, lwgeom_get_srid(lwgeom_in)); lwgeom_result = GEOS2LWGEOM(g3, lwgeom_has_z(lwgeom_in)); GEOSGeom_destroy(g3); if (lwgeom_result == NULL) { lwerror("lwgeom_offsetcurve: GEOS2LWGEOM returned null"); return NULL; } return lwgeom_result; #endif /* POSTGIS_GEOS_VERSION < 32 */ }
void object::test<4> () { initGEOS(notice, notice); GEOSGeometry* geom1 = GEOSGeomFromWKT("LINESTRING(0 0, 1 0)"); ensure("GEOSGeomFromWKT failed", nullptr != geom1); GEOS_interruptRegisterCallback(interruptNow); GEOSGeometry* geom2 = GEOSBuffer(geom1, 1, 8); ensure("GEOSBuffer wasn't interrupted", nullptr == geom2); GEOS_interruptRegisterCallback(nullptr); /* unregister */ // TODO: check the actual exception ? (sent to notice() callback) GEOSGeom_destroy(geom1); finishGEOS(); }
void msudf_init(UDF_INIT *initid) { msudf_params *params; DEBUG("initGeosInitialized %d", initGeosInitialized); if (!initGeosInitialized) { DEBUG("Initializing GEOS ..."); initGeosInitialized = 1; initGEOS(gu_debug,gu_debug); } params = (msudf_params *) malloc(sizeof(msudf_params)); params->pj_src = NULL; params->pj_dst = NULL; params->srid_src = 0; params->srid_dst = 0; params->buf = NULL; initid->ptr = (char *)params; }
Datum ST_RelateMatch(PG_FUNCTION_ARGS) { #if POSTGIS_GEOS_VERSION < 33 lwerror("The GEOS version this postgis binary " "was compiled against (%d) doesn't support " "'ST_RelateMatch' function (3.3.0+ required)", POSTGIS_GEOS_VERSION); PG_RETURN_NULL(); #else /* POSTGIS_GEOS_VERSION >= 33 */ char *mat, *pat; text *mat_text, *pat_text; int result; /* Read the arguments */ mat_text = (PG_GETARG_TEXT_P(0)); pat_text = (PG_GETARG_TEXT_P(1)); /* Convert from text to cstring */ mat = text2cstring(mat_text); pat = text2cstring(pat_text); initGEOS(lwnotice, lwgeom_geos_error); result = GEOSRelatePatternMatch(mat, pat); if (result == 2) { lwfree(mat); lwfree(pat); lwerror("GEOSRelatePatternMatch: %s", lwgeom_geos_errmsg); PG_RETURN_NULL(); } lwfree(mat); lwfree(pat); PG_RETURN_BOOL(result); #endif /* POSTGIS_GEOS_VERSION >= 33 */ }
LWGEOM * lwgeom_normalize(const LWGEOM *geom1) { LWGEOM *result ; GEOSGeometry *g1; int is3d ; int srid ; srid = (int)(geom1->srid); is3d = FLAGS_GET_Z(geom1->flags); initGEOS(lwnotice, lwgeom_geos_error); g1 = LWGEOM2GEOS(geom1); if ( 0 == g1 ) /* exception thrown at construction */ { lwerror("First argument geometry could not be converted to GEOS."); return NULL ; } if ( -1 == GEOSNormalize(g1) ) { lwerror("Error in GEOSNormalize: %s", lwgeom_geos_errmsg); return NULL; /* never get here */ } GEOSSetSRID(g1, srid); /* needed ? */ result = GEOS2LWGEOM(g1, is3d); GEOSGeom_destroy(g1); if (result == NULL) { lwerror("Error performing intersection: GEOS2LWGEOM: %s", lwgeom_geos_errmsg); return NULL ; /* never get here */ } return result ; }
SPATIALITE_DECLARE void spatialite_init (int verbose) { /* used when SQLite initializes as an ordinary lib OBSOLETE - strongly discouraged !!!!! always using spatialite_init_ex() as a replacement is warmly reccomended */ spatialite_initialize (); #ifndef OMIT_GEOS /* initializing GEOS */ initGEOS (geos_warning, geos_error); #endif /* end GEOS */ #ifdef POSTGIS_2_1 /* initializing liblwgeom from PostGIS 2.1.x (or later) */ splite_lwgeom_init (); #endif /* end POSTGIS_2_1 */ sqlite3_auto_extension ((void (*)(void)) init_spatialite_extension); spatialite_splash_screen (verbose); }
int main(void) { GEOSWKTReader *reader; GEOSGeometry *mp; GEOSGeometry *p; const GEOSPreparedGeometry *prep_mp; unsigned long int i; unsigned long int count = 1e6; initGEOS(NULL, NULL); reader = GEOSWKTReader_create(); mp = GEOSWKTReader_read(reader, "MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))"); p = GEOSWKTReader_read(reader, "POLYGON((2 2, 6 2, 6 6, 2 6, 2 2))"); assert(GEOSisValid(mp)); assert(GEOSisValid(p)); prep_mp = GEOSPrepare(mp); for (i=0; i<count; i++) { if ( !(i%100) ) printf("%lu iterations\n", i); /* does not leak */ /* GEOSContains(mp, p); */ /* leaks */ GEOSPreparedContains(prep_mp, p); } printf("%lu iterations (END)\n", i); return 0; }
void object::test<5> () { numcalls = 0; initGEOS(notice, notice); GEOSGeometry* geom1 = GEOSGeomFromWKT("LINESTRING(0 0, 1 0)"); ensure("GEOSGeomFromWKT failed", nullptr != geom1); GEOS_interruptRegisterCallback(interruptNow); nextcb = GEOS_interruptRegisterCallback(countCalls); GEOSGeometry* geom2 = GEOSBuffer(geom1, 1, 8); ensure("GEOSBuffer wasn't interrupted", nullptr == geom2); ensure_equals(numcalls, 1); GEOS_interruptRegisterCallback(nullptr); /* unregister */ nextcb = nullptr; GEOSGeom_destroy(geom1); finishGEOS(); }
LWGEOM* lwgeom_geos_noop(const LWGEOM* geom_in) { GEOSGeometry *geosgeom; LWGEOM* geom_out; int is3d = FLAGS_GET_Z(geom_in->flags); initGEOS(lwnotice, lwgeom_geos_error); geosgeom = LWGEOM2GEOS(geom_in); if ( ! geosgeom ) { lwerror("Geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } geom_out = GEOS2LWGEOM(geosgeom, is3d); GEOSGeom_destroy(geosgeom); if ( ! geom_out ) { lwerror("GEOS Geometry could not be converted to LWGEOM: %s", lwgeom_geos_errmsg); } return geom_out; }
test_capigeouserdata_data() : geom_(nullptr) { initGEOS(notice, notice); }
test_capigeoswithin_data() : geom1_(nullptr), geom2_(nullptr) { initGEOS(notice, notice); }
test_capigeosrelatepatternmatch_data() { initGEOS(notice, notice); }
/* Initializes and uses GEOS internally */ static LWGEOM* lwpoly_split_by_line(const LWPOLY* lwpoly_in, const LWLINE* blade_in) { LWCOLLECTION* out; GEOSGeometry* g1; GEOSGeometry* g2; GEOSGeometry* g1_bounds; GEOSGeometry* polygons; const GEOSGeometry *vgeoms[1]; int i,n; int hasZ = FLAGS_GET_Z(lwpoly_in->flags); /* Possible outcomes: * * 1. The line does not split the polygon * -> Return a collection with single element * 2. The line does split the polygon * -> Return a collection of all elements resulting from the split */ initGEOS(lwgeom_geos_error, lwgeom_geos_error); g1 = LWGEOM2GEOS((LWGEOM*)lwpoly_in, 0); if ( NULL == g1 ) { lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } g1_bounds = GEOSBoundary(g1); if ( NULL == g1_bounds ) { GEOSGeom_destroy(g1); lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg); return NULL; } g2 = LWGEOM2GEOS((LWGEOM*)blade_in, 0); if ( NULL == g2 ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g1_bounds); lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } vgeoms[0] = GEOSUnion(g1_bounds, g2); if ( NULL == vgeoms[0] ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); lwerror("GEOSUnion: %s", lwgeom_geos_errmsg); return NULL; } polygons = GEOSPolygonize(vgeoms, 1); if ( NULL == polygons ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); lwerror("GEOSPolygonize: %s", lwgeom_geos_errmsg); return NULL; } #if PARANOIA_LEVEL > 0 if ( GEOSGeomTypeId(polygons) != COLLECTIONTYPE ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); GEOSGeom_destroy(polygons); lwerror("%s [%s] Unexpected return from GEOSpolygonize", __FILE__, __LINE__); return 0; } #endif /* We should now have all polygons, just skip * the ones which are in holes of the original * geometries and return the rest in a collection */ n = GEOSGetNumGeometries(polygons); out = lwcollection_construct_empty(COLLECTIONTYPE, lwpoly_in->srid, hasZ, 0); /* Allocate space for all polys */ out->geoms = lwrealloc(out->geoms, sizeof(LWGEOM*)*n); assert(0 == out->ngeoms); for (i=0; i<n; ++i) { GEOSGeometry* pos; /* point on surface */ const GEOSGeometry* p = GEOSGetGeometryN(polygons, i); int contains; pos = GEOSPointOnSurface(p); if ( ! pos ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); GEOSGeom_destroy(polygons); lwerror("GEOSPointOnSurface: %s", lwgeom_geos_errmsg); return NULL; } contains = GEOSContains(g1, pos); if ( 2 == contains ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); GEOSGeom_destroy(polygons); GEOSGeom_destroy(pos); lwerror("GEOSContains: %s", lwgeom_geos_errmsg); return NULL; } GEOSGeom_destroy(pos); if ( 0 == contains ) { /* Original geometry doesn't contain * a point in this ring, must be an hole */ continue; } out->geoms[out->ngeoms++] = GEOS2LWGEOM(p, hasZ); } GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); GEOSGeom_destroy(polygons); return (LWGEOM*)out; }
test_capigeospreparedgeometry_data() : geom1_(nullptr), geom2_(nullptr), prepGeom1_(nullptr), prepGeom2_(nullptr) { initGEOS(notice, notice); }
Datum extractGridData(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { TupleDesc tupdesc; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); /* switch to memory context appropriate for multiple function calls */ MemoryContext oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); funcctx->tuple_desc = BlessTupleDesc(tupdesc); // Initalize geos static int geosInitialized = 0; if ( ! geosInitialized ) { initGEOS(logInfo, logError); geosInitialized = 1; } // Get the data to be returned struct GridPointDataListIterator * points = getExtractGridDataReturnValues(fcinfo); // Convert data into a set of Datums funcctx->max_calls = points->list->count; Datum * returnValues = palloc(sizeof(Datum) * funcctx->max_calls); int i; for ( i = 0; i < funcctx->max_calls; ++ i ) returnValues[i] = getNextReturnTupleViaDatums(GridPointDataListIteratorNext(points), funcctx->tuple_desc); funcctx->user_fctx = (void *) returnValues; // Delete intermediate data // GridPointDataListDelete(points->list); // GridPointDataListIteratorDelete(points); MemoryContextSwitchTo(oldcontext); } /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); if ( funcctx->call_cntr < funcctx->max_calls ) { Datum * ret = (Datum *) funcctx->user_fctx; Datum result = ret[funcctx->call_cntr]; SRF_RETURN_NEXT(funcctx, result); } else { //GridPointDataListDelete(iterator->list); SRF_RETURN_DONE(funcctx); } }
/* Initializes and uses GEOS internally */ static LWGEOM* lwline_split_by_line(const LWLINE* lwline_in, const LWGEOM* blade_in) { LWGEOM** components; LWGEOM* diff; LWCOLLECTION* out; GEOSGeometry* gdiff; /* difference */ GEOSGeometry* g1; GEOSGeometry* g2; int ret; /* ASSERT blade_in is LINE or MULTILINE */ assert (blade_in->type == LINETYPE || blade_in->type == MULTILINETYPE || blade_in->type == POLYGONTYPE || blade_in->type == MULTIPOLYGONTYPE ); /* Possible outcomes: * * 1. The lines do not cross or overlap * -> Return a collection with single element * 2. The lines cross * -> Return a collection of all elements resulting from the split */ initGEOS(lwgeom_geos_error, lwgeom_geos_error); g1 = LWGEOM2GEOS((LWGEOM*)lwline_in, 0); if ( ! g1 ) { lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } g2 = LWGEOM2GEOS(blade_in, 0); if ( ! g2 ) { GEOSGeom_destroy(g1); lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } /* If blade is a polygon, pick its boundary */ if ( blade_in->type == POLYGONTYPE || blade_in->type == MULTIPOLYGONTYPE ) { gdiff = GEOSBoundary(g2); GEOSGeom_destroy(g2); if ( ! gdiff ) { GEOSGeom_destroy(g1); lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg); return NULL; } g2 = gdiff; gdiff = NULL; } /* If interior intersecton is linear we can't split */ ret = GEOSRelatePattern(g1, g2, "1********"); if ( 2 == ret ) { lwerror("GEOSRelatePattern: %s", lwgeom_geos_errmsg); GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); return NULL; } if ( ret ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); lwerror("Splitter line has linear intersection with input"); return NULL; } gdiff = GEOSDifference(g1,g2); GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); if (gdiff == NULL) { lwerror("GEOSDifference: %s", lwgeom_geos_errmsg); return NULL; } diff = GEOS2LWGEOM(gdiff, FLAGS_GET_Z(lwline_in->flags)); GEOSGeom_destroy(gdiff); if (NULL == diff) { lwerror("GEOS2LWGEOM: %s", lwgeom_geos_errmsg); return NULL; } out = lwgeom_as_lwcollection(diff); if ( ! out ) { components = lwalloc(sizeof(LWGEOM*)*1); components[0] = diff; out = lwcollection_construct(COLLECTIONTYPE, lwline_in->srid, NULL, 1, components); } else { /* Set SRID */ lwgeom_set_srid((LWGEOM*)out, lwline_in->srid); /* Force collection type */ out->type = COLLECTIONTYPE; } return (LWGEOM*)out; }
void _init_geos() { initGEOS(_msg_handler,_msg_handler); }
test_capigeossimplify_data() { initGEOS(notice, notice); }
LWGEOM* lwgeom_node(const LWGEOM* lwgeom_in) { #if POSTGIS_GEOS_VERSION < 33 lwerror("The GEOS version this postgis binary " "was compiled against (%d) doesn't support " "'GEOSUnaryUnion' function (3.3.0+ required)", POSTGIS_GEOS_VERSION); return NULL; #else /* POSTGIS_GEOS_VERSION >= 33 */ GEOSGeometry *g1, *gu, *gm; LWGEOM *ep, *lines; LWCOLLECTION *col, *tc; int pn, ln, np, nl; if ( lwgeom_dimension(lwgeom_in) != 1 ) { lwerror("Noding geometries of dimension != 1 is unsupported"); return NULL; } initGEOS(lwgeom_geos_error, lwgeom_geos_error); g1 = LWGEOM2GEOS(lwgeom_in); if ( ! g1 ) { lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } ep = lwgeom_extract_unique_endpoints(lwgeom_in); if ( ! ep ) { GEOSGeom_destroy(g1); lwerror("Error extracting unique endpoints from input"); return NULL; } /* Unary union input to fully node */ gu = GEOSUnaryUnion(g1); GEOSGeom_destroy(g1); if ( ! gu ) { lwgeom_free(ep); lwerror("GEOSUnaryUnion: %s", lwgeom_geos_errmsg); return NULL; } /* Linemerge (in case of overlaps) */ gm = GEOSLineMerge(gu); GEOSGeom_destroy(gu); if ( ! gm ) { lwgeom_free(ep); lwerror("GEOSLineMerge: %s", lwgeom_geos_errmsg); return NULL; } lines = GEOS2LWGEOM(gm, FLAGS_GET_Z(lwgeom_in->flags)); GEOSGeom_destroy(gm); if ( ! lines ) { lwgeom_free(ep); lwerror("Error during GEOS2LWGEOM"); return NULL; } /* * Reintroduce endpoints from input, using split-line-by-point. * Note that by now we can be sure that each point splits at * most _one_ segment as any point shared by multiple segments * would already be a node. Also we can be sure that any of * the segments endpoints won't split any other segment. * We can use the above 2 assertions to early exit the loop. */ col = lwcollection_construct_empty(MULTILINETYPE, lwgeom_in->srid, FLAGS_GET_Z(lwgeom_in->flags), FLAGS_GET_M(lwgeom_in->flags)); np = lwgeom_ngeoms(ep); for (pn=0; pn<np; ++pn) { /* for each point */ const LWPOINT* p = (LWPOINT*)lwgeom_subgeom(ep, pn); nl = lwgeom_ngeoms(lines); for (ln=0; ln<nl; ++ln) { /* for each line */ const LWLINE* l = (LWLINE*)lwgeom_subgeom(lines, ln); int s = lwline_split_by_point_to(l, p, (LWMLINE*)col); if ( ! s ) continue; /* not on this line */ if ( s == 1 ) { /* found on this line, but not splitting it */ break; } /* splits this line */ /* replace this line with the two splits */ if ( lwgeom_is_collection(lines) ) { tc = (LWCOLLECTION*)lines; lwcollection_reserve(tc, nl + 1); while (nl > ln+1) { tc->geoms[nl] = tc->geoms[nl-1]; --nl; } lwgeom_free(tc->geoms[ln]); tc->geoms[ln] = col->geoms[0]; tc->geoms[ln+1] = col->geoms[1]; tc->ngeoms++; } else { lwgeom_free(lines); /* transfer ownership rather than cloning */ lines = (LWGEOM*)lwcollection_clone_deep(col); assert(col->ngeoms == 2); lwgeom_free(col->geoms[0]); lwgeom_free(col->geoms[1]); } /* reset the vector */ assert(col->ngeoms == 2); col->ngeoms = 0; break; } } lwgeom_free(ep); lwcollection_free(col); lines->srid = lwgeom_in->srid; return (LWGEOM*)lines; #endif /* POSTGIS_GEOS_VERSION >= 33 */ }