From a5826ea92bbe298eb8bb586c864f2b309d257eec Mon Sep 17 00:00:00 2001 From: Kiss Lorand <50251547+kisslorand@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:31:52 +0300 Subject: [PATCH] Fix crashing if slicing with non organic tree support (#14074) Fix non organic tree support crashing Fix Orca crashing during slicing if non organic tree support is used --- src/libslic3r/ShortestPath.cpp | 31 +++++++++++++++++++++++++-- src/libslic3r/Support/TreeSupport.cpp | 7 +++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/ShortestPath.cpp b/src/libslic3r/ShortestPath.cpp index c1325a4264..e2fc258e31 100644 --- a/src/libslic3r/ShortestPath.cpp +++ b/src/libslic3r/ShortestPath.cpp @@ -6,6 +6,7 @@ #include "clipper.hpp" #include "ShortestPath.hpp" +#include "ExtrusionEntityCollection.hpp" #include "KDTreeIndirect.hpp" #include "MutablePriorityQueue.hpp" #include "Print.hpp" @@ -15,6 +16,30 @@ namespace Slic3r { +// Orca: Some support entities may contain empty nested paths, which cannot be reordered safely. +static bool extrusion_entity_has_endpoints(const ExtrusionEntity *entity) +{ + auto paths_have_endpoints = [](const ExtrusionPaths &paths) { + return !paths.empty() && + !paths.front().polyline.points.empty() && + !paths.back().polyline.points.empty(); + }; + + if (entity == nullptr) + return false; + if (const auto *collection = dynamic_cast(entity)) + return !collection->entities.empty() && + extrusion_entity_has_endpoints(collection->entities.front()) && + extrusion_entity_has_endpoints(collection->entities.back()); + if (const auto *path = dynamic_cast(entity)) + return !path->polyline.points.empty(); + if (const auto *multipath = dynamic_cast(entity)) + return paths_have_endpoints(multipath->paths); + if (const auto *loop = dynamic_cast(entity)) + return paths_have_endpoints(loop->paths); + return true; +} + // Naive implementation of the Traveling Salesman Problem, it works by always taking the next closest neighbor. // This implementation will always produce valid result even if some segments cannot reverse. template @@ -1035,8 +1060,10 @@ void chain_and_reorder_extrusion_entities(std::vector &entitie void chain_and_reorder_extrusion_entities(std::vector &entities, const Point *start_near) { - // this function crashes if there are empty elements in entities - entities.erase(std::remove_if(entities.begin(), entities.end(), [](ExtrusionEntity *entity) { return static_cast(entity)->empty(); }), + // Orca: Reordering queries first_point() / last_point(); drop entities that cannot provide valid endpoints. + entities.erase(std::remove_if(entities.begin(), entities.end(), [](ExtrusionEntity *entity) { + return !extrusion_entity_has_endpoints(entity); + }), entities.end()); reorder_extrusion_entities(entities, chain_extrusion_entities(entities, start_near)); } diff --git a/src/libslic3r/Support/TreeSupport.cpp b/src/libslic3r/Support/TreeSupport.cpp index e690fb899f..8e6033f43a 100644 --- a/src/libslic3r/Support/TreeSupport.cpp +++ b/src/libslic3r/Support/TreeSupport.cpp @@ -1332,7 +1332,12 @@ static void make_perimeter_and_infill(ExtrusionEntitiesPtr& dst, const ExPolygon dst = std::move(loops_entities); } } - dst.erase(std::remove_if(dst.begin(), dst.end(), [](ExtrusionEntity *entity) { return static_cast(entity)->empty(); }), dst.end()); + + // Orca: Some entities are direct paths, so check the type before testing for an empty collection. + dst.erase(std::remove_if(dst.begin(), dst.end(), [](ExtrusionEntity *entity) { + return entity != nullptr && entity->is_collection() && static_cast(entity)->empty(); + }), dst.end()); + if (infill_first) { // sort regions to reduce travel Points ordering_points;