Skip to content

Commit

Permalink
Add GEOSGeom_transformXYZ (#1157)
Browse files Browse the repository at this point in the history
* Add GEOSGeom_transformXYZ
  • Loading branch information
Oreilles authored Sep 9, 2024
1 parent 1c0840a commit 1765c12
Show file tree
Hide file tree
Showing 4 changed files with 416 additions and 2 deletions.
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

0 comments on commit 1765c12

Please sign in to comment.