|
| 1 | +#include <pybind11/pybind11.h> |
| 2 | +#include <pybind11/operators.h> |
| 3 | + |
| 4 | +#include "s2/s1interval.h" |
| 5 | + |
| 6 | +namespace py = pybind11; |
| 7 | + |
| 8 | +void bind_s1interval(py::module& m) { |
| 9 | + py::class_<S1Interval>(m, "S1Interval") |
| 10 | + // Constructors |
| 11 | + .def(py::init<>(), "Default constructor (empty interval)") |
| 12 | + .def(py::init<double, double>(), |
| 13 | + py::arg("lo"), py::arg("hi"), |
| 14 | + "Construct interval from lo and hi bounds (in radians)") |
| 15 | + |
| 16 | + // Static factory methods |
| 17 | + .def_static("empty", &S1Interval::Empty, "Return an empty interval") |
| 18 | + .def_static("full", &S1Interval::Full, "Return a full interval") |
| 19 | + .def_static("from_point", &S1Interval::FromPoint, py::arg("p"), |
| 20 | + "Construct interval containing a single point") |
| 21 | + .def_static("from_point_pair", &S1Interval::FromPointPair, |
| 22 | + py::arg("p1"), py::arg("p2"), |
| 23 | + "Construct minimal interval containing two points") |
| 24 | + |
| 25 | + // Properties |
| 26 | + .def_property("lo", &S1Interval::lo, &S1Interval::set_lo, "Lower bound") |
| 27 | + .def_property("hi", &S1Interval::hi, &S1Interval::set_hi, "Upper bound") |
| 28 | + .def("bounds", [](const S1Interval& self) { |
| 29 | + return py::make_tuple(self.lo(), self.hi()); |
| 30 | + }, "Return bounds as a tuple (lo, hi)") |
| 31 | + |
| 32 | + // Predicates |
| 33 | + .def("is_valid", &S1Interval::is_valid, "Check if interval is valid") |
| 34 | + .def("is_full", &S1Interval::is_full, "Check if interval is full") |
| 35 | + .def("is_empty", &S1Interval::is_empty, "Check if interval is empty") |
| 36 | + .def("is_inverted", &S1Interval::is_inverted, |
| 37 | + "Check if interval is inverted (lo > hi)") |
| 38 | + |
| 39 | + // Geometric operations |
| 40 | + .def("get_center", &S1Interval::GetCenter, "Return center of interval") |
| 41 | + .def("get_length", &S1Interval::GetLength, "Return length of interval") |
| 42 | + .def("get_complement_center", &S1Interval::GetComplementCenter, |
| 43 | + "Return center of complement") |
| 44 | + .def("contains", py::overload_cast<double>(&S1Interval::Contains, py::const_), |
| 45 | + py::arg("p"), "Check if interval contains a point") |
| 46 | + .def("interior_contains", py::overload_cast<double>( |
| 47 | + &S1Interval::InteriorContains, py::const_), |
| 48 | + py::arg("p"), "Check if interval's interior contains a point") |
| 49 | + .def("contains", py::overload_cast<const S1Interval&>( |
| 50 | + &S1Interval::Contains, py::const_), |
| 51 | + py::arg("other"), "Check if interval contains another interval") |
| 52 | + .def("interior_contains", py::overload_cast<const S1Interval&>( |
| 53 | + &S1Interval::InteriorContains, py::const_), |
| 54 | + py::arg("other"), |
| 55 | + "Check if interval's interior contains another interval") |
| 56 | + .def("intersects", &S1Interval::Intersects, py::arg("other"), |
| 57 | + "Check if interval intersects another") |
| 58 | + .def("interior_intersects", &S1Interval::InteriorIntersects, |
| 59 | + py::arg("other"), |
| 60 | + "Check if interval's interior intersects another") |
| 61 | + .def("add_point", &S1Interval::AddPoint, py::arg("p"), |
| 62 | + "Expand interval to include a point") |
| 63 | + .def("project", &S1Interval::Project, py::arg("p"), |
| 64 | + "Return closest point in interval") |
| 65 | + .def("expanded", &S1Interval::Expanded, py::arg("margin"), |
| 66 | + "Return expanded interval") |
| 67 | + .def("union", &S1Interval::Union, py::arg("other"), |
| 68 | + "Return union with another interval") |
| 69 | + .def("intersection", &S1Interval::Intersection, py::arg("other"), |
| 70 | + "Return intersection with another interval") |
| 71 | + .def("complement", &S1Interval::Complement, |
| 72 | + "Return complement of this interval") |
| 73 | + .def("get_directed_hausdorff_distance", |
| 74 | + &S1Interval::GetDirectedHausdorffDistance, |
| 75 | + py::arg("other"), |
| 76 | + "Return directed Hausdorff distance to another interval") |
| 77 | + .def("approx_equals", &S1Interval::ApproxEquals, |
| 78 | + py::arg("other"), py::arg("max_error") = 1e-15, |
| 79 | + "Check if approximately equal") |
| 80 | + |
| 81 | + // Operators |
| 82 | + .def(py::self == py::self, "Check equality") |
| 83 | + .def(py::self != py::self, "Check inequality") |
| 84 | + |
| 85 | + // String representation |
| 86 | + .def("__repr__", [](const S1Interval& i) { |
| 87 | + return "S1Interval(" + std::to_string(i.lo()) + ", " + |
| 88 | + std::to_string(i.hi()) + ")"; |
| 89 | + }) |
| 90 | + .def("__str__", [](const S1Interval& i) { |
| 91 | + if (i.is_empty()) return std::string("[∅]"); |
| 92 | + if (i.is_full()) return std::string("[0, 2π)"); |
| 93 | + return "[" + std::to_string(i.lo()) + ", " + |
| 94 | + std::to_string(i.hi()) + "]"; |
| 95 | + }); |
| 96 | +} |
0 commit comments