diff --git a/src/geo/stbox_functions.cpp b/src/geo/stbox_functions.cpp index b5398f02..37dd9924 100644 --- a/src/geo/stbox_functions.cpp +++ b/src/geo/stbox_functions.cpp @@ -4,13 +4,11 @@ #include "geo/stbox_functions.hpp" #include "time_util.hpp" #include "geo_util.hpp" -#include #include "duckdb/common/exception.hpp" #include "duckdb/common/vector.hpp" #include "duckdb/common/typedefs.hpp" -#include #include #include "spatial/spatial_types.hpp" @@ -20,36 +18,6 @@ namespace duckdb { namespace { -/* MEOS stbox_area() can SIGSEGV on geodetic boxes (3D / PolyhedralSurface path). For geodetic - * footprints use spherical rectangle area (WGS84 sphere); avoids MEOS geog_in/geog_area faults. */ -/* Sphere zone area between two meridians and parallels (m^2). Matches MEOS/PostGIS sphere model - * closely enough for tests; avoids MEOS geog_in/geog_area which can SIGSEGV in this extension. */ -inline double Spherical_lonlat_rect_area_m2(double xmin, double ymin, double xmax, double ymax, - bool use_spheroid) { - (void)use_spheroid; - constexpr double DEG_TO_RAD = M_PI / 180.0; - /* WGS84 semi-major axis (m); MEOS geog_area on sphere uses ~this for spheroid=false path. */ - constexpr double R = 6378137.0; - const double lam1 = xmin * DEG_TO_RAD; - const double lam2 = xmax * DEG_TO_RAD; - const double phi1 = ymin * DEG_TO_RAD; - const double phi2 = ymax * DEG_TO_RAD; - return R * R * (lam2 - lam1) * (std::sin(phi2) - std::sin(phi1)); -} - -inline double Geodetic_stbox_footprint_area(const STBox *box, bool use_spheroid) { - return Spherical_lonlat_rect_area_m2(box->xmin, box->ymin, box->xmax, box->ymax, use_spheroid); -} - -/* For stbox_to_geo: 2D geodetic box via MEOS constructor (no Z dimension in output geometry). */ -inline STBox *Stbox_geodetic_xy_copy(const STBox *box) { - if (!stbox_isgeodetic(box) || !stbox_hasz(box)) { - return nullptr; - } - return stbox_make(stbox_hasx(box), false, true, box->srid, box->xmin, box->xmax, box->ymin, box->ymax, - 0.0, 0.0, stbox_hast(box) ? &box->period : nullptr); -} - inline void Stbox_normalize_geodetic_srid(STBox *box) { if ((stbox_isgeodetic(box) || MEOS_FLAGS_GET_GEODETIC(box->flags)) && box->srid == 0) { box->srid = 4326; @@ -497,11 +465,8 @@ bool StboxFunctions::Geo_to_stbox_cast(Vector &source, Vector &result, idx_t cou throw InternalException("Failure in Stbox_expand_space: unable to cast binary to stbox"); } - STBox *flat = Stbox_geodetic_xy_copy(stbox); - STBox *geo_src = flat ? flat : stbox; - GSERIALIZED *gs = stbox_to_geo(geo_src); + GSERIALIZED *gs = stbox_to_geo(stbox); if (!gs) { - free(flat); free(stbox); throw InvalidInputException("Failed to convert stbox to geometry"); } @@ -510,7 +475,6 @@ bool StboxFunctions::Geo_to_stbox_cast(Vector &source, Vector &result, idx_t cou string_t stored_result = StringVector::AddStringOrBlob(result, geometry_blob); free(gs); - free(flat); free(stbox); return stored_result; } @@ -1142,16 +1106,10 @@ void StboxFunctions::Stbox_area(DataChunk &args, ExpressionState &state, Vector throw InternalException("Failure in Stbox_area: unable to cast binary to stbox"); } bool spheroid = true; // default value, TODO: handle argument - double ret; - /* MEOS stbox_area() can SIGSEGV on geodetic boxes; use spherical lon/lat footprint. */ - const bool geodetic = stbox_isgeodetic(stbox) || MEOS_FLAGS_GET_GEODETIC(stbox->flags); - if (geodetic) { - ret = Geodetic_stbox_footprint_area(stbox, spheroid); - } else { - ret = stbox_area(stbox, spheroid); - } + double ret = stbox_area(stbox, spheroid); free(stbox); - if (ret == DBL_MAX) { + /* MEOS stbox_area returns -1.0 on error (null box or no X dimension). */ + if (ret < 0) { mask.SetInvalid(idx); return double(); } diff --git a/test/sql/stbox.test b/test/sql/stbox.test index 87b4dcc7..64291fd7 100644 --- a/test/sql/stbox.test +++ b/test/sql/stbox.test @@ -85,11 +85,20 @@ SELECT area(stbox 'STBOX ZT(((1.0,2.0,3.0),(4.0,5.0,6.0)),[2000-01-01,2000-01-02 ---- 9 -# TODO: re-enable when MEOS stbox_area no longer SIGSEGVs on GEODSTBOX ZT (PolyhedralSurface path). -# query I -# SELECT round(area(stbox 'GEODSTBOX ZT(((1.0,2.0,3.0),(4.0,5.0,6.0)),[2000-01-01,2000-01-02])'), 1); -# ---- -# 110593375170.3 +query I +SELECT round(area(stbox 'GEODSTBOX ZT(((1.0,2.0,3.0),(4.0,5.0,6.0)),[2000-01-01,2000-01-02])'), 1); +---- +110593375170.3 + +query I +SELECT round(area(stbox 'GEODSTBOX X((1.0,2.0),(3.0,4.0))'), 1); +---- +49173168695.2 + +query I +SELECT round(area(stbox 'GEODSTBOX Z((1.0,2.0,3.0),(4.0,5.0,6.0))'), 1); +---- +110593375170.3 query I SELECT expandSpace(stbox 'STBOX XT(((1.0,2.0),(1.0,2.0)),[2000-01-01,2000-01-01])', 2.0); diff --git a/vcpkg_ports/meos/portfile.cmake b/vcpkg_ports/meos/portfile.cmake index 82619e3a..9aeff5d5 100644 --- a/vcpkg_ports/meos/portfile.cmake +++ b/vcpkg_ports/meos/portfile.cmake @@ -1,8 +1,8 @@ vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO estebanzimanyi/MobilityDB - REF a8178dc9d56d841d0eb5025a7e8717c8d25a1d0f - SHA512 030a144bb3247695702dd2de11f4c389ed28c6eb0186e6988a489e2b00e9801179ba8f27bcbcd81ae89e398a7277ed7f9ff7058dbf15f5db322ae4644365c560 + REF 3db47f887c61f049a6a03db55c48bedf6d10eee4 + SHA512 b73123bca036813c43937f90f0d0ce45af5cb9e39d6a597304199d21ae854212319a3a7b58ecd075eb5678d89d6d5990b9faf63dd29bd8c9a4e2ed83282b94c5 ) vcpkg_replace_string(