diff --git a/src/Mod/Path/libarea/CMakeLists.txt b/src/Mod/Path/libarea/CMakeLists.txt index aaf0652136..ef95c29d37 100644 --- a/src/Mod/Path/libarea/CMakeLists.txt +++ b/src/Mod/Path/libarea/CMakeLists.txt @@ -11,27 +11,33 @@ endif(MSVC) include_directories(${PYTHON_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER) - if(NOT PYTHON_VERSION_MAJOR LESS 3) - find_package( Boost COMPONENTS python3) - if (NOT Boost_PYTHON3_FOUND) - find_package( Boost COMPONENTS python REQUIRED) + +OPTION(USE_BOOST_PYTHON "use BOOST_PYTHON, otherwise use PYBIND11" ON) + +if(USE_BOOST_PYTHON) + if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER) + if(NOT PYTHON_VERSION_MAJOR LESS 3) + find_package( Boost COMPONENTS python3) + if (NOT Boost_PYTHON3_FOUND) + find_package( Boost COMPONENTS python REQUIRED) + endif() + else() + find_package( Boost COMPONENTS python REQUIRED) # find BOOST and boost-python + endif() + + if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + MESSAGE(STATUS "found Boost: " ${Boost_LIB_VERSION}) + MESSAGE(STATUS "boost-incude dirs are: " ${Boost_INCLUDE_DIRS}) + MESSAGE(STATUS "boost-python lib is: " ${Boost_PYTHON_LIBRARY}) + MESSAGE(STATUS "boost_LIBRARY_DIRS is: " ${Boost_LIBRARY_DIRS}) + MESSAGE(STATUS "Boost_LIBRARIES is: " ${Boost_LIBRARIES}) endif() else() - find_package( Boost COMPONENTS python REQUIRED) # find BOOST and boost-python - endif() - - if(Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) - MESSAGE(STATUS "found Boost: " ${Boost_LIB_VERSION}) - MESSAGE(STATUS "boost-incude dirs are: " ${Boost_INCLUDE_DIRS}) - MESSAGE(STATUS "boost-python lib is: " ${Boost_PYTHON_LIBRARY}) - MESSAGE(STATUS "boost_LIBRARY_DIRS is: " ${Boost_LIBRARY_DIRS}) - MESSAGE(STATUS "Boost_LIBRARIES is: " ${Boost_LIBRARIES}) endif() -else() - include_directories(${Boost_INCLUDE_DIRS}) -endif() +endif(USE_BOOST_PYTHON) + # this defines the source-files for library set(AREA_SRC_COMMON @@ -56,9 +62,15 @@ set(AREA_SRC_CLIPPER ) # this defines the additional source-files for python module (wrapper to libarea) -set(PYAREA_SRC - PythonStuff.cpp -) +if (USE_BOOST_PYTHON) + set(PYAREA_SRC + PythonStuff.cpp + ) +else(USE_BOOST_PYTHON) + set(PYAREA_SRC + pyarea.cpp + ) +endif(USE_BOOST_PYTHON) # this defines the headers if(DEFINED INCLUDE_INSTALL_DIR) diff --git a/src/Mod/Path/libarea/pyarea.cpp b/src/Mod/Path/libarea/pyarea.cpp new file mode 100644 index 0000000000..1a8d78673a --- /dev/null +++ b/src/Mod/Path/libarea/pyarea.cpp @@ -0,0 +1,360 @@ +// pyarea.cpp +// Copyright 2017, Lorenz Lechner +// This program is released under the BSD license. See the file COPYING for details. + +#include "Area.h" +#include "Point.h" +#include "AreaDxf.h" +#include "kurve/geometry.h" + +#include +#include +#include + +#include + +namespace py = pybind11; + + +std::list getVertices(const CCurve& curve) { + return curve.m_vertices; +} + +std::list getCurves(const CArea& area) { + return area.m_curves; +} + +py::tuple transformed_point(const geoff_geometry::Matrix &matrix, double x, double y, double z) +{ + geoff_geometry::Point3d p(x,y,z); + p = p.Transform(matrix); + + return py::make_tuple(p.x,p.y,p.z); +} + +static void print_curve(const CCurve& c) +{ + std::size_t nvertices = c.m_vertices.size(); +#if defined SIZEOF_SIZE_T && SIZEOF_SIZE_T == 4 + printf("number of vertices = %d\n", nvertices); +#else + printf("number of vertices = %lu\n", nvertices); +#endif + int i = 0; + for(std::list::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); It++, i++) + { + const CVertex& vertex = *It; + printf("vertex %d type = %d, x = %g, y = %g", i+1, vertex.m_type, vertex.m_p.x / CArea::get_units(), vertex.m_p.y / CArea::get_units()); + if(vertex.m_type)printf(", xc = %g, yc = %g", vertex.m_c.x / CArea::get_units(), vertex.m_c.y / CArea::get_units()); + printf("\n"); + } +} + +static void print_area(const CArea &a) +{ + for(std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) + { + const CCurve& curve = *It; + print_curve(curve); + } +} + +static unsigned int num_vertices(const CCurve& curve) +{ + return static_cast(curve.m_vertices.size()); +} + +static CVertex FirstVertex(const CCurve& curve) +{ + return curve.m_vertices.front(); +} + +static CVertex LastVertex(const CCurve& curve) +{ + return curve.m_vertices.back(); +} + +static void set_units(double units) +{ + CArea::set_units(units); +} + +static double get_units() +{ + return CArea::get_units(); +} + +static bool holes_linked() +{ + return CArea::HolesLinked(); +} + +static CArea AreaFromDxf(const char* filepath) +{ + CArea area; + AreaDxfRead dxf(&area, filepath); + dxf.DoRead(); + return area; +} + +static void append_point(CCurve& c, const Point& p) +{ + c.m_vertices.push_back(CVertex(p)); +} + +static py::tuple nearest_point_to_curve(CCurve& c1, const CCurve& c2) +{ + double dist; + Point p = c1.NearestPoint(c2, &dist); + + return py::make_tuple(p, dist); +} + +std::list MakePocketToolpath(const CArea& a, double tool_radius, double extra_offset, double stepover, bool from_center, bool use_zig_zag, double zig_angle) +{ + std::list toolpath; + + CAreaPocketParams params(tool_radius, extra_offset, stepover, from_center, use_zig_zag ? ZigZagPocketMode : SpiralPocketMode, zig_angle); + a.SplitAndMakePocketToolpath(toolpath, params); + + return toolpath; +} + +std::list SplitArea(const CArea& a) +{ + std::list areas; + a.Split(areas); + + return areas; +} + +void dxfArea(CArea& area, const char* /*str*/) +{ + area = CArea(); +} + +py::list getCurveSpans(const CCurve& c) +{ + py::list span_list; + const Point *prev_p = NULL; + + for(std::list::const_iterator VIt = c.m_vertices.begin(); VIt != c.m_vertices.end(); VIt++) + { + const CVertex& vertex = *VIt; + + if(prev_p) + { + span_list.append(Span(*prev_p, vertex)); + } + prev_p = &(vertex.m_p); + } + + return span_list; +} + +Span getFirstCurveSpan(const CCurve& c) +{ + if(c.m_vertices.size() < 2)return Span(); + + std::list::const_iterator VIt = c.m_vertices.begin(); + const Point &p = (*VIt).m_p; + VIt++; + return Span(p, *VIt, true); +} + +Span getLastCurveSpan(const CCurve& c) +{ + if(c.m_vertices.size() < 2)return Span(); + + std::list::const_reverse_iterator VIt = c.m_vertices.rbegin(); + const CVertex &v = (*VIt); + VIt++; + + return Span((*VIt).m_p, v, c.m_vertices.size() == 2); +} + +py::tuple TangentialArc(const Point &p0, const Point &p1, const Point &v0) +{ + Point c; + int dir; + tangential_arc(p0, p1, v0, c, dir); + + return py::make_tuple(c, dir); +} + +std::list spanIntersect(const Span& span1, const Span& span2) { + std::list pts; + span1.Intersect(span2, pts); + return pts; +} + + +void MatrixFromVector(geoff_geometry::Matrix& instance, std::vector v){ + double array[16]; + int i = 0; + for (double vi: v){ + array[i] = vi; + i++; + if(i>=16) break; + } + new (&instance) geoff_geometry::Matrix(array); +} + +std::list InsideCurves(const CArea& a, const CCurve& curve) { + std::list curves_inside; + a.InsideCurves(curve, curves_inside); + return curves_inside; +} + +std::list CurveIntersections(const CCurve& c1, const CCurve& c2) { + std::list pts; + c1.CurveIntersections(c2, pts); + return pts; +} + +std::list AreaIntersections(const CArea& a, const CCurve& c2) { + std::list pts; + a.CurveIntersections(c2, pts); + return pts; +} + +double AreaGetArea(const CArea& a) +{ + return a.GetArea(); +} + + +void init_pyarea(py::module &m){ + py::class_(m, "Point") + .def(py::init()) + .def(py::init()) + .def(float() * py::self) + .def(py::self * float()) + .def(py::self / float()) + .def(py::self * py::self) + .def(py::self - py::self) + .def(py::self + py::self) + .def(py::self ^ py::self) + .def(py::self == py::self) + .def(py::self != py::self) + .def(-py::self) + .def(~py::self) + .def("dist", &Point::dist) + .def("length", &Point::length) + .def("normalize", &Point::normalize) + .def("Rotate", static_cast< void (Point::*)(double, double) >(&Point::Rotate)) + .def("Rotate", static_cast< void (Point::*)(double) >(&Point::Rotate)) + .def_readwrite("x", &Point::x) + .def_readwrite("y", &Point::y) + .def("Transform", &Point::Transform) + ; + + py::class_(m, "Vertex") + .def(py::init()) + .def(py::init()) + .def(py::init()) + .def(py::init()) + .def_readwrite("type", &CVertex::m_type) + .def_readwrite("p", &CVertex::m_p) + .def_readwrite("c", &CVertex::m_c) + .def_readwrite("user_data", &CVertex::m_user_data) + ; + + py::class_(m, "Span") + .def(py::init()) + .def(py::init()) + .def("NearestPoint", static_cast< Point (Span::*)(const Point& p)const >(&Span::NearestPoint)) + .def("NearestPoint", static_cast< Point (Span::*)(const Span& p, double *d)const >(&Span::NearestPoint)) + .def("GetBox", &Span::GetBox) + .def("IncludedAngle", &Span::IncludedAngle) + .def("GetArea", &Span::GetArea) + .def("On", &Span::On) + .def("MidPerim", &Span::MidPerim) + .def("MidParam", &Span::MidParam) + .def("Length", &Span::Length) + .def("GetVector", &Span::GetVector) + .def("Intersect", &spanIntersect) + .def_readwrite("p", &Span::m_p) + .def_readwrite("v", &Span::m_v) + ; + + py::class_(m, "Curve") + .def(py::init()) + .def("getVertices", &getVertices) + .def("append",&CCurve::append) + .def("append",&append_point) + .def("text", &print_curve) + .def("NearestPoint", static_cast< Point (CCurve::*)(const Point& p)const >(&CCurve::NearestPoint)) + .def("NearestPoint", &nearest_point_to_curve) + .def("Reverse", &CCurve::Reverse) + .def("getNumVertices", &num_vertices) + .def("FirstVertex", &FirstVertex) + .def("LastVertex", &LastVertex) + .def("GetArea", &CCurve::GetArea) + .def("IsClockwise", &CCurve::IsClockwise) + .def("IsClosed", &CCurve::IsClosed) + .def("ChangeStart",&CCurve::ChangeStart) + .def("ChangeEnd",&CCurve::ChangeEnd) + .def("Offset",&CCurve::Offset) + .def("OffsetForward",&CCurve::OffsetForward) + .def("GetSpans",&getCurveSpans) + .def("GetFirstSpan",&getFirstCurveSpan) + .def("GetLastSpan",&getLastCurveSpan) + .def("Break",&CCurve::Break) + .def("Perim",&CCurve::Perim) + .def("PerimToPoint",&CCurve::PerimToPoint) + .def("PointToPerim",&CCurve::PointToPerim) + .def("FitArcs",&CCurve::FitArcs) + .def("UnFitArcs",&CCurve::UnFitArcs) + .def("Intersections",&CurveIntersections) + ; + + py::class_(m, "Box") + .def(py::init()) + .def("MinX", &CBox2D::MinX) + .def("MaxX", &CBox2D::MaxX) + .def("MinY", &CBox2D::MinY) + .def("MaxY", &CBox2D::MaxY) + ; + + py::class_(m, "Area") + .def(py::init()) + .def("getCurves", &getCurves) + .def("append",&CArea::append) + .def("Subtract",&CArea::Subtract) + .def("Intersect",&CArea::Intersect) + .def("Union",&CArea::Union) + .def("Offset",&CArea::Offset) + .def("FitArcs",&CArea::FitArcs) + .def("text", &print_area) + .def("num_curves", &CArea::num_curves) + .def("NearestPoint", &CArea::NearestPoint) + .def("GetBox", &CArea::GetBox) + .def("Reorder", &CArea::Reorder) + .def("MakePocketToolpath", &MakePocketToolpath) + .def("Split", &SplitArea) + .def("InsideCurves", &InsideCurves) + .def("Thicken", &CArea::Thicken) + .def("Intersections",&AreaIntersections) + .def("GetArea",&AreaGetArea) + ; + + py::class_ > (m, "Matrix") + .def(py::init()) + .def("__init__", &MatrixFromVector) + .def("TransformedPoint", &transformed_point) + .def("Multiply", &geoff_geometry::Matrix::Multiply) + ; + + m.def("set_units", set_units); + m.def("get_units", get_units); + m.def("holes_linked", holes_linked); + m.def("AreaFromDxf", AreaFromDxf); + m.def("TangentialArc", TangentialArc); +} + +PYBIND11_PLUGIN(area){ + py::module m("area"); + init_pyarea(m); + return m.ptr(); +}; \ No newline at end of file