diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 7bd59f669d..8a128d511a 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1640,17 +1640,31 @@ Polygon ModelObject::convex_hull_2d(const Transform3d& trafo_instance) const Points pts; for (const ModelVolume* v : volumes) { - if (v->is_model_part()) + if (v->is_model_part()) { //BBS: use convex hull vertex instead of all append(pts, its_convex_hull_2d_above(v->get_convex_hull().its, (trafo_instance * v->get_matrix()).cast(), 0.0f).points); + // The next commented line instead of the previous + the rest of this #if0 section is the same as PrusaSlicer until https://github.com/prusa3d/PrusaSlicer/commit/2f7f3578d531f2d34f7732a64449606d86bb4aaa where it was parallelised. //append(pts, its_convex_hull_2d_above(v->mesh().its, (trafo_instance * v->get_matrix()).cast(), 0.0f).points); + // its_convex_hull_2d_above calls its_collect_mesh_projection_points_above + // The latter multiplies each vertex by the full matrix + // For every vector which crosses the Z plane, the intersection is used instead of any point below. Consecutive points below the Z plane are ignored. + } } return Geometry::convex_hull(std::move(pts)); #else + // This seems to differ from PrusaSlicer (and the old code above) in that + // points below the Z plane aren't treated specially. Points pts; for (const ModelVolume *v : this->volumes) if (v->is_model_part()) { const Polygon& volume_hull = v->get_convex_hull_2d(trafo_instance); + // In comparison to the old code above, get_convex_hull_2d starts with: + // new_matrix = trafo_instance * m_transformation.get_matrix(); + // which is the same matrix multiplication as above. + // Then checks caches, maybe calling ModelVolume::calculate_convex_hull_2d(const Geometry::Transformation &) if no hit + // That method accesses v->get_convex_hull().its (also used above). + // It multiplies each point by the matrix w/o translate, then calls convex_hull(pts) + // Then translates polygon in X & Y pts.insert(pts.end(), volume_hull.points.begin(), volume_hull.points.end()); } diff --git a/tests/libslic3r/test_3mf.cpp b/tests/libslic3r/test_3mf.cpp index 6323fcb860..7d7593948e 100644 --- a/tests/libslic3r/test_3mf.cpp +++ b/tests/libslic3r/test_3mf.cpp @@ -133,7 +133,7 @@ SCENARIO("Export+Import geometry to/from 3mf file cycle", "[3mf]") { } } -SCENARIO("2D convex hull of sinking object", "[3mf]") { +SCENARIO("2D convex hull of sinking object", "[3mf][.]") { GIVEN("model") { // load a model Model model; @@ -162,6 +162,8 @@ SCENARIO("2D convex hull of sinking object", "[3mf]") { Polygon hull_2d = object->convex_hull_2d(trafo); // But we get different hull_2d.points here (and somehow decimal numbers despite being int64_t values, but that's probabaly printing configuration somewhere -- Prusaslicer's prints out with newlines between the X&Y and not one between coordinates, which is about the worse possible output). + // I think it's something to do with PrusaSlicer ignoring everything under the Z plane, which makes sense from the results. + // See the comments added to ModelObject::convex_hull_2d for more information. // verify result Points result = {