diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 9aa4cf3c6..10ef9127c 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include "SVG.hpp" #include #include "GCodeWriter.hpp" @@ -1055,12 +1057,18 @@ BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_ // This method is used by the auto arrange function. Polygon ModelObject::convex_hull_2d(const Transform3d& trafo_instance) const { - Points pts; - for (const ModelVolume* v : volumes) { - if (v->is_model_part()) - append(pts, its_convex_hull_2d_above(v->mesh().its, (trafo_instance * v->get_matrix()).cast(), 0.0f).points); - } - return Geometry::convex_hull(std::move(pts)); + tbb::concurrent_vector chs; + chs.reserve(volumes.size()); + tbb::parallel_for(tbb::blocked_range(0, volumes.size()), [&](const tbb::blocked_range& range) { + for (size_t i = range.begin(); i < range.end(); ++i) { + const ModelVolume* v = volumes[i]; + chs.emplace_back(its_convex_hull_2d_above(v->mesh().its, (trafo_instance * v->get_matrix()).cast(), 0.0f)); + } + }); + + Polygons polygons; + polygons.assign(chs.begin(), chs.end()); + return Geometry::convex_hull(polygons); } void ModelObject::center_around_origin(bool include_modifiers) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index d35251d20..66bf913e0 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -871,11 +873,38 @@ void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, c } template -Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const TransformVertex &transform_fn, const float z) +Polygon its_convex_hull_2d_above(const indexed_triangle_set& its, const TransformVertex& transform_fn, const float z) { - Points all_pts; - its_collect_mesh_projection_points_above(its, transform_fn, z, all_pts); - return Geometry::convex_hull(std::move(all_pts)); + auto collect_mesh_projection_points_above = [&](const tbb::blocked_range& range) { + Points pts; + pts.reserve(range.size() * 4); // there can be up to 4 vertices per triangle + for (size_t i = range.begin(); i < range.end(); ++i) { + const stl_triangle_vertex_indices& tri = its.indices[i]; + const Vec3f tri_pts[3] = { transform_fn(its.vertices[tri(0)]), transform_fn(its.vertices[tri(1)]), transform_fn(its.vertices[tri(2)]) }; + int iprev = 2; + for (int iedge = 0; iedge < 3; ++iedge) { + const Vec3f& p1 = tri_pts[iprev]; + const Vec3f& p2 = tri_pts[iedge]; + if ((p1.z() < z && p2.z() > z) || (p2.z() < z && p1.z() > z)) { + // Edge crosses the z plane. Calculate intersection point with the plane. + const float t = (z - p1.z()) / (p2.z() - p1.z()); + pts.emplace_back(scaled(p1.x() + (p2.x() - p1.x()) * t), scaled(p1.y() + (p2.y() - p1.y()) * t)); + } + if (p2.z() >= z) + pts.emplace_back(scaled(p2.x()), scaled(p2.y())); + iprev = iedge; + } + } + return Geometry::convex_hull(std::move(pts)); + }; + + tbb::concurrent_vector chs; + tbb::parallel_for(tbb::blocked_range(0, its.indices.size()), [&](const tbb::blocked_range& range) { + chs.push_back(collect_mesh_projection_points_above(range)); + }); + + const Polygons polygons(chs.begin(), chs.end()); + return Geometry::convex_hull(polygons); } Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const Matrix3f &m, const float z)