Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GEOSGeom_transformXYZ #1157

Merged
merged 2 commits into from
Sep 9, 2024
Merged
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
6 changes: 6 additions & 0 deletions capi/geos_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,12 @@ extern "C" {
}


Geometry*
GEOSGeom_transformXYZ(const GEOSGeometry* g, GEOSTransformXYZCallback callback, void* userdata) {
return GEOSGeom_transformXYZ_r(handle, g, callback, userdata);
}


//-------------------------------------------------------------------
// memory management functions
//------------------------------------------------------------------
Expand Down
50 changes: 48 additions & 2 deletions capi/geos_c.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ typedef int (*GEOSDistanceCallback)(
/**
* Callback function for use in GEOSGeom_transformXY.
* Allows custom function to be applied to x and y values for each coordinate
* in a geometry. Z values are unchanged by this function.
* in a geometry. Z and M values are unchanged by this function.
* Extra data for the calculation can be passed via the userdata.
*
* \param x coordinate value to be updated
Expand All @@ -299,6 +299,26 @@ typedef int (*GEOSTransformXYCallback)(
void* userdata);


/**
* Callback function for use in GEOSGeom_transformXYZ.
* Allows custom function to be applied to x, y and z values for each coordinate
* in a geometry. M values are unchanged by this function.
* Extra data for the calculation can be passed via the userdata.
*
* \param x coordinate value to be updated
* \param y coordinate value to be updated
* \param z coordinate value to be updated
* \param userdata extra data for the calculation
*
* \return 1 if calculation succeeded, 0 on failure
*/
typedef int (*GEOSTransformXYZCallback)(
double* x,
double* y,
double* z,
void* userdata);


/* ========== Interruption ========== */

/**
Expand Down Expand Up @@ -1821,6 +1841,13 @@ extern GEOSGeometry GEOS_DLL *GEOSGeom_transformXY_r(
GEOSTransformXYCallback callback,
void* userdata);

/** \see GEOSGeom_transformXYZ */
extern GEOSGeometry GEOS_DLL *GEOSGeom_transformXYZ_r(
GEOSContextHandle_t handle,
const GEOSGeometry* g,
GEOSTransformXYZCallback callback,
void* userdata);

/* ========= Algorithms ========= */

/** \see GEOSOrientationIndex */
Expand Down Expand Up @@ -4696,7 +4723,7 @@ extern int GEOS_DLL GEOSHilbertCode(
/**
* Apply XY coordinate transform callback to all coordinates in a copy of
* input geometry. If the callback returns an error, returned geometry will be
* NULL. Z values, if present, are not modified by this function.
* NULL. Z and M values, if present, are not modified by this function.
* \param[in] g Input geometry
* \param[in] callback a function to be executed for each coordinate in the
geometry. The callback takes 3 parameters: x and y coordinate
Expand All @@ -4712,6 +4739,25 @@ extern GEOSGeometry GEOS_DLL *GEOSGeom_transformXY(
GEOSTransformXYCallback callback,
void* userdata);

/**
* Apply XYZ coordinate transform callback to all coordinates in a copy of
* input geometry. If the callback returns an error, returned geometry will be
* NULL. M values, if present, are not modified by this function.
* \param[in] g Input geometry
* \param[in] callback a function to be executed for each coordinate in the
geometry. The callback takes 4 parameters: x, y and z coordinate
values to be updated and a void userdata pointer.
* \param userdata an optional pointer to pe passed to 'callback' as an argument
* \return a copy of the input geometry with transformed coordinates.
* Caller must free with GEOSGeom_destroy().
*
* \since 3.13
*/
extern GEOSGeometry GEOS_DLL *GEOSGeom_transformXYZ(
const GEOSGeometry* g,
GEOSTransformXYZCallback callback,
void* userdata);

/**
* Snaps the vertices and segments of the first geometry to vertices of the
* second geometry within the given tolerance.
Expand Down
29 changes: 29 additions & 0 deletions capi/geos_ts_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1655,6 +1655,35 @@ extern "C" {
}


Geometry*
GEOSGeom_transformXYZ_r(GEOSContextHandle_t handle, const GEOSGeometry* g, GEOSTransformXYZCallback callback, void* userdata) {

struct TransformFilter final: public geos::geom::CoordinateFilter {
TransformFilter(GEOSTransformXYZCallback p_callback,
void* p_userdata) :
m_callback(p_callback),
m_userdata(p_userdata) {}

void filter_rw(Coordinate* c) const override {
if (!m_callback(&(c->x), &(c->y), &(c->z), m_userdata)) {
throw std::runtime_error(std::string("Failed to transform coordinates."));
}
}

GEOSTransformXYZCallback m_callback;
void* m_userdata;
};

return execute(handle, [&]() {
TransformFilter filter(callback, userdata);
auto ret = g->clone();
ret->apply_rw(&filter);
ret->geometryChanged();
return ret.release();
});
}


//-------------------------------------------------------------------
// memory management functions
//------------------------------------------------------------------
Expand Down
Loading