Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/libslic3r/GCode/ToolOrdering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1041,10 +1041,14 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
LayerTools lt_new(0.5f * (lt.print_z + lt_object.print_z));
// Find the 1st layer above lt_new.
for (j = i + 1; j < m_layer_tools.size() && m_layer_tools[j].print_z < lt_new.print_z - EPSILON; ++ j);
if (std::abs(m_layer_tools[j].print_z - lt_new.print_z) < EPSILON) {
if (j < m_layer_tools.size() && std::abs(m_layer_tools[j].print_z - lt_new.print_z) < EPSILON) {
m_layer_tools[j].has_wipe_tower = true;
} else {
LayerTools &lt_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new);
} else if (j < m_layer_tools.size() && ! m_layer_tools[j].extruders.empty()) {
// The layer right above the inserted one may carry no extruders, e.g. when
// support generation was toggled off after a slice that had it enabled: the
// layer plan for the raft gap then contains no extrusions for some layers.
// lt_next.extruders.front() would dereference a null begin() and crash.
LayerTools &lt_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new);
//LayerTools &lt_prev = m_layer_tools[j];
LayerTools &lt_next = m_layer_tools[j + 1];
assert(! m_layer_tools[j - 1].extruders.empty() && ! lt_next.extruders.empty());
Expand Down
31 changes: 29 additions & 2 deletions src/libslic3r/ShortestPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "clipper.hpp"
#include "ShortestPath.hpp"
#include "ExtrusionEntityCollection.hpp"
#include "KDTreeIndirect.hpp"
#include "MutablePriorityQueue.hpp"
#include "Print.hpp"
Expand All @@ -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>
Expand Down Expand Up @@ -1030,8 +1055,10 @@ void reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const s

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));
}
Expand Down
7 changes: 6 additions & 1 deletion src/libslic3r/Support/TreeSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,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;
Expand Down
11 changes: 9 additions & 2 deletions src/slic3r/GUI/Field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1654,8 +1654,15 @@ boost::any& Choice::get_value()
m_opt_id == "ironing_pattern" || m_opt_id == "support_ironing_pattern" ||
m_opt_id == "support_style" || m_opt_id == "curr_bed_type")
{
const std::string &key = m_opt.enum_values[field->GetSelection()];
m_value = int(m_opt.enum_keys_map->at(key));
// Selection can be invalid when the current value is not present in the rebuilt
// enum list (e.g. stale support_style vs support_type); fall back to the first
// entry instead of indexing out of bounds.
const int selection = field->GetSelection();
if (! m_opt.enum_values.empty()) {
const int index = (selection >= 0 && selection < static_cast<int>(m_opt.enum_values.size())) ? selection : 0;
const std::string &key = m_opt.enum_values[index];
m_value = static_cast<int>(m_opt.enum_keys_map->at(key));
}
}
// Support ThirdPartyPrinter
else if (m_opt_id.compare("host_type") == 0 && m_opt.enum_values.size() > field->GetCount())
Expand Down
5 changes: 5 additions & 0 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2766,6 +2766,11 @@ void TabPrint::toggle_options()
cb->Append(_(def->enum_labels[i]));
}
cb->SetValue(n);
// The stale label (e.g. a tree style left over after support_type changed while support
// is disabled) may not exist in the rebuilt list; GetValue()/SetValue() then leaves the
// selection invalid, and Choice::get_value would index enum_values out of bounds.
if (cb->GetSelection() == wxNOT_FOUND && cb->GetCount() > 0)
cb->SetSelection(0);
}

// Keep plate bed-type list in sync with currently selected printer.
Expand Down
Loading