Merge some BS1.7 changes:

Port object canceling for BL X1 from BS.

Todo: refactor
This commit is contained in:
SoftFever 2023-08-08 00:13:33 +08:00
parent 3acd89e877
commit 7ece35931e
15 changed files with 557 additions and 162 deletions

View file

@ -2,6 +2,7 @@
#define _libslic3r_Exception_h_ #define _libslic3r_Exception_h_
#include <stdexcept> #include <stdexcept>
#include <vector>
namespace Slic3r { namespace Slic3r {
@ -35,6 +36,16 @@ public:
private: private:
size_t objectId_ = 0; size_t objectId_ = 0;
}; };
class SlicingErrors : public Exception
{
public:
using Exception::Exception;
SlicingErrors(const std::vector<SlicingError> &errors) : Exception("Errors"), errors_(errors) {}
std::vector<SlicingError> errors_;
};
#undef SLIC3R_DERIVE_EXCEPTION #undef SLIC3R_DERIVE_EXCEPTION
} // namespace Slic3r } // namespace Slic3r

View file

@ -11,6 +11,7 @@
#include "Print.hpp" #include "Print.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
#include "libslic3r.h"
#include "LocalesUtils.hpp" #include "LocalesUtils.hpp"
#include "libslic3r/format.hpp" #include "libslic3r/format.hpp"
#include "Time.hpp" #include "Time.hpp"
@ -78,6 +79,7 @@ namespace Slic3r {
static const float g_min_purge_volume = 100.f; static const float g_min_purge_volume = 100.f;
static const float g_purge_volume_one_time = 135.f; static const float g_purge_volume_one_time = 135.f;
static const int g_max_flush_count = 4; static const int g_max_flush_count = 4;
static const size_t g_max_label_object = 64;
Vec2d travel_point_1; Vec2d travel_point_1;
Vec2d travel_point_2; Vec2d travel_point_2;
@ -420,6 +422,9 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
gcode += gcodegen.unretract(); gcode += gcodegen.unretract();
} }
//BBS: if needed, write the gcode_label_objects_end then priming tower, if the retract, didn't did it.
gcodegen.m_writer.add_object_end_labels(gcode);
double current_z = gcodegen.writer().get_position().z(); double current_z = gcodegen.writer().get_position().z();
if (z == -1.) // in case no specific z was provided, print at current_z pos if (z == -1.) // in case no specific z was provided, print at current_z pos
z = current_z; z = current_z;
@ -484,6 +489,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate; new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate;
config.set_key_value("max_layer_z", new ConfigOptionFloat(gcodegen.m_max_layer_z)); config.set_key_value("max_layer_z", new ConfigOptionFloat(gcodegen.m_max_layer_z));
config.set_key_value("relative_e_axis", new ConfigOptionBool(full_config.use_relative_e_distances));
config.set_key_value("toolchange_count", new ConfigOptionInt((int)gcodegen.m_toolchange_count)); config.set_key_value("toolchange_count", new ConfigOptionInt((int)gcodegen.m_toolchange_count));
//BBS: fan speed is useless placeholer now, but we don't remove it to avoid //BBS: fan speed is useless placeholer now, but we don't remove it to avoid
//slicing error in old change_filament_gcode in old 3MF //slicing error in old change_filament_gcode in old 3MF
@ -834,6 +840,10 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
double extra_gap = (layer_to_print.support_layer ? bottom_cd : top_cd); double extra_gap = (layer_to_print.support_layer ? bottom_cd : top_cd);
// raft contact distance should not trigger any warning
if(last_extrusion_layer && last_extrusion_layer->support_layer)
extra_gap = std::max(extra_gap, object.config().raft_contact_distance.value);
double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.) double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.)
+ layer_to_print.layer()->height + layer_to_print.layer()->height
+ std::max(0., extra_gap); + std::max(0., extra_gap);
@ -876,8 +886,16 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
std::vector<std::vector<LayerToPrint>> per_object(print.objects().size(), std::vector<LayerToPrint>()); std::vector<std::vector<LayerToPrint>> per_object(print.objects().size(), std::vector<LayerToPrint>());
std::vector<OrderingItem> ordering; std::vector<OrderingItem> ordering;
std::vector<Slic3r::SlicingError> errors;
for (size_t i = 0; i < print.objects().size(); ++i) { for (size_t i = 0; i < print.objects().size(); ++i) {
per_object[i] = collect_layers_to_print(*print.objects()[i]); try {
per_object[i] = collect_layers_to_print(*print.objects()[i]);
} catch (const Slic3r::SlicingError &e) {
errors.push_back(e);
continue;
}
OrderingItem ordering_item; OrderingItem ordering_item;
ordering_item.object_idx = i; ordering_item.object_idx = i;
ordering.reserve(ordering.size() + per_object[i].size()); ordering.reserve(ordering.size() + per_object[i].size());
@ -889,6 +907,8 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
} }
} }
if (!errors.empty()) { throw Slic3r::SlicingErrors(errors); }
std::sort(ordering.begin(), ordering.end(), [](const OrderingItem& oi1, const OrderingItem& oi2) { return oi1.print_z < oi2.print_z; }); std::sort(ordering.begin(), ordering.end(), [](const OrderingItem& oi1, const OrderingItem& oi2) { return oi1.print_z < oi2.print_z; });
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print; std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print;
@ -1037,6 +1057,13 @@ namespace DoExport {
} }
} // namespace DoExport } // namespace DoExport
bool GCode::is_BBL_Printer()
{
if (m_curr_print)
return m_curr_print->is_BBL_printer();
return false;
}
void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb) void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb)
{ {
PROFILE_CLEAR(); PROFILE_CLEAR();
@ -1143,6 +1170,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
BOOST_LOG_TRIVIAL(info) << "Exporting G-code finished" << log_memory_info(); BOOST_LOG_TRIVIAL(info) << "Exporting G-code finished" << log_memory_info();
print->set_done(psGCodeExport); print->set_done(psGCodeExport);
// Used by BBL only
result->label_object_enabled = m_enable_label_object;
// Write the profiler measurements to file // Write the profiler measurements to file
PROFILE_UPDATE(); PROFILE_UPDATE();
@ -1455,13 +1484,12 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
if (print.config().print_sequence == PrintSequence::ByObject) { if (print.config().print_sequence == PrintSequence::ByObject) {
// Add each of the object's layers separately. // Add each of the object's layers separately.
for (auto object : print.objects()) { for (auto object : print.objects()) {
//BBS: fix the issue that total layer is not right std::vector<coordf_t> zs;
std::vector<coord_t> zs;
zs.reserve(object->layers().size() + object->support_layers().size()); zs.reserve(object->layers().size() + object->support_layers().size());
for (auto layer : object->layers()) for (auto layer : object->layers())
zs.push_back((coord_t)(layer->print_z / EPSILON)); zs.push_back(layer->print_z);
for (auto layer : object->support_layers()) for (auto layer : object->support_layers())
zs.push_back((coord_t)(layer->print_z / EPSILON)); zs.push_back(layer->print_z);
std::sort(zs.begin(), zs.end()); std::sort(zs.begin(), zs.end());
//BBS: merge numerically very close Z values. //BBS: merge numerically very close Z values.
auto end_it = std::unique(zs.begin(), zs.end()); auto end_it = std::unique(zs.begin(), zs.end());
@ -1474,22 +1502,24 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
} }
} else { } else {
// Print all objects with the same print_z together. // Print all objects with the same print_z together.
//BBS: fix the issue that total layer is not right std::vector<coordf_t> zs;
std::vector<coord_t> zs;
for (auto object : print.objects()) { for (auto object : print.objects()) {
zs.reserve(zs.size() + object->layers().size() + object->support_layers().size()); zs.reserve(zs.size() + object->layers().size() + object->support_layers().size());
for (auto layer : object->layers()) for (auto layer : object->layers())
zs.push_back((coord_t)(layer->print_z / EPSILON)); zs.push_back(layer->print_z);
for (auto layer : object->support_layers()) for (auto layer : object->support_layers())
zs.push_back((coord_t)(layer->print_z / EPSILON)); zs.push_back(layer->print_z);
} }
std::sort(zs.begin(), zs.end()); if (!zs.empty())
//BBS: merge numerically very close Z values. {
auto end_it = std::unique(zs.begin(), zs.end()); std::sort(zs.begin(), zs.end());
m_layer_count = (unsigned int)(end_it - zs.begin()); //BBS: merge numerically very close Z values.
for (auto it = zs.begin(); it != end_it - 1; it++) { auto end_it = std::unique(zs.begin(), zs.end());
if (abs(*it - *(it + 1)) < EPSILON) m_layer_count = (unsigned int)(end_it - zs.begin());
m_layer_count--; for (auto it = zs.begin(); it != end_it - 1; it++) {
if (abs(*it - *(it + 1)) < EPSILON)
m_layer_count--;
}
} }
} }
print.throw_if_canceled(); print.throw_if_canceled();
@ -1518,6 +1548,29 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str()); file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str());
//BBS: total layer number //BBS: total layer number
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Total_Layer_Number_Placeholder).c_str()); file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Total_Layer_Number_Placeholder).c_str());
//BBS: judge whether support skipping, if yes, list all label_object_id with sorted order here
if (print.extruders(true).size() == 1 && //Don't support multi-color
print.num_object_instances() <= g_max_label_object && //Don't support too many objects on one plate
print.calib_params().mode == CalibMode::Calib_None) { //Don't support skipping in cali mode
m_enable_label_object = true;
m_label_objects_ids.clear();
m_label_objects_ids.reserve(print.num_object_instances());
for (const PrintObject* print_object : print.objects())
for (const PrintInstance& print_instance : print_object->instances())
m_label_objects_ids.push_back(print_instance.model_instance->get_labeled_id());
std::sort(m_label_objects_ids.begin(), m_label_objects_ids.end());
std::string objects_id_list = "; model label id: ";
for (auto it = m_label_objects_ids.begin(); it != m_label_objects_ids.end(); it++)
objects_id_list += (std::to_string(*it) + (it != m_label_objects_ids.end() - 1 ? "," : "\n"));
file.writeln(objects_id_list);
}
else {
m_enable_label_object = false;
m_label_objects_ids.clear();
}
file.write_format("; HEADER_BLOCK_END\n\n"); file.write_format("; HEADER_BLOCK_END\n\n");
@ -2058,6 +2111,14 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
//BBS: the last retraction //BBS: the last retraction
// Write end commands to file. // Write end commands to file.
file.write(this->retract(false, true)); file.write(this->retract(false, true));
// if needed, write the gcode_label_objects_end
{
std::string gcode;
m_writer.add_object_change_labels(gcode);
file.write(gcode);
}
file.write(m_writer.set_fan(0)); file.write(m_writer.set_fan(0));
//BBS: make sure the additional fan is closed when end //BBS: make sure the additional fan is closed when end
if(m_config.auxiliary_fan.value) if(m_config.auxiliary_fan.value)
@ -2539,7 +2600,7 @@ std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
const PrintObject *print_object = layers[layer_id].original_object; const PrintObject *print_object = layers[layer_id].original_object;
//const PrintObject *print_object = layers[layer_id].object(); //const PrintObject *print_object = layers[layer_id].object();
if (print_object) if (print_object)
out.emplace_back(object_by_extruder, layer_id, *print_object, single_object_instance_idx); out.emplace_back(object_by_extruder, layer_id, *print_object, single_object_instance_idx, print_object->instances()[single_object_instance_idx].model_instance->get_labeled_id());
} }
} else { } else {
// Create mapping from PrintObject* to ObjectByExtruder*. // Create mapping from PrintObject* to ObjectByExtruder*.
@ -2567,7 +2628,7 @@ std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
auto it = std::lower_bound(sorted.begin(), sorted.end(), key); auto it = std::lower_bound(sorted.begin(), sorted.end(), key);
if (it != sorted.end() && it->first == &print_object) if (it != sorted.end() && it->first == &print_object)
// ObjectByExtruder for this PrintObject was found. // ObjectByExtruder for this PrintObject was found.
out.emplace_back(*it->second, it->second - objects_by_extruder.data(), print_object, instance - print_object.instances().data()); out.emplace_back(*it->second, it->second - objects_by_extruder.data(), print_object, instance - print_object.instances().data(), instance->model_instance->get_labeled_id());
} }
} }
} }
@ -2721,7 +2782,6 @@ namespace Skirt {
#if 0 #if 0
// Prime just the first printing extruder. This is original Slic3r's implementation. // Prime just the first printing extruder. This is original Slic3r's implementation.
skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair<size_t, size_t>(0, print.config().skirt_loops.value); skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair<size_t, size_t>(0, print.config().skirt_loops.value);
skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair<size_t, size_t>(0, print.config().skirt_loops.value);
#else #else
// Prime all extruders planned for this layer, see // Prime all extruders planned for this layer, see
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
@ -3264,6 +3324,16 @@ GCode::LayerResult GCode::process_layer(
m_object_layer_over_raft = object_layer_over_raft; m_object_layer_over_raft = object_layer_over_raft;
if (m_config.reduce_crossing_wall) if (m_config.reduce_crossing_wall)
m_avoid_crossing_perimeters.init_layer(*m_layer); m_avoid_crossing_perimeters.init_layer(*m_layer);
// Skip objects
if (m_enable_label_object) {
std::string start_str = std::string("; start printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n";
if (print.is_BBL_printer()) {
start_str += ("M624 " + _encode_label_ids_to_base64({ instance_to_print.label_object_id }));
start_str += "\n";
}
m_writer.set_object_start_str(start_str);
}
bool reset_e = false; bool reset_e = false;
if (this->config().gcode_label_objects) { if (this->config().gcode_label_objects) {
gcode += std::string("; printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " + std::to_string(inst.id) + "\n"; gcode += std::string("; printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " + std::to_string(inst.id) + "\n";
@ -3282,7 +3352,7 @@ GCode::LayerResult GCode::process_layer(
m_extrusion_quality_estimator.set_current_object(&instance_to_print.print_object); m_extrusion_quality_estimator.set_current_object(&instance_to_print.print_object);
// When starting a new object, use the external motion planner for the first travel move. // When starting a new object, use the external motion planner for the first travel move.
const Point &offset = inst.shift; const Point &offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object, offset); std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object, offset);
if (m_last_obj_copy != this_object_copy) if (m_last_obj_copy != this_object_copy)
m_avoid_crossing_perimeters.use_external_mp_once(); m_avoid_crossing_perimeters.use_external_mp_once();
@ -3365,6 +3435,15 @@ GCode::LayerResult GCode::process_layer(
} }
// ironing // ironing
gcode += this->extrude_infill(print,by_region_specific, true); gcode += this->extrude_infill(print,by_region_specific, true);
}
// Don't set m_gcode_label_objects_end if you don't had to write the m_gcode_label_objects_start.
if (!m_writer.empty_object_start_str()) {
m_writer.set_object_start_str("");
} else if (m_enable_label_object) {
std::string end_str = std::string("; stop printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n";
if (print.is_BBL_printer())
end_str += "M625\n";
m_writer.set_object_end_str(end_str);
} }
if (this->config().gcode_label_objects) { if (this->config().gcode_label_objects) {
gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " + std::to_string(inst.id) + "\n"; gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " + std::to_string(inst.id) + "\n";
@ -3501,6 +3580,8 @@ std::string GCode::change_layer(coordf_t print_z, bool lazy_raise)
//BBS: force to use SpiralLift when change layer if lift type is auto //BBS: force to use SpiralLift when change layer if lift type is auto
gcode += this->retract(false, false, ZHopType(EXTRUDER_CONFIG(z_hop_types)) == ZHopType::zhtAuto ? LiftType::SpiralLift : lift_type); gcode += this->retract(false, false, ZHopType(EXTRUDER_CONFIG(z_hop_types)) == ZHopType::zhtAuto ? LiftType::SpiralLift : lift_type);
} }
m_writer.add_object_change_labels(gcode);
if (!lazy_raise) { if (!lazy_raise) {
std::ostringstream comment; std::ostringstream comment;
@ -3511,7 +3592,6 @@ std::string GCode::change_layer(coordf_t print_z, bool lazy_raise)
m_need_change_layer_lift_z = true; m_need_change_layer_lift_z = true;
} }
// BBS
m_nominal_z = print_z; m_nominal_z = print_z;
// forget last wiping path as wiping after raising Z is pointless // forget last wiping path as wiping after raising Z is pointless
@ -3882,6 +3962,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
m_need_change_layer_lift_z = false; m_need_change_layer_lift_z = false;
} }
// if needed, write the gcode_label_objects_end then gcode_label_objects_start
// should be already done by travel_to, but just in case
m_writer.add_object_change_labels(gcode);
// compensate retraction // compensate retraction
gcode += this->unretract(); gcode += this->unretract();
m_config.apply(m_calib_config); m_config.apply(m_calib_config);
@ -4296,6 +4380,37 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
return gcode; return gcode;
} }
std::string encodeBase64(uint64_t value)
{
//Always use big endian mode
uint8_t src[8];
for (size_t i = 0; i < 8; i++)
src[i] = (value >> (8 * i)) & 0xff;
std::string dest;
dest.resize(boost::beast::detail::base64::encoded_size(sizeof(src)));
dest.resize(boost::beast::detail::base64::encode(&dest[0], src, sizeof(src)));
return dest;
}
std::string GCode::_encode_label_ids_to_base64(std::vector<size_t> ids)
{
assert(m_label_objects_ids.size() < 64);
uint64_t bitset = 0;
for (size_t id : ids) {
auto index = std::lower_bound(m_label_objects_ids.begin(), m_label_objects_ids.end(), id);
if (index != m_label_objects_ids.end() && *index == id)
bitset |= (1ull << (index - m_label_objects_ids.begin()));
else
throw Slic3r::LogicError("Unknown label object id!");
}
if (bitset == 0)
throw Slic3r::LogicError("Label object id error!");
return encodeBase64(bitset);
}
// This method accepts &point in print coordinates. // This method accepts &point in print coordinates.
std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string comment) std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string comment)
{ {
@ -4369,6 +4484,9 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
// Reset the wipe path when traveling, so one would not wipe along an old path. // Reset the wipe path when traveling, so one would not wipe along an old path.
m_wipe.reset_path(); m_wipe.reset_path();
// if needed, write the gcode_label_objects_end then gcode_label_objects_start
m_writer.add_object_change_labels(gcode);
// use G1 because we rely on paths being straight (G0 may make round paths) // use G1 because we rely on paths being straight (G0 may make round paths)
if (travel.size() >= 2) { if (travel.size() >= 2) {
for (size_t i = 1; i < travel.size(); ++ i) { for (size_t i = 1; i < travel.size(); ++ i) {
@ -4410,32 +4528,60 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp
return false; return false;
} }
//BBS: input travel polyline must be in current plate coordinate system
auto is_through_overhang = [this](const Polyline& travel) { auto is_through_overhang = [this](const Polyline& travel) {
BoundingBox travel_bbox = get_extents(travel);
travel_bbox.inflated(1);
travel_bbox.defined = true;
const float protect_z_scaled = scale_(0.4); const float protect_z_scaled = scale_(0.4);
std::pair<float, float> z_range; std::pair<float, float> z_range;
z_range.second = m_layer ? m_layer->print_z : 0.f; z_range.second = m_layer ? m_layer->print_z : 0.f;
z_range.first = std::max(0.f, z_range.second - protect_z_scaled); z_range.first = std::max(0.f, z_range.second - protect_z_scaled);
for (auto object : m_curr_print->objects()) { std::vector<LayerPtrs> layers_of_objects;
BoundingBox obj_bbox = object->bounding_box(); std::vector<BoundingBox> boundingBox_for_objects;
BoundingBox travel_bbox = get_extents(travel); std::vector<Points> objects_instances_shift;
obj_bbox.offset(scale_(EPSILON)); std::vector<size_t> idx_of_object_sorted = m_curr_print->layers_sorted_for_object(z_range.first, z_range.second, layers_of_objects, boundingBox_for_objects, objects_instances_shift);
if (!obj_bbox.overlap(travel_bbox))
continue;
for (auto layer : object->layers()) { std::vector<bool> is_layers_of_objects_sorted(layers_of_objects.size(), false);
if (layer->print_z < z_range.first)
for (size_t idx : idx_of_object_sorted) {
for (const Point & instance_shift : objects_instances_shift[idx]) {
BoundingBox instance_bbox = boundingBox_for_objects[idx];
if (!instance_bbox.defined) //BBS: Don't need to check when bounding box of overhang area is empty(undefined)
continue; continue;
if (layer->print_z > z_range.second + EPSILON) instance_bbox.offset(scale_(EPSILON));
break; instance_bbox.translate(instance_shift.x(), instance_shift.y());
if (!instance_bbox.overlap(travel_bbox))
continue;
Polygons temp;
temp.emplace_back(std::move(instance_bbox.polygon()));
if (intersection_pl(travel, temp).empty())
continue;
if (!is_layers_of_objects_sorted[idx]) {
std::sort(layers_of_objects[idx].begin(), layers_of_objects[idx].end(), [](auto left, auto right) { return left->loverhangs_bbox.area() > right->loverhangs_bbox.area();});
is_layers_of_objects_sorted[idx] = true;
}
for (const auto& layer : layers_of_objects[idx]) {
for (ExPolygon overhang : layer->loverhangs) {
overhang.translate(instance_shift);
BoundingBox bbox1 = get_extents(overhang);
if (!bbox1.overlap(travel_bbox))
continue;
if (intersection_pl(travel, overhang).empty())
continue;
for (ExPolygon& overhang : layer->loverhangs) {
if (overhang.contains(travel))
return true; return true;
}
} }
} }
} }
return false; return false;
}; };
@ -4445,17 +4591,12 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp
float travel_len_thresh = max_z_hop / tan(GCodeWriter::slope_threshold); float travel_len_thresh = max_z_hop / tan(GCodeWriter::slope_threshold);
float accum_len = 0.f; float accum_len = 0.f;
Polyline clipped_travel; Polyline clipped_travel;
for (auto line : travel.lines()) {
if (accum_len + line.length() > travel_len_thresh + EPSILON) { clipped_travel.append(Polyline(travel.points[0], travel.points[1]));
Point end_pnt = line.a + line.normal() * (travel_len_thresh - accum_len); if (clipped_travel.length() > travel_len_thresh)
clipped_travel.append(Polyline(line.a, end_pnt)); clipped_travel.points.back() = clipped_travel.points.front()+(clipped_travel.points.back() - clipped_travel.points.front()) * (travel_len_thresh / clipped_travel.length());
break; //BBS: translate to current plate coordinate system
} clipped_travel.translate(Point::new_scale(double(m_origin.x() - m_writer.get_xy_offset().x()), double(m_origin.y() - m_writer.get_xy_offset().y())));
else {
clipped_travel.append(Polyline(line.a, line.b));
accum_len += line.length();
}
}
//BBS: force to retract when leave from external perimeter for a long travel //BBS: force to retract when leave from external perimeter for a long travel
//Better way is judging whether the travel move direction is same with last extrusion move. //Better way is judging whether the travel move direction is same with last extrusion move.
@ -4549,9 +4690,7 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
can_lift = false; can_lift = false;
} }
//BBS
if (needs_lift && can_lift) { if (needs_lift && can_lift) {
// BBS: don't do lazy_lift when enable spiral vase
size_t extruder_id = m_writer.extruder()->id(); size_t extruder_id = m_writer.extruder()->id();
gcode += m_writer.lift(!m_spiral_vase ? lift_type : LiftType::NormalLift); gcode += m_writer.lift(!m_spiral_vase ? lift_type : LiftType::NormalLift);
} }
@ -4660,6 +4799,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
dyn_config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); dyn_config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
dyn_config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); dyn_config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
dyn_config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z)); dyn_config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
dyn_config.set_key_value("relative_e_axis", new ConfigOptionBool(m_config.use_relative_e_distances));
dyn_config.set_key_value("toolchange_count", new ConfigOptionInt((int)m_toolchange_count)); dyn_config.set_key_value("toolchange_count", new ConfigOptionInt((int)m_toolchange_count));
//BBS: fan speed is useless placeholer now, but we don't remove it to avoid //BBS: fan speed is useless placeholer now, but we don't remove it to avoid
//slicing error in old change_filament_gcode in old 3MF //slicing error in old change_filament_gcode in old 3MF

View file

@ -203,6 +203,7 @@ public:
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift); std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); } std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z); std::string set_extruder(unsigned int extruder_id, double print_z);
bool is_BBL_Printer();
// SoftFever // SoftFever
std::string set_object_info(Print* print); std::string set_object_info(Print* print);
@ -382,8 +383,8 @@ private:
struct InstanceToPrint struct InstanceToPrint
{ {
InstanceToPrint(ObjectByExtruder &object_by_extruder, size_t layer_id, const PrintObject &print_object, size_t instance_id) : InstanceToPrint(ObjectByExtruder &object_by_extruder, size_t layer_id, const PrintObject &print_object, size_t instance_id, size_t label_object_id) :
object_by_extruder(object_by_extruder), layer_id(layer_id), print_object(print_object), instance_id(instance_id) {} object_by_extruder(object_by_extruder), layer_id(layer_id), print_object(print_object), instance_id(instance_id), label_object_id(label_object_id) {}
// Repository // Repository
ObjectByExtruder &object_by_extruder; ObjectByExtruder &object_by_extruder;
@ -392,6 +393,8 @@ private:
const PrintObject &print_object; const PrintObject &print_object;
// Instance idx of the copy of a print object. // Instance idx of the copy of a print object.
const size_t instance_id; const size_t instance_id;
//BBS: Unique id to label object to support skiping during printing
const size_t label_object_id;
}; };
std::vector<InstanceToPrint> sort_print_object_instances( std::vector<InstanceToPrint> sort_print_object_instances(
@ -441,7 +444,11 @@ private:
// of the G-code lines: _EXTRUDE_SET_SPEED, _WIPE, _OVERHANG_FAN_START, _OVERHANG_FAN_END // of the G-code lines: _EXTRUDE_SET_SPEED, _WIPE, _OVERHANG_FAN_START, _OVERHANG_FAN_END
// Those comments are received and consumed (removed from the G-code) by the CoolingBuffer.pm Perl module. // Those comments are received and consumed (removed from the G-code) by the CoolingBuffer.pm Perl module.
bool m_enable_cooling_markers; bool m_enable_cooling_markers;
// for bbl printer
bool m_enable_label_object;
std::vector<size_t> m_label_objects_ids;
std::string _encode_label_ids_to_base64(std::vector<size_t> ids);
// Orca // Orca
bool m_is_overhang_fan_on; bool m_is_overhang_fan_on;
bool m_is_supp_interface_fan_on; bool m_is_supp_interface_fan_on;

View file

@ -81,6 +81,13 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags_compatible = {
const std::string GCodeProcessor::Flush_Start_Tag = " FLUSH_START"; const std::string GCodeProcessor::Flush_Start_Tag = " FLUSH_START";
const std::string GCodeProcessor::Flush_End_Tag = " FLUSH_END"; const std::string GCodeProcessor::Flush_End_Tag = " FLUSH_END";
const std::map<NozzleType,int> GCodeProcessor::Nozzle_Type_To_HRC={
{NozzleType::ntStainlessSteel,20},
{NozzleType::ntHardenedSteel,55},
{NozzleType::ntBrass,2},
{NozzleType::ntUndefine,0}
};
const float GCodeProcessor::Wipe_Width = 0.05f; const float GCodeProcessor::Wipe_Width = 0.05f;
const float GCodeProcessor::Wipe_Height = 0.05f; const float GCodeProcessor::Wipe_Height = 0.05f;
@ -792,6 +799,8 @@ void GCodeProcessorResult::reset() {
bed_exclude_area = Pointfs(); bed_exclude_area = Pointfs();
//BBS: add toolpath_outside //BBS: add toolpath_outside
toolpath_outside = false; toolpath_outside = false;
//BBS: add label_object_enabled
label_object_enabled = false;
printable_height = 0.0f; printable_height = 0.0f;
settings_ids.reset(); settings_ids.reset();
extruders_count = 0; extruders_count = 0;
@ -817,6 +826,8 @@ void GCodeProcessorResult::reset() {
bed_exclude_area = Pointfs(); bed_exclude_area = Pointfs();
//BBS: add toolpath_outside //BBS: add toolpath_outside
toolpath_outside = false; toolpath_outside = false;
//BBS: add label_object_enabled
label_object_enabled = false;
printable_height = 0.0f; printable_height = 0.0f;
settings_ids.reset(); settings_ids.reset();
extruders_count = 0; extruders_count = 0;
@ -936,7 +947,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_result.filament_vitrification_temperature.resize(extruders_count); m_result.filament_vitrification_temperature.resize(extruders_count);
m_extruder_temps.resize(extruders_count); m_extruder_temps.resize(extruders_count);
m_result.nozzle_hrc = static_cast<int>(config.nozzle_hrc.getInt()); m_result.nozzle_hrc = static_cast<int>(config.nozzle_hrc.getInt());
m_result.nozzle_type = config.nozzle_type;
for (size_t i = 0; i < extruders_count; ++ i) { for (size_t i = 0; i < extruders_count; ++ i) {
m_extruder_offsets[i] = to_3d(config.extruder_offset.get_at(i).cast<float>().eval(), 0.f); m_extruder_offsets[i] = to_3d(config.extruder_offset.get_at(i).cast<float>().eval(), 0.f);
m_extruder_colors[i] = static_cast<unsigned char>(i); m_extruder_colors[i] = static_cast<unsigned char>(i);
@ -1000,6 +1011,10 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
const ConfigOptionInt *nozzle_HRC = config.option<ConfigOptionInt>("nozzle_hrc"); const ConfigOptionInt *nozzle_HRC = config.option<ConfigOptionInt>("nozzle_hrc");
if (nozzle_HRC != nullptr) m_result.nozzle_hrc = nozzle_HRC->value; if (nozzle_HRC != nullptr) m_result.nozzle_hrc = nozzle_HRC->value;
const ConfigOptionEnum<NozzleType>* nozzle_type = config.option<ConfigOptionEnum<NozzleType>>("nozzle_type");
if (nozzle_type != nullptr)
m_result.nozzle_type=nozzle_type->value;
const ConfigOptionEnum<GCodeFlavor>* gcode_flavor = config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor"); const ConfigOptionEnum<GCodeFlavor>* gcode_flavor = config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor");
if (gcode_flavor != nullptr) if (gcode_flavor != nullptr)
m_flavor = gcode_flavor->value; m_flavor = gcode_flavor->value;
@ -1252,6 +1267,11 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
const ConfigOptionBool* spiral_vase = config.option<ConfigOptionBool>("spiral_mode"); const ConfigOptionBool* spiral_vase = config.option<ConfigOptionBool>("spiral_mode");
if (spiral_vase != nullptr) if (spiral_vase != nullptr)
m_spiral_vase_active = spiral_vase->value; m_spiral_vase_active = spiral_vase->value;
const ConfigOptionEnumGeneric *bed_type = config.option<ConfigOptionEnumGeneric>("curr_bed_type");
if (bed_type != nullptr)
m_result.bed_type = (BedType)bed_type->value;
} }
void GCodeProcessor::enable_stealth_time_estimator(bool enabled) void GCodeProcessor::enable_stealth_time_estimator(bool enabled)
@ -4305,12 +4325,16 @@ void GCodeProcessor::update_slice_warnings()
//bbs:HRC checker //bbs:HRC checker
warning.params.clear(); warning.params.clear();
warning.level=1; warning.level=1;
if (m_result.nozzle_hrc!=0) {
int nozzle_hrc = m_result.nozzle_hrc;
if(nozzle_hrc <= 0)
nozzle_hrc = Nozzle_Type_To_HRC.find(m_result.nozzle_type)->second;
if (nozzle_hrc!=0) {
for (size_t i = 0; i < used_extruders.size(); i++) { for (size_t i = 0; i < used_extruders.size(); i++) {
int HRC=0; int HRC=0;
if (used_extruders[i] < m_result.required_nozzle_HRC.size()) if (used_extruders[i] < m_result.required_nozzle_HRC.size())
HRC = m_result.required_nozzle_HRC[used_extruders[i]]; HRC = m_result.required_nozzle_HRC[used_extruders[i]];
if (HRC != 0 && (m_result.nozzle_hrc<HRC)) if (HRC != 0 && (nozzle_hrc<HRC))
warning.params.push_back(std::to_string(used_extruders[i])); warning.params.push_back(std::to_string(used_extruders[i]));
} }
} }

View file

@ -177,6 +177,8 @@ namespace Slic3r {
Pointfs bed_exclude_area; Pointfs bed_exclude_area;
//BBS: add toolpath_outside //BBS: add toolpath_outside
bool toolpath_outside; bool toolpath_outside;
//BBS: add object_label_enabled
bool label_object_enabled;
float printable_height; float printable_height;
SettingsIds settings_ids; SettingsIds settings_ids;
size_t extruders_count; size_t extruders_count;
@ -191,7 +193,8 @@ namespace Slic3r {
//BBS //BBS
std::vector<SliceWarning> warnings; std::vector<SliceWarning> warnings;
int nozzle_hrc; int nozzle_hrc;
NozzleType nozzle_type;
BedType bed_type = BedType::btCount;
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
int64_t time{ 0 }; int64_t time{ 0 };
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
@ -208,6 +211,7 @@ namespace Slic3r {
printable_area = other.printable_area; printable_area = other.printable_area;
bed_exclude_area = other.bed_exclude_area; bed_exclude_area = other.bed_exclude_area;
toolpath_outside = other.toolpath_outside; toolpath_outside = other.toolpath_outside;
label_object_enabled = other.label_object_enabled;
printable_height = other.printable_height; printable_height = other.printable_height;
settings_ids = other.settings_ids; settings_ids = other.settings_ids;
extruders_count = other.extruders_count; extruders_count = other.extruders_count;
@ -218,6 +222,7 @@ namespace Slic3r {
custom_gcode_per_print_z = other.custom_gcode_per_print_z; custom_gcode_per_print_z = other.custom_gcode_per_print_z;
spiral_vase_layers = other.spiral_vase_layers; spiral_vase_layers = other.spiral_vase_layers;
warnings = other.warnings; warnings = other.warnings;
bed_type = other.bed_type;
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
time = other.time; time = other.time;
#endif #endif
@ -234,7 +239,7 @@ namespace Slic3r {
static const std::vector<std::string> Reserved_Tags_compatible; static const std::vector<std::string> Reserved_Tags_compatible;
static const std::string Flush_Start_Tag; static const std::string Flush_Start_Tag;
static const std::string Flush_End_Tag; static const std::string Flush_End_Tag;
static const std::map<NozzleType, int>Nozzle_Type_To_HRC;
public: public:
enum class ETags : unsigned char enum class ETags : unsigned char
{ {

View file

@ -377,22 +377,21 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
Vec3d target = { dest_point(0) - m_x_offset, dest_point(1) - m_y_offset, dest_point(2) }; Vec3d target = { dest_point(0) - m_x_offset, dest_point(1) - m_y_offset, dest_point(2) };
Vec3d delta = target - source; Vec3d delta = target - source;
Vec2d delta_no_z = { delta(0), delta(1) }; Vec2d delta_no_z = { delta(0), delta(1) };
//BBS: don'need slope travel because we don't know where is the source position the first time //BBS: don'need slope travel because we don't know where is the source position the first time
//BBS: Also don't need to do slope move or spiral lift if x-y distance is absolute zero //BBS: Also don't need to do slope move or spiral lift if x-y distance is absolute zero
if (this->is_current_position_clear() && delta(2) > 0 && delta_no_z.norm() != 0.0f) { if (delta(2) > 0 && delta_no_z.norm() != 0.0f) {
double radius = delta(2) / (2 * PI * atan(GCodeWriter::slope_threshold));
Vec2d ij_offset = radius * delta_no_z.normalized();
ij_offset = { -ij_offset(1), ij_offset(0) };
//BBS: SpiralLift //BBS: SpiralLift
if (m_to_lift_type == LiftType::SpiralLift) { if (m_to_lift_type == LiftType::SpiralLift && this->is_current_position_clear()) {
//BBS: todo: check the arc move all in bed area, if not, then use lazy lift //BBS: todo: check the arc move all in bed area, if not, then use lazy lift
double radius = delta(2) / (2 * PI * atan(GCodeWriter::slope_threshold));
Vec2d ij_offset = radius * delta_no_z.normalized();
ij_offset = { -ij_offset(1), ij_offset(0) };
slop_move = this->_spiral_travel_to_z(target(2), ij_offset, "spiral lift Z"); slop_move = this->_spiral_travel_to_z(target(2), ij_offset, "spiral lift Z");
} }
//BBS: LazyLift //BBS: LazyLift
else if (atan2(delta(2), delta_no_z.norm()) < GCodeWriter::slope_threshold) { else if (m_to_lift_type == LiftType::LazyLift &&
this->is_current_position_clear() &&
atan2(delta(2), delta_no_z.norm()) < GCodeWriter::slope_threshold) {
//BBS: check whether we can make a travel like //BBS: check whether we can make a travel like
// _____ // _____
// / to make the z list early to avoid to hit some warping place when travel is long. // / to make the z list early to avoid to hit some warping place when travel is long.
@ -405,6 +404,9 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
w0.emit_comment(GCodeWriter::full_gcode_comment, comment); w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
slop_move = w0.string(); slop_move = w0.string();
} }
else if (m_to_lift_type == LiftType::NormalLift) {
slop_move = _travel_to_z(target.z(), "normal lift Z");
}
} }
std::string xy_z_move; std::string xy_z_move;
@ -687,12 +689,11 @@ std::string GCodeWriter::unretract()
/* If this method is called more than once before calling unlift(), /* If this method is called more than once before calling unlift(),
it will not perform subsequent lifts, even if Z was raised manually it will not perform subsequent lifts, even if Z was raised manually
(i.e. with travel_to_z()) and thus _lifted was reduced. */ (i.e. with travel_to_z()) and thus _lifted was reduced. */
std::string GCodeWriter::lift(LiftType lift_type) std::string GCodeWriter::lift(LiftType lift_type, bool spiral_vase)
{ {
// check whether the above/below conditions are met // check whether the above/below conditions are met
double target_lift = 0; double target_lift = 0;
{ {
//BBS
double above = this->config.retract_lift_above.get_at(m_extruder->id()); double above = this->config.retract_lift_above.get_at(m_extruder->id());
double below = this->config.retract_lift_below.get_at(m_extruder->id()); double below = this->config.retract_lift_below.get_at(m_extruder->id());
if (m_pos(2) >= above && (below == 0 || m_pos(2) <= below)) if (m_pos(2) >= above && (below == 0 || m_pos(2) <= below))
@ -700,13 +701,14 @@ std::string GCodeWriter::lift(LiftType lift_type)
} }
// BBS // BBS
if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) { if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) {
if (lift_type == LiftType::LazyLift || lift_type == LiftType::SpiralLift) { if (spiral_vase) {
m_to_lift = target_lift;
m_to_lift_type = lift_type;
} else {
m_lifted = target_lift; m_lifted = target_lift;
return this->_travel_to_z(m_pos(2) + target_lift, "lift Z"); return this->_travel_to_z(m_pos(2) + target_lift, "lift Z");
} }
else {
m_to_lift = target_lift;
m_to_lift_type = lift_type;
}
} }
return ""; return "";
} }
@ -778,6 +780,28 @@ std::string GCodeWriter::set_additional_fan(unsigned int speed)
return gcode.str(); return gcode.str();
} }
void GCodeWriter::add_object_start_labels(std::string& gcode)
{
if (!m_gcode_label_objects_start.empty()) {
gcode += m_gcode_label_objects_start;
m_gcode_label_objects_start = "";
}
}
void GCodeWriter::add_object_end_labels(std::string& gcode)
{
if (!m_gcode_label_objects_end.empty()) {
gcode += m_gcode_label_objects_end;
m_gcode_label_objects_end = "";
}
}
void GCodeWriter::add_object_change_labels(std::string& gcode)
{
add_object_end_labels(gcode);
add_object_start_labels(gcode);
}
void GCodeFormatter::emit_axis(const char axis, const double v, size_t digits) { void GCodeFormatter::emit_axis(const char axis, const double v, size_t digits) {
assert(digits <= 9); assert(digits <= 9);
static constexpr const std::array<int, 10> pow_10{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; static constexpr const std::array<int, 10> pow_10{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};

View file

@ -73,7 +73,7 @@ public:
std::string retract(bool before_wipe = false); std::string retract(bool before_wipe = false);
std::string retract_for_toolchange(bool before_wipe = false); std::string retract_for_toolchange(bool before_wipe = false);
std::string unretract(); std::string unretract();
std::string lift(LiftType lift_type = LiftType::NormalLift); std::string lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false);
std::string unlift(); std::string unlift();
Vec3d get_position() const { return m_pos; } Vec3d get_position() const { return m_pos; }
void set_position(Vec3d& in) { m_pos = in; } void set_position(Vec3d& in) { m_pos = in; }
@ -88,6 +88,14 @@ public:
std::string set_fan(unsigned int speed) const; std::string set_fan(unsigned int speed) const;
//BBS: set additional fan speed for BBS machine only //BBS: set additional fan speed for BBS machine only
static std::string set_additional_fan(unsigned int speed); static std::string set_additional_fan(unsigned int speed);
//BBS
void set_object_start_str(std::string start_string) { m_gcode_label_objects_start = start_string; }
bool empty_object_start_str() { return m_gcode_label_objects_start.empty(); }
void set_object_end_str(std::string end_string) { m_gcode_label_objects_end = end_string; }
bool empty_object_end_str() { return m_gcode_label_objects_end.empty(); }
void add_object_start_labels(std::string& gcode);
void add_object_end_labels(std::string& gcode);
void add_object_change_labels(std::string& gcode);
//BBS: //BBS:
void set_current_position_clear(bool clear) { m_is_current_pos_clear = clear; }; void set_current_position_clear(bool clear) { m_is_current_pos_clear = clear; };
@ -136,12 +144,15 @@ private:
//BBS: x, y offset for gcode generated //BBS: x, y offset for gcode generated
double m_x_offset{ 0 }; double m_x_offset{ 0 };
double m_y_offset{ 0 }; double m_y_offset{ 0 };
std::string m_gcode_label_objects_start;
std::string m_gcode_label_objects_end;
//SoftFever //SoftFever
bool m_is_bbl_printers = false; bool m_is_bbl_printers = false;
double m_current_speed; double m_current_speed;
bool m_is_first_layer = true; bool m_is_first_layer = true;
std::string _travel_to_z(double z, const std::string &comment); std::string _travel_to_z(double z, const std::string &comment);
std::string _spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment); std::string _spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment);
std::string _retract(double length, double restart_extra, const std::string &comment); std::string _retract(double length, double restart_extra, const std::string &comment);

View file

@ -95,7 +95,8 @@ public:
// Is there any valid extrusion assigned to this LayerRegion? // Is there any valid extrusion assigned to this LayerRegion?
bool has_extrusions() const { return ! this->perimeters.entities.empty() || ! this->fills.entities.empty(); } bool has_extrusions() const { return ! this->perimeters.entities.empty() || ! this->fills.entities.empty(); }
//BBS //BBS
void simplify_extrusion_entity(); void simplify_infill_extrusion_entity() { simplify_entity_collection(&fills); }
void simplify_wall_extrusion_entity() { simplify_entity_collection(&perimeters); }
private: private:
void simplify_entity_collection(ExtrusionEntityCollection* entity_collection); void simplify_entity_collection(ExtrusionEntityCollection* entity_collection);
void simplify_path(ExtrusionPath* path); void simplify_path(ExtrusionPath* path);
@ -149,7 +150,7 @@ public:
// BBS // BBS
ExPolygons loverhangs; ExPolygons loverhangs;
BoundingBox loverhangs_bbox;
size_t region_count() const { return m_regions.size(); } size_t region_count() const { return m_regions.size(); }
const LayerRegion* get_region(int idx) const { return m_regions[idx]; } const LayerRegion* get_region(int idx) const { return m_regions[idx]; }
LayerRegion* get_region(int idx) { return m_regions[idx]; } LayerRegion* get_region(int idx) { return m_regions[idx]; }
@ -190,10 +191,45 @@ public:
virtual bool has_extrusions() const { for (auto layerm : m_regions) if (layerm->has_extrusions()) return true; return false; } virtual bool has_extrusions() const { for (auto layerm : m_regions) if (layerm->has_extrusions()) return true; return false; }
//BBS //BBS
void simplify_extrusion_path() { for (auto layerm : m_regions) layerm->simplify_extrusion_entity();} void simplify_wall_extrusion_path() { for (auto layerm : m_regions) layerm->simplify_wall_extrusion_entity();}
void simplify_infill_extrusion_path() { for (auto layerm : m_regions) layerm->simplify_infill_extrusion_entity(); }
//BBS: this function calculate the maximum void grid area of sparse infill of this layer. Just estimated value //BBS: this function calculate the maximum void grid area of sparse infill of this layer. Just estimated value
coordf_t get_sparse_infill_max_void_area(); coordf_t get_sparse_infill_max_void_area();
// FN_HIGHER_EQUAL: the provided object pointer has a Z value >= of an internal threshold.
// Find the first item with Z value >= of an internal threshold of fn_higher_equal.
// If no vec item with Z value >= of an internal threshold of fn_higher_equal is found, return vec.size()
// If the initial idx is size_t(-1), then use binary search.
// Otherwise search linearly upwards.
template<typename IteratorType, typename IndexType, typename FN_HIGHER_EQUAL>
static IndexType idx_higher_or_equal(IteratorType begin, IteratorType end, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal)
{
auto size = int(end - begin);
if (size == 0) {
idx = 0;
}
else if (idx == IndexType(-1)) {
// First of the batch of layers per thread pool invocation. Use binary search.
int idx_low = 0;
int idx_high = std::max(0, size - 1);
while (idx_low + 1 < idx_high) {
int idx_mid = (idx_low + idx_high) / 2;
if (fn_higher_equal(begin[idx_mid]))
idx_high = idx_mid;
else
idx_low = idx_mid;
}
idx = fn_higher_equal(begin[idx_low]) ? idx_low :
(fn_higher_equal(begin[idx_high]) ? idx_high : size);
}
else {
// For the other layers of this batch of layers, search incrementally, which is cheaper than the binary search.
while (int(idx) < size && !fn_higher_equal(begin[idx]))
++idx;
}
return idx;
}
protected: protected:
friend class PrintObject; friend class PrintObject;
friend std::vector<Layer*> new_layers(PrintObject*, const std::vector<coordf_t>&); friend std::vector<Layer*> new_layers(PrintObject*, const std::vector<coordf_t>&);

View file

@ -533,13 +533,6 @@ void LayerRegion::export_region_fill_surfaces_to_svg_debug(const char *name) con
this->export_region_fill_surfaces_to_svg(debug_out_path("LayerRegion-fill_surfaces-%s-%d.svg", name, idx ++).c_str()); this->export_region_fill_surfaces_to_svg(debug_out_path("LayerRegion-fill_surfaces-%s-%d.svg", name, idx ++).c_str());
} }
//BBS
void LayerRegion::simplify_extrusion_entity()
{
simplify_entity_collection(&perimeters);
simplify_entity_collection(&fills);
}
void LayerRegion::simplify_entity_collection(ExtrusionEntityCollection* entity_collection) void LayerRegion::simplify_entity_collection(ExtrusionEntityCollection* entity_collection)
{ {
for (size_t i = 0; i < entity_collection->entities.size(); i++) { for (size_t i = 0; i < entity_collection->entities.size(); i++) {

View file

@ -1220,9 +1220,18 @@ public:
ModelInstanceEPrintVolumeState print_volume_state; ModelInstanceEPrintVolumeState print_volume_state;
// Whether or not this instance is printable // Whether or not this instance is printable
bool printable; bool printable;
bool use_loaded_id_for_label {false};
int arrange_order = 0; // BBS int arrange_order = 0; // BBS
size_t loaded_id = 0; // BBS size_t loaded_id = 0; // BBS
size_t get_labeled_id() const
{
if (use_loaded_id_for_label && (loaded_id > 0))
return loaded_id;
else
return id().id;
}
ModelObject* get_object() const { return this->object; } ModelObject* get_object() const { return this->object; }
const Geometry::Transformation& get_transformation() const { return m_transformation; } const Geometry::Transformation& get_transformation() const { return m_transformation; }

View file

@ -260,7 +260,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
osteps.emplace_back(posPerimeters); osteps.emplace_back(posPerimeters);
osteps.emplace_back(posInfill); osteps.emplace_back(posInfill);
osteps.emplace_back(posSupportMaterial); osteps.emplace_back(posSupportMaterial);
osteps.emplace_back(posSimplifyPath); osteps.emplace_back(posSimplifyPath);
osteps.emplace_back(posSimplifyInfill);
osteps.emplace_back(posSimplifySupportPath); osteps.emplace_back(posSimplifySupportPath);
steps.emplace_back(psSkirtBrim); steps.emplace_back(psSkirtBrim);
} }
@ -332,6 +333,18 @@ std::vector<unsigned int> Print::object_extruders() const
extruders.push_back(extruder - 1); extruders.push_back(extruder - 1);
} }
} }
// layer range
for (auto layer_range : mo->layer_config_ranges) {
if (layer_range.second.has("extruder")) {
//BBS: actually when user doesn't change filament by height range(value is default 0), height range should not save key "extruder".
//Don't know why height range always save key "extruder" because of no change(should only save difference)...
//Add protection here to avoid overflow
auto value = layer_range.second.option("extruder")->getInt();
if (value > 0)
extruders.push_back(value - 1);
}
}
} }
#endif #endif
sort_remove_duplicates(extruders); sort_remove_duplicates(extruders);
@ -436,6 +449,25 @@ bool Print::has_brim() const
} }
//BBS //BBS
std::vector<size_t> Print::layers_sorted_for_object(float start, float end, std::vector<LayerPtrs> &layers_of_objects, std::vector<BoundingBox> &boundingBox_for_objects, std::vector<Points> &objects_instances_shift)
{
std::vector<size_t> idx_of_object_sorted;
size_t idx = 0;
for (const auto &object : m_objects) {
idx_of_object_sorted.push_back(idx++);
object->get_certain_layers(start, end, layers_of_objects, boundingBox_for_objects);
}
std::sort(idx_of_object_sorted.begin(), idx_of_object_sorted.end(),
[boundingBox_for_objects](auto left, auto right) { return boundingBox_for_objects[left].area() > boundingBox_for_objects[right].area(); });
objects_instances_shift.clear();
objects_instances_shift.reserve(m_objects.size());
for (const auto& object : m_objects)
objects_instances_shift.emplace_back(object->get_instances_shift_without_plate_offset());
return idx_of_object_sorted;
};
StringObjectException Print::sequential_print_clearance_valid(const Print &print, Polygons *polygons, std::vector<std::pair<Polygon, float>>* height_polygons) StringObjectException Print::sequential_print_clearance_valid(const Print &print, Polygons *polygons, std::vector<std::pair<Polygon, float>>* height_polygons)
{ {
StringObjectException single_object_exception; StringObjectException single_object_exception;
@ -534,19 +566,24 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
// if output needed, collect indices (inside convex_hulls_other) of intersecting hulls // if output needed, collect indices (inside convex_hulls_other) of intersecting hulls
for (size_t i = 0; i < convex_hulls_other.size(); ++i) { for (size_t i = 0; i < convex_hulls_other.size(); ++i) {
if (! intersection(convex_hulls_other[i], convex_hull).empty()) { if (! intersection(convex_hulls_other[i], convex_hull).empty()) {
bool has_exception = false;
if (single_object_exception.string.empty()) { if (single_object_exception.string.empty()) {
single_object_exception.string = (boost::format(L("%1% is too close to others, and collisions may be caused.")) %instance.model_instance->get_object()->name).str(); single_object_exception.string = (boost::format(L("%1% is too close to others, and collisions may be caused.")) %instance.model_instance->get_object()->name).str();
single_object_exception.object = instance.model_instance->get_object(); single_object_exception.object = instance.model_instance->get_object();
has_exception = true;
} }
else { else {
single_object_exception.string += "\n"+(boost::format(L("%1% is too close to others, and collisions may be caused.")) %instance.model_instance->get_object()->name).str(); single_object_exception.string += "\n"+(boost::format(L("%1% is too close to others, and collisions may be caused.")) %instance.model_instance->get_object()->name).str();
single_object_exception.object = nullptr; single_object_exception.object = nullptr;
has_exception = true;
} }
if (polygons) { if (polygons) {
intersecting_idxs.emplace_back(i); intersecting_idxs.emplace_back(i);
intersecting_idxs.emplace_back(convex_hulls_other.size()); intersecting_idxs.emplace_back(convex_hulls_other.size());
} }
if (has_exception) break;
} }
} }
struct print_instance_info print_info {&instance, convex_hull.bounding_box(), convex_hull}; struct print_instance_info print_info {&instance, convex_hull.bounding_box(), convex_hull};
@ -865,40 +902,51 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
return {}; return {};
} }
//BBS bool Print::check_multi_filaments_compatibility(const std::vector<std::string>& filament_types)
static std::map<std::string, bool> filament_is_high_temp {
{"PLA", false},
{"PLA-CF", false},
//{"PETG", true},
{"ABS", true},
{"TPU", false},
{"PA", true},
{"PA-CF", true},
{"PET-CF", true},
{"PC", true},
{"ASA", true}
};
//BBS: this function is used to check whether multi filament can be printed
StringObjectException Print::check_multi_filament_valid(const Print& print)
{ {
static std::map<std::string, bool> filament_is_high_temp{
{"PLA", false},
{"PLA-CF", false},
//{"PETG", true},
{"ABS", true},
{"TPU", false},
{"PA", true},
{"PA-CF", true},
{"PET-CF", true},
{"PC", true},
{"ASA", true},
{"HIPS", true}
};
bool has_high_temperature_filament = false; bool has_high_temperature_filament = false;
bool has_low_temperature_filament = false; bool has_low_temperature_filament = false;
auto print_config = print.config(); for (const auto& type : filament_types)
std::vector<unsigned int> extruders = print.extruders(); if (filament_is_high_temp.find(type) != filament_is_high_temp.end()) {
if (filament_is_high_temp[type])
for (const auto& extruder_idx : extruders) {
std::string filament_type = print_config.filament_type.get_at(extruder_idx);
if (filament_is_high_temp.find(filament_type) != filament_is_high_temp.end()) {
if (filament_is_high_temp[filament_type])
has_high_temperature_filament = true; has_high_temperature_filament = true;
else else
has_low_temperature_filament = true; has_low_temperature_filament = true;
} }
}
if (has_high_temperature_filament && has_low_temperature_filament) if (has_high_temperature_filament && has_low_temperature_filament)
return false;
return true;
}
//BBS: this function is used to check whether multi filament can be printed
StringObjectException Print::check_multi_filament_valid(const Print& print)
{
auto print_config = print.config();
std::vector<unsigned int> extruders = print.extruders();
std::vector<std::string> filament_types;
filament_types.reserve(extruders.size());
for (const auto& extruder_idx : extruders)
filament_types.push_back(print_config.filament_type.get_at(extruder_idx));
if (!check_multi_filaments_compatibility(filament_types))
return { L("Can not print multiple filaments which have large difference of temperature together. Otherwise, the extruder and nozzle may be blocked or damaged during printing") }; return { L("Can not print multiple filaments which have large difference of temperature together. Otherwise, the extruder and nozzle may be blocked or damaged during printing") };
return {std::string()}; return {std::string()};
@ -917,28 +965,11 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
return { L("No extrusions under current settings.") }; return { L("No extrusions under current settings.") };
if (extruders.size() > 1 && m_config.print_sequence != PrintSequence::ByObject) { if (extruders.size() > 1 && m_config.print_sequence != PrintSequence::ByObject) {
if (m_config.single_extruder_multi_material) { auto ret = check_multi_filament_valid(*this);
auto ret = check_multi_filament_valid(*this); if (!ret.string.empty())
if (!ret.string.empty()) {
return ret; ret.type = STRING_EXCEPT_FILAMENTS_DIFFERENT_TEMP;
} return ret;
if (warning) {
for (unsigned int extruder_a: extruders) {
const ConfigOptionInts* bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
const ConfigOptionInts* bed_temp_1st_opt = m_config.option<ConfigOptionInts>(get_bed_temp_1st_layer_key(m_config.curr_bed_type));
int bed_temp_a = bed_temp_opt->get_at(extruder_a);
int bed_temp_1st_a = bed_temp_1st_opt->get_at(extruder_a);
for (unsigned int extruder_b: extruders) {
int bed_temp_b = bed_temp_opt->get_at(extruder_b);
int bed_temp_1st_b = bed_temp_1st_opt->get_at(extruder_b);
if (std::abs(bed_temp_a - bed_temp_b) > 15 || std::abs(bed_temp_1st_a - bed_temp_1st_b) > 15) {
warning->string = L("Bed temperatures for the used filaments differ significantly.");
goto DONE;
}
}
}
DONE:;
} }
} }
@ -948,13 +979,16 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
//BBS: refine seq-print validation logic //BBS: refine seq-print validation logic
auto ret = sequential_print_clearance_valid(*this, collison_polygons, height_polygons); auto ret = sequential_print_clearance_valid(*this, collison_polygons, height_polygons);
if (!ret.string.empty()) if (!ret.string.empty()) {
ret.type = STRING_EXCEPT_OBJECT_COLLISION_IN_SEQ_PRINT;
return ret; return ret;
}
} }
else { else {
//BBS //BBS
auto ret = layered_print_cleareance_valid(*this, warning); auto ret = layered_print_cleareance_valid(*this, warning);
if (!ret.string.empty()) { if (!ret.string.empty()) {
ret.type = STRING_EXCEPT_OBJECT_COLLISION_IN_LAYER_PRINT;
return ret; return ret;
} }
} }
@ -984,10 +1018,9 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
// BBS: remove L() // BBS: remove L()
return { ("Different nozzle diameters and different filament diameters is not allowed when prime tower is enabled.") }; return { ("Different nozzle diameters and different filament diameters is not allowed when prime tower is enabled.") };
} }
if (! m_config.use_relative_e_distances) if (! m_config.use_relative_e_distances)
return { ("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).") }; return { ("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).") };
if (m_config.ooze_prevention) if (m_config.ooze_prevention)
return { ("Ooze prevention is currently not supported with the prime tower enabled.") }; return { ("Ooze prevention is currently not supported with the prime tower enabled.") };
@ -1393,6 +1426,20 @@ void PrintObject::copy_layers_from_shared_object()
} }
} }
void PrintObject::copy_layers_overhang_from_shared_object()
{
if (m_shared_object) {
for (size_t index = 0; index < m_layers.size() && index < m_shared_object->m_layers.size(); index++)
{
Layer* layer_src = m_layers[index];
layer_src->loverhangs = m_shared_object->m_layers[index]->loverhangs;
layer_src->loverhangs_bbox = m_shared_object->m_layers[index]->loverhangs_bbox;
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": this=%1%, copied layer overhang from object %2%")%this%m_shared_object;
}
}
// BBS // BBS
BoundingBox PrintObject::get_first_layer_bbox(float& a, float& layer_height, std::string& name) BoundingBox PrintObject::get_first_layer_bbox(float& a, float& layer_height, std::string& name)
{ {
@ -1403,7 +1450,7 @@ BoundingBox PrintObject::get_first_layer_bbox(float& a, float& layer_height, std
auto layer = get_layer(0); auto layer = get_layer(0);
layer_height = layer->height; layer_height = layer->height;
// only work for object with single instance // only work for object with single instance
auto shift = instances()[0].shift; auto shift = instances()[0].shift_without_plate_offset();
for (auto bb : layer->lslices_bboxes) for (auto bb : layer->lslices_bboxes)
{ {
bb.translate(shift.x(), shift.y()); bb.translate(shift.x(), shift.y());
@ -1494,6 +1541,7 @@ void Print::process(bool use_cache)
}; };
int object_count = m_objects.size(); int object_count = m_objects.size();
std::set<PrintObject*> need_slicing_objects; std::set<PrintObject*> need_slicing_objects;
std::set<PrintObject*> re_slicing_objects;
if (!use_cache) { if (!use_cache) {
for (int index = 0; index < object_count; index++) for (int index = 0; index < object_count; index++)
{ {
@ -1530,8 +1578,12 @@ void Print::process(bool use_cache)
} }
} }
if (!found_shared) { if (!found_shared) {
BOOST_LOG_TRIVIAL(error) << boost::format("Also can not find the shared object, identify_id %1%")%obj->model_object()->instances[0]->loaded_id; BOOST_LOG_TRIVIAL(warning) << boost::format("Also can not find the shared object, identify_id %1%, maybe shared object is skipped")%obj->model_object()->instances[0]->loaded_id;
throw Slic3r::SlicingError("Can not find the cached data."); //throw Slic3r::SlicingError("Can not find the cached data.");
//don't report errot, set use_cache to false, and reslice these objects
need_slicing_objects.insert(obj);
re_slicing_objects.insert(obj);
//use_cache = false;
} }
} }
} }
@ -1589,18 +1641,26 @@ void Print::process(bool use_cache)
} }
else { else {
for (PrintObject *obj : m_objects) { for (PrintObject *obj : m_objects) {
if (obj->set_started(posSlice)) if (re_slicing_objects.count(obj) == 0) {
obj->set_done(posSlice); if (obj->set_started(posSlice))
if (obj->set_started(posPerimeters)) obj->set_done(posSlice);
obj->set_done(posPerimeters); if (obj->set_started(posPerimeters))
if (obj->set_started(posPrepareInfill)) obj->set_done(posPerimeters);
obj->set_done(posPrepareInfill); if (obj->set_started(posPrepareInfill))
if (obj->set_started(posInfill)) obj->set_done(posPrepareInfill);
obj->set_done(posInfill); if (obj->set_started(posInfill))
if (obj->set_started(posIroning)) obj->set_done(posInfill);
obj->set_done(posIroning); if (obj->set_started(posIroning))
if (obj->set_started(posSupportMaterial)) obj->set_done(posIroning);
obj->set_done(posSupportMaterial); if (obj->set_started(posSupportMaterial))
obj->set_done(posSupportMaterial);
}
else {
obj->make_perimeters();
obj->infill();
obj->ironing();
obj->generate_support_material();
}
} }
} }
@ -1713,12 +1773,15 @@ void Print::process(bool use_cache)
} }
//BBS //BBS
for (PrintObject *obj : m_objects) { for (PrintObject *obj : m_objects) {
if ((!use_cache)&&(need_slicing_objects.count(obj) != 0)) { if (((!use_cache)&&(need_slicing_objects.count(obj) != 0))
|| (use_cache &&(re_slicing_objects.count(obj) != 0))){
obj->simplify_extrusion_path(); obj->simplify_extrusion_path();
} }
else { else {
if (obj->set_started(posSimplifyPath)) if (obj->set_started(posSimplifyPath))
obj->set_done(posSimplifyPath); obj->set_done(posSimplifyPath);
if (obj->set_started(posSimplifyInfill))
obj->set_done(posSimplifyInfill);
if (obj->set_started(posSimplifySupportPath)) if (obj->set_started(posSimplifySupportPath))
obj->set_done(posSimplifySupportPath); obj->set_done(posSimplifySupportPath);
} }
@ -1730,6 +1793,7 @@ void Print::process(bool use_cache)
obj->detect_overhangs_for_lift(); obj->detect_overhangs_for_lift();
} }
else { else {
obj->copy_layers_overhang_from_shared_object();
if (obj->set_started(posDetectOverhangsForLift)) if (obj->set_started(posDetectOverhangsForLift))
obj->set_done(posDetectOverhangsForLift); obj->set_done(posDetectOverhangsForLift);
} }
@ -3094,7 +3158,14 @@ int Print::export_cached_data(const std::string& directory, bool with_space)
if (fs::exists(directory_path)) { if (fs::exists(directory_path)) {
fs::remove_all(directory_path); fs::remove_all(directory_path);
} }
if (!fs::create_directory(directory_path)) { try {
if (!fs::create_directory(directory_path)) {
BOOST_LOG_TRIVIAL(error) << boost::format("create directory %1% failed")%directory;
return CLI_EXPORT_CACHE_DIRECTORY_CREATE_FAILED;
}
}
catch (...)
{
BOOST_LOG_TRIVIAL(error) << boost::format("create directory %1% failed")%directory; BOOST_LOG_TRIVIAL(error) << boost::format("create directory %1% failed")%directory;
return CLI_EXPORT_CACHE_DIRECTORY_CREATE_FAILED; return CLI_EXPORT_CACHE_DIRECTORY_CREATE_FAILED;
} }
@ -3528,4 +3599,12 @@ Polygon PrintInstance::get_convex_hull_2d() {
return poly; return poly;
} }
//BBS: instance_shift is too large because of multi-plate, apply without plate offset.
Point PrintInstance::shift_without_plate_offset() const
{
const Print* print = print_object->print();
const Vec3d plate_offset = print->get_plate_origin();
return shift - Point(scaled(plate_offset.x()), scaled(plate_offset.y()));
}
} // namespace Slic3r } // namespace Slic3r

View file

@ -89,6 +89,7 @@ enum PrintObjectStep {
posSlice, posPerimeters, posPrepareInfill, posSlice, posPerimeters, posPrepareInfill,
posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifySupportPath, posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifySupportPath,
// BBS // BBS
posSimplifyInfill,
posDetectOverhangsForLift, posDetectOverhangsForLift,
posCount, posCount,
}; };
@ -200,6 +201,9 @@ struct PrintInstance
// //
// instance id // instance id
size_t id; size_t id;
//BBS: instance_shift is too large because of multi-plate, apply without plate offset.
Point shift_without_plate_offset() const;
}; };
typedef std::vector<PrintInstance> PrintInstances; typedef std::vector<PrintInstance> PrintInstances;
@ -419,11 +423,13 @@ public:
//BBS //BBS
BoundingBox get_first_layer_bbox(float& area, float& layer_height, std::string& name); BoundingBox get_first_layer_bbox(float& area, float& layer_height, std::string& name);
void get_certain_layers(float start, float end, std::vector<LayerPtrs> &out, std::vector<BoundingBox> &boundingbox_objects);
std::vector<Point> get_instances_shift_without_plate_offset();
PrintObject* get_shared_object() const { return m_shared_object; } PrintObject* get_shared_object() const { return m_shared_object; }
void set_shared_object(PrintObject *object); void set_shared_object(PrintObject *object);
void clear_shared_object(); void clear_shared_object();
void copy_layers_from_shared_object(); void copy_layers_from_shared_object();
void copy_layers_overhang_from_shared_object();
// BBS: Boundingbox of the first layer // BBS: Boundingbox of the first layer
BoundingBox firstLayerObjectBrimBoundingBox; BoundingBox firstLayerObjectBrimBoundingBox;
@ -755,7 +761,7 @@ public:
// For Perl bindings. // For Perl bindings.
PrintObjectPtrs& objects_mutable() { return m_objects; } PrintObjectPtrs& objects_mutable() { return m_objects; }
PrintRegionPtrs& print_regions_mutable() { return m_print_regions; } PrintRegionPtrs& print_regions_mutable() { return m_print_regions; }
std::vector<size_t> layers_sorted_for_object(float start, float end, std::vector<LayerPtrs> &layers_of_objects, std::vector<BoundingBox> &boundingBox_for_objects, std::vector<Points>& objects_instances_shift);
const ExtrusionEntityCollection& skirt() const { return m_skirt; } const ExtrusionEntityCollection& skirt() const { return m_skirt; }
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line. // Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
// It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower. // It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
@ -818,6 +824,9 @@ public:
Vec2d translate_to_print_space(const Vec2d &point) const; Vec2d translate_to_print_space(const Vec2d &point) const;
// scaled point // scaled point
Vec2d translate_to_print_space(const Point &point) const; Vec2d translate_to_print_space(const Point &point) const;
static bool check_multi_filaments_compatibility(const std::vector<std::string>& filament_types);
protected: protected:
// Invalidates the step, and its depending steps in Print. // Invalidates the step, and its depending steps in Print.
bool invalidate_step(PrintStep step); bool invalidate_step(PrintStep step);

View file

@ -19,6 +19,9 @@ namespace Slic3r {
enum StringExceptionType { enum StringExceptionType {
STRING_EXCEPT_NOT_DEFINED = 0, STRING_EXCEPT_NOT_DEFINED = 0,
STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE = 1, STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE = 1,
STRING_EXCEPT_FILAMENTS_DIFFERENT_TEMP = 2,
STRING_EXCEPT_OBJECT_COLLISION_IN_SEQ_PRINT = 3,
STRING_EXCEPT_OBJECT_COLLISION_IN_LAYER_PRINT = 4,
STRING_EXCEPT_COUNT STRING_EXCEPT_COUNT
}; };

View file

@ -444,6 +444,7 @@ void PrintObject::detect_overhangs_for_lift()
ExPolygons overhangs = diff_ex(layer.lslices, offset_ex(lower_layer.lslices, scale_(min_overlap))); ExPolygons overhangs = diff_ex(layer.lslices, offset_ex(lower_layer.lslices, scale_(min_overlap)));
layer.loverhangs = std::move(offset2_ex(overhangs, -0.1f * scale_(line_width), 0.1f * scale_(line_width))); layer.loverhangs = std::move(offset2_ex(overhangs, -0.1f * scale_(line_width), 0.1f * scale_(line_width)));
layer.loverhangs_bbox = get_extents(layer.loverhangs);
} }
}); });
@ -507,15 +508,33 @@ void PrintObject::simplify_extrusion_path()
[this](const tbb::blocked_range<size_t>& range) { [this](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
m_print->throw_if_canceled(); m_print->throw_if_canceled();
m_layers[layer_idx]->simplify_extrusion_path(); m_layers[layer_idx]->simplify_wall_extrusion_path();
} }
} }
); );
m_print->throw_if_canceled(); m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of object in parallel - end"; BOOST_LOG_TRIVIAL(debug) << "Simplify wall extrusion path of object in parallel - end";
this->set_done(posSimplifyPath); this->set_done(posSimplifyPath);
} }
if (this->set_started(posSimplifyInfill)) {
m_print->set_status(75, L("Optimizing toolpath"));
BOOST_LOG_TRIVIAL(debug) << "Simplify infill extrusion path of object in parallel - start";
//BBS: infills
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()),
[this](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
m_print->throw_if_canceled();
m_layers[layer_idx]->simplify_infill_extrusion_path();
}
}
);
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Simplify infill extrusion path of object in parallel - end";
this->set_done(posSimplifyInfill);
}
if (this->set_started(posSimplifySupportPath)) { if (this->set_started(posSimplifySupportPath)) {
//BBS: share same progress //BBS: share same progress
m_print->set_status(75, L("Optimizing toolpath")); m_print->set_status(75, L("Optimizing toolpath"));
@ -764,6 +783,7 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "support_angle" || opt_key == "support_angle"
|| opt_key == "support_on_build_plate_only" || opt_key == "support_on_build_plate_only"
|| opt_key == "support_critical_regions_only" || opt_key == "support_critical_regions_only"
|| opt_key == "support_remove_small_overhang"
|| opt_key == "enforce_support_layers" || opt_key == "enforce_support_layers"
|| opt_key == "support_filament" || opt_key == "support_filament"
|| opt_key == "support_line_width" || opt_key == "support_line_width"
@ -939,15 +959,15 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
// propagate to dependent steps // propagate to dependent steps
if (step == posPerimeters) { if (step == posPerimeters) {
invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSimplifyPath }); invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSimplifyPath, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim }); invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posPrepareInfill) { } else if (step == posPrepareInfill) {
invalidated |= this->invalidate_steps({ posInfill, posIroning, posSimplifyPath }); invalidated |= this->invalidate_steps({ posInfill, posIroning, posSimplifyPath, posSimplifyInfill });
} else if (step == posInfill) { } else if (step == posInfill) {
invalidated |= this->invalidate_steps({ posIroning, posSimplifyPath }); invalidated |= this->invalidate_steps({ posIroning, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim }); invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posSlice) { } else if (step == posSlice) {
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial, posSimplifyPath }); invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim }); invalidated |= m_print->invalidate_steps({ psSkirtBrim });
m_slicing_params.valid = false; m_slicing_params.valid = false;
} else if (step == posSupportMaterial) { } else if (step == posSupportMaterial) {
@ -2036,6 +2056,31 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
return updated; return updated;
} }
//BBS:
void PrintObject::get_certain_layers(float start, float end, std::vector<LayerPtrs> &out, std::vector<BoundingBox> &boundingbox_objects)
{
BoundingBox temp;
LayerPtrs out_temp;
for (const auto &layer : layers()) {
if (layer->print_z < start) continue;
if (layer->print_z > end + EPSILON) break;
temp.merge(layer->loverhangs_bbox);
out_temp.emplace_back(layer);
}
boundingbox_objects.emplace_back(std::move(temp));
out.emplace_back(std::move(out_temp));
};
std::vector<Point> PrintObject::get_instances_shift_without_plate_offset()
{
std::vector<Point> out;
out.reserve(m_instances.size());
for (const auto& instance : m_instances)
out.push_back(instance.shift_without_plate_offset());
return out;
}
// Only active if config->infill_only_where_needed. This step trims the sparse infill, // Only active if config->infill_only_where_needed. This step trims the sparse infill,
// so it acts as an internal support. It maintains all other infill types intact. // so it acts as an internal support. It maintains all other infill types intact.

View file

@ -2677,9 +2677,8 @@ void TabFilament::build()
optgroup = page->new_optgroup(L("Print temperature"), L"param_temperature"); optgroup = page->new_optgroup(L("Print temperature"), L"param_temperature");
optgroup->split_multi_line = true; optgroup->split_multi_line = true;
optgroup->option_label_at_right = true; optgroup->option_label_at_right = true;
line = { L("Chamber temperature"), L("Chamber temperature") }; optgroup->append_single_option_line("chamber_temperatures");
line.append_option(optgroup->get_option("chamber_temperature"));
optgroup->append_line(line);
line = { L("Nozzle"), L("Nozzle temperature when printing") }; line = { L("Nozzle"), L("Nozzle temperature when printing") };
line.append_option(optgroup->get_option("nozzle_temperature_initial_layer")); line.append_option(optgroup->get_option("nozzle_temperature_initial_layer"));
@ -2897,7 +2896,7 @@ void TabFilament::toggle_options()
toggle_line("cool_plate_temp_initial_layer", is_BBL_printer); toggle_line("cool_plate_temp_initial_layer", is_BBL_printer);
toggle_line("eng_plate_temp_initial_layer", is_BBL_printer); toggle_line("eng_plate_temp_initial_layer", is_BBL_printer);
toggle_line("textured_plate_temp_initial_layer", is_BBL_printer); toggle_line("textured_plate_temp_initial_layer", is_BBL_printer);
toggle_option("chamber_temperature", !is_BBL_printer); toggle_option("chamber_temperatures", !is_BBL_printer);
} }
if (m_active_page->title() == "Setting Overrides") if (m_active_page->title() == "Setting Overrides")
update_filament_overrides_page(); update_filament_overrides_page();
@ -3690,7 +3689,7 @@ void TabPrinter::toggle_options()
// SoftFever: hide BBL specific settings // SoftFever: hide BBL specific settings
for (auto el : for (auto el :
{"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "nozzle_type", "bbl_calib_mark_logo"}) {"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "bbl_calib_mark_logo"})
toggle_line(el, is_BBL_printer); toggle_line(el, is_BBL_printer);
// SoftFever: hide non-BBL settings // SoftFever: hide non-BBL settings