#include #include // std::pair ?? #include #include #include "dashing.hh" namespace py = pybind11; namespace { py::tuple PSMatrixAsTuple(const dashing::PSMatrix & m) { return py::make_tuple(m.a, m.b, m.c, m.d, m.e, m.f); } py::str PSMatrixRepr(const dashing::PSMatrix &m) { return py::str("PSMatrix") + py::str(PSMatrixAsTuple(m)); } py::tuple dashAsTuple(const dashing::Dash d) { return py::make_tuple(d.tf, d.dash); } py::str dashRepr(const dashing::Dash &m) { return py::str("dash") + py::str(dashAsTuple(m)); } dashing::HatchPattern hatchPatternFromString(std::string s, dashing::F scale) { std::istringstream is(s); return dashing::HatchPattern::FromFile(is, scale); } dashing::HatchPattern hatchPatternFromFile(py::object open_file, dashing::F scale) { auto content = open_file.attr("read")(); return hatchPatternFromString(content.cast(), scale); } py::tuple hatchPatternAsTuple(const dashing::HatchPattern &pattern) { return py::tuple(py::make_iterator(pattern.d.begin(), pattern.d.end())); } py::str hatchPatternRepr(const dashing::HatchPattern &pattern) { return py::str("HatchPattern") + py::str(hatchPatternAsTuple(pattern)); } enum WindingRule { EvenOdd, NonZero, GreaterThanZero }; using pyPoint = std::pair; using pySegment = std::pair; std::vector hatchPatternHatch(const dashing::HatchPattern &pattern, std::vector pyBoundary, WindingRule wr) { std::vector boundary; for(auto i: pyBoundary) { boundary.push_back(dashing::Segment{i.first.first, i.first.second, i.second.first, i.second.second, false}); } std::vector result; auto cb = [&result](dashing::Segment s) { result.push_back(pySegment{{s.p.x, s.p.y}, {s.q.x, s.q.y}}); }; switch(wr) { case EvenOdd: dashing::xyhatch(pattern, boundary, cb, [](int i) { return i & 1; }); break; case NonZero: dashing::xyhatch(pattern, boundary, cb, [](int i) { return i != 0; }); break; case GreaterThanZero: dashing::xyhatch(pattern, boundary, cb, [](int i) { return i > 0; }); break; default: throw std::runtime_error("Invalid winding rule"); } return result; } } PYBIND11_MODULE(dashing, m) { py::options options; options.enable_enum_members_docstring(); options.enable_function_signatures(); options.enable_user_defined_docstrings(); m.doc() = R"pbdoc( Python wrapper for autocad-style hatch patterns )pbdoc"; py::enum_(m, "WindingRule") .value("EvenOdd", WindingRule::EvenOdd) .value("NonZero", WindingRule::NonZero) .value("GreaterThanZero", WindingRule::GreaterThanZero) ; py::class_(m, "HatchPattern",R"pbdoc( Encapsulate an autocad-style hatch pattern )pbdoc") .def(py::init&>()) .def("as_tuple", hatchPatternAsTuple) .def_static("fromString", hatchPatternFromString) .def_static("fromFile", hatchPatternFromFile) .def("hatch", hatchPatternHatch) .def("transformed", [](dashing::HatchPattern a, const dashing::PSMatrix b) { auto b_inv = b.inverse(); for(auto &dash: a.d) { dash.tf = b * dash.tf; dash.tr = dash.tr * b_inv; } return a; }) .def("__repr__", hatchPatternRepr) .def("__str__", hatchPatternRepr) ; py::class_(m, "Dash") .def(py::init &>()) .def("as_tuple", dashAsTuple) .def("__repr__", dashRepr) .def("__str__", dashRepr) ; py::class_(m, "PSMatrix") .def("as_tuple", PSMatrixAsTuple) .def("__repr__", PSMatrixRepr) .def("__str__", PSMatrixRepr) .def("determinant", &dashing::PSMatrix::determinant) .def("inverse", &dashing::PSMatrix::inverse) .def("identity", []() { return dashing::PSMatrix(1,0,0,1,0,0); }) .def_static("translation", dashing::Translation) .def_static("rotation", dashing::Rotation) .def_static("xSkew", dashing::XSkew) .def_static("yScale", dashing::YScale) .def("__mul__", [](const dashing::PSMatrix &a, const dashing::PSMatrix b) { return a * b; }); ; }