mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-18 20:28:08 -06:00
Merge some BS1.7 changes:
Port object canceling for BL X1 from BS. Todo: refactor
This commit is contained in:
parent
3acd89e877
commit
7ece35931e
15 changed files with 557 additions and 162 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>&);
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue