void geo_wkt(sqlite3_context *context,int argc,sqlite3_value **argv) { if(argc == 1 && sqlite3_value_type(argv[0]) == SQLITE_BLOB) { GEOSGeometry* geometry; char* wkt; const void* data = sqlite3_value_blob(argv[0]); size_t data_size = sqlite3_value_bytes(argv[0]); _init_geos(); geometry = _geo_from_wkb((const unsigned char*)data,data_size); if(geometry != 0) { wkt = GEOSGeomToWKT(geometry); sqlite3_result_text(context,wkt,-1,SQLITE_TRANSIENT); GEOSFree(wkt); } GEOSGeom_destroy(geometry); finishGEOS(); } }
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_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 ; }
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; }
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; }