Changeset: 13d799d7d4f0 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=13d799d7d4f0 Modified Files: geom/monetdb5/geom.c geom/monetdb5/geom.h geom/monetdb5/geom.mal geom/monetdb5/geomBulk.c geom/sql/40_geom.sql Branch: sfcgal Log Message:
Add ST_IntersectsXYZ, it does the same as ST_Intersects for points but you can pass the point as X, Y and Z coordinates and also the SRID. This avoids us to use ST_SetSRID(ST_MakePoint(... diffs (truncated from 305 to 300 lines): diff --git a/geom/monetdb5/geom.c b/geom/monetdb5/geom.c --- a/geom/monetdb5/geom.c +++ b/geom/monetdb5/geom.c @@ -4692,6 +4692,75 @@ wkbBuffer(wkb **out, wkb **geom, dbl *di return MAL_SUCCEED; } +/* Gets a geometry and Point(X, Y, Z, SRID) and returns a Boolean by comparing them */ +static str +wkbspatialXYZ(bit *out, wkb **geomWKB_a, double *x, double *y, double *z, int *srid, char (*func) (const GEOSGeometry *, const GEOSGeometry *), const char *name) +{ + int res; + GEOSGeom geosGeometry_a, geosGeometry_b; + GEOSCoordSeq seq; + + if (wkb_isnil(*geomWKB_a)) { + *out = bit_nil; + return MAL_SUCCEED; + } + + geosGeometry_a = wkb2geos(*geomWKB_a); + if (geosGeometry_a == NULL) { + throw(MAL, name, "wkb2geos failed"); + } + + /*Build Geometry b*/ + if (*x == dbl_nil || *y == dbl_nil || *z == dbl_nil) { + GEOSGeom_destroy(geosGeometry_a); + *out = bit_nil; + return MAL_SUCCEED; + } + + //create the point from the coordinates + seq = GEOSCoordSeq_create(1, 3); + + if (seq == NULL) { + GEOSGeom_destroy(geosGeometry_a); + throw(MAL, name, "GEOSCoordSeq_create failed"); + } + + if (!GEOSCoordSeq_setOrdinate(seq, 0, 0, *x) || + !GEOSCoordSeq_setOrdinate(seq, 0, 1, *y) || + !GEOSCoordSeq_setOrdinate(seq, 0, 2, *z)) { + GEOSGeom_destroy(geosGeometry_a); + GEOSCoordSeq_destroy(seq); + throw(MAL, name, "GEOSCoordSeq_setOrdinate failed"); + } + + if ((geosGeometry_b = GEOSGeom_createPoint(seq)) == NULL) { + GEOSGeom_destroy(geosGeometry_a); + GEOSCoordSeq_destroy(seq); + throw(MAL, name, "Failed to create GEOSGeometry from the coordinates"); + } + + if (*srid != int_nil) + GEOSSetSRID(geosGeometry_b, *srid); + + if (GEOSGetSRID(geosGeometry_a) != GEOSGetSRID(geosGeometry_b)) { + GEOSGeom_destroy(geosGeometry_a); + GEOSGeom_destroy(geosGeometry_b); + throw(MAL, name, "Geometries of different SRID"); + } + + res = (*func) (geosGeometry_a, geosGeometry_b); + + GEOSGeom_destroy(geosGeometry_a); + GEOSGeom_destroy(geosGeometry_b); + + if (res == 2) + throw(MAL, name, "GEOS%s failed", name + 5); + + *out = res; + + return MAL_SUCCEED; +} + /* Gets two geometries and returns a Boolean by comparing them */ static str wkbspatial(bit *out, wkb **geomWKB_a, wkb **geomWKB_b, char (*func) (const GEOSGeometry *, const GEOSGeometry *), const char *name) @@ -4764,6 +4833,12 @@ wkbIntersects(bit *out, wkb **geomWKB_a, } str +wkbIntersectsXYZ(bit *out, wkb **geomWKB_a, dbl *x, dbl *y, dbl *z, int *srid) +{ + return wkbspatialXYZ(out, geomWKB_a, x, y, z, srid, GEOSIntersects, "geom.Intersects"); +} + +str wkbOverlaps(bit *out, wkb **geomWKB_a, wkb **geomWKB_b) { return wkbspatial(out, geomWKB_a, geomWKB_b, GEOSOverlaps, "geom.Overlaps"); diff --git a/geom/monetdb5/geom.h b/geom/monetdb5/geom.h --- a/geom/monetdb5/geom.h +++ b/geom/monetdb5/geom.h @@ -144,7 +144,9 @@ geom_export str wkbBoundary_bat(bat *inB geom_export str wkbEquals(bit*, wkb**, wkb**); geom_export str wkbDisjoint(bit*, wkb**, wkb**); geom_export str wkbIntersects(bit*, wkb**, wkb**); +geom_export str wkbIntersectsXYZ(bit*, wkb**, dbl*, dbl*, dbl*, int*); geom_export str wkbIntersects_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id); +geom_export str wkbIntersectsXYZ_bat(bat *outBAT_id, bat *inBAT_id, bat *inXBAT_id, double *dx, bat *inYBAT_id, double *dy, bat *inZBAT_id, double *dz, int* srid); geom_export str wkbTouches(bit*, wkb**, wkb**); geom_export str wkbCrosses(bit*, wkb**, wkb**); geom_export str wkbWithin(bit*, wkb**, wkb**); diff --git a/geom/monetdb5/geom.mal b/geom/monetdb5/geom.mal --- a/geom/monetdb5/geom.mal +++ b/geom/monetdb5/geom.mal @@ -304,6 +304,8 @@ command Equals(a:wkb, b:wkb) :bit addres comment "Returns true if the given geometries represent the same geometry. Directionality is ignored."; command Intersects(a:wkb, b:wkb) :bit address wkbIntersects comment "Returns true if these Geometries 'spatially intersect in 2D'"; +command IntersectsXYZ(a:wkb, x:dbl, y:dbl, z:dbl, srid:int) :bit address wkbIntersectsXYZ +comment "Returns true if these Geometries 'spatially intersect in 2D'"; command Overlaps(a:wkb, b:wkb) :bit address wkbOverlaps comment " Returns TRUE if the Geometries intersect but are not completely contained by each other."; command Relate(a:wkb, b:wkb, intersection_matrix_pattern:str) :bit address wkbRelate @@ -831,6 +833,44 @@ comment "Returns the area of the surface command Intersects(a:bat[:oid,:wkb], b:bat[:oid,:wkb]) :bat[:oid,:bit] address wkbIntersects_bat comment "Returns true if these Geometries 'spatially intersect in 2D'"; +command Intersects3D(g:bat[:oid,:wkb], dxBAT:bat[:oid,:dbl], dx:dbl, dyBAT:bat[:oid,:dbl], dy:dbl, dzBAT:bat[:oid,:dbl], dz:dbl, srid:int) :bat[:oid,:bit] address wkbIntersectsXYZ_bat +comment "Returns true if these Geometries 'spatially intersect in 2D'"; + +function IntersectsXYZ(g:bat[:oid,:wkb], dxBAT:bat[:oid,:dbl], dyBAT:bat[:oid,:dbl], dzBAT:bat[:oid,:dbl], srid:int) :bat[:oid,:bit]; + x := Intersects3D(g, dxBAT, 0:dbl, dyBAT, 0:dbl, dzBAT, 0:dbl, srid); + return x; +end IntersectsXYZ; + +function IntersectsXYZ(g:bat[:oid,:wkb], dx:dbl, dy:dbl, dzBAT:bat[:oid,:dbl], srid:int) :bat[:oid,:bit]; + x := Intersects3D(g, nil:bat, dx, nil:bat, dy, dzBAT, 0:dbl, srid); + return x; +end IntersectsXYZ; + +function IntersectsXYZ(g:bat[:oid,:wkb], dxBAT:bat[:oid,:dbl], dy:dbl, dzBAT:bat[:oid,:dbl], srid:int) :bat[:oid,:bit]; + x := Intersects3D(g, dxBAT, 0:dbl, nil:bat, dy, dzBAT, 0:dbl, srid); + return x; +end IntersectsXYZ; + +function IntersectsXYZ(g:bat[:oid,:wkb], dx:dbl, dyBAT:bat[:oid,:dbl], dzBAT:bat[:oid,:dbl], srid:int) :bat[:oid,:bit]; + x := Intersects3D(g, nil:bat, dx, dyBAT, 0:dbl, dzBAT, 0:dbl, srid); + return x; +end IntersectsXYZ; + +function IntersectsXYZ(g:bat[:oid,:wkb], dxBAT:bat[:oid,:dbl], dyBAT:bat[:oid,:dbl], dz:dbl, srid:int) :bat[:oid,:bit]; + x := Intersects3D(g, dxBAT, 0:dbl, dyBAT, 0:dbl, nil:bat, dz, srid); + return x; +end IntersectsXYZ; + +function IntersectsXYZ(g:bat[:oid,:wkb], dx:dbl, dyBAT:bat[:oid,:dbl], dz:dbl, srid:int) :bat[:oid,:bit]; + x := Intersects3D(g, nil:bat, dx, dyBAT, 0:dbl, nil:bat, dz, srid); + return x; +end IntersectsXYZ; + +function IntersectsXYZ(g:bat[:oid,:wkb], dxBAT:bat[:oid,:dbl], dy:dbl, dz:dbl, srid:int) :bat[:oid,:bit]; + x := Intersects3D(g, dxBAT, 0:dbl, nil:bat, dy, nil:bat, dz, srid); + return x; +end IntersectsXYZ; + module calc; command mbr(v:str) :mbr address mbrFromString; diff --git a/geom/monetdb5/geomBulk.c b/geom/monetdb5/geomBulk.c --- a/geom/monetdb5/geomBulk.c +++ b/geom/monetdb5/geomBulk.c @@ -586,6 +586,119 @@ wkbIntersects_bat(bat *outBAT_id, bat *a return WKBWKBtoBIT_bat(outBAT_id, aBAT_id, bBAT_id, wkbIntersects, "batgeom.wkbIntersects"); } +/******************************************************************************************/ +/************************* IN: wkb dbl dbl dbl - OUT: bit - SRID **************************/ +/******************************************************************************************/ + +static str +WKBtoBITxyzDBL_bat(bat *outBAT_id, bat *inBAT_id, bat *inXBAT_id, double *dx, bat *inYBAT_id, double *dy, bat *inZBAT_id, double * dz, int *srid, str (*func) (bit *, wkb **, double *x, double *y, double *z, int *srid), const char *name) +{ + BAT *outBAT = NULL, *inBAT = NULL, *inXBAT = NULL, *inYBAT = NULL, *inZBAT = NULL; + BUN p = 0, q = 0; + BATiter inBAT_iter, inXBAT_iter, inYBAT_iter, inZBAT_iter; + + //get the descriptor of the BAT + if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) { + throw(MAL, name, RUNTIME_OBJECT_MISSING); + } + if (*inXBAT_id != bat_nil && (inXBAT = BATdescriptor(*inXBAT_id)) == NULL) { + BBPunfix(inBAT->batCacheid); + throw(MAL, name, RUNTIME_OBJECT_MISSING); + } + if (*inYBAT_id != bat_nil && (inYBAT = BATdescriptor(*inYBAT_id)) == NULL) { + BBPunfix(inBAT->batCacheid); + if (*inXBAT_id != bat_nil) + BBPunfix(inXBAT->batCacheid); + throw(MAL, name, RUNTIME_OBJECT_MISSING); + } + if (*inZBAT_id != bat_nil && (inZBAT = BATdescriptor(*inZBAT_id)) == NULL) { + BBPunfix(inBAT->batCacheid); + if (*inXBAT_id != bat_nil) + BBPunfix(inXBAT->batCacheid); + if (*inYBAT_id != bat_nil) + BBPunfix(inYBAT->batCacheid); + throw(MAL, name, RUNTIME_OBJECT_MISSING); + } + + //create a new for the output BAT + if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("bit"), BATcount(inBAT), TRANSIENT)) == NULL) { + BBPunfix(inBAT->batCacheid); + if (*inXBAT_id != bat_nil) + BBPunfix(inXBAT->batCacheid); + if (*inYBAT_id != bat_nil) + BBPunfix(inYBAT->batCacheid); + if (*inZBAT_id != bat_nil) + BBPunfix(inZBAT->batCacheid); + throw(MAL, name, MAL_MALLOC_FAIL); + } + + //iterator over the input BAT + inBAT_iter = bat_iterator(inBAT); + + if (*inXBAT_id != bat_nil) + inXBAT_iter = bat_iterator(inXBAT); + if (*inYBAT_id != bat_nil) + inYBAT_iter = bat_iterator(inYBAT); + if (*inZBAT_id != bat_nil) + inZBAT_iter = bat_iterator(inZBAT); + + BATloop(inBAT, p, q) { //iterate over all valid elements + str err = NULL; + wkb *inWKB = NULL; + bit outSingle; + double x, y, z; + + + inWKB = (wkb *) BUNtail(inBAT_iter, p); + + if (*inXBAT_id != bat_nil) + x = *(double *) BUNtail(inXBAT_iter, p); + else + x = *dx; + if (*inYBAT_id != bat_nil) + y = *(double *) BUNtail(inYBAT_iter, p); + else + y = *dy; + if (*inZBAT_id != bat_nil) + z = *(double *) BUNtail(inZBAT_iter, p); + else + z = *dz; + + if ((err = (*func) (&outSingle, &inWKB, &x, &y, &z, srid)) != MAL_SUCCEED) { + BBPunfix(inBAT->batCacheid); + if (*inXBAT_id != bat_nil) + BBPunfix(inXBAT->batCacheid); + if (*inYBAT_id != bat_nil) + BBPunfix(inYBAT->batCacheid); + if (*inZBAT_id != bat_nil) + BBPunfix(inZBAT->batCacheid); + BBPunfix(outBAT->batCacheid); + return err; + } + BUNappend(outBAT, &outSingle, TRUE); //add the result to the new BAT + } + + //set the number of elements in the outBAT + BATsetcount(outBAT, BATcount(inBAT)); + + BBPunfix(inBAT->batCacheid); + if (*inXBAT_id != bat_nil) + BBPunfix(inXBAT->batCacheid); + if (*inYBAT_id != bat_nil) + BBPunfix(inYBAT->batCacheid); + if (*inZBAT_id != bat_nil) + BBPunfix(inZBAT->batCacheid); + BBPkeepref(*outBAT_id = outBAT->batCacheid); + + return MAL_SUCCEED; +} + +str +wkbIntersectsXYZ_bat(bat *outBAT_id, bat *inBAT_id, bat *inXBAT_id, double *dx, bat *inYBAT_id, double *dy, bat *inZBAT_id, double *dz, int* srid) +{ + return WKBtoBITxyzDBL_bat(outBAT_id, inBAT_id, inXBAT_id, dx, inYBAT_id, dy, inZBAT_id, dz, srid, wkbIntersectsXYZ, "batgeom.IntersectsXYZ"); +} + /***************************************************************************/ /*************************** IN: wkb - OUT: int ****************************/ /***************************************************************************/ @@ -755,7 +868,7 @@ wkbGetCoordinate_bat(bat *outBAT_id, bat } /******************************************************************************************/ -/************************** IN: wkb - OUT: wkb - X, Y and Z: dbl **************************/ +/***************************** IN: wkb dbl dbl dbl - OUT: wkb *****************************/ /******************************************************************************************/ static str diff --git a/geom/sql/40_geom.sql b/geom/sql/40_geom.sql --- a/geom/sql/40_geom.sql +++ b/geom/sql/40_geom.sql @@ -4035,6 +4035,7 @@ CREATE FUNCTION ST_Envelope(geom Geometr CREATE FUNCTION ST_Equals(geom1 Geometry, geom2 Geometry) RETURNS boolean EXTERNAL NAME geom."Equals"; CREATE FUNCTION ST_Disjoint(geom1 Geometry, geom2 Geometry) RETURNS boolean EXTERNAL NAME geom."Disjoint"; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list