mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-31 13:57:07 +00:00
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 "clipper.hpp"
|
||||||
#include "ShortestPath.hpp"
|
#include "ShortestPath.hpp"
|
||||||
|
#include "ExtrusionEntityCollection.hpp"
|
||||||
#include "KDTreeIndirect.hpp"
|
#include "KDTreeIndirect.hpp"
|
||||||
#include "MutablePriorityQueue.hpp"
|
#include "MutablePriorityQueue.hpp"
|
||||||
#include "Print.hpp"
|
#include "Print.hpp"
|
||||||
@@ -15,6 +16,30 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
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.
|
// 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.
|
// This implementation will always produce valid result even if some segments cannot reverse.
|
||||||
template<typename EndPointType, typename KDTreeType, typename CouldReverseFunc>
|
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)
|
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point *start_near)
|
||||||
{
|
{
|
||||||
// this function crashes if there are empty elements in entities
|
// 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 static_cast<ExtrusionEntityCollection *>(entity)->empty(); }),
|
entities.erase(std::remove_if(entities.begin(), entities.end(), [](ExtrusionEntity *entity) {
|
||||||
|
return !extrusion_entity_has_endpoints(entity);
|
||||||
|
}),
|
||||||
entities.end());
|
entities.end());
|
||||||
reorder_extrusion_entities(entities, chain_extrusion_entities(entities, start_near));
|
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 = 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) {
|
if (infill_first) {
|
||||||
// sort regions to reduce travel
|
// sort regions to reduce travel
|
||||||
Points ordering_points;
|
Points ordering_points;
|
||||||
|
|||||||
Reference in New Issue
Block a user