char *msudf_convexHull(UDF_INIT *initid,UDF_ARGS *args, char *buf, unsigned long *length, char *is_null, char *error) { char *result; GEOSGeom geom1,geom2; DEBUG("msudf_convexHull"); geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]); if (geom1 == NULL) { strcpy(error,"Invalid geometry."); *is_null = 1; return NULL; } geom2 = GEOSConvexHull(geom1); if (geom2 != NULL) { GEOSSetSRID(geom2,GEOSGetSRID(geom1)); result = msudf_returnGeometry(initid,length,geom2); GEOSGeom_destroy(geom1); GEOSGeom_destroy(geom2); return result; } else { GEOSGeom_destroy(geom1); *is_null = 1; return NULL; } }
char *msudf_lineSubstring(UDF_INIT *initid,UDF_ARGS *args, char *buf, unsigned long *length, char *is_null, char *error) { char *result; GEOSGeom geom2; GEOSGeom geom1; double start; double end; DEBUG("msudf_lineSubstring"); geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]); if (geom1 == NULL) { strcpy(error,"Invalid geometry."); *is_null = 1; return NULL; } start = *(double*) args->args[1] ; end = *(double*) args->args[2] ; geom2 = gu_substringLineGeom(geom1,start,end); if (geom2 != NULL) { GEOSSetSRID(geom2,GEOSGetSRID(geom1)); result = msudf_returnGeometry(initid,length,geom2); GEOSGeom_destroy(geom1); GEOSGeom_destroy(geom2); return result; } else { GEOSGeom_destroy(geom1); *is_null = 1; return NULL; } }
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 */ }
char *msudf_simplifyPreserveTopology(UDF_INIT *initid,UDF_ARGS *args, char *buf, unsigned long *length, char *is_null, char *error) { char *result; GEOSGeom geom2; GEOSGeom geom1; double tolerance; DEBUG("msudf_simplifyPreserveTopology"); geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]); if (geom1 == NULL) { strcpy(error,"Invalid geometry."); *is_null = 1; return NULL; } tolerance = *(double*) args->args[1] ; geom2 = GEOSTopologyPreserveSimplify(geom1,tolerance); if (geom2 != NULL) { GEOSSetSRID(geom2,GEOSGetSRID(geom1)); result = msudf_returnGeometry(initid,length,geom2); GEOSGeom_destroy(geom1); GEOSGeom_destroy(geom2); return result; } else { GEOSGeom_destroy(geom1); *is_null = 1; return NULL; } }
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 */ }
GEOSGeom msudf_getGeometry(unsigned char *buf,unsigned int length) { int srid; GEOSGeom geom; geom = GEOSGeomFromWKB_buf(buf + 4,length - 4); if (geom != NULL) { srid = msudf_getInt(buf); GEOSSetSRID(geom,srid); } return geom; }
char *msudf_buffer(UDF_INIT *initid,UDF_ARGS *args, char *buf, unsigned long *length, char *is_null, char *error) { char *result; GEOSGeom geom1,geom2; double buffer; int quadsegs; DEBUG("msudf_buffer"); geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]); if (geom1 == NULL) { strcpy(error,"Invalid geometry."); *is_null = 1; return NULL; } buffer = *((double*) args->args[1]); if (args->arg_count > 2 && args->arg_type[2] == INT_RESULT) { quadsegs = *((int *)args->args[2]); } else { quadsegs = 8; } geom2 = GEOSBuffer(geom1,buffer,quadsegs); if (geom2 != NULL) { GEOSSetSRID(geom2,GEOSGetSRID(geom1)); result = msudf_returnGeometry(initid,length,geom2); GEOSGeom_destroy(geom1); GEOSGeom_destroy(geom2); return result; } else { GEOSGeom_destroy(geom1); *is_null = 1; return NULL; } }
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 ; }
char *msudf_intersection(UDF_INIT *initid,UDF_ARGS *args, char *buf, unsigned long *length, char *is_null, char *error) { char *result; GEOSGeom geomFirst,geomSecond,geomResult; DEBUG("msudf_intersection"); geomFirst = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]); if (geomFirst == NULL) { strcpy(error,"Invalid geometry."); *is_null = 1; return 0; } geomSecond = msudf_getGeometry((unsigned char *)args->args[1],args->lengths[1]); if (geomSecond == NULL) { GEOSGeom_destroy(geomFirst); strcpy(error,"Invalid geometry."); *is_null = 1; return 0; } geomResult = GEOSIntersection(geomFirst,geomSecond); if (geomResult!= NULL) { GEOSSetSRID(geomResult,GEOSGetSRID(geomFirst)); result = msudf_returnGeometry(initid,length,geomResult); GEOSGeom_destroy(geomFirst); GEOSGeom_destroy(geomSecond); GEOSGeom_destroy(geomResult); return result; } else { GEOSGeom_destroy(geomFirst); GEOSGeom_destroy(geomSecond); *is_null = 1; return NULL; } }
LWGEOM* lwgeom_snap(const LWGEOM* geom1, const LWGEOM* geom2, double tolerance) { #if POSTGIS_GEOS_VERSION < 33 lwerror("The GEOS version this lwgeom library " "was compiled against (%d) doesn't support " "'Snap' function (3.3.0+ required)", POSTGIS_GEOS_VERSION); return NULL; #else /* POSTGIS_GEOS_VERSION >= 33 */ int srid, is3d; GEOSGeometry *g1, *g2, *g3; LWGEOM* out; 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 = GEOSSnap(g1, g2, tolerance); if (g3 == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); lwerror("GEOSSnap: %s", lwgeom_geos_errmsg); return NULL; } GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSSetSRID(g3, srid); out = GEOS2LWGEOM(g3, is3d); if (out == NULL) { GEOSGeom_destroy(g3); lwerror("GEOSSnap() threw an error (result LWGEOM geometry formation)!"); return NULL; } GEOSGeom_destroy(g3); return out; #endif /* POSTGIS_GEOS_VERSION >= 33 */ }
static GEOSGeometry * toGeosGeometry (const gaiaGeomCollPtr gaia) { /* converting a GAIA Geometry into a GEOS Geometry */ int pts = 0; int lns = 0; int pgs = 0; int type; int geos_type; unsigned int dims; int iv; int ib; int nItem; double x; double y; double z; double m; gaiaPointPtr pt; gaiaLinestringPtr ln; gaiaPolygonPtr pg; gaiaRingPtr rng; GEOSGeometry *geos; GEOSGeometry *geos_ext; GEOSGeometry *geos_int; GEOSGeometry *geos_item; GEOSGeometry **geos_holes; GEOSGeometry **geos_coll; GEOSCoordSequence *cs; if (!gaia) return NULL; pt = gaia->FirstPoint; while (pt) { /* counting how many POINTs are there */ pts++; pt = pt->Next; } ln = gaia->FirstLinestring; while (ln) { /* counting how many LINESTRINGs are there */ lns++; ln = ln->Next; } pg = gaia->FirstPolygon; while (pg) { /* counting how many POLYGONs are there */ pgs++; pg = pg->Next; } if (pts == 0 && lns == 0 && pgs == 0) type = GAIA_UNKNOWN; else if (pts == 1 && lns == 0 && pgs == 0) { if (gaia->DeclaredType == GAIA_MULTIPOINT) type = GAIA_MULTIPOINT; else if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION) type = GAIA_GEOMETRYCOLLECTION; else type = GAIA_POINT; } else if (pts == 0 && lns == 1 && pgs == 0) { if (gaia->DeclaredType == GAIA_MULTILINESTRING) type = GAIA_MULTILINESTRING; else if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION) type = GAIA_GEOMETRYCOLLECTION; else type = GAIA_LINESTRING; } else if (pts == 0 && lns == 0 && pgs == 1) { if (gaia->DeclaredType == GAIA_MULTIPOLYGON) type = GAIA_MULTIPOLYGON; else if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION) type = GAIA_GEOMETRYCOLLECTION; else type = GAIA_POLYGON; } else if (pts > 1 && lns == 0 && pgs == 0) { if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION) type = GAIA_GEOMETRYCOLLECTION; else type = GAIA_MULTIPOINT; } else if (pts == 0 && lns > 1 && pgs == 0) { if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION) type = GAIA_GEOMETRYCOLLECTION; else type = GAIA_MULTILINESTRING; } else if (pts == 0 && lns == 0 && pgs > 1) { if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION) type = GAIA_GEOMETRYCOLLECTION; else type = GAIA_MULTIPOLYGON; } else type = GAIA_GEOMETRYCOLLECTION; switch (gaia->DimensionModel) { case GAIA_XY_Z: case GAIA_XY_Z_M: dims = 3; break; default: dims = 2; break; }; switch (type) { case GAIA_POINT: pt = gaia->FirstPoint; cs = GEOSCoordSeq_create (1, dims); switch (gaia->DimensionModel) { case GAIA_XY_Z: case GAIA_XY_Z_M: GEOSCoordSeq_setX (cs, 0, pt->X); GEOSCoordSeq_setY (cs, 0, pt->Y); GEOSCoordSeq_setZ (cs, 0, pt->Z); break; default: GEOSCoordSeq_setX (cs, 0, pt->X); GEOSCoordSeq_setY (cs, 0, pt->Y); break; }; geos = GEOSGeom_createPoint (cs); break; case GAIA_LINESTRING: ln = gaia->FirstLinestring; cs = GEOSCoordSeq_create (ln->Points, dims); for (iv = 0; iv < ln->Points; iv++) { switch (ln->DimensionModel) { case GAIA_XY_Z: gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; case GAIA_XY_M: gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; case GAIA_XY_Z_M: gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; default: gaiaGetPoint (ln->Coords, iv, &x, &y); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; }; } geos = GEOSGeom_createLineString (cs); break; case GAIA_POLYGON: pg = gaia->FirstPolygon; rng = pg->Exterior; /* exterior ring */ cs = GEOSCoordSeq_create (rng->Points, dims); for (iv = 0; iv < rng->Points; iv++) { switch (rng->DimensionModel) { case GAIA_XY_Z: gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; case GAIA_XY_M: gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; case GAIA_XY_Z_M: gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; default: gaiaGetPoint (rng->Coords, iv, &x, &y); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; }; } geos_ext = GEOSGeom_createLinearRing (cs); geos_holes = NULL; if (pg->NumInteriors > 0) { geos_holes = malloc (sizeof (GEOSGeometry *) * pg->NumInteriors); for (ib = 0; ib < pg->NumInteriors; ib++) { /* interior ring */ rng = pg->Interiors + ib; cs = GEOSCoordSeq_create (rng->Points, dims); for (iv = 0; iv < rng->Points; iv++) { switch (rng->DimensionModel) { case GAIA_XY_Z: gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; case GAIA_XY_M: gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; case GAIA_XY_Z_M: gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; default: gaiaGetPoint (rng->Coords, iv, &x, &y); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; }; } geos_int = GEOSGeom_createLinearRing (cs); *(geos_holes + ib) = geos_int; } } geos = GEOSGeom_createPolygon (geos_ext, geos_holes, pg->NumInteriors); if (geos_holes) free (geos_holes); break; case GAIA_MULTIPOINT: case GAIA_MULTILINESTRING: case GAIA_MULTIPOLYGON: case GAIA_GEOMETRYCOLLECTION: nItem = 0; geos_coll = malloc (sizeof (GEOSGeometry *) * (pts + lns + pgs)); pt = gaia->FirstPoint; while (pt) { cs = GEOSCoordSeq_create (1, dims); switch (pt->DimensionModel) { case GAIA_XY_Z: case GAIA_XY_Z_M: GEOSCoordSeq_setX (cs, 0, pt->X); GEOSCoordSeq_setY (cs, 0, pt->Y); GEOSCoordSeq_setZ (cs, 0, pt->Z); break; default: GEOSCoordSeq_setX (cs, 0, pt->X); GEOSCoordSeq_setY (cs, 0, pt->Y); break; }; geos_item = GEOSGeom_createPoint (cs); *(geos_coll + nItem++) = geos_item; pt = pt->Next; } ln = gaia->FirstLinestring; while (ln) { cs = GEOSCoordSeq_create (ln->Points, dims); for (iv = 0; iv < ln->Points; iv++) { switch (ln->DimensionModel) { case GAIA_XY_Z: gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; case GAIA_XY_M: gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; case GAIA_XY_Z_M: gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; default: gaiaGetPoint (ln->Coords, iv, &x, &y); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; }; } geos_item = GEOSGeom_createLineString (cs); *(geos_coll + nItem++) = geos_item; ln = ln->Next; } pg = gaia->FirstPolygon; while (pg) { rng = pg->Exterior; /* exterior ring */ cs = GEOSCoordSeq_create (rng->Points, dims); for (iv = 0; iv < rng->Points; iv++) { switch (rng->DimensionModel) { case GAIA_XY_Z: gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; case GAIA_XY_M: gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; case GAIA_XY_Z_M: gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; default: gaiaGetPoint (rng->Coords, iv, &x, &y); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; }; } geos_ext = GEOSGeom_createLinearRing (cs); geos_holes = NULL; if (pg->NumInteriors > 0) { geos_holes = malloc (sizeof (GEOSGeometry *) * pg->NumInteriors); for (ib = 0; ib < pg->NumInteriors; ib++) { /* interior ring */ rng = pg->Interiors + ib; cs = GEOSCoordSeq_create (rng->Points, dims); for (iv = 0; iv < rng->Points; iv++) { switch (rng->DimensionModel) { case GAIA_XY_Z: gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; case GAIA_XY_M: gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; case GAIA_XY_Z_M: gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); GEOSCoordSeq_setZ (cs, iv, z); break; default: gaiaGetPoint (rng->Coords, iv, &x, &y); GEOSCoordSeq_setX (cs, iv, x); GEOSCoordSeq_setY (cs, iv, y); break; }; } geos_int = GEOSGeom_createLinearRing (cs); *(geos_holes + ib) = geos_int; } } geos_item = GEOSGeom_createPolygon (geos_ext, geos_holes, pg->NumInteriors); if (geos_holes) free (geos_holes); *(geos_coll + nItem++) = geos_item; pg = pg->Next; } geos_type = GEOS_GEOMETRYCOLLECTION; if (type == GAIA_MULTIPOINT) geos_type = GEOS_MULTIPOINT; if (type == GAIA_MULTILINESTRING) geos_type = GEOS_MULTILINESTRING; if (type == GAIA_MULTIPOLYGON) geos_type = GEOS_MULTIPOLYGON; geos = GEOSGeom_createCollection (geos_type, geos_coll, pts + lns + pgs); if (geos_coll) free (geos_coll); break; default: geos = NULL; }; if (geos) GEOSSetSRID (geos, gaia->Srid); return geos; }
LWGEOM* lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2) { int is3d; int srid; GEOSGeometry *g1, *g2, *g3; LWGEOM *result; LWDEBUG(2, "in geomunion"); /* A.Union(empty) == A */ if ( lwgeom_is_empty(geom1) ) return lwgeom_clone(geom2); /* B.Union(empty) == B */ if ( lwgeom_is_empty(geom2) ) return lwgeom_clone(geom1); /* ensure srids are identical */ srid = (int)(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 = 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 = LWGEOM2GEOS(geom2); if ( 0 == g2 ) /* exception thrown at construction */ { GEOSGeom_destroy(g1); lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } LWDEBUGF(3, "g1=%s", GEOSGeomToWKT(g1)); LWDEBUGF(3, "g2=%s", GEOSGeomToWKT(g2)); g3 = GEOSUnion(g1,g2); LWDEBUGF(3, "g3=%s", GEOSGeomToWKT(g3)); GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); if (g3 == NULL) { lwerror("GEOSUnion: %s", lwgeom_geos_errmsg); return NULL; /* never get here */ } GEOSSetSRID(g3, srid); result = GEOS2LWGEOM(g3, is3d); GEOSGeom_destroy(g3); if (result == NULL) { lwerror("Error performing union: GEOS2LWGEOM: %s", lwgeom_geos_errmsg); return NULL; /*never get here */ } return result; }
LWGEOM * lwgeom_symdifference(const LWGEOM* geom1, const LWGEOM* geom2) { GEOSGeometry *g1, *g2, *g3; LWGEOM *result; int is3d; int srid; /* A.SymDifference(Empty) == A */ if ( lwgeom_is_empty(geom2) ) return lwgeom_clone(geom1); /* Empty.DymDifference(B) == Empty */ if ( lwgeom_is_empty(geom1) ) return lwgeom_clone(geom1); /* ensure srids are identical */ srid = (int)(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 = 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 = 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 = GEOSSymDifference(g1,g2); if (g3 == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); lwerror("GEOSSymDifference: %s", lwgeom_geos_errmsg); return NULL; /*never get here */ } LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3)); GEOSSetSRID(g3, srid); result = GEOS2LWGEOM(g3, is3d); if (result == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g3); lwerror("GEOS symdifference() threw an error (result postgis geometry formation)!"); return NULL ; /*never get here */ } GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g3); return result; }
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2) { LWGEOM *result ; GEOSGeometry *g1, *g2, *g3 ; int is3d ; int srid ; /* A.Intersection(Empty) == Empty */ if ( lwgeom_is_empty(geom2) ) return lwgeom_clone(geom2); /* Empty.Intersection(A) == Empty */ if ( lwgeom_is_empty(geom1) ) return lwgeom_clone(geom1); /* ensure srids are identical */ srid = (int)(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); LWDEBUG(3, "intersection() START"); g1 = LWGEOM2GEOS(geom1); if ( 0 == g1 ) /* exception thrown at construction */ { lwerror("First argument geometry could not be converted to GEOS."); return NULL ; } g2 = LWGEOM2GEOS(geom2); if ( 0 == g2 ) /* exception thrown at construction */ { lwerror("Second argument geometry could not be converted to GEOS."); GEOSGeom_destroy(g1); return NULL ; } LWDEBUG(3, " constructed geometrys - calling geos"); LWDEBUGF(3, " g1 = %s", GEOSGeomToWKT(g1)); LWDEBUGF(3, " g2 = %s", GEOSGeomToWKT(g2)); /*LWDEBUGF(3, "g2 is valid = %i",GEOSisvalid(g2)); */ /*LWDEBUGF(3, "g1 is valid = %i",GEOSisvalid(g1)); */ g3 = GEOSIntersection(g1,g2); LWDEBUG(3, " intersection finished"); if (g3 == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); lwerror("Error performing intersection: %s", lwgeom_geos_errmsg); return NULL; /* never get here */ } LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3) ) ; GEOSSetSRID(g3, srid); result = GEOS2LWGEOM(g3, is3d); if (result == NULL) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g3); lwerror("Error performing intersection: GEOS2LWGEOM: %s", lwgeom_geos_errmsg); return NULL ; /* never get here */ } GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g3); return result ; }
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom) { GEOSCoordSeq sq; GEOSGeom g, shell; GEOSGeom *geoms = NULL; /* LWGEOM *tmp; */ uint32_t ngeoms, i; int geostype; #if LWDEBUG_LEVEL >= 4 char *wkt; #endif LWDEBUGF(4, "LWGEOM2GEOS got a %s", lwtype_name(lwgeom->type)); if (lwgeom_has_arc(lwgeom)) { LWDEBUG(3, "LWGEOM2GEOS: arced geometry found."); lwerror("Exception in LWGEOM2GEOS: curved geometry not supported."); return NULL; } switch (lwgeom->type) { LWPOINT *lwp = NULL; LWPOLY *lwpoly = NULL; LWLINE *lwl = NULL; LWCOLLECTION *lwc = NULL; #if POSTGIS_GEOS_VERSION < 33 POINTARRAY *pa = NULL; #endif case POINTTYPE: lwp = (LWPOINT *)lwgeom; if ( lwgeom_is_empty(lwgeom) ) { #if POSTGIS_GEOS_VERSION < 33 pa = ptarray_construct_empty(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 2); sq = ptarray_to_GEOSCoordSeq(pa); shell = GEOSGeom_createLinearRing(sq); g = GEOSGeom_createPolygon(shell, NULL, 0); #else g = GEOSGeom_createEmptyPolygon(); #endif } else { sq = ptarray_to_GEOSCoordSeq(lwp->point); g = GEOSGeom_createPoint(sq); } if ( ! g ) { /* lwnotice("Exception in LWGEOM2GEOS"); */ return NULL; } break; case LINETYPE: lwl = (LWLINE *)lwgeom; if ( lwl->points->npoints == 1 ) { /* Duplicate point, to make geos-friendly */ lwl->points = ptarray_addPoint(lwl->points, getPoint_internal(lwl->points, 0), FLAGS_NDIMS(lwl->points->flags), lwl->points->npoints); } sq = ptarray_to_GEOSCoordSeq(lwl->points); g = GEOSGeom_createLineString(sq); if ( ! g ) { /* lwnotice("Exception in LWGEOM2GEOS"); */ return NULL; } break; case POLYGONTYPE: lwpoly = (LWPOLY *)lwgeom; if ( lwgeom_is_empty(lwgeom) ) { #if POSTGIS_GEOS_VERSION < 33 POINTARRAY *pa = ptarray_construct_empty(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 2); sq = ptarray_to_GEOSCoordSeq(pa); shell = GEOSGeom_createLinearRing(sq); g = GEOSGeom_createPolygon(shell, NULL, 0); #else g = GEOSGeom_createEmptyPolygon(); #endif } else { sq = ptarray_to_GEOSCoordSeq(lwpoly->rings[0]); /* TODO: check ring for being closed and fix if not */ shell = GEOSGeom_createLinearRing(sq); if ( ! shell ) return NULL; /*lwerror("LWGEOM2GEOS: exception during polygon shell conversion"); */ ngeoms = lwpoly->nrings-1; if ( ngeoms > 0 ) geoms = malloc(sizeof(GEOSGeom)*ngeoms); for (i=1; i<lwpoly->nrings; ++i) { sq = ptarray_to_GEOSCoordSeq(lwpoly->rings[i]); geoms[i-1] = GEOSGeom_createLinearRing(sq); if ( ! geoms[i-1] ) { --i; while (i) GEOSGeom_destroy(geoms[--i]); free(geoms); GEOSGeom_destroy(shell); return NULL; } /*lwerror("LWGEOM2GEOS: exception during polygon hole conversion"); */ } g = GEOSGeom_createPolygon(shell, geoms, ngeoms); if (geoms) free(geoms); } if ( ! g ) return NULL; break; case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: if ( lwgeom->type == MULTIPOINTTYPE ) geostype = GEOS_MULTIPOINT; else if ( lwgeom->type == MULTILINETYPE ) geostype = GEOS_MULTILINESTRING; else if ( lwgeom->type == MULTIPOLYGONTYPE ) geostype = GEOS_MULTIPOLYGON; else geostype = GEOS_GEOMETRYCOLLECTION; lwc = (LWCOLLECTION *)lwgeom; ngeoms = lwc->ngeoms; if ( ngeoms > 0 ) geoms = malloc(sizeof(GEOSGeom)*ngeoms); for (i=0; i<ngeoms; ++i) { GEOSGeometry* g = LWGEOM2GEOS(lwc->geoms[i]); if ( ! g ) { while (i) GEOSGeom_destroy(geoms[--i]); free(geoms); return NULL; } geoms[i] = g; } g = GEOSGeom_createCollection(geostype, geoms, ngeoms); if ( geoms ) free(geoms); if ( ! g ) return NULL; break; default: lwerror("Unknown geometry type: %d - %s", lwgeom->type, lwtype_name(lwgeom->type)); return NULL; } GEOSSetSRID(g, lwgeom->srid); #if LWDEBUG_LEVEL >= 4 wkt = GEOSGeomToWKT(g); LWDEBUGF(4, "LWGEOM2GEOS: GEOSGeom: %s", wkt); free(wkt); #endif return g; }
GEOSGeometry* LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in) { GEOSGeometry *tmp; GEOSGeometry *geos_result, *shp; GEOSGeometry const *vgeoms[1]; uint32_t i, ngeoms; int srid = GEOSGetSRID(geom_in); Face ** geoms; vgeoms[0] = geom_in; #ifdef LWGEOM_PROFILE_BUILDAREA lwnotice("Polygonizing"); #endif geos_result = GEOSPolygonize(vgeoms, 1); LWDEBUGF(3, "GEOSpolygonize returned @ %p", geos_result); /* Null return from GEOSpolygonize (an exception) */ if ( ! geos_result ) return 0; /* * We should now have a collection */ #if PARANOIA_LEVEL > 0 if ( GEOSGeometryTypeId(geos_result) != COLLECTIONTYPE ) { GEOSGeom_destroy(geos_result); lwerror("Unexpected return from GEOSpolygonize"); return 0; } #endif ngeoms = GEOSGetNumGeometries(geos_result); #ifdef LWGEOM_PROFILE_BUILDAREA lwnotice("Num geometries from polygonizer: %d", ngeoms); #endif LWDEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms); LWDEBUGF(3, "GEOSpolygonize: polygonized:%s", lwgeom_to_ewkt(GEOS2LWGEOM(geos_result, 0))); /* * No geometries in collection, early out */ if ( ngeoms == 0 ) { GEOSSetSRID(geos_result, srid); return geos_result; } /* * Return first geometry if we only have one in collection, * to avoid the unnecessary Geometry clone below. */ if ( ngeoms == 1 ) { tmp = (GEOSGeometry *)GEOSGetGeometryN(geos_result, 0); if ( ! tmp ) { GEOSGeom_destroy(geos_result); return 0; /* exception */ } shp = GEOSGeom_clone(tmp); GEOSGeom_destroy(geos_result); /* only safe after the clone above */ GEOSSetSRID(shp, srid); return shp; } LWDEBUGF(2, "Polygonize returned %d geoms", ngeoms); /* * Polygonizer returns a polygon for each face in the built topology. * * This means that for any face with holes we'll have other faces * representing each hole. We can imagine a parent-child relationship * between these faces. * * In order to maximize the number of visible rings in output we * only use those faces which have an even number of parents. * * Example: * * +---------------+ * | L0 | L0 has no parents * | +---------+ | * | | L1 | | L1 is an hole of L0 * | | +---+ | | * | | |L2 | | | L2 is an hole of L1 (which is an hole of L0) * | | | | | | * | | +---+ | | * | +---------+ | * | | * +---------------+ * * See http://trac.osgeo.org/postgis/ticket/1806 * */ #ifdef LWGEOM_PROFILE_BUILDAREA lwnotice("Preparing face structures"); #endif /* Prepare face structures for later analysis */ geoms = lwalloc(sizeof(Face**)*ngeoms); for (i=0; i<ngeoms; ++i) geoms[i] = newFace(GEOSGetGeometryN(geos_result, i)); #ifdef LWGEOM_PROFILE_BUILDAREA lwnotice("Finding face holes"); #endif /* Find faces representing other faces holes */ findFaceHoles(geoms, ngeoms); #ifdef LWGEOM_PROFILE_BUILDAREA lwnotice("Colletting even ancestor faces"); #endif /* Build a MultiPolygon composed only by faces with an * even number of ancestors */ tmp = collectFacesWithEvenAncestors(geoms, ngeoms); #ifdef LWGEOM_PROFILE_BUILDAREA lwnotice("Cleaning up"); #endif /* Cleanup face structures */ for (i=0; i<ngeoms; ++i) delFace(geoms[i]); lwfree(geoms); /* Faces referenced memory owned by geos_result. * It is safe to destroy geos_result after deleting them. */ GEOSGeom_destroy(geos_result); #ifdef LWGEOM_PROFILE_BUILDAREA lwnotice("Self-unioning"); #endif /* Run a single overlay operation to dissolve shared edges */ shp = GEOSUnionCascaded(tmp); if ( ! shp ) { GEOSGeom_destroy(tmp); return 0; /* exception */ } #ifdef LWGEOM_PROFILE_BUILDAREA lwnotice("Final cleanup"); #endif GEOSGeom_destroy(tmp); GEOSSetSRID(shp, srid); return shp; }
GEOSGeometry* LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in) { GEOSGeometry *tmp; GEOSGeometry *geos_result, *shp; GEOSGeometry const *vgeoms[1]; uint32_t i, ngeoms; int srid = GEOSGetSRID(geom_in); vgeoms[0] = geom_in; geos_result = GEOSPolygonize(vgeoms, 1); LWDEBUGF(3, "GEOSpolygonize returned @ %p", geos_result); /* Null return from GEOSpolygonize (an exception) */ if ( ! geos_result ) return 0; /* * We should now have a collection */ #if PARANOIA_LEVEL > 0 if ( GEOSGeometryTypeId(geos_result) != COLLECTIONTYPE ) { GEOSGeom_destroy(geos_result); lwerror("Unexpected return from GEOSpolygonize"); return 0; } #endif ngeoms = GEOSGetNumGeometries(geos_result); LWDEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms); LWDEBUGF(3, "GEOSpolygonize: polygonized:%s", lwgeom_to_ewkt(GEOS2LWGEOM(geos_result, 0))); /* * No geometries in collection, early out */ if ( ngeoms == 0 ) { GEOSSetSRID(geos_result, srid); return geos_result; } /* * Return first geometry if we only have one in collection, * to avoid the unnecessary Geometry clone below. */ if ( ngeoms == 1 ) { tmp = (GEOSGeometry *)GEOSGetGeometryN(geos_result, 0); if ( ! tmp ) { GEOSGeom_destroy(geos_result); return 0; /* exception */ } shp = GEOSGeom_clone(tmp); GEOSGeom_destroy(geos_result); /* only safe after the clone above */ GEOSSetSRID(shp, srid); return shp; } /* * Iteratively invoke symdifference on outer rings * as suggested by Carl Anderson: * postgis-devel/2005-December/001805.html */ shp = NULL; for (i=0; i<ngeoms; ++i) { GEOSGeom extring; GEOSCoordSeq sq; /* * Construct a Polygon from geometry i exterior ring * We don't use GEOSGeom_clone on the ExteriorRing * due to a bug in CAPI contained in GEOS 2.2 branch * failing to properly return a LinearRing from * a LinearRing clone. */ sq=GEOSCoordSeq_clone(GEOSGeom_getCoordSeq( GEOSGetExteriorRing(GEOSGetGeometryN( geos_result, i)) )); extring = GEOSGeom_createPolygon( GEOSGeom_createLinearRing(sq), NULL, 0 ); if ( extring == NULL ) /* exception */ { lwerror("GEOSCreatePolygon threw an exception"); return 0; } if ( shp == NULL ) { shp = extring; LWDEBUGF(3, "GEOSpolygonize: shp:%s", lwgeom_to_ewkt(GEOS2LWGEOM(shp, 0))); } else { tmp = GEOSSymDifference(shp, extring); LWDEBUGF(3, "GEOSpolygonize: SymDifference(%s, %s):%s", lwgeom_to_ewkt(GEOS2LWGEOM(shp, 0)), lwgeom_to_ewkt(GEOS2LWGEOM(extring, 0)), lwgeom_to_ewkt(GEOS2LWGEOM(tmp, 0)) ); GEOSGeom_destroy(shp); GEOSGeom_destroy(extring); shp = tmp; } } GEOSGeom_destroy(geos_result); GEOSSetSRID(shp, srid); return shp; }
void Geometry::SetSRID(Local<String> name, Local<Value> value, const AccessorInfo& info) { Geometry *geom = ObjectWrap::Unwrap<Geometry>(info.Holder()); GEOSSetSRID(geom->geos_geom_, value->Int32Value()); }