Merge branch 'master' of https://github.com/Prusa-Development/PrusaSlicerPrivate into et_transformations

This commit is contained in:
enricoturri1966 2023-02-07 08:40:52 +01:00
commit 62d0b65b83
8 changed files with 64 additions and 37 deletions

View File

@ -288,12 +288,12 @@ inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, const Pol
} }
} }
inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &&polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &&polylines, ExtrusionRole role, double mm3_per_mm, float width, float height, bool can_reverse = true)
{ {
dst.reserve(dst.size() + polylines.size()); dst.reserve(dst.size() + polylines.size());
for (Polyline &polyline : polylines) for (Polyline &polyline : polylines)
if (polyline.is_valid()) { if (polyline.is_valid()) {
ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height); ExtrusionPath *extrusion_path = can_reverse ? new ExtrusionPath(role, mm3_per_mm, width, height) : new ExtrusionPathOriented(role, mm3_per_mm, width, height);
dst.push_back(extrusion_path); dst.push_back(extrusion_path);
extrusion_path->polyline = std::move(polyline); extrusion_path->polyline = std::move(polyline);
} }

View File

@ -461,23 +461,24 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
} }
active_speed_modifier = size_t(-1); active_speed_modifier = size_t(-1);
} else if (boost::starts_with(sline, m_toolchange_prefix)) { } else if (boost::starts_with(sline, m_toolchange_prefix)) {
unsigned int new_extruder; unsigned int new_extruder = 0;
auto res = std::from_chars(sline.data() + m_toolchange_prefix.size(), sline.data() + sline.size(), new_extruder); auto res = std::from_chars(sline.data() + m_toolchange_prefix.size(), sline.data() + sline.size(), new_extruder);
// Only change extruder in case the number is meaningful. User could provide an out-of-range index through custom gcodes - those shall be ignored. if (res.ec != std::errc::invalid_argument) {
if (new_extruder < map_extruder_to_per_extruder_adjustment.size()) { // Only change extruder in case the number is meaningful. User could provide an out-of-range index through custom gcodes - those shall be ignored.
if (new_extruder != current_extruder) { if (new_extruder < map_extruder_to_per_extruder_adjustment.size()) {
// Switch the tool. if (new_extruder != current_extruder) {
line.type = CoolingLine::TYPE_SET_TOOL; // Switch the tool.
current_extruder = new_extruder; line.type = CoolingLine::TYPE_SET_TOOL;
adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]]; current_extruder = new_extruder;
adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]];
}
}
else {
// Only log the error in case of MM printer. Single extruder printers likely ignore any T anyway.
if (map_extruder_to_per_extruder_adjustment.size() > 1)
BOOST_LOG_TRIVIAL(error) << "CoolingBuffer encountered an invalid toolchange, maybe from a custom gcode: " << sline;
} }
} }
else {
// Only log the error in case of MM printer. Single extruder printers likely ignore any T anyway.
if (map_extruder_to_per_extruder_adjustment.size() > 1)
BOOST_LOG_TRIVIAL(error) << "CoolingBuffer encountered an invalid toolchange, maybe from a custom gcode: " << sline;
}
} else if (boost::starts_with(sline, ";_BRIDGE_FAN_START")) { } else if (boost::starts_with(sline, ";_BRIDGE_FAN_START")) {
line.type = CoolingLine::TYPE_BRIDGE_FAN_START; line.type = CoolingLine::TYPE_BRIDGE_FAN_START;
} else if (boost::starts_with(sline, ";_BRIDGE_FAN_END")) { } else if (boost::starts_with(sline, ";_BRIDGE_FAN_END")) {
@ -785,9 +786,9 @@ std::string CoolingBuffer::apply_layer_cooldown(
if (line_start > pos) if (line_start > pos)
new_gcode.append(pos, line_start - pos); new_gcode.append(pos, line_start - pos);
if (line->type & CoolingLine::TYPE_SET_TOOL) { if (line->type & CoolingLine::TYPE_SET_TOOL) {
unsigned int new_extruder; unsigned int new_extruder = 0;
auto res = std::from_chars(line_start + m_toolchange_prefix.size(), line_end, new_extruder); auto res = std::from_chars(line_start + m_toolchange_prefix.size(), line_end, new_extruder);
if (new_extruder != m_current_extruder) { if (res.ec != std::errc::invalid_argument && new_extruder != m_current_extruder) {
m_current_extruder = new_extruder; m_current_extruder = new_extruder;
change_extruder_set_fan(); change_extruder_set_fan();
} }

View File

@ -754,7 +754,7 @@ ExtrusionPaths sort_and_connect_extra_perimeters(const std::vector<ExtrusionPath
std::unordered_set<Pidx, PidxHash> current_dependencies{}; std::unordered_set<Pidx, PidxHash> current_dependencies{};
if (shell > 0) { if (shell > 0) {
for (const auto &prev_path : dependencies[shell - 1]) { for (const auto &prev_path : dependencies[shell - 1]) {
if (paths_touch(get_path(current_path), get_path(prev_path.first), extrusion_spacing * 2.0)) { if (paths_touch(get_path(current_path), get_path(prev_path.first), extrusion_spacing * 1.5f)) {
current_dependencies.insert(prev_path.first); current_dependencies.insert(prev_path.first);
}; };
} }

View File

@ -1204,7 +1204,7 @@ void Print::alert_when_supports_needed()
for (const auto &obj : objects_isssues) { for (const auto &obj : objects_isssues) {
for (const auto &issue : obj.second) { for (const auto &issue : obj.second) {
po_by_support_issues[issue].push_back(obj.first); po_by_support_issues[issue].push_back(obj.first);
if (issue.first == SupportSpotsGenerator::SupportPointCause::SeparationFromBed){ if (issue.first == SupportSpotsGenerator::SupportPointCause::SeparationFromBed && !obj.first->has_brim()){
recommend_brim = true; recommend_brim = true;
} }
} }
@ -1235,7 +1235,9 @@ void Print::alert_when_supports_needed()
} }
} }
message += "\n" + L("Consider enabling supports") + (recommend_brim ? (" " + L("and/or brim")) : "") + "."; bool brim_or_supp = recommend_brim && po_by_support_issues.size() < 2;
auto brim_part = " " + (brim_or_supp ? L("or") : L("and")) + " " + L("brim");
message += "\n" + L("Consider enabling supports") + (recommend_brim ? brim_part : "") + ".";
if (objects_isssues.size() > 0) { if (objects_isssues.size() > 0) {
this->active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, message); this->active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, message);

View File

@ -3246,6 +3246,10 @@ static Polylines draw_perimeters(const ExPolygon &expoly, double clip_length)
for (size_t i = 0; i <= expoly.holes.size(); ++ i) { for (size_t i = 0; i <= expoly.holes.size(); ++ i) {
Polyline pl(i == 0 ? expoly.contour.points : expoly.holes[i - 1].points); Polyline pl(i == 0 ? expoly.contour.points : expoly.holes[i - 1].points);
pl.points.emplace_back(pl.points.front()); pl.points.emplace_back(pl.points.front());
if (i > 0)
// It is a hole, reverse it.
pl.reverse();
// so that all contours are CCW oriented.
pl.clip_end(clip_length); pl.clip_end(clip_length);
polylines.emplace_back(std::move(pl)); polylines.emplace_back(std::move(pl));
} }
@ -3351,13 +3355,17 @@ static inline void tree_supports_generate_paths(
const double anchor_length = spacing * 6.; const double anchor_length = spacing * 6.;
ClipperLib_Z::Paths anchor_candidates; ClipperLib_Z::Paths anchor_candidates;
for (ExPolygon& expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width()))) { for (ExPolygon& expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width()))) {
std::unique_ptr<ExtrusionEntityCollection> eec;
double area = expoly.area(); double area = expoly.area();
if (area > sqr(scaled<double>(5.))) { if (area > sqr(scaled<double>(5.))) {
eec = std::make_unique<ExtrusionEntityCollection>();
// Don't reoder internal / external loops of the same island, always start with the internal loop.
eec->no_sort = true;
// Make the tree branch stable by adding another perimeter. // Make the tree branch stable by adding another perimeter.
ExPolygons level2 = offset2_ex({ expoly }, -1.5 * flow.scaled_width(), 0.5 * flow.scaled_width()); ExPolygons level2 = offset2_ex({ expoly }, -1.5 * flow.scaled_width(), 0.5 * flow.scaled_width());
if (level2.size() == 1) { if (level2.size() == 1) {
Polylines polylines; Polylines polylines;
extrusion_entities_append_paths(dst, draw_perimeters(expoly, clip_length), ExtrusionRole::SupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(), extrusion_entities_append_paths(eec->entities, draw_perimeters(expoly, clip_length), ExtrusionRole::SupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
// Disable reversal of the path, always start with the anchor, always print CCW. // Disable reversal of the path, always start with the anchor, always print CCW.
false); false);
expoly = level2.front(); expoly = level2.front();
@ -3369,20 +3377,21 @@ static inline void tree_supports_generate_paths(
// The anchor candidate points are annotated with an index of the source contour or with -1 if on intersection. // The anchor candidate points are annotated with an index of the source contour or with -1 if on intersection.
anchor_candidates.clear(); anchor_candidates.clear();
shrink_expolygon_with_contour_idx(expoly, flow.scaled_width(), DefaultJoinType, 1.2, anchor_candidates); shrink_expolygon_with_contour_idx(expoly, flow.scaled_width(), DefaultJoinType, 1.2, anchor_candidates);
// Orient all contours CCW. // Orient all contours CW.
for (auto &path : anchor_candidates) for (auto &path : anchor_candidates)
if (ClipperLib_Z::Area(path) < 0) if (ClipperLib_Z::Area(path) > 0)
std::reverse(path.begin(), path.end()); std::reverse(path.begin(), path.end());
// Draw the perimeters. // Draw the perimeters.
Polylines polylines; Polylines polylines;
polylines.reserve(expoly.holes.size() + 1); polylines.reserve(expoly.holes.size() + 1);
for (size_t idx_loop = 0; idx_loop <= expoly.holes.size(); ++ idx_loop) { for (size_t idx_loop = 0; idx_loop < expoly.num_contours(); ++ idx_loop) {
// Open the loop with a seam. // Open the loop with a seam.
const Polygon &loop = idx_loop == 0 ? expoly.contour : expoly.holes[idx_loop - 1]; const Polygon &loop = expoly.contour_or_hole(idx_loop);
Polyline pl(loop.points); Polyline pl(loop.points);
// Orient all contours CCW. // Orient all contours CW, because the anchor will be added to the end of polyline while we want to start a loop with the anchor.
if (loop.area() < 0) if (idx_loop == 0)
// It is an outer contour.
pl.reverse(); pl.reverse();
pl.points.emplace_back(pl.points.front()); pl.points.emplace_back(pl.points.front());
pl.clip_end(clip_length); pl.clip_end(clip_length);
@ -3421,7 +3430,7 @@ static inline void tree_supports_generate_paths(
} }
if (d2min < sqr(flow.scaled_width() * 3.)) { if (d2min < sqr(flow.scaled_width() * 3.)) {
// Try to cut an anchor from the closest_contour. // Try to cut an anchor from the closest_contour.
// Both closest_contour and pl are CCW oriented. // Both closest_contour and pl are CW oriented.
pl.points.emplace_back(closest_point.cast<coord_t>()); pl.points.emplace_back(closest_point.cast<coord_t>());
const ClipperLib_Z::Path &path = *closest_contour; const ClipperLib_Z::Path &path = *closest_contour;
double remaining_length = anchor_length - (seam_pt - closest_point).norm(); double remaining_length = anchor_length - (seam_pt - closest_point).norm();
@ -3460,9 +3469,15 @@ static inline void tree_supports_generate_paths(
pl.reverse(); pl.reverse();
polylines.emplace_back(std::move(pl)); polylines.emplace_back(std::move(pl));
} }
extrusion_entities_append_paths(dst, polylines, ExtrusionRole::SupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
ExtrusionEntitiesPtr &out = eec ? eec->entities : dst;
extrusion_entities_append_paths(out, std::move(polylines), ExtrusionRole::SupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
// Disable reversal of the path, always start with the anchor, always print CCW. // Disable reversal of the path, always start with the anchor, always print CCW.
false); false);
if (eec) {
std::reverse(eec->entities.begin(), eec->entities.end());
dst.emplace_back(eec.release());
}
} }
} }

View File

@ -2500,8 +2500,10 @@ static void create_nodes_from_area(
// Point is chosen based on an inaccurate estimate where the branches will split into two, but every point inside the influence area would produce a valid result. // Point is chosen based on an inaccurate estimate where the branches will split into two, but every point inside the influence area would produce a valid result.
{ {
SupportElements *layer_above = move_bounds.size() > 1 ? &move_bounds[1] : nullptr; SupportElements *layer_above = move_bounds.size() > 1 ? &move_bounds[1] : nullptr;
for (SupportElement &elem : *layer_above) if (layer_above) {
elem.state.marked = false; for (SupportElement &elem : *layer_above)
elem.state.marked = false;
}
for (SupportElement &init : move_bounds.front()) { for (SupportElement &init : move_bounds.front()) {
init.state.result_on_layer = move_inside_if_outside(init.influence_area, init.state.next_position); init.state.result_on_layer = move_inside_if_outside(init.influence_area, init.state.next_position);
// Also set the parent nodes, as these will be required for the first iteration of the loop below and mark the parent nodes. // Also set the parent nodes, as these will be required for the first iteration of the loop below and mark the parent nodes.

View File

@ -201,7 +201,14 @@ bool Field::is_matched(const std::string& string, const std::string& pattern)
return std::regex_match(string, regex_pattern); return std::regex_match(string, regex_pattern);
} }
static wxString na_value() { return _(L("N/A")); } static wxString na_value(bool for_spin_ctrl = false)
{
#ifdef __linux__
if (for_spin_ctrl)
return "";
#endif
return _(L("N/A"));
}
void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true*/) void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true*/)
{ {
@ -888,7 +895,7 @@ void SpinCtrl::set_value(const boost::any& value, bool change_event/* = false*/)
if (m_opt.nullable) { if (m_opt.nullable) {
const bool m_is_na_val = tmp_value == ConfigOptionIntsNullable::nil_value(); const bool m_is_na_val = tmp_value == ConfigOptionIntsNullable::nil_value();
if (m_is_na_val) if (m_is_na_val)
dynamic_cast<wxSpinCtrl*>(window)->SetValue(na_value()); dynamic_cast<wxSpinCtrl*>(window)->SetValue(na_value(true));
else { else {
m_last_meaningful_value = value; m_last_meaningful_value = value;
dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value); dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value);
@ -909,7 +916,7 @@ void SpinCtrl::set_last_meaningful_value()
void SpinCtrl::set_na_value() void SpinCtrl::set_na_value()
{ {
dynamic_cast<wxSpinCtrl*>(window)->SetValue(na_value()); dynamic_cast<wxSpinCtrl*>(window)->SetValue(na_value(true));
m_value = ConfigOptionIntsNullable::nil_value(); m_value = ConfigOptionIntsNullable::nil_value();
propagate_value(); propagate_value();
} }
@ -917,7 +924,7 @@ void SpinCtrl::set_na_value()
boost::any& SpinCtrl::get_value() boost::any& SpinCtrl::get_value()
{ {
wxSpinCtrl* spin = static_cast<wxSpinCtrl*>(window); wxSpinCtrl* spin = static_cast<wxSpinCtrl*>(window);
if (spin->GetTextValue() == na_value()) if (spin->GetTextValue() == na_value(true))
return m_value; return m_value;
int value = spin->GetValue(); int value = spin->GetValue();

View File

@ -943,7 +943,7 @@ bool MainFrame::can_export_supports() const
const PrintObjects& objects = m_plater->sla_print().objects(); const PrintObjects& objects = m_plater->sla_print().objects();
for (const SLAPrintObject* object : objects) for (const SLAPrintObject* object : objects)
{ {
if (!object->support_mesh().empty()) if (!object->support_mesh().empty() || !object->pad_mesh().empty())
{ {
can_export = true; can_export = true;
break; break;