Skip to content

Commit

Permalink
C API cluster functions: Return ids instead of GEOSGeometry*
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaston committed Sep 23, 2024
1 parent 5d2cde7 commit 140130d
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 129 deletions.
35 changes: 20 additions & 15 deletions capi/geos_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,29 +343,34 @@ extern "C" {
return GEOSNearestPoints_r(handle, g1, g2);
}

GEOSGeometry*
GEOSClusterDBSCAN(Geometry* g, double eps, unsigned minPoints) {
return GEOSClusterDBSCAN_r(handle, g, eps, minPoints);
unsigned*
GEOSClusterDBSCAN(const GEOSGeometry* g, double eps, unsigned minPoints, unsigned* numClusters)
{
return GEOSClusterDBSCAN_r(handle, g, eps, minPoints, numClusters);
}

GEOSGeometry*
GEOSClusterGeometryDistance(GEOSGeometry* g, double d) {
return GEOSClusterGeometryDistance_r(handle, g, d);
unsigned*
GEOSClusterGeometryDistance(const GEOSGeometry* g, double d, unsigned* numClusters)
{
return GEOSClusterGeometryDistance_r(handle, g, d, numClusters);
}

GEOSGeometry*
GEOSClusterGeometryIntersects(GEOSGeometry* g) {
return GEOSClusterGeometryIntersects_r(handle, g);
unsigned*
GEOSClusterGeometryIntersects(const GEOSGeometry* g, unsigned* numClusters)
{
return GEOSClusterGeometryIntersects_r(handle, g, numClusters);
}

GEOSGeometry*
GEOSClusterEnvelopeDistance(GEOSGeometry* g, double d) {
return GEOSClusterEnvelopeDistance_r(handle, g, d);
unsigned*
GEOSClusterEnvelopeDistance(const GEOSGeometry* g, double d, unsigned* numClusters)
{
return GEOSClusterEnvelopeDistance_r(handle, g, d, numClusters);
}

GEOSGeometry*
GEOSClusterEnvelopeIntersects(GEOSGeometry* g) {
return GEOSClusterEnvelopeIntersects_r(handle, g);
unsigned*
GEOSClusterEnvelopeIntersects(const GEOSGeometry* g, unsigned* numClusters)
{
return GEOSClusterEnvelopeIntersects_r(handle, g, numClusters);
}

Geometry*
Expand Down
83 changes: 48 additions & 35 deletions capi/geos_c.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -1849,34 +1849,38 @@ extern GEOSGeometry GEOS_DLL *GEOSGeom_transformXYZ_r(
void* userdata);

/** \see GEOSClusterDBSCAN */
extern GEOSGeometry GEOS_DLL *GEOSClusterDBSCAN_r(
GEOSContextHandle_t handle,
GEOSGeometry* g,
double eps,
unsigned minPoints);

extern unsigned GEOS_DLL* GEOSClusterDBSCAN_r(
GEOSContextHandle_t handle,
const GEOSGeometry* g,
double eps,
unsigned minPoints,
unsigned* numClusters);

/** \see GEOSClusterGeometryDistance */
extern GEOSGeometry GEOS_DLL *GEOSClusterGeometryDistance_r(
GEOSContextHandle_t handle,
GEOSGeometry* g,
double d);
extern unsigned GEOS_DLL* GEOSClusterGeometryDistance_r(
GEOSContextHandle_t handle,
const GEOSGeometry* g,
double d,
unsigned* numClusters);

/** \see GEOSClusterGeometryIntersects */
extern GEOSGeometry GEOS_DLL *GEOSClusterGeometryIntersects_r(
GEOSContextHandle_t handle,
GEOSGeometry* g);
extern unsigned GEOS_DLL* GEOSClusterGeometryIntersects_r(
GEOSContextHandle_t handle,
const GEOSGeometry* g,
unsigned* numClusters);

/** \see GEOSClusterEnvelopeDistance */
extern GEOSGeometry GEOS_DLL *GEOSClusterEnvelopeDistance_r(
GEOSContextHandle_t handle,
GEOSGeometry* g,
double d);
extern unsigned GEOS_DLL* GEOSClusterEnvelopeDistance_r(
GEOSContextHandle_t handle,
const GEOSGeometry* g,
double d,
unsigned* numClusters);

/** \see GEOSClusterEnvelopeIntersects */
extern GEOSGeometry GEOS_DLL *GEOSClusterEnvelopeIntersects_r(
GEOSContextHandle_t handle,
GEOSGeometry* g);
extern unsigned GEOS_DLL* GEOSClusterEnvelopeIntersects_r(
GEOSContextHandle_t handle,
const GEOSGeometry* g,
unsigned* numClusters);

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

Expand Down Expand Up @@ -3791,10 +3795,13 @@ extern GEOSGeometry GEOS_DLL *GEOSSharedPaths(
const GEOSGeometry* g2);
///@}

/* ========== Buffer related functions ========== */
/* ========== Clustering functions ========== */
/** @name Clustering
* Functions for clustering geometries
*/

static const unsigned GEOS_CLUSTER_NONE = 4294967295;

///@{
/**
* @brief GEOSClusterDBSCAN
Expand All @@ -3804,51 +3811,57 @@ extern GEOSGeometry GEOS_DLL *GEOSSharedPaths(
* @param g a collection of geometries to be clustered
* @param eps distance parameter for clustering
* @param minPoints density parameter for clustering
* @return GeometryCollection whose components represent individual clusters
* @param numClusters the number of clusters formed
* @return an array of cluster identifiers
*/
extern GEOSGeometry GEOS_DLL *GEOSClusterDBSCAN(GEOSGeometry* g, double eps, unsigned minPoints);
extern unsigned GEOS_DLL* GEOSClusterDBSCAN(const GEOSGeometry* g, double eps, unsigned minPoints,
unsigned* numClusters);

/**
* @brief GEOSClusterGeometryDistance
*
* Cluster geometries according to a distance threshold
*
* @param g a collection of geometries to be clustered
* @param d minimim distance between geometries in the same cluster
* @return GeometryCollection whose components represent individual clusters
* @param d minimum distance between geometries in the same cluster
* @param numClusters the number of clusters formed
* @return an array of cluster identifiers
*/
extern GEOSGeometry GEOS_DLL *GEOSClusterGeometryDistance(GEOSGeometry* g, double d);
extern unsigned GEOS_DLL* GEOSClusterGeometryDistance(const GEOSGeometry* g, double d, unsigned* numClusters);

/**
* @brief GEOSClusterGeometryIntersects
*
* Cluster geometries that intersect
*
* @param g a collection of geometries to be clustered
* @return GeometryCollection whose components represent individual clusters
* @param numClusters the number of clusters formed
* @return an array of cluster identifiers
*/
extern GEOSGeometry GEOS_DLL *GEOSClusterGeometryIntersects(GEOSGeometry* g);
extern unsigned GEOS_DLL* GEOSClusterGeometryIntersects(const GEOSGeometry* g, unsigned* numClusters);

/**
* @brief GEOSClusterEnvelopeDistance
*
* Cluster geometries according to an envelope distance threshold
*
* @param g a collection of geometries to be clustered
* @param d minimim envelope distance between geometries in the same cluster
* @return GeometryCollection whose components represent individual clusters
* @param d minimum envelope distance between geometries in the same cluster
* @param numClusters the number of clusters formed
* @return an array of cluster identifiers
*/
extern GEOSGeometry GEOS_DLL *GEOSClusterEnvelopeDistance(GEOSGeometry* g, double d);
extern unsigned GEOS_DLL* GEOSClusterEnvelopeDistance(const GEOSGeometry* g, double d, unsigned* numClusters);

/**
* @brief GEOSClusterEnvelopeIntersects
*
* Cluster geometries whose envelopes intersect
*
* @param g
* @return GeometryCollection whose components represent individual clusters
* @param numClusters the number of clusters formed
* @return an array of cluster identifiers
*/
extern GEOSGeometry GEOS_DLL *GEOSClusterEnvelopeIntersects(GEOSGeometry* g);
extern unsigned GEOS_DLL* GEOSClusterEnvelopeIntersects(const GEOSGeometry* g, unsigned* numClusters);
///@}

/* ========== Buffer related functions ========== */
Expand Down Expand Up @@ -5064,9 +5077,9 @@ extern char GEOS_DLL GEOSEqualsIdentical(

/**
* Calculate the [DE9IM](https://en.wikipedia.org/wiki/DE-9IM) string for a geometry pair
* and compare against a DE9IM pattern.
* and compare against a DE9IM pattern.
* Returns true if the computed matrix matches the pattern.
* The pattern is a 9-character string
* The pattern is a 9-character string
* containing symbols in the set "012TF*".
* "012F" match the corresponding dimension symbol;
* "T" matches any non-empty dimension; "*" matches any dimension.
Expand Down
61 changes: 41 additions & 20 deletions capi/geos_ts_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -953,53 +953,74 @@ extern "C" {
});
}

Geometry*
GEOSClusterDBSCAN_r(GEOSContextHandle_t extHandle, Geometry* g, double eps, unsigned minPoints)
static unsigned* capi_clusters(const Geometry* g,
geos::operation::cluster::AbstractClusterFinder& finder,
unsigned* numClusters)
{
std::vector<const Geometry*> input{g->getNumGeometries()};
for (std::size_t i = 0; i < input.size(); i++) {
input[i] = g->getGeometryN(i);
}

auto result = finder.cluster(input);

if (numClusters) {
*numClusters = static_cast<unsigned>(result.getNumClusters());
}

auto cluster_ids = result.getClusterIds(GEOS_CLUSTER_NONE);
unsigned* ids = (unsigned*) malloc(cluster_ids.size() * sizeof(unsigned));
for (std::size_t i = 0; i < cluster_ids.size(); i++) {
ids[i] = static_cast<unsigned>(cluster_ids[i]);
}

return ids;
}

unsigned*
GEOSClusterDBSCAN_r(GEOSContextHandle_t extHandle, const Geometry* g, double eps, unsigned minPoints,
unsigned* numClusters)
{
return execute(extHandle, [&]() {
std::unique_ptr<Geometry> in(g);
geos::operation::cluster::DBSCANClusterFinder finder(eps, minPoints);
return finder.clusterToCollection(std::move(in)).release();

return capi_clusters(g, finder, numClusters);
});
}

Geometry*
GEOSClusterGeometryIntersects_r(GEOSContextHandle_t extHandle, Geometry* g)
unsigned*
GEOSClusterGeometryIntersects_r(GEOSContextHandle_t extHandle, const Geometry* g, unsigned* numClusters)
{
return execute(extHandle, [&]() {
std::unique_ptr<Geometry> in(g);
geos::operation::cluster::GeometryIntersectsClusterFinder finder;
return finder.clusterToCollection(std::move(in)).release();
return capi_clusters(g, finder, numClusters);
});
}

Geometry*
GEOSClusterEnvelopeIntersects_r(GEOSContextHandle_t extHandle, Geometry* g)
unsigned*
GEOSClusterEnvelopeIntersects_r(GEOSContextHandle_t extHandle, const Geometry* g, unsigned* numClusters)
{
return execute(extHandle, [&]() {
std::unique_ptr<Geometry> in(g);
geos::operation::cluster::EnvelopeIntersectsClusterFinder finder;
return finder.clusterToCollection(std::move(in)).release();
return capi_clusters(g, finder, numClusters);
});
}

Geometry*
GEOSClusterEnvelopeDistance_r(GEOSContextHandle_t extHandle, Geometry* g, double d)
unsigned*
GEOSClusterEnvelopeDistance_r(GEOSContextHandle_t extHandle, const Geometry* g, double d, unsigned* numClusters)
{
return execute(extHandle, [&]() {
std::unique_ptr<Geometry> in(g);
geos::operation::cluster::EnvelopeDistanceClusterFinder finder(d);
return finder.clusterToCollection(std::move(in)).release();
return capi_clusters(g, finder, numClusters);
});
}

Geometry*
GEOSClusterGeometryDistance_r(GEOSContextHandle_t extHandle, Geometry* g, double d)
unsigned*
GEOSClusterGeometryDistance_r(GEOSContextHandle_t extHandle, const Geometry* g, double d, unsigned* numClusters)
{
return execute(extHandle, [&]() {
std::unique_ptr<Geometry> in(g);
geos::operation::cluster::GeometryDistanceClusterFinder finder(d);
return finder.clusterToCollection(std::move(in)).release();
return capi_clusters(g, finder, numClusters);
});
}

Expand Down
Loading

0 comments on commit 140130d

Please sign in to comment.