Changeset: 8a27bd9efb0f for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/8a27bd9efb0f Modified Files: geom/monetdb5/geom.c geom/monetdb5/geom.h Branch: geo-update Log Message:
Added simpler data types to represent geometries (instead of using GEOSGeom) and refactored the code to use them. diffs (truncated from 913 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 @@ -16,54 +16,22 @@ #include "mal_exception.h" /** - * Auxilary Functions - * - **/ -/* Destroy a Geos geometry */ -static void destroyGeom(GEOSGeom *g) -{ - if (*g) - GEOSGeom_destroy((*g)); - (*g) = NULL; -} - -/* Converts wkb into Geos Geometries, if they are not NULL and have the same SRID (used for geographic functions) */ -static str wkbGetComplatibleGeometries(wkb **a, wkb **b, GEOSGeom *ga, GEOSGeom *gb) -{ - str err = MAL_SUCCEED; - - if (is_wkb_nil(*a) || is_wkb_nil(*b)) - { - destroyGeom(ga); - destroyGeom(gb); - return MAL_SUCCEED; - } - (*ga) = wkb2geos(*a); - (*gb) = wkb2geos(*b); - if ((*ga) == NULL || (*gb) == NULL) - { - destroyGeom(ga); - destroyGeom(gb); - err = createException(MAL, "geom.GetComplatibleGeometries", SQLSTATE(38000) "Geos operation wkb2geos failed"); - } - else if (GEOSGetSRID((*ga)) != GEOSGetSRID((*gb))) - { - destroyGeom(ga); - destroyGeom(gb); - err = createException(MAL, "geom.GetComplatibleGeometries", SQLSTATE(38000) "Geometries of different SRID"); - } - return err; -} - -/** * Convertions * **/ -/* Converts a latitude value in degrees to radians */ -static double longitudeDegreesToRadians(double lon_degrees) -{ +const double earth_radius = 6371.009; +const double earth_radius_meters = 6371009; + +/** + * Converts a longitude value in degrees to radians + * The normalization part was taken from PostGIS + */ +static double deg2RadLongitude(double lon_degrees) +{ + //Convert double lon = M_PI * lon_degrees / 180.0; + //Normalize if (lon == -1.0 * M_PI) return M_PI; if (lon == -2.0 * M_PI) @@ -87,10 +55,15 @@ static double longitudeDegreesToRadians( return lon; } -/* Converts a latitude value in degrees to radians */ -static double latitudeDegreesToRadians(double lat_degrees) -{ +/** + * Converts a latitude value in degrees to radians + * The normalization part was taken from PostGIS + */ +static double deg2RadLatitude(double lat_degrees) +{ + //Convert double lat = M_PI * lat_degrees / 180.0; + //Normalize if (lat > 2.0 * M_PI) lat = remainder(lat, 2.0 * M_PI); @@ -112,135 +85,264 @@ static double latitudeDegreesToRadians(d return lat; } +/* Converts the GeoPoint from degrees to radians latitude and longitude*/ +static GeoPoint deg2RadPoint(GeoPoint geo) +{ + geo.lon = deg2RadLongitude(geo.lon); + geo.lat = deg2RadLatitude(geo.lat); + return geo; +} + +#if 0 /** -* Convert spherical coordinates to cartesian coordinates on unit sphere -* From PostGIS -*/ -static void geog2cart(double lon, double lat, double *x, double *y, double *z) -{ - (*x) = cos(lat) * cos(lon); - (*y) = cos(lat) * sin(lon); - (*z) = sin(lat); -} - -static void geog2cart_r(double lon, double lat, double *x, double *y, double *z) -{ - double r = 6371.009; - (*x) = r * cos(lat) * cos(lon); - (*y) = r * cos(lat) * sin(lon); - (*z) = r * sin(lat); + * Converts a longitude value in radians to degrees + * The normalization part was taken from PostGIS + */ +static double rad2DegLongitude(double lon_radians) +{ + //Convert + double lon = lon_radians * 180.0 / M_PI; + //Normalize + if (lon > 360.0) + lon = remainder(lon, 360.0); + + if (lon < -360.0) + lon = remainder(lon, -360.0); + + if (lon > 180.0) + lon = -360.0 + lon; + + if (lon < -180.0) + lon = 360 + lon; + + if (lon == -180.0) + return 180.0; + + if (lon == -360.0) + return 0.0; + + return lon; } /** -* Convert cartesian coordinates on unit sphere to spherical coordinates -* From PostGIS -*/ -/*static void cart2geog(double x, double y, double z, double *lon, double *lat) -{ - (*lon) = atan2(y, x); - (*lat) = asin(z); + * Converts a latitude value in radians to degrees + * The normalization part was taken from PostGIS + */ +static double rad2DegLatitude(double lat_radians) +{ + //Convert + double lat = lat_radians * 180.0 / M_PI; + //Normalize + if (lat > 360.0) + lat = remainder(lat, 360.0); + + if (lat < -360.0) + lat = remainder(lat, -360.0); + + if (lat > 180.0) + lat = 180.0 - lat; + + if (lat < -180.0) + lat = -180.0 - lat; + + if (lat > 90.0) + lat = 180.0 - lat; + + if (lat < -90.0) + lat = -180.0 - lat; + + return lat; +} + +/* Converts the GeoPoint from degrees to radians latitude and longitude*/ +static void rad2DegPoint(GeoPoint *geo) +{ + geo->lon = rad2DegLongitude(geo->lon); + geo->lat = rad2DegLatitude(geo->lat); +} +#endif + +static GeoPoint geoPointFromGeom(GEOSGeom geom) +{ + GeoPoint geo; + GEOSGeomGetX(geom, &(geo.lon)); + GEOSGeomGetY(geom, &(geo.lat)); + return geo; +} + +/*static GeoLine geoLineFromGeom(GEOSGeom geom) +{ + GeoLine geo; + GEOSGeomGetX(GEOSGeomGetStartPoint(geom), &(geo.start.lon)); + GEOSGeomGetY(GEOSGeomGetStartPoint(geom), &(geo.start.lat)); + GEOSGeomGetX(GEOSGeomGetEndPoint(geom), &(geo.end.lon)); + GEOSGeomGetY(GEOSGeomGetEndPoint(geom), &(geo.end.lat)); + return geo; }*/ -static void cart2geog_r(double x, double y, double z, double *lon, double *lat) -{ - double r = 6371.009; - (*lon) = atan2(y, x); - (*lat) = asin(z / r); -} - -/* Returns the latitude and longitude (in radians) from a geographic Geom point */ -static void pointToRadian(GEOSGeom geom, double *lat_r, double *lon_r) -{ - double lat_d, lon_d; - GEOSGeomGetX(geom, &lon_d); - GEOSGeomGetY(geom, &lat_d); - - (*lat_r) = latitudeDegreesToRadians(lat_d); - (*lon_r) = longitudeDegreesToRadians(lon_d); -} - -/* Converts two lat/lon points into cartesian coordinates and creates a Line geometry */ -static GEOSGeom geographicPointsToCartesianLine(double lat1, double lon1, double lat2, double lon2) -{ - double x1, y1, z1, x2, y2, z2; - geog2cart(lon1, lat1, &x1, &y1, &z1); - geog2cart(lon2, lat2, &x2, &y2, &z2); - GEOSCoordSequence *lineSeq = GEOSCoordSeq_create(2, 3); - GEOSCoordSeq_setXYZ(lineSeq, 0, x1, y1, z1); - GEOSCoordSeq_setXYZ(lineSeq, 1, x2, y2, z2); - return GEOSGeom_createLineString(lineSeq); -} +static GeoLines geoLinesFromGeom(GEOSGeom geom) +{ + const GEOSCoordSequence *gcs = GEOSGeom_getCoordSeq(geom); + int segmentCount = GEOSGeomGetNumPoints(geom) - 1; + GeoLines geo; + geo.segmentCount = segmentCount; + //TODO Malloc fail exception? + geo.segments = GDKmalloc(sizeof(GeoLine) * segmentCount); + for (int i = 0; i < segmentCount; i++) + { + GEOSCoordSeq_getXY(gcs, i, &geo.segments[i].start.lon, &geo.segments[i].start.lat); + GEOSCoordSeq_getXY(gcs, i + 1, &geo.segments[i].end.lon, &geo.segments[i].end.lat); + } + return geo; +} + +static GeoPoint geoPointFromLatLon(double lon, double lat) +{ + GeoPoint geo; + geo.lon = lon; + geo.lat = lat; + return geo; +} + +static CartPoint cartPointFromXYZ(double x, double y, double z) +{ + CartPoint cart; + cart.x = x; + cart.y = y; + cart.z = z; + return cart; +} + +/* Converts Well-Known Bytes into Geos Geometries, if they are not NULL and have the same SRID (used for geographic functions) */ +static str wkbGetComplatibleGeometries(wkb **a, wkb **b, GEOSGeom *ga, GEOSGeom *gb) +{ + str err = MAL_SUCCEED; + + if (is_wkb_nil(*a) || is_wkb_nil(*b)) + { + (*ga) = NULL; + (*gb) = NULL; + return MAL_SUCCEED; + } + (*ga) = wkb2geos(*a); + (*gb) = wkb2geos(*b); + if ((*ga) == NULL || (*gb) == NULL) + { + err = createException(MAL, "geom.wkbGetComplatibleGeometries", SQLSTATE(38000) "Geos operation wkb2geos failed"); + } + else if (GEOSGetSRID((*ga)) != GEOSGetSRID((*gb))) + { + GEOSGeom_destroy(*ga); + GEOSGeom_destroy(*gb); + err = createException(MAL, "geom.wkbGetComplatibleGeometries", SQLSTATE(38000) "Geometries of different SRID"); + } + return err; +} + +/** +* Convert spherical coordinates to cartesian coordinates on unit sphere _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list