diff --git a/bindings/python/examples/all_apis.py b/bindings/python/examples/all_apis.py index b82d65255..84bea5c46 100644 --- a/bindings/python/examples/all_apis.py +++ b/bindings/python/examples/all_apis.py @@ -19,6 +19,14 @@ def all_cross_section(): c = CrossSection([poly]) c = CrossSection() + c a = c.area() + c = CrossSection.batch_boolean( + [ + CrossSection.circle(1), + CrossSection.square((3, 3)), + CrossSection.circle(3).translate((1, 1)), + ], + OpType.Add, + ) c = CrossSection.batch_hull([c, c.translate((1, 0))]) b = c.bounds() c = CrossSection.circle(1) @@ -50,6 +58,14 @@ def all_manifold(): m = Manifold(mesh) m = Manifold() + m m = m.as_original() + m = Manifold.batch_boolean( + [ + Manifold.cylinder(4, 1), + Manifold.cube((3, 2, 1)), + Manifold.cylinder(5, 3).translate((1, 1, 1)), + ], + OpType.Add, + ) m = Manifold.batch_hull([m, m.translate((0, 0, 1))]) b = m.bounding_box() m = m.calculate_curvature(4, 5) diff --git a/bindings/python/manifold3d.cpp b/bindings/python/manifold3d.cpp index 964e70215..216bec060 100644 --- a/bindings/python/manifold3d.cpp +++ b/bindings/python/manifold3d.cpp @@ -379,6 +379,9 @@ NB_MODULE(manifold3d, m) { nb::arg("edge_smoothness") = nb::list(), // todo params slightly diff manifold__smooth__mesh_gl__sharpened_edges) + .def_static("batch_boolean", &Manifold::BatchBoolean, + nb::arg("manifolds"), nb::arg("op"), + manifold__batch_boolean__manifolds__op) .def_static("compose", &Manifold::Compose, nb::arg("manifolds"), manifold__compose__manifolds) .def_static("tetrahedron", &Manifold::Tetrahedron, manifold__tetrahedron) @@ -581,6 +584,11 @@ NB_MODULE(manifold3d, m) { "joins would exceed a given maximum miter distance (relative to the " "offset distance), these are 'squared' instead."); + nb::enum_(m, "OpType", "Operation types for batch_boolean") + .value("Add", OpType::Add) + .value("Subtract", OpType::Subtract) + .value("Intersect", OpType::Intersect); + nb::class_( m, "CrossSection", "Two-dimensional cross sections guaranteed to be without " @@ -658,6 +666,9 @@ NB_MODULE(manifold3d, m) { [](std::vector pts) { return CrossSection::Hull(pts); }, nb::arg("pts"), cross_section__hull__pts) .def("decompose", &CrossSection::Decompose, cross_section__decompose) + .def_static("batch_boolean", &CrossSection::BatchBoolean, + nb::arg("cross_sections"), nb::arg("op"), + cross_section__batch_boolean__cross_sections__op) .def_static("compose", &CrossSection::Compose, nb::arg("cross_sections"), cross_section__compose__cross_sections) .def("to_polygons", &CrossSection::ToPolygons, cross_section__to_polygons) diff --git a/src/manifold/src/manifold.cpp b/src/manifold/src/manifold.cpp index 79870e492..72efe8bb3 100644 --- a/src/manifold/src/manifold.cpp +++ b/src/manifold/src/manifold.cpp @@ -689,6 +689,10 @@ Manifold Manifold::Boolean(const Manifold& second, OpType op) const { return Manifold(pNode_->Boolean(second.pNode_, op)); } +/** + * Perform the given boolean operation on a list of Manifolds. In case of + * Subtract, all Manifolds in the tail are differenced from the head. + */ Manifold Manifold::BatchBoolean(const std::vector& manifolds, OpType op) { if (manifolds.size() == 0)