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:
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user