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 clustering functions to C API #1154

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
57 changes: 57 additions & 0 deletions capi/geos_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <geos/io/GeoJSONReader.h>
#include <geos/io/GeoJSONWriter.h>
#include <geos/operation/buffer/BufferParameters.h>
#include <geos/operation/cluster/Clusters.h>
#include <geos/util/Interrupt.h>

#include <stdexcept>
Expand All @@ -40,6 +41,7 @@
// violations.
#define GEOSGeometry geos::geom::Geometry
#define GEOSPreparedGeometry geos::geom::prep::PreparedGeometry
#define GEOSClusterInfo geos::operation::cluster::Clusters
#define GEOSCoordSequence geos::geom::CoordinateSequence
#define GEOSBufferParams geos::operation::buffer::BufferParameters
#define GEOSSTRtree geos::index::strtree::TemplateSTRtree<void*>
Expand Down Expand Up @@ -343,6 +345,61 @@ extern "C" {
return GEOSNearestPoints_r(handle, g1, g2);
}

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

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

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

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

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

std::size_t GEOSClusterInfo_getNumClusters(const GEOSClusterInfo* clusters)
{
return GEOSClusterInfo_getNumClusters_r(handle, clusters);
}

std::size_t GEOSClusterInfo_getClusterSize(const GEOSClusterInfo* clusters, size_t i)
{
return GEOSClusterInfo_getClusterSize_r(handle, clusters, i);
}

const std::size_t* GEOSClusterInfo_getInputsForClusterN(const GEOSClusterInfo* clusters, size_t i)
{
return GEOSClusterInfo_getInputsForClusterN_r(handle, clusters, i);
}

std::size_t* GEOSClusterInfo_getClustersForInputs(const GEOSClusterInfo* clusters)
{
return GEOSClusterInfo_getClustersForInputs_r(handle, clusters);
}

void GEOSClusterInfo_destroy(GEOSClusterInfo* info)
{
GEOSClusterInfo_destroy_r(handle, info);
}

Geometry*
GEOSGeomFromWKT(const char* wkt)
{
Expand Down
171 changes: 169 additions & 2 deletions capi/geos_c.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ typedef struct GEOSBufParams_t GEOSBufferParams;
*/
typedef struct GEOSMakeValidParams_t GEOSMakeValidParams;

/**
* Object containing information about cluster of geometries.
* \see GEOSClusterInfo_destroy()
*/
typedef struct GEOSClusterInfo_t GEOSClusterInfo;

#endif

/** \cond */
Expand Down Expand Up @@ -1848,6 +1854,50 @@ extern GEOSGeometry GEOS_DLL *GEOSGeom_transformXYZ_r(
GEOSTransformXYZCallback callback,
void* userdata);

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

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

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

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

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

/** \see GEOSClusterInfo_getNumClusters */
extern size_t GEOS_DLL GEOSClusterInfo_getNumClusters_r(GEOSContextHandle_t, const GEOSClusterInfo* clusters);

/** \see GEOSClusterInfo_getClusterSize */
extern size_t GEOS_DLL GEOSClusterInfo_getClusterSize_r(GEOSContextHandle_t, const GEOSClusterInfo* clusters, size_t i);

/** \see GEOSClusterInfo_getClustersForInputs */
extern size_t GEOS_DLL* GEOSClusterInfo_getClustersForInputs_r(GEOSContextHandle_t, const GEOSClusterInfo* clusters);

/** \see GEOSClusterInfo_getInputsForClusterN */
extern const size_t GEOS_DLL* GEOSClusterInfo_getInputsForClusterN_r(GEOSContextHandle_t, const GEOSClusterInfo* clusters, size_t i);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that we are returning const size_t* here. This avoids a memory allocation and array copy for each cluster, but constrains our implementation of GEOSClusterInfo to actually store these values in a contiguous block somewhere. I think that's a reasonable tradeoff.


/** \see GEOSClusterInfo_destroy */
extern void GEOS_DLL GEOSClusterInfo_destroy_r(GEOSContextHandle_t, GEOSClusterInfo* info);

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

/** \see GEOSOrientationIndex */
Expand Down Expand Up @@ -3759,6 +3809,123 @@ extern GEOSGeometry GEOS_DLL *GEOSClipByRect(
extern GEOSGeometry GEOS_DLL *GEOSSharedPaths(
const GEOSGeometry* g1,
const GEOSGeometry* g2);
///@}

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




static const size_t GEOS_CLUSTER_NONE = (size_t) -1;

///@{
/**
* @brief GEOSClusterDBSCAN
*
* Cluster geometries using the DBSCAN algorithm
*
* @param g a collection of geometries to be clustered
* @param eps distance parameter for clustering
* @param minPoints density parameter for clustering
* @return cluster information object
*/
extern GEOSClusterInfo GEOS_DLL* GEOSClusterDBSCAN(const GEOSGeometry* g, double eps, unsigned minPoints);

/**
* @brief GEOSClusterGeometryDistance
*
* Cluster geometries according to a distance threshold
*
* @param g a collection of geometries to be clustered
* @param d minimum distance between geometries in the same cluster
* @return cluster information object
*/
extern GEOSClusterInfo GEOS_DLL* GEOSClusterGeometryDistance(const GEOSGeometry* g, double d);

/**
* @brief GEOSClusterGeometryIntersects
*
* Cluster geometries that intersect
*
* @param g a collection of geometries to be clustered
* @return cluster information object
*/
extern GEOSClusterInfo GEOS_DLL* GEOSClusterGeometryIntersects(const GEOSGeometry* g);

/**
* @brief GEOSClusterEnvelopeDistance
*
* Cluster geometries according to an envelope distance threshold
*
* @param g a collection of geometries to be clustered
* @param d minimum envelope distance between geometries in the same cluster
* @return cluster information object
*/
extern GEOSClusterInfo GEOS_DLL* GEOSClusterEnvelopeDistance(const GEOSGeometry* g, double d);

/**
* @brief GEOSClusterEnvelopeIntersects
*
* Cluster geometries whose envelopes intersect
*
* @param g
* @return cluster information object
*/
extern GEOSClusterInfo GEOS_DLL* GEOSClusterEnvelopeIntersects(const GEOSGeometry* g);

/**
* @brief GEOSClusterInfo_getNumClusters
*
* Get the number of clusters identifed by a clustering operation
*
* @param clusters cluster information object
* @return number of clusters identifed
*/
extern size_t GEOS_DLL GEOSClusterInfo_getNumClusters(const GEOSClusterInfo* clusters);

/**
* @brief GEOSClusterInfo_getSize
*
* Get the number of elements in the ith cluster (0-indexed)
*
* @param clusters cluster information object
* @param i cluster for which a size will be returned
* @return number of elements in the cluster
*/
extern size_t GEOS_DLL GEOSClusterInfo_getClusterSize(const GEOSClusterInfo* clusters, size_t i );

/**
* @brief GEOSClusterInfo_getClustersForInputs
*
* Get the cluster index associated with each input to the clustering operation.
* Inputs that do are not associated with any cluster will have an index of GEOS_CLUSTER_NONE.
*
* @param clusters cluster information object
* @return an array of cluster indices, to be freed by the caller.
*/
extern size_t GEOS_DLL* GEOSClusterInfo_getClustersForInputs(const GEOSClusterInfo* clusters);

/**
* @brief GEOSClusterInfo_getInputsForClusterN
* @param clusters cluster information object
* @param i index of the cluster for which indices should be retrieved
* @return a pointer to an array of cluster indices. Size of the array is indicated by
* GEOSClusterInfo_getNumElements. The array is owner by the cluster information
* object and should not be modified or freed by the caller.
*/
extern const size_t GEOS_DLL* GEOSClusterInfo_getInputsForClusterN(const GEOSClusterInfo* clusters, size_t i);

/**
* @brief GEOSClusterInfo_destroy
*
* Destroy a cluster information object.
*
* @param clusters cluster information object
*/
extern void GEOS_DLL GEOSClusterInfo_destroy(GEOSClusterInfo* clusters);

///@}

Expand Down Expand Up @@ -4975,9 +5142,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
Loading
Loading