From 8db2d96c75006155af969633ea493950a4011756 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 May 2021 12:01:30 +0200 Subject: [PATCH 1/9] Point::ccw() optimization: Calculate with int64, not doubles. --- src/libslic3r/Point.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/Point.cpp b/src/libslic3r/Point.cpp index b16abe7be..7f351d259 100644 --- a/src/libslic3r/Point.cpp +++ b/src/libslic3r/Point.cpp @@ -117,7 +117,9 @@ bool Point::nearest_point(const Points &points, Point* point) const */ double Point::ccw(const Point &p1, const Point &p2) const { - return (double)(p2(0) - p1(0))*(double)((*this)(1) - p1(1)) - (double)(p2(1) - p1(1))*(double)((*this)(0) - p1(0)); + static_assert(sizeof(coord_t) == 4, "Point::ccw() requires a 32 bit coord_t"); + return cross2((p2 - p1).cast(), (*this - p1).cast()); +// return cross2((p2 - p1).cast(), (*this - p1).cast()); } double Point::ccw(const Line &line) const @@ -129,9 +131,9 @@ double Point::ccw(const Line &line) const // i.e. this assumes a CCW rotation from p1 to p2 around this double Point::ccw_angle(const Point &p1, const Point &p2) const { - double angle = atan2(p1(0) - (*this)(0), p1(1) - (*this)(1)) - - atan2(p2(0) - (*this)(0), p2(1) - (*this)(1)); - + //FIXME this calculates an atan2 twice! Project one vector into the other! + double angle = atan2(p1.x() - (*this).x(), p1.y() - (*this).y()) + - atan2(p2.x() - (*this).x(), p2.y() - (*this).y()); // we only want to return only positive angles return angle <= 0 ? angle + 2*PI : angle; } @@ -201,12 +203,12 @@ int orient(const Vec2crd &p1, const Vec2crd &p2, const Vec2crd &p3) { Slic3r::Vector v1(p2 - p1); Slic3r::Vector v2(p3 - p1); - return Int128::sign_determinant_2x2_filtered(v1(0), v1(1), v2(0), v2(1)); + return Int128::sign_determinant_2x2_filtered(v1.x(), v1.y(), v2.x(), v2.y()); } int cross(const Vec2crd &v1, const Vec2crd &v2) { - return Int128::sign_determinant_2x2_filtered(v1(0), v1(1), v2(0), v2(1)); + return Int128::sign_determinant_2x2_filtered(v1.x(), v1.y(), v2.x(), v2.y()); } } From 5644b98d3bc7c8733699802425410944d9251e2c Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 May 2021 13:23:19 +0200 Subject: [PATCH 2/9] Factored out convex hull calculation from ModelObject::convex_hull_2d() to Geometry::convex_hull(). Update Geometry::convex_hull() to handle duplicate points. --- src/libslic3r/Geometry.cpp | 28 ++++++++++++---------------- src/libslic3r/Model.cpp | 26 +------------------------- 2 files changed, 13 insertions(+), 41 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index e60eb01b6..e9fc22ab0 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -212,36 +212,32 @@ static bool sort_pointfs(const Vec3d& a, const Vec3d& b) } // This implementation is based on Andrew's monotone chain 2D convex hull algorithm -Polygon convex_hull(Points points) +Polygon convex_hull(Points pts) { - assert(points.size() >= 3); - // sort input points - std::sort(points.begin(), points.end(), sort_points); + std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); }); + pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end()); - int n = points.size(), k = 0; Polygon hull; - + int n = (int)pts.size(); if (n >= 3) { + int k = 0; hull.points.resize(2 * n); - // Build lower hull - for (int i = 0; i < n; i++) { - while (k >= 2 && points[i].ccw(hull[k-2], hull[k-1]) <= 0) k--; - hull[k++] = points[i]; + for (int i = 0; i < n; ++ i) { + while (k >= 2 && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) + -- k; + hull[k ++] = pts[i]; } - // Build upper hull for (int i = n-2, t = k+1; i >= 0; i--) { - while (k >= t && points[i].ccw(hull[k-2], hull[k-1]) <= 0) k--; - hull[k++] = points[i]; + while (k >= t && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) + -- k; + hull[k ++] = pts[i]; } - hull.points.resize(k); - assert(hull.points.front() == hull.points.back()); hull.points.pop_back(); } - return hull; } diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 4b6b838be..f916fbdcd 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -937,31 +937,7 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const } #endif // ENABLE_ALLOW_NEGATIVE_Z } - std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); }); - pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end()); - - Polygon hull; - int n = (int)pts.size(); - if (n >= 3) { - int k = 0; - hull.points.resize(2 * n); - // Build lower hull - for (int i = 0; i < n; ++ i) { - while (k >= 2 && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) - -- k; - hull[k ++] = pts[i]; - } - // Build upper hull - for (int i = n-2, t = k+1; i >= 0; i--) { - while (k >= t && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) - -- k; - hull[k ++] = pts[i]; - } - hull.points.resize(k); - assert(hull.points.front() == hull.points.back()); - hull.points.pop_back(); - } - return hull; + return Geometry::convex_hull(std::move(pts)); } void ModelObject::center_around_origin(bool include_modifiers) From 66cf7ea9d30421d3a2b2a223896d92e2da7db492 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 May 2021 13:39:56 +0200 Subject: [PATCH 3/9] Extracting its_collect_mesh_projection_points_above() out of its_convex_hull_2d_above(), so that the projected points may get collected over multiple volumes before applying Geometry::convex_hull() --- src/libslic3r/TriangleMesh.cpp | 20 ++++++++++++++++++-- src/libslic3r/TriangleMesh.hpp | 5 +++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index a92e55194..8487e43cb 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -900,9 +900,8 @@ void its_shrink_to_fit(indexed_triangle_set &its) } template -Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const TransformVertex &transform_fn, const float z) +void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const TransformVertex &transform_fn, const float z, Points &all_pts) { - Points all_pts; for (const stl_triangle_vertex_indices &tri : its.indices) { const Vec3f pts[3] = { transform_fn(its.vertices[tri(0)]), transform_fn(its.vertices[tri(1)]), transform_fn(its.vertices[tri(2)]) }; int iprev = 3; @@ -919,6 +918,23 @@ Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const Transfor iprev = iedge; } } +} + +void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const Matrix3f &m, const float z, Points &all_pts) +{ + return its_collect_mesh_projection_points_above(its, [m](const Vec3f &p){ return m * p; }, z, all_pts); +} + +void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const Transform3f &t, const float z, Points &all_pts) +{ + return its_collect_mesh_projection_points_above(its, [t](const Vec3f &p){ return t * p; }, z, all_pts); +} + +template +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)); } diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index 59a8715a0..29a42eab3 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -113,6 +113,11 @@ int its_compactify_vertices(indexed_triangle_set &its, bool shrink_to_fit = true // Shrink the vectors of its.vertices and its.faces to a minimum size by reallocating the two vectors. void its_shrink_to_fit(indexed_triangle_set &its); +// For convex hull calculation: Transform mesh, trim it by the Z plane and collect all vertices. Duplicate vertices will be produced. +void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const Matrix3f &m, const float z, Points &all_pts); +void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const Transform3f &t, const float z, Points &all_pts); + +// Calculate 2D convex hull of a transformed and clipped mesh. Uses the function above. Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const Matrix3f &m, const float z); Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const Transform3f &t, const float z); From e952aded781591d21a8b15f7fc4d358def71d3c9 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 May 2021 13:52:47 +0200 Subject: [PATCH 4/9] cut_mesh(): new parameter to optionally not triangulate the caps. --- src/libslic3r/TriangleMeshSlicer.cpp | 58 +++++++++++++++------------- src/libslic3r/TriangleMeshSlicer.hpp | 3 +- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/libslic3r/TriangleMeshSlicer.cpp b/src/libslic3r/TriangleMeshSlicer.cpp index 7d0c2516c..e27766fb8 100644 --- a/src/libslic3r/TriangleMeshSlicer.cpp +++ b/src/libslic3r/TriangleMeshSlicer.cpp @@ -1179,6 +1179,7 @@ std::vector slice_mesh_ex( return layers; } +// Remove duplicates of slice_vertices, optionally triangulate the cut. static void triangulate_slice( indexed_triangle_set &its, IntersectionLines &lines, @@ -1186,7 +1187,8 @@ static void triangulate_slice( // Vertices of the original (unsliced) mesh. Newly added vertices are those on the slice. int num_original_vertices, // Z height of the slice. - float z) + float z, + bool triangulate) { sort_remove_duplicates(slice_vertices); @@ -1230,33 +1232,35 @@ static void triangulate_slice( f(i) = map_duplicate_vertex[f(i) - num_original_vertices]; } - size_t idx_vertex_new_first = its.vertices.size(); - Pointf3s triangles = triangulate_expolygons_3d(make_expolygons_simple(lines), z, true); - for (size_t i = 0; i < triangles.size(); ) { - stl_triangle_vertex_indices facet; - for (size_t j = 0; j < 3; ++ j) { - Vec3f v = triangles[i ++].cast(); - auto it = lower_bound_by_predicate(map_vertex_to_index.begin(), map_vertex_to_index.end(), - [&v](const std::pair &l) { return l.first.x() < v.x() || (l.first.x() == v.x() && l.first.y() < v.y()); }); - int idx = -1; - if (it != map_vertex_to_index.end() && it->first.x() == v.x() && it->first.y() == v.y()) - idx = it->second; - else { - // Try to find the vertex in the list of newly added vertices. Those vertices are not matched on the cut and they shall be rare. - for (size_t k = idx_vertex_new_first; k < its.vertices.size(); ++ k) - if (its.vertices[k] == v) { - idx = int(k); - break; + if (triangulate) { + size_t idx_vertex_new_first = its.vertices.size(); + Pointf3s triangles = triangulate_expolygons_3d(make_expolygons_simple(lines), z, true); + for (size_t i = 0; i < triangles.size(); ) { + stl_triangle_vertex_indices facet; + for (size_t j = 0; j < 3; ++ j) { + Vec3f v = triangles[i ++].cast(); + auto it = lower_bound_by_predicate(map_vertex_to_index.begin(), map_vertex_to_index.end(), + [&v](const std::pair &l) { return l.first.x() < v.x() || (l.first.x() == v.x() && l.first.y() < v.y()); }); + int idx = -1; + if (it != map_vertex_to_index.end() && it->first.x() == v.x() && it->first.y() == v.y()) + idx = it->second; + else { + // Try to find the vertex in the list of newly added vertices. Those vertices are not matched on the cut and they shall be rare. + for (size_t k = idx_vertex_new_first; k < its.vertices.size(); ++ k) + if (its.vertices[k] == v) { + idx = int(k); + break; + } + if (idx == -1) { + idx = int(its.vertices.size()); + its.vertices.emplace_back(v); } - if (idx == -1) { - idx = int(its.vertices.size()); - its.vertices.emplace_back(v); } + facet(j) = idx; } - facet(j) = idx; + if (facet(0) != facet(1) && facet(0) != facet(2) && facet(1) != facet(2)) + its.indices.emplace_back(facet); } - if (facet(0) != facet(1) && facet(0) != facet(2) && facet(1) != facet(2)) - its.indices.emplace_back(facet); } // Remove vertices, which are not referenced by any face. @@ -1266,7 +1270,7 @@ static void triangulate_slice( // its_remove_degenerate_faces(its); } -void cut_mesh(const indexed_triangle_set &mesh, float z, indexed_triangle_set *upper, indexed_triangle_set *lower) +void cut_mesh(const indexed_triangle_set &mesh, float z, indexed_triangle_set *upper, indexed_triangle_set *lower, bool triangulate_caps) { assert(upper || lower); if (upper == nullptr && lower == nullptr) @@ -1413,10 +1417,10 @@ void cut_mesh(const indexed_triangle_set &mesh, float z, indexed_triangle_set *u } if (upper != nullptr) - triangulate_slice(*upper, upper_lines, upper_slice_vertices, int(mesh.vertices.size()), z); + triangulate_slice(*upper, upper_lines, upper_slice_vertices, int(mesh.vertices.size()), z, triangulate_caps); if (lower != nullptr) - triangulate_slice(*lower, lower_lines, lower_slice_vertices, int(mesh.vertices.size()), z); + triangulate_slice(*lower, lower_lines, lower_slice_vertices, int(mesh.vertices.size()), z, triangulate_caps); } } diff --git a/src/libslic3r/TriangleMeshSlicer.hpp b/src/libslic3r/TriangleMeshSlicer.hpp index 4ae972d00..3a144d834 100644 --- a/src/libslic3r/TriangleMeshSlicer.hpp +++ b/src/libslic3r/TriangleMeshSlicer.hpp @@ -76,7 +76,8 @@ void cut_mesh( const indexed_triangle_set &mesh, float z, indexed_triangle_set *upper, - indexed_triangle_set *lower); + indexed_triangle_set *lower, + bool triangulate_caps = true); } From 31942e03db4a6cd9df6462d4184dbb5fb581c908 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 May 2021 13:59:34 +0200 Subject: [PATCH 5/9] Optimization of its_collect_mesh_projection_points_above(): Reserve points. --- src/libslic3r/TriangleMesh.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 8487e43cb..5e18e43ef 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -902,6 +902,7 @@ void its_shrink_to_fit(indexed_triangle_set &its) template void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const TransformVertex &transform_fn, const float z, Points &all_pts) { + all_pts.reserve(all_pts.size() + its.indices.size() * 3); for (const stl_triangle_vertex_indices &tri : its.indices) { const Vec3f pts[3] = { transform_fn(its.vertices[tri(0)]), transform_fn(its.vertices[tri(1)]), transform_fn(its.vertices[tri(2)]) }; int iprev = 3; From 116e2b2112b682efd775615f88e76f86b26562ad Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 May 2021 16:09:45 +0200 Subject: [PATCH 6/9] Fixing the slice_mesh() after recent refactoring. --- src/libslic3r/TriangleMeshSlicer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/TriangleMeshSlicer.cpp b/src/libslic3r/TriangleMeshSlicer.cpp index e27766fb8..ea9eb5ff2 100644 --- a/src/libslic3r/TriangleMeshSlicer.cpp +++ b/src/libslic3r/TriangleMeshSlicer.cpp @@ -1075,7 +1075,7 @@ std::vector slice_mesh( auto t = params.trafo; t.prescale(Vec3d(s, s, 1.)); auto tf = t.cast(); - slice_make_lines(mesh.vertices, [tf](const Vec3f &p) { return tf * p; }, mesh.indices, facets_edges, zs, throw_on_cancel); + lines = slice_make_lines(mesh.vertices, [tf](const Vec3f &p) { return tf * p; }, mesh.indices, facets_edges, zs, throw_on_cancel); } } else { // Copy and scale vertices in XY, don't scale in Z. From ff6623b0f47cc8d47f7335c1de9f9eeba96afd45 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 May 2021 16:51:25 +0200 Subject: [PATCH 7/9] Fixing --- src/libslic3r/TriangleMesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 5e18e43ef..c81f9066e 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -911,8 +911,8 @@ void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, c const Vec3f &p2 = 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. - float t = z / (p2.z() - p1.z()); - all_pts.emplace_back(scaled(p1.x() + (p2.x() - p1.x()) * t), scaled(p2.x() + (p2.y() - p2.y()) * t)); + float t = (z - p1.z()) / (p2.z() - p1.z()); + all_pts.emplace_back(scaled(p1.x() + (p2.x() - p1.x()) * t), scaled(p1.y() + (p2.y() - p1.y()) * t)); } if (p2.z() > z) all_pts.emplace_back(scaled(p2.x()), scaled(p2.y())); From 8377b6ef4f9b27b9fc26d9f6ee7bffbfbccd4062 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 20 May 2021 09:09:19 +0200 Subject: [PATCH 8/9] Fixed typo in its_collect_mesh_projection_points_above() and method TriangleMesh::slice() set as const --- src/libslic3r/TriangleMesh.cpp | 4 ++-- src/libslic3r/TriangleMesh.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index c81f9066e..8648edc52 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -611,7 +611,7 @@ TriangleMesh TriangleMesh::convex_hull_3d() const return output_mesh; } -std::vector TriangleMesh::slice(const std::vector &z) +std::vector TriangleMesh::slice(const std::vector &z) const { // convert doubles to floats std::vector z_f(z.begin(), z.end()); @@ -905,7 +905,7 @@ void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, c all_pts.reserve(all_pts.size() + its.indices.size() * 3); for (const stl_triangle_vertex_indices &tri : its.indices) { const Vec3f pts[3] = { transform_fn(its.vertices[tri(0)]), transform_fn(its.vertices[tri(1)]), transform_fn(its.vertices[tri(2)]) }; - int iprev = 3; + int iprev = 2; for (int iedge = 0; iedge < 3; ++ iedge) { const Vec3f &p1 = pts[iprev]; const Vec3f &p2 = pts[iedge]; diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index 29a42eab3..49b11465e 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -65,7 +65,7 @@ public: // Returns the convex hull of this TriangleMesh TriangleMesh convex_hull_3d() const; // Slice this mesh at the provided Z levels and return the vector - std::vector slice(const std::vector& z); + std::vector slice(const std::vector& z) const; void reset_repair_stats(); bool needed_repair() const; void require_shared_vertices(); From a218e0ef1860df6865f0bbcead02a4f1993147ab Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 20 May 2021 09:32:17 +0200 Subject: [PATCH 9/9] Tech ENABLE_ALLOW_NEGATIVE_Z -> New implementation for method ModelObject::convex_hull_2d() --- src/libslic3r/Model.cpp | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index f916fbdcd..21b13cbc2 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1,3 +1,4 @@ +#include "libslic3r.h" #include "Exception.hpp" #include "Model.hpp" #include "ModelArrange.hpp" @@ -889,35 +890,22 @@ BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_ // Calculate 2D convex hull of of a projection of the transformed printable volumes into the XY plane. // This method is cheap in that it does not make any unnecessary copy of the volume meshes. // This method is used by the auto arrange function. +#if ENABLE_ALLOW_NEGATIVE_Z +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)); +} +#else Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const { Points pts; for (const ModelVolume *v : this->volumes) if (v->is_model_part()) { -#if ENABLE_ALLOW_NEGATIVE_Z - const Transform3d trafo = trafo_instance * v->get_matrix(); - const TriangleMesh& hull_3d = v->get_convex_hull(); - const indexed_triangle_set& its = hull_3d.its; - if (its.vertices.empty()) { - // Using the STL faces. - const stl_file& stl = hull_3d.stl; - for (const stl_facet& facet : stl.facet_start) { - for (size_t j = 0; j < 3; ++j) { - const Vec3d p = trafo * facet.vertex[j].cast(); - if (p.z() >= 0.0) - pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); - } - } - } - else { - // Using the shared vertices should be a bit quicker than using the STL faces. - for (size_t i = 0; i < its.vertices.size(); ++i) { - const Vec3d p = trafo * its.vertices[i].cast(); - if (p.z() >= 0.0) - pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); - } - } -#else Transform3d trafo = trafo_instance * v->get_matrix(); const indexed_triangle_set &its = v->mesh().its; if (its.vertices.empty()) { @@ -935,10 +923,10 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); } } -#endif // ENABLE_ALLOW_NEGATIVE_Z } return Geometry::convex_hull(std::move(pts)); } +#endif // ENABLE_ALLOW_NEGATIVE_Z void ModelObject::center_around_origin(bool include_modifiers) {