Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 4 additions & 46 deletions src/geo/stbox_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
#include "geo/stbox_functions.hpp"
#include "time_util.hpp"
#include "geo_util.hpp"
#include <cfloat>

#include "duckdb/common/exception.hpp"
#include "duckdb/common/vector.hpp"
#include "duckdb/common/typedefs.hpp"

#include <cmath>
#include <string>

#include "spatial/spatial_types.hpp"
Expand All @@ -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;
Expand Down Expand Up @@ -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");
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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();
}
Expand Down
19 changes: 14 additions & 5 deletions test/sql/stbox.test
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions vcpkg_ports/meos/portfile.cmake
Original file line number Diff line number Diff line change
@@ -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(
Expand Down
Loading