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 GEOSPrepared<PRED>XY functions to C API #677

Merged
merged 5 commits into from
Sep 12, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
xxxx-xx-xx

- New things:
- Polygonal coverage operations: CoverageValidator, CoveragePolygonValidator,
- Polygonal coverage operations: CoverageValidator, CoveragePolygonValidator,
CoverageGapFinder, CoverageUnion (JTS-900, Martin Davis & Paul Ramsey)
- CAPI: GEOSPreparedContainsXY, GEOSPreparedContainsProperlyXY,
GEOSPreparedIntersectsXY (GH-677, Dan Baston)

- Fixes/Improvements:
-
Expand Down
104 changes: 62 additions & 42 deletions benchmarks/capi/GEOSPreparedContainsPerfTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,80 +32,100 @@
class GEOSPreparedContainsPerfTest {

public:
void test(const GEOSGeometry* g, std::size_t num_points) {
void test(const std::vector<GEOSGeometry*>& geoms, std::size_t num_points) {
using namespace geos::geom;

double xmin, xmax, ymin, ymax;
geos::util::Profile sw("GEOSPreparedContains");
geos::util::Profile sw_xy("GEOSPreparedContainsXY");

GEOSGeom_getXMin(g, &xmin);
GEOSGeom_getXMax(g, &xmax);
GEOSGeom_getYMin(g, &ymin);
GEOSGeom_getYMax(g, &ymax);
std::size_t hits = 0;
std::size_t hits_xy = 0;

std::default_random_engine e(12345);
std::uniform_real_distribution<> xdist(xmin, xmax);
std::uniform_real_distribution<> ydist(ymin, ymax);
for (const auto& g: geoms) {
double xmin, xmax, ymin, ymax;

std::vector<Coordinate> coords(num_points);
std::generate(coords.begin(), coords.end(), [&xdist, &ydist, &e]() {
return Coordinate(xdist(e), ydist(e));
});
GEOSGeom_getXMin(g, &xmin);
GEOSGeom_getXMax(g, &xmax);
GEOSGeom_getYMin(g, &ymin);
GEOSGeom_getYMax(g, &ymax);

geos::util::Profile sw("GEOSPreparedContains");
sw.start();

std::size_t hits = 0;
auto prep = GEOSPrepare(g);
for (const auto& c : coords) {
auto pt = GEOSGeom_createPointFromXY(c.x, c.y);
std::default_random_engine e(12345);
std::uniform_real_distribution<> xdist(xmin, xmax);
std::uniform_real_distribution<> ydist(ymin, ymax);

if (GEOSPreparedContains(prep, pt)) {
hits++;
}
std::vector<Coordinate> coords(num_points);
std::generate(coords.begin(), coords.end(), [&xdist, &ydist, &e]() {
return Coordinate(xdist(e), ydist(e));
});

GEOSGeom_destroy(pt);
}

GEOSPreparedGeom_destroy(prep);
sw.start();
auto prep = GEOSPrepare(g);
for (const auto& c : coords) {
auto pt = GEOSGeom_createPointFromXY(c.x, c.y);
if (GEOSPreparedContains(prep, pt)) {
hits++;
}

sw.stop();
GEOSGeom_destroy(pt);
}
GEOSPreparedGeom_destroy(prep);
sw.stop();

sw_xy.start();
prep = GEOSPrepare(g);
for (const auto& c : coords) {
if (GEOSPreparedContainsXY(prep, c.x, c.y)) {
hits_xy++;
}
}
GEOSPreparedGeom_destroy(prep);
sw_xy.stop();
}

std::cout << sw.name << ": " << hits << " hits from " << num_points << " points in " << sw.getTotFormatted() << std::endl;

std::cout << sw_xy.name << ": " << hits_xy << " hits from " << num_points << " points in " << sw_xy.getTotFormatted() << std::endl;
}
};

int main(int argc, char** argv) {
if (argc != 3) {
std::cout << "perf_geospreparedcontins performs a specified number of point-in-polygon tests" << std::endl;
std::cout << "on randomly generated points from the bounding box of a single geometry provided" << std::endl;
std::cout << "perf_geospreparedcontains performs a specified number of point-in-polygon tests" << std::endl;
std::cout << "on randomly generated points from the bounding box of each geometry provided" << std::endl;
std::cout << "in a file as WKT." << std::endl;
std::cout << std::endl;
std::cout << "Usage: perf_geospreparedcontins [wktfile] [n]" << std::endl;
std::cout << "Usage: perf_geospreparedcontains [wktfile] [n]" << std::endl;
return 0;
}

initGEOS(nullptr, nullptr);

GEOSPreparedContainsPerfTest tester;

std::size_t n = static_cast<std::size_t>(std::atoi(argv[2]));
std::cout << "Performing " << n << " point-in-polygon tests." << std::endl;

std::string fname{argv[1]};
std::cout << "Reading shape from " << fname << std::endl;
std::cout << "Reading shapes from " << fname << std::endl;

std::vector<GEOSGeometry*> geoms;

std::ifstream f(fname);
std::stringstream buff;
buff << f.rdbuf();
std::string line;
long i = 0;
while(std::getline(f, line)) {
if (line != "") {
geoms.push_back(GEOSGeomFromWKT(line.c_str()));
i++;
}
}
f.close();

std::string wkt = buff.str();
buff.clear();

initGEOS(nullptr, nullptr);
GEOSGeometry* g = GEOSGeomFromWKT(wkt.c_str());
wkt.clear();
std::cout << "Read " << geoms.size() << " geometries." << std::endl;

tester.test(g, n);
tester.test(geoms, n);

GEOSGeom_destroy(g);
for (auto& g : geoms) {
GEOSGeom_destroy(g);
}
}
18 changes: 18 additions & 0 deletions capi/geos_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1449,12 +1449,24 @@ extern "C" {
return GEOSPreparedContains_r(handle, pg1, g2);
}

char
GEOSPreparedContainsXY(const geos::geom::prep::PreparedGeometry* pg1, double x, double y)
{
return GEOSPreparedContainsXY_r(handle, pg1, x, y);
}

char
GEOSPreparedContainsProperly(const geos::geom::prep::PreparedGeometry* pg1, const Geometry* g2)
{
return GEOSPreparedContainsProperly_r(handle, pg1, g2);
}

char
GEOSPreparedContainsProperlyXY(const geos::geom::prep::PreparedGeometry* pg1, double x, double y)
{
return GEOSPreparedContainsProperlyXY_r(handle, pg1, x, y);
}

char
GEOSPreparedCoveredBy(const geos::geom::prep::PreparedGeometry* pg1, const Geometry* g2)
{
Expand Down Expand Up @@ -1485,6 +1497,12 @@ extern "C" {
return GEOSPreparedIntersects_r(handle, pg1, g2);
}

char
GEOSPreparedIntersectsXY(const geos::geom::prep::PreparedGeometry* pg1, double x, double y)
{
return GEOSPreparedIntersectsXY_r(handle, pg1, x, y);
}

char
GEOSPreparedOverlaps(const geos::geom::prep::PreparedGeometry* pg1, const Geometry* g2)
{
Expand Down
85 changes: 74 additions & 11 deletions capi/geos_c.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -1111,12 +1111,26 @@ extern char GEOS_DLL GEOSPreparedContains_r(
const GEOSPreparedGeometry* pg1,
const GEOSGeometry* g2);

/** \see GEOSPreparedContainsXY */
extern char GEOS_DLL GEOSPreparedContainsXY_r(
GEOSContextHandle_t handle,
const GEOSPreparedGeometry* pg1,
double x,
double y);

/** \see GEOSPreparedContainsProperly */
extern char GEOS_DLL GEOSPreparedContainsProperly_r(
GEOSContextHandle_t handle,
const GEOSPreparedGeometry* pg1,
const GEOSGeometry* g2);

/** \see GEOSPreparedContainsProperlyXY */
extern char GEOS_DLL GEOSPreparedContainsProperlyXY_r(
GEOSContextHandle_t handle,
const GEOSPreparedGeometry* pg1,
double x,
double y);

/** \see GEOSPreparedCoveredBy */
extern char GEOS_DLL GEOSPreparedCoveredBy_r(
GEOSContextHandle_t handle,
Expand Down Expand Up @@ -1147,6 +1161,13 @@ extern char GEOS_DLL GEOSPreparedIntersects_r(
const GEOSPreparedGeometry* pg1,
const GEOSGeometry* g2);

/** \see GEOSPreparedIntersectsXY */
extern char GEOS_DLL GEOSPreparedIntersectsXY_r(
GEOSContextHandle_t handle,
const GEOSPreparedGeometry* pg1,
double x,
double y);

/** \see GEOSPreparedOverlaps */
extern char GEOS_DLL GEOSPreparedOverlaps_r(
GEOSContextHandle_t handle,
Expand Down Expand Up @@ -4156,7 +4177,7 @@ extern char GEOS_DLL GEOSCovers(const GEOSGeometry* g1, const GEOSGeometry* g2);
* \param g1 Input geometry
* \param g2 Input geometry
* \returns 1 on true, 0 on false, 2 on exception
* \see geos::geom::Geometry::coveredby
* \see geos::geom::Geometry::coveredBy
*/
extern char GEOS_DLL GEOSCoveredBy(const GEOSGeometry* g1, const GEOSGeometry* g2);

Expand Down Expand Up @@ -4285,7 +4306,21 @@ extern char GEOS_DLL GEOSPreparedContains(
const GEOSGeometry* g2);

/**
* Using a \ref GEOSPreparedGeometry do a high performance
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided point is contained.
* \param pg1 The prepared geometry
* \param x x coordinate of point to test
* \param y y coordinate of point to test
* \returns 1 on true, 0 on false, 2 on exception
* \see GEOSContains
*/
extern char GEOS_DLL GEOSPreparedContainsXY(
const GEOSPreparedGeometry* pg1,
double x,
double y);

/**
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided geometry is contained properly.
* \param pg1 The prepared geometry
* \param g2 The geometry to test
Expand All @@ -4296,6 +4331,20 @@ extern char GEOS_DLL GEOSPreparedContainsProperly(
const GEOSPreparedGeometry* pg1,
const GEOSGeometry* g2);

/**
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided point is contained properly.
* \param pg1 The prepared geometry
* \param x x coordinate of point to test
* \param y y coordinate of point to test
* \returns 1 on true, 0 on false, 2 on exception
* \see GEOSContainsProperly
*/
extern char GEOS_DLL GEOSPreparedContainsProperlyXY(
const GEOSPreparedGeometry* pg1,
double x,
double y);

/**
* Using a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided geometry is covered by.
Expand Down Expand Up @@ -4333,31 +4382,45 @@ extern char GEOS_DLL GEOSPreparedCrosses(
const GEOSGeometry* g2);

/**
* Using a \ref GEOSPreparedDisjoint do a high performance
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided geometry is disjoint.
* \param pg1 The prepared geometry
* \param g2 The geometry to test
* \returns 1 on true, 0 on false, 2 on exception
* \see GEOSDisjoin
* \see GEOSDisjoint
*/
extern char GEOS_DLL GEOSPreparedDisjoint(
const GEOSPreparedGeometry* pg1,
const GEOSGeometry* g2);

/**
* Using a \ref GEOSPreparedDisjoint do a high performance
* calculation of whether the provided geometry is disjoint.
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided geometry intersects.
* \param pg1 The prepared geometry
* \param g2 The geometry to test
* \returns 1 on true, 0 on false, 2 on exception
* \see GEOSDisjoin
* \see GEOSIntersects
*/
extern char GEOS_DLL GEOSPreparedIntersects(
const GEOSPreparedGeometry* pg1,
const GEOSGeometry* g2);

/**
* Using a \ref GEOSPreparedDisjoint do a high performance
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided point intersects.
* \param pg1 The prepared geometry
* \param x x coordinate of point to test
* \param y y coordinate of point to test
* \returns 1 on true, 0 on false, 2 on exception
* \see GEOSIntersects
*/
extern char GEOS_DLL GEOSPreparedIntersectsXY(
const GEOSPreparedGeometry* pg1,
double x,
double y);

/**
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided geometry overlaps.
* \param pg1 The prepared geometry
* \param g2 The geometry to test
Expand All @@ -4369,7 +4432,7 @@ extern char GEOS_DLL GEOSPreparedOverlaps(
const GEOSGeometry* g2);

/**
* Using a \ref GEOSPreparedDisjoint do a high performance
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided geometry touches.
* \param pg1 The prepared geometry
* \param g2 The geometry to test
Expand All @@ -4381,7 +4444,7 @@ extern char GEOS_DLL GEOSPreparedTouches(
const GEOSGeometry* g2);

/**
* Using a \ref GEOSPreparedDisjoint do a high performance
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation of whether the provided geometry is within.
* \param pg1 The prepared geometry
* \param g2 The geometry to test
Expand All @@ -4393,7 +4456,7 @@ extern char GEOS_DLL GEOSPreparedWithin(
const GEOSGeometry* g2);

/**
* Using a \ref GEOSPreparedDisjoint do a high performance
* Use a \ref GEOSPreparedGeometry do a high performance
* calculation to find the nearest points between the
* prepared and provided geometry.
* \param pg1 The prepared geometry
Expand Down