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
This commit is contained in:
Kiss Lorand
2026-06-07 08:31:52 +03:00
committed by GitHub
parent 59a06bc8fa
commit a5826ea92b
2 changed files with 35 additions and 3 deletions

View File

@@ -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<const ExtrusionEntityCollection *>(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<const ExtrusionPath *>(entity))
return !path->polyline.points.empty();
if (const auto *multipath = dynamic_cast<const ExtrusionMultiPath *>(entity))
return paths_have_endpoints(multipath->paths);
if (const auto *loop = dynamic_cast<const ExtrusionLoop *>(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<typename EndPointType, typename KDTreeType, typename CouldReverseFunc>
@@ -1035,8 +1060,10 @@ void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entitie
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &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<ExtrusionEntityCollection *>(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));
}

View File

@@ -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<ExtrusionEntityCollection *>(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<ExtrusionEntityCollection *>(entity)->empty();
}), dst.end());
if (infill_first) {
// sort regions to reduce travel
Points ordering_points;