From 4c1276edbb2243b22dcb9bbb9e20753f432362a8 Mon Sep 17 00:00:00 2001 From: Joel Jaeschke Date: Fri, 1 Nov 2024 21:30:30 +0100 Subject: [PATCH] Exposed options from Predicate Functor and added a specialization for touches --- src/predicates.cpp | 82 ++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/src/predicates.cpp b/src/predicates.cpp index fd5135d..f18f222 100644 --- a/src/predicates.cpp +++ b/src/predicates.cpp @@ -22,6 +22,10 @@ class Predicate { template Predicate(F&& func) : m_func(std::forward(func)) {} + template + Predicate(F&& func, const S2BooleanOperation::Options& options) + : m_func(std::forward(func)), m_options(options) {} + bool operator()(PyObjectGeography a, PyObjectGeography b) const { const auto& a_index = a.as_geog_ptr()->geog_index(); const auto& b_index = b.as_geog_ptr()->geog_index(); @@ -33,6 +37,33 @@ class Predicate { S2BooleanOperation::Options m_options; }; +/* +** A specialization of the `Predicate` class for the touches operation, +** as two `S2BooleanOpteration::Options` objects are necessary. +*/ +class TouchesPredicate { +public: + TouchesPredicate() : m_closed_options(), m_open_options() { + m_closed_options.set_polyline_model(S2BooleanOperation::PolylineModel::CLOSED); + m_closed_options.set_polygon_model(S2BooleanOperation::PolygonModel::CLOSED); + + m_open_options.set_polyline_model(S2BooleanOperation::PolylineModel::OPEN); + m_open_options.set_polygon_model(S2BooleanOperation::PolygonModel::OPEN); + } + + bool operator()(PyObjectGeography a, PyObjectGeography b) const { + const auto& a_index = a.as_geog_ptr()->geog_index(); + const auto& b_index = b.as_geog_ptr()->geog_index(); + + return s2geog::s2_intersects(a_index, b_index, m_closed_options) && + !s2geog::s2_intersects(a_index, b_index, m_open_options); + } + +private: + S2BooleanOperation::Options m_closed_options; + S2BooleanOperation::Options m_open_options; +}; + void init_predicates(py::module& m) { m.def("intersects", py::vectorize(Predicate(s2geog::s2_intersects)), @@ -119,20 +150,7 @@ void init_predicates(py::module& m) { )pbdoc"); m.def("touches", - py::vectorize(Predicate([](const s2geog::ShapeIndexGeography& a_index, - const s2geog::ShapeIndexGeography& b_index, - const S2BooleanOperation::Options& options) { - S2BooleanOperation::Options closedOptions = options; - closedOptions.set_polygon_model(S2BooleanOperation::PolygonModel::CLOSED); - closedOptions.set_polyline_model(S2BooleanOperation::PolylineModel::CLOSED); - - S2BooleanOperation::Options openOptions = options; - openOptions.set_polygon_model(S2BooleanOperation::PolygonModel::OPEN); - openOptions.set_polyline_model(S2BooleanOperation::PolylineModel::OPEN); - - return s2geog::s2_intersects(a_index, b_index, closedOptions) && - !s2geog::s2_intersects(a_index, b_index, openOptions); - })), + py::vectorize(TouchesPredicate()), py::arg("a"), py::arg("b"), R"pbdoc( @@ -147,16 +165,18 @@ void init_predicates(py::module& m) { )pbdoc"); - m.def("covers", - py::vectorize(Predicate([](const s2geog::ShapeIndexGeography& a_index, - const s2geog::ShapeIndexGeography& b_index, - const S2BooleanOperation::Options& options) { - S2BooleanOperation::Options closedOptions = options; - closedOptions.set_polyline_model(S2BooleanOperation::PolylineModel::CLOSED); - closedOptions.set_polygon_model(S2BooleanOperation::PolygonModel::CLOSED); + S2BooleanOperation::Options closed_options; + closed_options.set_polyline_model(S2BooleanOperation::PolylineModel::CLOSED); + closed_options.set_polygon_model(S2BooleanOperation::PolygonModel::CLOSED); - return s2geog::s2_contains(a_index, b_index, closedOptions); - })), + m.def("covers", + py::vectorize(Predicate( + [](const s2geog::ShapeIndexGeography& a_index, + const s2geog::ShapeIndexGeography& b_index, + const S2BooleanOperation::Options& options) { + return s2geog::s2_contains(a_index, b_index, options); + }, + closed_options)), py::arg("a"), py::arg("b"), R"pbdoc( @@ -170,15 +190,13 @@ void init_predicates(py::module& m) { )pbdoc"); m.def("covered_by", - py::vectorize(Predicate([](const s2geog::ShapeIndexGeography& a_index, - const s2geog::ShapeIndexGeography& b_index, - const S2BooleanOperation::Options& options) { - S2BooleanOperation::Options closedOptions = options; - closedOptions.set_polyline_model(S2BooleanOperation::PolylineModel::CLOSED); - closedOptions.set_polygon_model(S2BooleanOperation::PolygonModel::CLOSED); - - return s2geog::s2_contains(b_index, a_index, closedOptions); - })), + py::vectorize(Predicate( + [](const s2geog::ShapeIndexGeography& a_index, + const s2geog::ShapeIndexGeography& b_index, + const S2BooleanOperation::Options& options) { + return s2geog::s2_contains(b_index, a_index, options); + }, + closed_options)), py::arg("a"), py::arg("b"), R"pbdoc(