From 9c3a3f8a870711f1f27098b54340555a7229b944 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 23 Oct 2023 12:02:22 +0200 Subject: [PATCH] #11484 - Fixed crash when applying Split to Objects command (SPE-1983) --- src/libslic3r/Print.cpp | 90 +++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 4f1c00b3ba..5b043bb468 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -417,54 +417,58 @@ bool Print::sequential_print_horizontal_clearance_valid(const Print& print, Poly polygons->clear(); std::vector intersecting_idxs; - std::map map_model_object_to_convex_hull; - for (const PrintObject *print_object : print.objects()) { - assert(! print_object->model_object()->instances.empty()); - assert(! print_object->instances().empty()); - ObjectID model_object_id = print_object->model_object()->id(); - auto it_convex_hull = map_model_object_to_convex_hull.find(model_object_id); + std::map map_model_object_to_convex_hull; + for (const PrintObject *print_object : print.objects()) { + assert(! print_object->model_object()->instances.empty()); + assert(! print_object->instances().empty()); + ObjectID model_object_id = print_object->model_object()->id(); + auto it_convex_hull = map_model_object_to_convex_hull.find(model_object_id); // Get convex hull of all printable volumes assigned to this print object. ModelInstance *model_instance0 = print_object->model_object()->instances.front(); - if (it_convex_hull == map_model_object_to_convex_hull.end()) { - // Calculate the convex hull of a printable object. - // Grow convex hull with the clearance margin. - // FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2) - // which causes that the warning will be showed after arrangement with the - // appropriate object distance. Even if I set this to jtMiter the warning still shows up. - Geometry::Transformation trafo = model_instance0->get_transformation(); - trafo.set_offset({ 0.0, 0.0, model_instance0->get_offset().z() }); - it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id, - offset(print_object->model_object()->convex_hull_2d(trafo.get_matrix()), - // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects - // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. - float(scale_(0.5 * print.config().extruder_clearance_radius.value - BuildVolume::BedEpsilon)), - jtRound, scale_(0.1)).front()); - } - // Make a copy, so it may be rotated for instances. - Polygon convex_hull0 = it_convex_hull->second; - const double z_diff = Geometry::rotation_diff_z(model_instance0->get_matrix(), print_object->instances().front().model_instance->get_matrix()); - if (std::abs(z_diff) > EPSILON) - convex_hull0.rotate(z_diff); - // Now we check that no instance of convex_hull intersects any of the previously checked object instances. - for (const PrintInstance &instance : print_object->instances()) { - Polygon convex_hull = convex_hull0; - // instance.shift is a position of a centered object, while model object may not be centered. - // Convert the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset. - convex_hull.translate(instance.shift - print_object->center_offset()); - // if output needed, collect indices (inside convex_hulls_other) of intersecting hulls - for (size_t i = 0; i < convex_hulls_other.size(); ++i) { - if (! intersection(convex_hulls_other[i], convex_hull).empty()) { - if (polygons == nullptr) - return false; - else { - intersecting_idxs.emplace_back(i); - intersecting_idxs.emplace_back(convex_hulls_other.size()); + if (it_convex_hull == map_model_object_to_convex_hull.end()) { + // Calculate the convex hull of a printable object. + // Grow convex hull with the clearance margin. + // FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2) + // which causes that the warning will be showed after arrangement with the + // appropriate object distance. Even if I set this to jtMiter the warning still shows up. + Geometry::Transformation trafo = model_instance0->get_transformation(); + trafo.set_offset({ 0.0, 0.0, model_instance0->get_offset().z() }); + Polygon ch2d = print_object->model_object()->convex_hull_2d(trafo.get_matrix()); + Polygons offs_ch2d = offset(ch2d, + // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects + // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. + float(scale_(0.5 * print.config().extruder_clearance_radius.value - BuildVolume::BedEpsilon)), jtRound, scale_(0.1)); + // for invalid geometries the vector returned by offset() may be empty + if (!offs_ch2d.empty()) + it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id, offs_ch2d.front()); + } + if (it_convex_hull != map_model_object_to_convex_hull.end()) { + // Make a copy, so it may be rotated for instances. + Polygon convex_hull0 = it_convex_hull->second; + const double z_diff = Geometry::rotation_diff_z(model_instance0->get_matrix(), print_object->instances().front().model_instance->get_matrix()); + if (std::abs(z_diff) > EPSILON) + convex_hull0.rotate(z_diff); + // Now we check that no instance of convex_hull intersects any of the previously checked object instances. + for (const PrintInstance& instance : print_object->instances()) { + Polygon convex_hull = convex_hull0; + // instance.shift is a position of a centered object, while model object may not be centered. + // Convert the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset. + convex_hull.translate(instance.shift - print_object->center_offset()); + // if output needed, collect indices (inside convex_hulls_other) of intersecting hulls + for (size_t i = 0; i < convex_hulls_other.size(); ++i) { + if (!intersection(convex_hulls_other[i], convex_hull).empty()) { + if (polygons == nullptr) + return false; + else { + intersecting_idxs.emplace_back(i); + intersecting_idxs.emplace_back(convex_hulls_other.size()); + } } } + convex_hulls_other.emplace_back(std::move(convex_hull)); } - convex_hulls_other.emplace_back(std::move(convex_hull)); - } - } + } + } if (!intersecting_idxs.empty()) { // use collected indices (inside convex_hulls_other) to update output