mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 15:44:12 -06:00
Merge branch 'main' into feature/support-fliament-cutter-explore-proper-flush-lenght
This commit is contained in:
commit
4b2a09bd07
210 changed files with 2325 additions and 1604 deletions
|
@ -18,9 +18,7 @@
|
|||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/property_tree/ptree_fwd.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/format/format_fwd.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//Copyright (c) 2022 Ultimaker B.V.
|
||||
//CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "BeadingStrategy.hpp"
|
||||
#include "Point.hpp"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "RedistributeBeadingStrategy.hpp"
|
||||
#include "OuterWallInsetBeadingStrategy.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "RedistributeBeadingStrategy.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
|
|
|
@ -1595,7 +1595,6 @@ SkeletalTrapezoidation::edge_t* SkeletalTrapezoidation::getQuadMaxRedgeTo(edge_t
|
|||
|
||||
void SkeletalTrapezoidation::propagateBeadingsUpward(std::vector<edge_t*>& upward_quad_mids, ptr_vector_t<BeadingPropagation>& node_beadings)
|
||||
{
|
||||
const auto _central_filter_dist = central_filter_dist();
|
||||
for (auto upward_quad_mids_it = upward_quad_mids.rbegin(); upward_quad_mids_it != upward_quad_mids.rend(); ++upward_quad_mids_it)
|
||||
{
|
||||
edge_t* upward_edge = *upward_quad_mids_it;
|
||||
|
@ -1612,7 +1611,7 @@ void SkeletalTrapezoidation::propagateBeadingsUpward(std::vector<edge_t*>& upwar
|
|||
{ // Only propagate to places where there is place
|
||||
continue;
|
||||
}
|
||||
assert((upward_edge->from->data.distance_to_boundary != upward_edge->to->data.distance_to_boundary || shorter_then(upward_edge->to->p - upward_edge->from->p, _central_filter_dist)) && "zero difference R edges should always be central");
|
||||
assert((upward_edge->from->data.distance_to_boundary != upward_edge->to->data.distance_to_boundary || shorter_then(upward_edge->to->p - upward_edge->from->p, central_filter_dist())) && "zero difference R edges should always be central");
|
||||
coord_t length = (upward_edge->to->p - upward_edge->from->p).cast<int64_t>().norm();
|
||||
BeadingPropagation upper_beading = lower_beading;
|
||||
upper_beading.dist_to_bottom_source += length;
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "utils/linearAlg2D.hpp"
|
||||
#include "../Line.hpp"
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
{
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "ExtrusionLine.hpp"
|
||||
#include "linearAlg2D.hpp"
|
||||
#include "../../VariableWidth.hpp"
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
//CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
#include "SquareGrid.hpp"
|
||||
#include "../../Point.hpp"
|
||||
|
||||
using namespace Slic3r::Arachne;
|
||||
|
||||
|
|
|
@ -199,23 +199,19 @@ void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPr
|
|||
}
|
||||
|
||||
if (std::abs(a00) > EPSILON) {
|
||||
double db1_2, db1_6, db1_12, db1_24, db1_20, db1_60;
|
||||
double m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;
|
||||
double db1_2, db1_6, db1_12, db1_24;
|
||||
double m00, m10, m01, m20, m11, m02;
|
||||
if (a00 > 0) {
|
||||
db1_2 = 0.5;
|
||||
db1_6 = 0.16666666666666666666666666666667;
|
||||
db1_12 = 0.083333333333333333333333333333333;
|
||||
db1_24 = 0.041666666666666666666666666666667;
|
||||
db1_20 = 0.05;
|
||||
db1_60 = 0.016666666666666666666666666666667;
|
||||
}
|
||||
else {
|
||||
db1_2 = -0.5;
|
||||
db1_6 = -0.16666666666666666666666666666667;
|
||||
db1_12 = -0.083333333333333333333333333333333;
|
||||
db1_24 = -0.041666666666666666666666666666667;
|
||||
db1_20 = -0.05;
|
||||
db1_60 = -0.016666666666666666666666666666667;
|
||||
}
|
||||
m00 = a00 * db1_2;
|
||||
m10 = a10 * db1_6;
|
||||
|
@ -223,10 +219,6 @@ void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPr
|
|||
m20 = a20 * db1_12;
|
||||
m11 = a11 * db1_24;
|
||||
m02 = a02 * db1_12;
|
||||
m30 = a30 * db1_20;
|
||||
m21 = a21 * db1_60;
|
||||
m12 = a12 * db1_60;
|
||||
m03 = a03 * db1_20;
|
||||
|
||||
double cx = m10 / m00;
|
||||
double cy = m01 / m00;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "BlacklistedLibraryCheck.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
|
@ -576,7 +576,6 @@ double getadhesionCoeff(const PrintObject* printObject)
|
|||
auto& insts = printObject->instances();
|
||||
auto objectVolumes = insts[0].model_instance->get_object()->volumes;
|
||||
|
||||
auto print = printObject->print();
|
||||
std::vector<size_t> extrudersFirstLayer;
|
||||
auto firstLayerRegions = printObject->layers().front()->regions();
|
||||
if (!firstLayerRegions.empty()) {
|
||||
|
@ -901,7 +900,6 @@ static ExPolygons outer_inner_brim_area(const Print& print,
|
|||
Polygons holes_object;
|
||||
Polygons holes_support;
|
||||
if (objectWithExtruder.second == extruderNo && brimToWrite.at(object->id()).obj) {
|
||||
double deltaT = getTemperatureFromExtruder(object);
|
||||
double adhesion = getadhesionCoeff(object);
|
||||
double maxSpeed = Model::findMaxSpeed(object->model_object());
|
||||
// BBS: brims are generated by volume groups
|
||||
|
@ -1585,7 +1583,6 @@ static void make_inner_brim(const Print& print, const ConstPrintObjectPtrs& top_
|
|||
//BBS: generate out brim by offseting ExPolygons 'islands_area_ex'
|
||||
Polygons tryExPolygonOffset(const ExPolygons islandAreaEx, const Print& print)
|
||||
{
|
||||
const auto scaled_resolution = scaled<double>(print.config().resolution.value);
|
||||
Polygons loops;
|
||||
ExPolygons islands_ex;
|
||||
Flow flow = print.brim_flow();
|
||||
|
@ -1660,7 +1657,6 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_
|
|||
std::map<ObjectID, ExPolygons> brimAreaMap;
|
||||
std::map<ObjectID, ExPolygons> supportBrimAreaMap;
|
||||
Flow flow = print.brim_flow();
|
||||
const auto scaled_resolution = scaled<double>(print.config().resolution.value);
|
||||
ExPolygons islands_area_ex = outer_inner_brim_area(print,
|
||||
float(flow.scaled_spacing()), brimAreaMap, supportBrimAreaMap, objPrintVec, printExtruders);
|
||||
|
||||
|
|
|
@ -156,6 +156,12 @@ set(lisbslic3r_sources
|
|||
GCode/RetractWhenCrossingPerimeters.hpp
|
||||
GCode/SmallAreaInfillFlowCompensator.cpp
|
||||
GCode/SmallAreaInfillFlowCompensator.hpp
|
||||
GCode/PchipInterpolatorHelper.cpp
|
||||
GCode/PchipInterpolatorHelper.hpp
|
||||
GCode/AdaptivePAInterpolator.cpp
|
||||
GCode/AdaptivePAInterpolator.hpp
|
||||
GCode/AdaptivePAProcessor.cpp
|
||||
GCode/AdaptivePAProcessor.hpp
|
||||
GCode/SpiralVase.cpp
|
||||
GCode/SpiralVase.hpp
|
||||
GCode/SeamPlacer.cpp
|
||||
|
|
|
@ -28,7 +28,7 @@ bool model_to_csgmesh(const ModelObject &mo,
|
|||
{
|
||||
bool do_positives = parts_to_include & mpartsPositive;
|
||||
bool do_negatives = parts_to_include & mpartsNegative;
|
||||
bool do_drillholes = parts_to_include & mpartsDrillHoles;
|
||||
// bool do_drillholes = parts_to_include & mpartsDrillHoles;
|
||||
bool do_splits = parts_to_include & mpartsDoSplits;
|
||||
bool has_splitable_volume = false;
|
||||
|
||||
|
|
|
@ -775,10 +775,9 @@ ConfigSubstitutions ConfigBase::load(const std::string &file, ForwardCompatibili
|
|||
//BBS: add json support
|
||||
ConfigSubstitutions ConfigBase::load_from_json(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule, std::map<std::string, std::string>& key_values, std::string& reason)
|
||||
{
|
||||
int ret = 0;
|
||||
ConfigSubstitutionContext substitutions_ctxt(compatibility_rule);
|
||||
|
||||
ret = load_from_json(file, substitutions_ctxt, true, key_values, reason);
|
||||
load_from_json(file, substitutions_ctxt, true, key_values, reason);
|
||||
return std::move(substitutions_ctxt.substitutions);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include "ShortestPath.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#include "../ClipperUtils.hpp"
|
||||
#include "../ExPolygon.hpp"
|
||||
#include "../Surface.hpp"
|
||||
#include "../VariableWidth.hpp"
|
||||
#include "Arachne/WallToolPaths.hpp"
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "../ClipperUtils.hpp"
|
||||
#include "../ShortestPath.hpp"
|
||||
#include "../Surface.hpp"
|
||||
#include <cmath>
|
||||
|
||||
#include "FillCrossHatch.hpp"
|
||||
|
@ -65,7 +64,6 @@ static Polylines generate_transform_pattern(double inprogress, int direction, co
|
|||
odd_poly.points.reserve(num_of_cycle * one_cycle.size());
|
||||
|
||||
// replicate to odd line
|
||||
Point translate = Point(0, 0);
|
||||
for (size_t i = 0; i < num_of_cycle; i++) {
|
||||
Polyline odd_points;
|
||||
odd_points = Polyline(one_cycle);
|
||||
|
@ -152,7 +150,6 @@ static Polylines generate_infill_layers(coordf_t z_height, double repeat_ratio,
|
|||
coordf_t period = trans_layer_size + repeat_layer_size;
|
||||
coordf_t remains = z_height - std::floor(z_height / period) * period;
|
||||
coordf_t trans_z = remains - repeat_layer_size; // put repeat layer first.
|
||||
coordf_t repeat_z = remains;
|
||||
|
||||
int phase = fmod(z_height, period * 2) - (period - 1); // add epsilon
|
||||
int direction = phase <= 0 ? -1 : 1;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include "Generator.hpp"
|
||||
#include "TreeNode.hpp"
|
||||
|
||||
#include "../../ClipperUtils.hpp"
|
||||
#include "../../Layer.hpp"
|
||||
#include "../../Print.hpp"
|
||||
|
||||
|
@ -35,7 +34,7 @@ static std::string get_svg_filename(std::string layer_nr_or_z, std::string tag
|
|||
rand_init = true;
|
||||
}
|
||||
|
||||
int rand_num = rand() % 1000000;
|
||||
// int rand_num = rand() % 1000000;
|
||||
//makedir("./SVG");
|
||||
std::string prefix = "./SVG/";
|
||||
std::string suffix = ".svg";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <cmath>
|
||||
#include <assert.h>
|
||||
#include "slic3r/Utils/ColorSpaceConvert.hpp"
|
||||
|
||||
#include "FlushVolCalc.hpp"
|
||||
|
|
|
@ -298,7 +298,6 @@ bool PrusaFileParser::check_3mf_from_prusa(const std::string filename)
|
|||
const std::string model_file = "3D/3dmodel.model";
|
||||
int model_file_index = mz_zip_reader_locate_file(&archive, model_file.c_str(), nullptr, 0);
|
||||
if (model_file_index != -1) {
|
||||
int depth = 0;
|
||||
m_parser = XML_ParserCreate(nullptr);
|
||||
XML_SetUserData(m_parser, (void *) this);
|
||||
XML_SetElementHandler(m_parser, start_element_handler, nullptr);
|
||||
|
|
|
@ -100,7 +100,6 @@ bool load_obj(const char *path, TriangleMesh *meshptr, ObjInfo& obj_info, std::s
|
|||
obj_info.is_single_mtl = data.usemtls.size() == 1 && mtl_data.new_mtl_unmap.size() == 1;
|
||||
obj_info.face_colors.reserve(num_faces + num_quads);
|
||||
}
|
||||
bool has_color = data.has_vertex_color;
|
||||
for (size_t i = 0; i < num_vertices; ++ i) {
|
||||
size_t j = i * OBJ_VERTEX_LENGTH;
|
||||
its.vertices.emplace_back(data.coordinates[j], data.coordinates[j + 1], data.coordinates[j + 2]);
|
||||
|
|
|
@ -878,7 +878,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool extract_object_model()
|
||||
{
|
||||
mz_zip_archive archive;
|
||||
mz_zip_archive_file_stat stat;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
if (!open_zip_reader(&archive, zip_path)) {
|
||||
|
@ -1617,9 +1616,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
}
|
||||
else {
|
||||
_extract_xml_from_archive(archive, sub_rels, _handle_start_relationships_element, _handle_end_relationships_element);
|
||||
int index = 0;
|
||||
|
||||
#if 0
|
||||
int index = 0;
|
||||
for (auto path : m_sub_model_paths) {
|
||||
if (proFn) {
|
||||
proFn(IMPORT_STAGE_READ_FILES, ++index, 3 + m_sub_model_paths.size(), cb_cancel);
|
||||
|
@ -2219,7 +2218,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
bool _BBS_3MF_Importer::_extract_from_archive(mz_zip_archive& archive, std::string const & path, std::function<bool (mz_zip_archive& archive, const mz_zip_archive_file_stat& stat)> extract, bool restore)
|
||||
{
|
||||
mz_uint num_entries = mz_zip_reader_get_num_files(&archive);
|
||||
mz_zip_archive_file_stat stat;
|
||||
std::string path2 = path;
|
||||
if (path2.front() == '/') path2 = path2.substr(1);
|
||||
|
@ -3319,9 +3317,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
// Adjust backup object/volume id
|
||||
std::istringstream iss(m_curr_object->uuid);
|
||||
int backup_id;
|
||||
bool need_replace = false;
|
||||
// bool need_replace = false;
|
||||
if (iss >> std::hex >> backup_id) {
|
||||
need_replace = (m_curr_object->id != backup_id);
|
||||
// need_replace = (m_curr_object->id != backup_id);
|
||||
m_curr_object->id = backup_id;
|
||||
}
|
||||
if (!m_curr_object->components.empty())
|
||||
|
@ -4994,9 +4992,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
if (is_bbl_3mf && boost::ends_with(current_object->uuid, OBJECT_UUID_SUFFIX) && top_importer->m_load_restore) {
|
||||
std::istringstream iss(current_object->uuid);
|
||||
int backup_id;
|
||||
bool need_replace = false;
|
||||
// bool need_replace = false;
|
||||
if (iss >> std::hex >> backup_id) {
|
||||
need_replace = (current_object->id != backup_id);
|
||||
// need_replace = (current_object->id != backup_id);
|
||||
current_object->id = backup_id;
|
||||
}
|
||||
//if (need_replace)
|
||||
|
@ -5991,8 +5989,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
auto src_gcode_file = plate_data->gcode_file;
|
||||
boost::filesystem::ifstream ifs(src_gcode_file, std::ios::binary);
|
||||
std::string buf(64 * 1024, 0);
|
||||
const std::size_t & size = boost::filesystem::file_size(src_gcode_file);
|
||||
std::size_t left_size = size;
|
||||
while (ifs) {
|
||||
ifs.read(buf.data(), buf.size());
|
||||
int read_bytes = ifs.gcount();
|
||||
|
@ -6230,7 +6226,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
bool _BBS_3MF_Exporter::_add_bbox_file_to_archive(mz_zip_archive& archive, const PlateBBoxData& id_bboxes, int index)
|
||||
{
|
||||
bool res = false;
|
||||
nlohmann::json j;
|
||||
id_bboxes.to_json(j);
|
||||
std::string out = j.dump();
|
||||
|
@ -6620,7 +6615,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
auto iter = objects_data.find(objects[i]);
|
||||
ObjectToObjectDataMap objects_data2;
|
||||
objects_data2.insert(*iter);
|
||||
auto & object = *iter->second.object;
|
||||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
mz_zip_writer_init_heap(&archive, 0, 1024 * 1024);
|
||||
|
@ -7537,7 +7531,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
if (!m_skip_model && instance_size > 0)
|
||||
{
|
||||
for (unsigned int j = 0; j < instance_size; ++j)
|
||||
for (int j = 0; j < instance_size; ++j)
|
||||
{
|
||||
stream << " <" << INSTANCE_TAG << ">\n";
|
||||
int obj_id = plate_data->objects_and_instances[j].first;
|
||||
|
|
|
@ -113,9 +113,6 @@ double get_profile_area(std::vector<std::pair<gp_Pnt, gp_Pnt>> profile_line_poin
|
|||
|
||||
double area = 0;
|
||||
for (auto line_points : profile_line_points) {
|
||||
bool flag = true;
|
||||
if (line_points.second.Y() < line_points.first.Y()) flag = false;
|
||||
|
||||
area += (line_points.second.X() + line_points.first.X() - 2 * min_x) * (line_points.second.Y() - line_points.first.Y()) / 2;
|
||||
}
|
||||
|
||||
|
@ -137,8 +134,6 @@ bool get_svg_profile(const char *path, std::vector<Element_Info> &element_infos,
|
|||
|
||||
int name_index = 1;
|
||||
for (NSVGshape *shape = svg_data->shapes; shape; shape = shape->next) {
|
||||
char * id = shape->id;
|
||||
|
||||
int interpolation_precision = 10; // Number of interpolation points
|
||||
float step = 1.0f / float(interpolation_precision - 1);
|
||||
|
||||
|
@ -384,7 +379,6 @@ bool load_svg(const char *path, Model *model, std::string &message)
|
|||
ModelObject *new_object = model->add_object();
|
||||
// new_object->name ?
|
||||
new_object->input_file = path;
|
||||
auto stage_unit3 = stl.size() / LOAD_STEP_STAGE_UNIT_NUM + 1;
|
||||
for (size_t i = 0; i < stl.size(); i++) {
|
||||
// BBS: maybe mesh is empty from step file. Don't add
|
||||
if (stl[i].stats.number_of_facets > 0) {
|
||||
|
|
|
@ -116,7 +116,6 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
if (excluse_area.size() != 4)
|
||||
return out_points;
|
||||
|
||||
double cutter_area_x = excluse_area[2].x() + 2;
|
||||
double cutter_area_y = excluse_area[2].y() + 2;
|
||||
|
||||
double start_x_position = start_point.x();
|
||||
|
@ -666,6 +665,9 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
// SoftFever: set new PA for new filament
|
||||
if (gcodegen.config().enable_pressure_advance.get_at(new_extruder_id)) {
|
||||
gcode += gcodegen.writer().set_pressure_advance(gcodegen.config().pressure_advance.get_at(new_extruder_id));
|
||||
// Orca: Adaptive PA
|
||||
// Reset Adaptive PA processor last PA value
|
||||
gcodegen.m_pa_processor->resetPreviousPA(gcodegen.config().pressure_advance.get_at(new_extruder_id));
|
||||
}
|
||||
|
||||
// A phony move to the end position at the wipe tower.
|
||||
|
@ -789,6 +791,9 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
// SoftFever: set new PA for new filament
|
||||
if (new_extruder_id != -1 && gcodegen.config().enable_pressure_advance.get_at(new_extruder_id)) {
|
||||
gcode += gcodegen.writer().set_pressure_advance(gcodegen.config().pressure_advance.get_at(new_extruder_id));
|
||||
// Orca: Adaptive PA
|
||||
// Reset Adaptive PA processor last PA value
|
||||
gcodegen.m_pa_processor->resetPreviousPA(gcodegen.config().pressure_advance.get_at(new_extruder_id));
|
||||
}
|
||||
|
||||
// A phony move to the end position at the wipe tower.
|
||||
|
@ -1886,6 +1891,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
|
||||
if (!print.config().small_area_infill_flow_compensation_model.empty())
|
||||
m_small_area_infill_flow_compensator = make_unique<SmallAreaInfillFlowCompensator>(print.config());
|
||||
|
||||
|
||||
file.write_format("; HEADER_BLOCK_START\n");
|
||||
// Write information on the generator.
|
||||
|
@ -2131,6 +2137,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
|
||||
m_cooling_buffer = make_unique<CoolingBuffer>(*this);
|
||||
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
||||
|
||||
// Orca: Initialise AdaptivePA processor filter
|
||||
m_pa_processor = std::make_unique<AdaptivePAProcessor>(*this, tool_ordering.all_extruders());
|
||||
|
||||
// Emit machine envelope limits for the Marlin firmware.
|
||||
this->print_machine_envelope(file, print);
|
||||
|
@ -2482,7 +2491,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
m_avoid_crossing_perimeters.use_external_mp_once();
|
||||
// BBS. change tool before moving to origin point.
|
||||
if (m_writer.need_toolchange(initial_extruder_id)) {
|
||||
const PrintObjectConfig& object_config = object.config();
|
||||
coordf_t initial_layer_print_height = print.config().initial_layer_print_height.value;
|
||||
file.write(this->set_extruder(initial_extruder_id, initial_layer_print_height, true));
|
||||
prime_extruder = true;
|
||||
|
@ -2773,6 +2781,12 @@ void GCode::process_layers(
|
|||
return in.gcode;
|
||||
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
|
||||
});
|
||||
const auto pa_processor_filter = tbb::make_filter<std::string, std::string>(slic3r_tbb_filtermode::serial_in_order,
|
||||
[&pa_processor = *this->m_pa_processor](std::string in) -> std::string {
|
||||
return pa_processor.process_layer(std::move(in));
|
||||
}
|
||||
);
|
||||
|
||||
const auto output = tbb::make_filter<std::string, void>(slic3r_tbb_filtermode::serial_in_order,
|
||||
[&output_stream](std::string s) { output_stream.write(s); }
|
||||
);
|
||||
|
@ -2803,9 +2817,9 @@ void GCode::process_layers(
|
|||
else if (m_spiral_vase)
|
||||
tbb::parallel_pipeline(12, generator & spiral_mode & cooling & fan_mover & output);
|
||||
else if (m_pressure_equalizer)
|
||||
tbb::parallel_pipeline(12, generator & pressure_equalizer & cooling & fan_mover & output);
|
||||
tbb::parallel_pipeline(12, generator & pressure_equalizer & cooling & fan_mover & pa_processor_filter & output);
|
||||
else
|
||||
tbb::parallel_pipeline(12, generator & cooling & fan_mover & output);
|
||||
tbb::parallel_pipeline(12, generator & cooling & fan_mover & pa_processor_filter & output);
|
||||
}
|
||||
|
||||
// Process all layers of a single object instance (sequential mode) with a parallel pipeline:
|
||||
|
@ -3261,14 +3275,17 @@ namespace ProcessLayer
|
|||
const PrintConfig &config)
|
||||
{
|
||||
std::string gcode;
|
||||
// BBS
|
||||
bool single_filament_print = config.filament_diameter.size() == 1;
|
||||
|
||||
if (custom_gcode != nullptr) {
|
||||
// Extruder switches are processed by LayerTools, they should be filtered out.
|
||||
assert(custom_gcode->type != CustomGCode::ToolChange);
|
||||
|
||||
CustomGCode::Type gcode_type = custom_gcode->type;
|
||||
|
||||
//BBS: inserting color gcode is removed
|
||||
#if 0
|
||||
// BBS
|
||||
bool single_filament_print = config.filament_diameter.size() == 1;
|
||||
bool color_change = gcode_type == CustomGCode::ColorChange;
|
||||
bool tool_change = gcode_type == CustomGCode::ToolChange;
|
||||
// Tool Change is applied as Color Change for a single extruder printer only.
|
||||
|
@ -3280,8 +3297,7 @@ namespace ProcessLayer
|
|||
m600_extruder_before_layer = custom_gcode->extruder - 1;
|
||||
else if (gcode_type == CustomGCode::PausePrint)
|
||||
pause_print_msg = custom_gcode->extra;
|
||||
//BBS: inserting color gcode is removed
|
||||
#if 0
|
||||
|
||||
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
|
||||
if (color_change || tool_change)
|
||||
{
|
||||
|
@ -3344,8 +3360,8 @@ namespace Skirt {
|
|||
{
|
||||
// Prime all extruders printing over the 1st layer over the skirt lines.
|
||||
size_t n_loops = print.skirt().entities.size();
|
||||
size_t n_tools = layer_tools.extruders.size();
|
||||
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
|
||||
// size_t n_tools = layer_tools.extruders.size();
|
||||
// size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
|
||||
|
||||
// BBS. Extrude skirt with first extruder if min_skirt_length is zero
|
||||
//ORCA: Always extrude skirt with first extruder, independantly of if the minimum skirt length is zero or not. The code below
|
||||
|
@ -3701,7 +3717,8 @@ LayerResult GCode::process_layer(
|
|||
Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done);
|
||||
|
||||
// BBS: get next extruder according to flush and soluble
|
||||
auto get_next_extruder = [&](int current_extruder,const std::vector<unsigned int>&extruders) {
|
||||
// Orca: Left unused due to removed code below
|
||||
/* auto get_next_extruder = [&](int current_extruder,const std::vector<unsigned int>&extruders) {
|
||||
std::vector<float> flush_matrix(cast<float>(m_config.flush_volumes_matrix.values));
|
||||
const unsigned int number_of_extruders = (unsigned int)(sqrt(flush_matrix.size()) + EPSILON);
|
||||
// Extract purging volumes for each extruder pair:
|
||||
|
@ -3719,7 +3736,7 @@ LayerResult GCode::process_layer(
|
|||
}
|
||||
}
|
||||
return next_extruder;
|
||||
};
|
||||
}; */
|
||||
|
||||
if (m_config.enable_overhang_speed && !m_config.overhang_speed_classic) {
|
||||
for (const auto &layer_to_print : layers) {
|
||||
|
@ -3972,7 +3989,7 @@ LayerResult GCode::process_layer(
|
|||
m_avoid_crossing_perimeters.use_external_mp();
|
||||
Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2])));
|
||||
double mm3_per_mm = layer_skirt_flow.mm3_per_mm();
|
||||
for (size_t i = loops.first; i < loops.second; ++i) {
|
||||
for (size_t i = (layer.id() == 0) ? loops.first : loops.second - 1; i < loops.second; ++i) {
|
||||
// Adjust flow according to this layer's layer height.
|
||||
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(print.skirt().entities[i]);
|
||||
for (ExtrusionPath &path : loop.paths) {
|
||||
|
@ -4456,6 +4473,7 @@ static std::unique_ptr<EdgeGrid::Grid> calculate_layer_edge_grid(const Layer& la
|
|||
|
||||
std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, double speed, const ExtrusionEntitiesPtr& region_perimeters)
|
||||
{
|
||||
|
||||
// get a copy; don't modify the orientation of the original loop object otherwise
|
||||
// next copies (if any) would not detect the correct orientation
|
||||
|
||||
|
@ -4465,6 +4483,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||
// if spiral vase, we have to ensure that all contour are in the same orientation.
|
||||
loop.make_counter_clockwise();
|
||||
}
|
||||
if (loop.loop_role() == elrSkirt && (this->m_layer->id() % 2 == 1))
|
||||
loop.reverse();
|
||||
|
||||
// find the point of the loop that is closest to the current extruder position
|
||||
// or randomize if requested
|
||||
|
@ -4581,7 +4601,9 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||
if(discoveredTouchingLines > 1){
|
||||
// use extrude instead of travel_to_xy to trigger the unretract
|
||||
ExtrusionPath fake_path_wipe(Polyline{pt, current_point}, paths.front());
|
||||
fake_path_wipe.set_force_no_extrusion(true);
|
||||
fake_path_wipe.mm3_per_mm = 0;
|
||||
//fake_path_wipe.set_extrusion_role(erExternalPerimeter);
|
||||
gcode += extrude_path(fake_path_wipe, "move inwards before retraction/seam", speed);
|
||||
}
|
||||
}
|
||||
|
@ -4593,9 +4615,32 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||
return is_small_peri ? small_peri_speed : speed;
|
||||
};
|
||||
|
||||
|
||||
//Orca: Adaptive PA: calculate average mm3_per_mm value over the length of the loop.
|
||||
//This is used for adaptive PA
|
||||
m_multi_flow_segment_path_pa_set = false; // always emit PA on the first path of the loop
|
||||
m_multi_flow_segment_path_average_mm3_per_mm = 0;
|
||||
double weighted_sum_mm3_per_mm = 0.0;
|
||||
double total_multipath_length = 0.0;
|
||||
for (const ExtrusionPath& path : paths) {
|
||||
if(!path.is_force_no_extrusion()){
|
||||
double path_length = unscale<double>(path.length()); //path length in mm
|
||||
weighted_sum_mm3_per_mm += path.mm3_per_mm * path_length;
|
||||
total_multipath_length += path_length;
|
||||
}
|
||||
}
|
||||
if (total_multipath_length > 0.0)
|
||||
m_multi_flow_segment_path_average_mm3_per_mm = weighted_sum_mm3_per_mm / total_multipath_length;
|
||||
// Orca: end of multipath average mm3_per_mm value calculation
|
||||
|
||||
if (!enable_seam_slope) {
|
||||
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
|
||||
gcode += this->_extrude(*path, description, speed_for_path(*path));
|
||||
// Orca: Adaptive PA - dont adapt PA after the first pultipath extrusion is completed
|
||||
// as we have already set the PA value to the average flow over the totality of the path
|
||||
// in the first extrude move
|
||||
// TODO: testing is needed with slope seams and adaptive PA.
|
||||
m_multi_flow_segment_path_pa_set = true;
|
||||
}
|
||||
} else {
|
||||
// Create seam slope
|
||||
|
@ -4627,6 +4672,10 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||
// Then extrude it
|
||||
for (const auto& p : new_loop.get_all_paths()) {
|
||||
gcode += this->_extrude(*p, description, speed_for_path(*p));
|
||||
// Orca: Adaptive PA - dont adapt PA after the first pultipath extrusion is completed
|
||||
// as we have already set the PA value to the average flow over the totality of the path
|
||||
// in the first extrude move
|
||||
m_multi_flow_segment_path_pa_set = true;
|
||||
}
|
||||
|
||||
// Fix path for wipe
|
||||
|
@ -4698,8 +4747,31 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
|
|||
{
|
||||
// extrude along the path
|
||||
std::string gcode;
|
||||
for (ExtrusionPath path : multipath.paths)
|
||||
|
||||
//Orca: calculate multipath average mm3_per_mm value over the length of the path.
|
||||
//This is used for adaptive PA
|
||||
m_multi_flow_segment_path_pa_set = false; // always emit PA on the first path of the multi-path
|
||||
m_multi_flow_segment_path_average_mm3_per_mm = 0;
|
||||
double weighted_sum_mm3_per_mm = 0.0;
|
||||
double total_multipath_length = 0.0;
|
||||
for (const ExtrusionPath& path : multipath.paths) {
|
||||
if(!path.is_force_no_extrusion()){
|
||||
double path_length = unscale<double>(path.length()); //path length in mm
|
||||
weighted_sum_mm3_per_mm += path.mm3_per_mm * path_length;
|
||||
total_multipath_length += path_length;
|
||||
}
|
||||
}
|
||||
if (total_multipath_length > 0.0)
|
||||
m_multi_flow_segment_path_average_mm3_per_mm = weighted_sum_mm3_per_mm / total_multipath_length;
|
||||
// Orca: end of multipath average mm3_per_mm value calculation
|
||||
|
||||
for (ExtrusionPath path : multipath.paths){
|
||||
gcode += this->_extrude(path, description, speed);
|
||||
// Orca: Adaptive PA - dont adapt PA after the first pultipath extrusion is completed
|
||||
// as we have already set the PA value to the average flow over the totality of the path
|
||||
// in the first extrude move.
|
||||
m_multi_flow_segment_path_pa_set = true;
|
||||
}
|
||||
|
||||
// BBS
|
||||
if (m_wipe.enable) {
|
||||
|
@ -4733,7 +4805,10 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string des
|
|||
|
||||
std::string GCode::extrude_path(ExtrusionPath path, std::string description, double speed)
|
||||
{
|
||||
// description += ExtrusionEntity::role_to_string(path.role());
|
||||
// Orca: Reset average multipath flow as this is a single line, single extrude volumetric speed path
|
||||
m_multi_flow_segment_path_pa_set = false;
|
||||
m_multi_flow_segment_path_average_mm3_per_mm = 0;
|
||||
// description += ExtrusionEntity::role_to_string(path.role());
|
||||
std::string gcode = this->_extrude(path, description, speed);
|
||||
if (m_wipe.enable) {
|
||||
m_wipe.path = std::move(path.polyline);
|
||||
|
@ -4794,8 +4869,8 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
|
|||
|
||||
std::string gcode;
|
||||
if (! support_fills.entities.empty()) {
|
||||
const double support_speed = m_config.support_speed.value;
|
||||
const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
|
||||
// const double support_speed = m_config.support_speed.value;
|
||||
// const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
|
||||
for (const ExtrusionEntity *ee : support_fills.entities) {
|
||||
ExtrusionRole role = ee->role();
|
||||
assert(role == erSupportMaterial || role == erSupportMaterialInterface || role == erSupportTransition);
|
||||
|
@ -5199,7 +5274,28 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
}
|
||||
|
||||
double F = speed * 60; // convert mm/sec to mm/min
|
||||
|
||||
|
||||
// Orca: Dynamic PA
|
||||
// If adaptive PA is enabled, by default evaluate PA on all extrusion moves
|
||||
bool evaluate_adaptive_pa = false;
|
||||
bool role_change = (m_last_extrusion_role != path.role());
|
||||
if(EXTRUDER_CONFIG(adaptive_pressure_advance) && EXTRUDER_CONFIG(enable_pressure_advance)){
|
||||
evaluate_adaptive_pa = true;
|
||||
// If we have already emmited a PA change because the m_multi_flow_segment_path_pa_set is set
|
||||
// skip re-issuing the PA change tag.
|
||||
if (m_multi_flow_segment_path_pa_set && evaluate_adaptive_pa)
|
||||
evaluate_adaptive_pa = false;
|
||||
// TODO: Explore forcing evaluation of PA if a role change is happening mid extrusion.
|
||||
// TODO: This would enable adapting PA for overhang perimeters as they are part of the current loop
|
||||
// TODO: The issue with simply enabling PA evaluation on a role change is that the speed change
|
||||
// TODO: is issued before the overhang perimeter role change is triggered
|
||||
// TODO: because for some reason (maybe path segmentation upstream?) there is a short path extruded
|
||||
// TODO: with the overhang speed and flow before the role change is flagged in the path.role() function.
|
||||
if(role_change)
|
||||
evaluate_adaptive_pa = true;
|
||||
}
|
||||
// Orca: End of dynamic PA trigger flag segment
|
||||
|
||||
//Orca: process custom gcode for extrusion role change
|
||||
if (path.role() != m_last_extrusion_role && !m_config.change_extrusion_role_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
|
@ -5255,6 +5351,45 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
sprintf(buf, ";%s%g\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height).c_str(), m_last_height);
|
||||
gcode += buf;
|
||||
}
|
||||
|
||||
// Orca: Dynamic PA
|
||||
// Post processor flag generation code segment when option to emit only at role changes is enabled
|
||||
// Variables published to the post processor:
|
||||
// 1) Tag to trigger a PA evaluation (because a role change was identified and the user has requested dynamic PA adjustments)
|
||||
// 2) Current extruder ID (to identify the PA model for the currently used extruder)
|
||||
// 3) mm3_per_mm value (to then multiply by the final model print speed after slowdown for cooling is applied)
|
||||
// 4) the current acceleration (to pass to the model for evaluation)
|
||||
// 5) whether this is an external perimeter (for future use)
|
||||
// 6) whether this segment is triggered because of a role change (to aid in calculation of average speed for the role)
|
||||
// This tag simplifies the creation of the gcode post processor while also keeping the feature decoupled from other tags.
|
||||
if (evaluate_adaptive_pa) {
|
||||
bool isOverhangPerimeter = (path.role() == erOverhangPerimeter);
|
||||
if (m_multi_flow_segment_path_average_mm3_per_mm > 0) {
|
||||
sprintf(buf, ";%sT%u MM3MM:%g ACCEL:%u BR:%d RC:%d OV:%d\n",
|
||||
GCodeProcessor::reserved_tag(GCodeProcessor::ETags::PA_Change).c_str(),
|
||||
m_writer.extruder()->id(),
|
||||
m_multi_flow_segment_path_average_mm3_per_mm,
|
||||
acceleration_i,
|
||||
((path.role() == erBridgeInfill) ||(path.role() == erOverhangPerimeter)),
|
||||
role_change,
|
||||
isOverhangPerimeter);
|
||||
gcode += buf;
|
||||
} else if(_mm3_per_mm >0 ){ // Triggered when extruding a single segment path (like a line).
|
||||
// Check if mm3_mm value is greater than zero as the wipe before external perimeter
|
||||
// is a zero mm3_mm path to force de-retraction to happen and we dont want
|
||||
// to issue a zero flow PA change command for this
|
||||
sprintf(buf, ";%sT%u MM3MM:%g ACCEL:%u BR:%d RC:%d OV:%d\n",
|
||||
GCodeProcessor::reserved_tag(GCodeProcessor::ETags::PA_Change).c_str(),
|
||||
m_writer.extruder()->id(),
|
||||
_mm3_per_mm,
|
||||
acceleration_i,
|
||||
((path.role() == erBridgeInfill) ||(path.role() == erOverhangPerimeter)),
|
||||
role_change,
|
||||
isOverhangPerimeter);
|
||||
gcode += buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto overhang_fan_threshold = EXTRUDER_CONFIG(overhang_fan_threshold);
|
||||
auto enable_overhang_bridge_fan = EXTRUDER_CONFIG(enable_overhang_bridge_fan);
|
||||
|
@ -5305,6 +5440,54 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
|
||||
if (!variable_speed) {
|
||||
// F is mm per minute.
|
||||
if( (std::abs(writer().get_current_speed() - F) > EPSILON) || (std::abs(_mm3_per_mm - m_last_mm3_mm) > EPSILON) ){
|
||||
// ORCA: Adaptive PA code segment when adjusting PA within the same feature
|
||||
// There is a speed change coming out of an overhang region
|
||||
// or a flow change, so emit the flag to evaluate PA for the upcomming extrusion
|
||||
// Emit tag before new speed is set so the post processor reads the next speed immediately and uses it.
|
||||
// Dont emit tag if it has just already been emitted from a role change above
|
||||
if(_mm3_per_mm >0 &&
|
||||
EXTRUDER_CONFIG(adaptive_pressure_advance) &&
|
||||
EXTRUDER_CONFIG(enable_pressure_advance) &&
|
||||
EXTRUDER_CONFIG(adaptive_pressure_advance_overhangs) &&
|
||||
!evaluate_adaptive_pa){
|
||||
if(writer().get_current_speed() > F){ // Ramping down speed - use overhang logic where the minimum speed is used between current and upcoming extrusion
|
||||
if(m_config.gcode_comments){
|
||||
sprintf(buf, "; Ramp down-non-variable\n");
|
||||
gcode += buf;
|
||||
}
|
||||
sprintf(buf, ";%sT%u MM3MM:%g ACCEL:%u BR:%d RC:%d OV:%d\n",
|
||||
GCodeProcessor::reserved_tag(GCodeProcessor::ETags::PA_Change).c_str(),
|
||||
m_writer.extruder()->id(),
|
||||
_mm3_per_mm,
|
||||
acceleration_i,
|
||||
((path.role() == erBridgeInfill) ||(path.role() == erOverhangPerimeter)),
|
||||
1, // Force a dummy "role change" & "overhang perimeter" for the post processor, as, while technically it is not a role change,
|
||||
// the properties of the extrusion in the overhang are different so it behaves similarly to a role
|
||||
// change for the Adaptive PA post processor.
|
||||
1);
|
||||
}else{ // Ramping up speed - use baseline logic where max speed is used between current and upcoming extrusion
|
||||
if(m_config.gcode_comments){
|
||||
sprintf(buf, "; Ramp up-non-variable\n");
|
||||
gcode += buf;
|
||||
}
|
||||
sprintf(buf, ";%sT%u MM3MM:%g ACCEL:%u BR:%d RC:%d OV:%d\n",
|
||||
GCodeProcessor::reserved_tag(GCodeProcessor::ETags::PA_Change).c_str(),
|
||||
m_writer.extruder()->id(),
|
||||
_mm3_per_mm,
|
||||
acceleration_i,
|
||||
((path.role() == erBridgeInfill) ||(path.role() == erOverhangPerimeter)),
|
||||
1, // Force a dummy "role change" & "overhang perimeter" for the post processor, as, while technically it is not a role change,
|
||||
// the properties of the extrusion in the overhang are different so it is technically similar to a role
|
||||
// change for the Adaptive PA post processor.
|
||||
0);
|
||||
}
|
||||
gcode += buf;
|
||||
m_last_mm3_mm = _mm3_per_mm;
|
||||
}
|
||||
// ORCA: End of adaptive PA code segment
|
||||
}
|
||||
|
||||
gcode += m_writer.set_speed(F, "", comment);
|
||||
{
|
||||
if (m_enable_cooling_markers) {
|
||||
|
@ -5499,6 +5682,52 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
continue;
|
||||
path_length += line_length;
|
||||
double new_speed = pre_processed_point.speed * 60.0;
|
||||
|
||||
if ((std::abs(last_set_speed - new_speed) > EPSILON) || (std::abs(_mm3_per_mm - m_last_mm3_mm) > EPSILON)) {
|
||||
// ORCA: Adaptive PA code segment when adjusting PA within the same feature
|
||||
// There is a speed change or flow change so emit the flag to evaluate PA for the upcomming extrusion
|
||||
// Emit tag before new speed is set so the post processor reads the next speed immediately and uses it.
|
||||
if(_mm3_per_mm >0 &&
|
||||
EXTRUDER_CONFIG(adaptive_pressure_advance) &&
|
||||
EXTRUDER_CONFIG(enable_pressure_advance) &&
|
||||
EXTRUDER_CONFIG(adaptive_pressure_advance_overhangs) ){
|
||||
if(last_set_speed > new_speed){ // Ramping down speed - use overhang logic where the minimum speed is used between current and upcoming extrusion
|
||||
if(m_config.gcode_comments) {
|
||||
sprintf(buf, "; Ramp up-variable\n");
|
||||
gcode += buf;
|
||||
}
|
||||
sprintf(buf, ";%sT%u MM3MM:%g ACCEL:%u BR:%d RC:%d OV:%d\n",
|
||||
GCodeProcessor::reserved_tag(GCodeProcessor::ETags::PA_Change).c_str(),
|
||||
m_writer.extruder()->id(),
|
||||
_mm3_per_mm,
|
||||
acceleration_i,
|
||||
((path.role() == erBridgeInfill) ||(path.role() == erOverhangPerimeter)),
|
||||
1, // Force a dummy "role change" & "overhang perimeter" for the post processor, as, while technically it is not a role change,
|
||||
// the properties of the extrusion in the overhang are different so it is technically similar to a role
|
||||
// change for the Adaptive PA post processor.
|
||||
1);
|
||||
}else{ // Ramping up speed - use baseline logic where max speed is used between current and upcoming extrusion
|
||||
if(m_config.gcode_comments) {
|
||||
sprintf(buf, "; Ramp down-variable\n");
|
||||
gcode += buf;
|
||||
}
|
||||
sprintf(buf, ";%sT%u MM3MM:%g ACCEL:%u BR:%d RC:%d OV:%d\n",
|
||||
GCodeProcessor::reserved_tag(GCodeProcessor::ETags::PA_Change).c_str(),
|
||||
m_writer.extruder()->id(),
|
||||
_mm3_per_mm,
|
||||
acceleration_i,
|
||||
((path.role() == erBridgeInfill) ||(path.role() == erOverhangPerimeter)),
|
||||
1, // Force a dummy "role change" & "overhang perimeter" for the post processor, as, while technically it is not a role change,
|
||||
// the properties of the extrusion in the overhang are different so it is technically similar to a role
|
||||
// change for the Adaptive PA post processor.
|
||||
0);
|
||||
}
|
||||
gcode += buf;
|
||||
m_last_mm3_mm = _mm3_per_mm;
|
||||
}
|
||||
}// ORCA: End of adaptive PA code segment
|
||||
|
||||
|
||||
if (last_set_speed != new_speed) {
|
||||
gcode += m_writer.set_speed(new_speed, "", comment);
|
||||
last_set_speed = new_speed;
|
||||
|
@ -5807,7 +6036,6 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp
|
|||
for (int i = 0; i < m_config.z_hop.size(); i++)
|
||||
max_z_hop = std::max(max_z_hop, (float)m_config.z_hop.get_at(i));
|
||||
float travel_len_thresh = scale_(max_z_hop / tan(this->writer().extruder()->travel_slope()));
|
||||
float accum_len = 0.f;
|
||||
Polyline clipped_travel;
|
||||
|
||||
clipped_travel.append(Polyline(travel.points[0], travel.points[1]));
|
||||
|
@ -5909,7 +6137,6 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
|
|||
}
|
||||
|
||||
if (needs_lift && can_lift) {
|
||||
size_t extruder_id = m_writer.extruder()->id();
|
||||
gcode += m_writer.lift(!m_spiral_vase ? lift_type : LiftType::NormalLift);
|
||||
}
|
||||
|
||||
|
@ -5944,6 +6171,9 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z, bool b
|
|||
}
|
||||
if (m_config.enable_pressure_advance.get_at(extruder_id)) {
|
||||
gcode += m_writer.set_pressure_advance(m_config.pressure_advance.get_at(extruder_id));
|
||||
// Orca: Adaptive PA
|
||||
// Reset Adaptive PA processor last PA value
|
||||
m_pa_processor->resetPreviousPA(m_config.pressure_advance.get_at(extruder_id));
|
||||
}
|
||||
|
||||
gcode += m_writer.toolchange(extruder_id);
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include "GCode/PressureEqualizer.hpp"
|
||||
#include "GCode/SmallAreaInfillFlowCompensator.hpp"
|
||||
// ORCA: post processor below used for Dynamic Pressure advance
|
||||
#include "GCode/AdaptivePAProcessor.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
@ -357,6 +359,19 @@ private:
|
|||
std::string extrude_loop(ExtrusionLoop loop, std::string description, double speed = -1., const ExtrusionEntitiesPtr& region_perimeters = ExtrusionEntitiesPtr());
|
||||
std::string extrude_multi_path(ExtrusionMultiPath multipath, std::string description = "", double speed = -1.);
|
||||
std::string extrude_path(ExtrusionPath path, std::string description = "", double speed = -1.);
|
||||
|
||||
// Orca: Adaptive PA variables
|
||||
// Used for adaptive PA when extruding paths with multiple, varying flow segments.
|
||||
// This contains the sum of the mm3_per_mm values weighted by the length of each path segment.
|
||||
// The m_multi_flow_segment_path_pa_set constrains the PA change request to the first extrusion segment.
|
||||
// It sets the mm3_mm value for the adaptive PA post processor to be the average of that path
|
||||
// as calculated and stored in the m_multi_segment_path_average_mm3_per_mm value
|
||||
double m_multi_flow_segment_path_average_mm3_per_mm = 0;
|
||||
bool m_multi_flow_segment_path_pa_set = false;
|
||||
// Adaptive PA last set flow to enable issuing of PA change commands when adaptive PA for overhangs
|
||||
// is enabled
|
||||
double m_last_mm3_mm = 0;
|
||||
// Orca: Adaptive PA code segment end
|
||||
|
||||
// Extruding multiple objects with soluble / non-soluble / combined supports
|
||||
// on a multi-material printer, trying to minimize tool switches.
|
||||
|
@ -539,11 +554,13 @@ private:
|
|||
std::unique_ptr<SpiralVase> m_spiral_vase;
|
||||
|
||||
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
|
||||
|
||||
std::unique_ptr<AdaptivePAProcessor> m_pa_processor;
|
||||
|
||||
std::unique_ptr<WipeTowerIntegration> m_wipe_tower;
|
||||
|
||||
std::unique_ptr<SmallAreaInfillFlowCompensator> m_small_area_infill_flow_compensator;
|
||||
|
||||
|
||||
// Heights (print_z) at which the skirt has already been extruded.
|
||||
std::vector<coordf_t> m_skirt_done;
|
||||
// Has the brim been extruded already? Brim is being extruded only for the first object of a multi-object print.
|
||||
|
|
114
src/libslic3r/GCode/AdaptivePAInterpolator.cpp
Normal file
114
src/libslic3r/GCode/AdaptivePAInterpolator.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
// AdaptivePAInterpolator.cpp
|
||||
// OrcaSlicer
|
||||
//
|
||||
// Implementation file for the AdaptivePAInterpolator class, providing methods to parse data and perform PA interpolation.
|
||||
|
||||
#include "AdaptivePAInterpolator.hpp"
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
/**
|
||||
* @brief Parses the input data and sets up the interpolators.
|
||||
* @param data A string containing the data in CSV format (PA, flow rate, acceleration).
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int AdaptivePAInterpolator::parseAndSetData(const std::string& data) {
|
||||
flow_interpolators_.clear();
|
||||
accelerations_.clear();
|
||||
|
||||
try {
|
||||
std::istringstream ss(data);
|
||||
std::string line;
|
||||
std::map<double, std::vector<std::pair<double, double>>> acc_to_flow_pa;
|
||||
|
||||
while (std::getline(ss, line)) {
|
||||
std::istringstream lineStream(line);
|
||||
std::string value;
|
||||
double paValue, flowRate, acceleration;
|
||||
paValue = flowRate = acceleration = 0.f; // initialize all to zero.
|
||||
|
||||
// Parse PA value
|
||||
if (std::getline(lineStream, value, ',')) {
|
||||
paValue = std::stod(value);
|
||||
}
|
||||
|
||||
// Parse flow rate value
|
||||
if (std::getline(lineStream, value, ',')) {
|
||||
flowRate = std::stod(value);
|
||||
}
|
||||
|
||||
// Parse acceleration value
|
||||
if (std::getline(lineStream, value, ',')) {
|
||||
acceleration = std::stod(value);
|
||||
}
|
||||
|
||||
// Store the parsed values in a map with acceleration as the key
|
||||
acc_to_flow_pa[acceleration].emplace_back(flowRate, paValue);
|
||||
}
|
||||
|
||||
// Iterate through the map to set up the interpolators
|
||||
for (const auto& kv : acc_to_flow_pa) {
|
||||
double acceleration = kv.first;
|
||||
const auto& data = kv.second;
|
||||
|
||||
std::vector<double> flowRates;
|
||||
std::vector<double> paValues;
|
||||
|
||||
for (const auto& pair : data) {
|
||||
flowRates.push_back(pair.first);
|
||||
paValues.push_back(pair.second);
|
||||
}
|
||||
|
||||
// Only set up the interpolator if there are enough data points
|
||||
if (flowRates.size() > 1) {
|
||||
PchipInterpolatorHelper interpolator(flowRates, paValues);
|
||||
flow_interpolators_[acceleration] = interpolator;
|
||||
accelerations_.push_back(acceleration);
|
||||
}
|
||||
}
|
||||
} catch (const std::exception&) {
|
||||
m_isInitialised = false;
|
||||
return -1; // Error: Exception during parsing
|
||||
}
|
||||
m_isInitialised = true;
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Interpolates the PA value for the given flow rate and acceleration.
|
||||
* @param flow_rate The flow rate at which to interpolate.
|
||||
* @param acceleration The acceleration at which to interpolate.
|
||||
* @return The interpolated PA value, or -1 if interpolation fails.
|
||||
*/
|
||||
double AdaptivePAInterpolator::operator()(double flow_rate, double acceleration) {
|
||||
std::vector<double> pa_values;
|
||||
std::vector<double> acc_values;
|
||||
|
||||
// Estimate PA value for every flow to PA model for the given flow rate
|
||||
for (const auto& kv : flow_interpolators_) {
|
||||
double pa_value = kv.second.interpolate(flow_rate);
|
||||
|
||||
// Check if the interpolated PA value is valid
|
||||
if (pa_value != -1) {
|
||||
pa_values.push_back(pa_value);
|
||||
acc_values.push_back(kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are enough acceleration values for interpolation
|
||||
if (acc_values.size() < 2) {
|
||||
// Special case: Only one acceleration value
|
||||
if (acc_values.size() == 1) {
|
||||
return std::round(pa_values[0] * 1000.0) / 1000.0; // Rounded to 3 decimal places
|
||||
}
|
||||
return -1; // Error: Not enough data points for interpolation
|
||||
}
|
||||
|
||||
// Create a new PchipInterpolatorHelper for PA-acceleration interpolation
|
||||
// Use the estimated PA values from the for loop above and their corresponding accelerations to
|
||||
// generate the new PCHIP model. Then run this model to interpolate the PA value for the given acceleration value.
|
||||
PchipInterpolatorHelper pa_accel_interpolator(acc_values, pa_values);
|
||||
return std::round(pa_accel_interpolator.interpolate(acceleration) * 1000.0) / 1000.0; // Rounded to 3 decimal places
|
||||
}
|
54
src/libslic3r/GCode/AdaptivePAInterpolator.hpp
Normal file
54
src/libslic3r/GCode/AdaptivePAInterpolator.hpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
// AdaptivePAInterpolator.hpp
|
||||
// OrcaSlicer
|
||||
//
|
||||
// Header file for the AdaptivePAInterpolator class, responsible for interpolating pressure advance (PA) values based on flow rate and acceleration using PCHIP interpolation.
|
||||
|
||||
#ifndef ADAPTIVEPAINTERPOLATOR_HPP
|
||||
#define ADAPTIVEPAINTERPOLATOR_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "PchipInterpolatorHelper.hpp"
|
||||
|
||||
/**
|
||||
* @class AdaptivePAInterpolator
|
||||
* @brief A class to interpolate pressure advance (PA) values based on flow rate and acceleration using Piecewise Cubic Hermite Interpolating Polynomial (PCHIP) interpolation.
|
||||
*/
|
||||
class AdaptivePAInterpolator {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
AdaptivePAInterpolator() : m_isInitialised(false) {}
|
||||
|
||||
/**
|
||||
* @brief Parses the input data and sets up the interpolators.
|
||||
* @param data A string containing the data in CSV format (PA, flow rate, acceleration).
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int parseAndSetData(const std::string& data);
|
||||
|
||||
/**
|
||||
* @brief Interpolates the PA value for the given flow rate and acceleration.
|
||||
* @param flow_rate The flow rate at which to interpolate.
|
||||
* @param acceleration The acceleration at which to interpolate.
|
||||
* @return The interpolated PA value, or -1 if interpolation fails.
|
||||
*/
|
||||
double operator()(double flow_rate, double acceleration);
|
||||
|
||||
/**
|
||||
* @brief Returns the initialization status.
|
||||
* @return The value of m_isInitialised.
|
||||
*/
|
||||
bool isInitialised() const {
|
||||
return m_isInitialised;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<double, PchipInterpolatorHelper> flow_interpolators_; ///< Map each acceleration to a flow-rate-to-PA interpolator.
|
||||
std::vector<double> accelerations_; ///< Store unique accelerations.
|
||||
bool m_isInitialised;
|
||||
};
|
||||
|
||||
#endif // ADAPTIVEPAINTERPOLATOR_HPP
|
285
src/libslic3r/GCode/AdaptivePAProcessor.cpp
Normal file
285
src/libslic3r/GCode/AdaptivePAProcessor.cpp
Normal file
|
@ -0,0 +1,285 @@
|
|||
// AdaptivePAProcessor.cpp
|
||||
// OrcaSlicer
|
||||
//
|
||||
// Implementation of the AdaptivePAProcessor class, responsible for processing G-code layers with adaptive pressure advance.
|
||||
|
||||
#include "../GCode.hpp"
|
||||
#include "AdaptivePAProcessor.hpp"
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
/**
|
||||
* @brief Constructor for AdaptivePAProcessor.
|
||||
*
|
||||
* This constructor initializes the AdaptivePAProcessor with a reference to a GCode object.
|
||||
* It also initializes the configuration reference, pressure advance interpolation object,
|
||||
* and regular expression patterns used for processing the G-code.
|
||||
*
|
||||
* @param gcodegen A reference to the GCode object that generates the G-code.
|
||||
*/
|
||||
AdaptivePAProcessor::AdaptivePAProcessor(GCode &gcodegen, const std::vector<unsigned int> &tools_used)
|
||||
: m_gcodegen(gcodegen),
|
||||
m_config(gcodegen.config()),
|
||||
m_last_predicted_pa(0.0),
|
||||
m_max_next_feedrate(0.0),
|
||||
m_next_feedrate(0.0),
|
||||
m_current_feedrate(0.0),
|
||||
m_last_extruder_id(-1),
|
||||
m_pa_change_pattern(R"(; PA_CHANGE:T(\d+) MM3MM:([0-9]*\.[0-9]+) ACCEL:(\d+) BR:(\d+) RC:(\d+) OV:(\d+))"),
|
||||
m_g1_f_pattern(R"(G1 F([0-9]+))")
|
||||
{
|
||||
// Constructor body can be used for further initialization if necessary
|
||||
for (unsigned int tool : tools_used) {
|
||||
// Only enable model for the tool if both PA and adaptive PA options are enabled
|
||||
if(m_config.adaptive_pressure_advance.get_at(tool) && m_config.enable_pressure_advance.get_at(tool)){
|
||||
auto interpolator = std::make_unique<AdaptivePAInterpolator>();
|
||||
// Get calibration values from extruder
|
||||
std::string pa_calibration_values = m_config.adaptive_pressure_advance_model.get_at(tool);
|
||||
// Setup the model and store it in the tool-interpolation model map
|
||||
interpolator->parseAndSetData(pa_calibration_values);
|
||||
m_AdaptivePAInterpolators[tool] = std::move(interpolator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method to get the interpolator for a specific tool ID
|
||||
AdaptivePAInterpolator* AdaptivePAProcessor::getInterpolator(unsigned int tool_id) {
|
||||
auto it = m_AdaptivePAInterpolators.find(tool_id);
|
||||
if (it != m_AdaptivePAInterpolators.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
return nullptr; // Handle the case where the tool_id is not found
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Processes a layer of G-code and applies adaptive pressure advance.
|
||||
*
|
||||
* This method processes the G-code for a single layer, identifying the appropriate
|
||||
* pressure advance settings and applying them based on the current state and configurations.
|
||||
*
|
||||
* @param gcode A string containing the G-code for the layer.
|
||||
* @return A string containing the processed G-code with adaptive pressure advance applied.
|
||||
*/
|
||||
std::string AdaptivePAProcessor::process_layer(std::string &&gcode) {
|
||||
std::istringstream stream(gcode);
|
||||
std::string line;
|
||||
std::ostringstream output;
|
||||
double mm3mm_value = 0.0;
|
||||
unsigned int accel_value = 0;
|
||||
std::string pa_change_line;
|
||||
bool wipe_command = false;
|
||||
|
||||
// Iterate through each line of the layer G-code
|
||||
while (std::getline(stream, line)) {
|
||||
|
||||
// If a wipe start command is found, ignore all speed changes till the wipe end part is found
|
||||
if (line.find("WIPE_START") != std::string::npos) {
|
||||
wipe_command = true;
|
||||
}
|
||||
|
||||
// Update current feed rate (this is preceding an extrude or wipe command only). Ignore any speed changes that are emitted during a wipe move.
|
||||
// Travel feedrate is output as part of a G1 X Y (Z) F command
|
||||
if ( (line.find("G1 F") == 0) && (!wipe_command) ) { // prune lines quickly before running pattern matching
|
||||
std::size_t pos = line.find('F');
|
||||
if (pos != std::string::npos){
|
||||
m_current_feedrate = std::stod(line.substr(pos + 1)) / 60.0; // Convert from mm/min to mm/s
|
||||
}
|
||||
}
|
||||
|
||||
// Wipe end found, continue searching for current feed rate.
|
||||
if (line.find("WIPE_END") != std::string::npos) {
|
||||
wipe_command = false;
|
||||
}
|
||||
|
||||
// Reset next feedrate to zero enable searching for the first encountered
|
||||
// feedrate change command after the PA change tag.
|
||||
m_next_feedrate = 0;
|
||||
|
||||
// Check for PA_CHANGE pattern in the line
|
||||
// We will only find this pattern for extruders where adaptive PA is enabled.
|
||||
// If there is mixed extruders in the layer (i.e. with adaptive PA on and off
|
||||
// this will only update the extruders where the adaptive PA is enabled
|
||||
// as these are the only ones where the PA pattern is output
|
||||
// For a mixed extruder layer with both adaptive PA enabled and disabled when the new tool is selected
|
||||
// the PA for that material is set. As no tag below will be found for this extruder, the original PA is retained.
|
||||
if (line.find("; PA_CHANGE") == 0) { // prune lines quickly before running regex check as regex is more expensive to run
|
||||
if (std::regex_search(line, m_match, m_pa_change_pattern)) {
|
||||
int extruder_id = std::stoi(m_match[1].str());
|
||||
mm3mm_value = std::stod(m_match[2].str());
|
||||
accel_value = std::stod(m_match[3].str());
|
||||
int isBridge = std::stoi(m_match[4].str());
|
||||
int roleChange = std::stoi(m_match[5].str());
|
||||
int isOverhang = std::stoi(m_match[6].str());
|
||||
|
||||
// Check if the extruder ID has changed
|
||||
bool extruder_changed = (extruder_id != m_last_extruder_id);
|
||||
m_last_extruder_id = extruder_id;
|
||||
|
||||
// Save the PA_CHANGE line to output later after finding feedrate
|
||||
pa_change_line = line;
|
||||
|
||||
// Look ahead for feedrate before any line containing both G and E commands
|
||||
std::streampos current_pos = stream.tellg();
|
||||
std::string next_line;
|
||||
double temp_feed_rate = 0;
|
||||
bool extrude_move_found = false;
|
||||
int line_counter = 0;
|
||||
|
||||
// Carry on searching on the layer gcode lines to find the print speed
|
||||
// If a G1 Fxxxx pattern is found, the new speed is identified
|
||||
// Carry on searching for feedrates to find the maximum print speed
|
||||
// until a feature change pattern or a wipe command is detected
|
||||
while (std::getline(stream, next_line)) {
|
||||
line_counter++;
|
||||
// Found an extrude move, set extrude move found flag and move to the next line
|
||||
if ((!extrude_move_found) && next_line.find("G1 ") == 0 &&
|
||||
next_line.find('X') != std::string::npos &&
|
||||
next_line.find('Y') != std::string::npos &&
|
||||
next_line.find('E') != std::string::npos) {
|
||||
// Pattern matched, break the loop
|
||||
extrude_move_found = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found a travel move after we've found at least one extrude move
|
||||
// We now need to stop searching for speeds as we're done printing this island
|
||||
if (next_line.find("G1 ") == 0 &&
|
||||
next_line.find('X') != std::string::npos && // X is present
|
||||
next_line.find('Y') != std::string::npos && // Y is present
|
||||
next_line.find('E') == std::string::npos && // no "E" present
|
||||
extrude_move_found) { // An extrude move has happened already
|
||||
// First travel move after extrude move found. Stop searching
|
||||
break;
|
||||
}
|
||||
|
||||
// Found a WIPE command
|
||||
// If we have a wipe command, usually the wipe speed is different (larger) than the max print speed
|
||||
// for that feature. So stop searching if a wipe command is found because we do not want to overwrite the
|
||||
// speed used for PA calculation by the Wipe speed.
|
||||
if (next_line.find("WIPE") != std::string::npos) {
|
||||
break; // Stop searching if wipe command is found
|
||||
}
|
||||
|
||||
// Found another PA_CHANGE pattern
|
||||
// If RC = 1, it means we have a role change, so stop trying to find the max speed for the feature.
|
||||
// This is possibly redundant as a new feature would always have a travel move preceding it
|
||||
// but check anyway. However check last so to not invoke it without reason...
|
||||
if (next_line.find("; PA_CHANGE") == 0) { // prune lines quickly before running pattern matching
|
||||
std::size_t rc_pos = next_line.rfind("RC:");
|
||||
if (rc_pos != std::string::npos) {
|
||||
int rc_value = std::stoi(next_line.substr(rc_pos + 3));
|
||||
if (rc_value == 1) {
|
||||
break; // Role change found, stop searching
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Found a Feedrate change command
|
||||
// If the new feedrate is greater than any feedrate encountered so far after the PA change command, use that to calculate the PA value
|
||||
// Also if this is the first feedrate we encounter, store it as the next feedrate.
|
||||
if (next_line.find("G1 F") == 0) { // prune lines quickly before running pattern matching
|
||||
std::size_t pos = next_line.find('F');
|
||||
if (pos != std::string::npos) {
|
||||
double feedrate = std::stod(next_line.substr(pos + 1)) / 60.0; // Convert from mm/min to mm/s
|
||||
if(line_counter==1){ // this is the first command after the PA change pattern, and hence before any extrusion has happened. Reset
|
||||
// the current speed to this one
|
||||
m_current_feedrate = feedrate;
|
||||
}
|
||||
if (temp_feed_rate < feedrate) {
|
||||
temp_feed_rate = feedrate;
|
||||
}
|
||||
if(m_next_feedrate < EPSILON){ // This the first feedrate found after the PA Change command
|
||||
m_next_feedrate = feedrate;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If we found a new maximum feedrate after the PA change command, use it
|
||||
if (temp_feed_rate > 0) {
|
||||
m_max_next_feedrate = temp_feed_rate;
|
||||
} else // If we didnt find a new feedrate at all after the PA change command, use the current feedrate.
|
||||
m_max_next_feedrate = m_current_feedrate;
|
||||
|
||||
// Restore stream position
|
||||
stream.clear();
|
||||
stream.seekg(current_pos);
|
||||
|
||||
// Calculate the predicted PA using the upcomming feature maximum feedrate
|
||||
// Get the interpolator for the active tool
|
||||
AdaptivePAInterpolator* interpolator = getInterpolator(m_last_extruder_id);
|
||||
|
||||
double predicted_pa = 0;
|
||||
double adaptive_PA_speed = 0;
|
||||
|
||||
if(!interpolator){ // Tool not found in the interpolator map
|
||||
// Tool not found in the PA interpolator to tool map
|
||||
predicted_pa = m_config.enable_pressure_advance.get_at(m_last_extruder_id) ? m_config.pressure_advance.get_at(m_last_extruder_id) : 0;
|
||||
if(m_config.gcode_comments) output << "; APA: Tool doesnt have APA enabled\n";
|
||||
} else if (!interpolator->isInitialised() || (!m_config.adaptive_pressure_advance.get_at(m_last_extruder_id)) )
|
||||
// Check if the model is not initialised by the constructor for the active extruder
|
||||
// Also check that adaptive PA is enabled for that extruder. This should not be needed
|
||||
// as the PA change flag should not be set upstream (in the GCode.cpp file) if adaptive PA is disabled
|
||||
// however check for robustness sake.
|
||||
{
|
||||
// Model failed or adaptive pressure advance not enabled - use default value from m_config
|
||||
predicted_pa = m_config.enable_pressure_advance.get_at(m_last_extruder_id) ? m_config.pressure_advance.get_at(m_last_extruder_id) : 0;
|
||||
if(m_config.gcode_comments) output << "; APA: Interpolator setup failed, using default pressure advance\n";
|
||||
} else { // Model setup succeeded
|
||||
// Proceed to identify the print speed to use to calculate the adaptive PA value
|
||||
if(isOverhang > 0){ // If we are in an overhang area, use the minimum between current print speed
|
||||
// and any speed immediately after
|
||||
// In most cases the current speed is the minimum one;
|
||||
// however if slowdown for layer cooling is enabled, the overhang
|
||||
// may be slowed down more than the current speed.
|
||||
adaptive_PA_speed = (m_current_feedrate == 0 || m_next_feedrate == 0) ?
|
||||
std::max(m_current_feedrate, m_next_feedrate) :
|
||||
std::min(m_current_feedrate, m_next_feedrate);
|
||||
}else{ // If this is not an overhang area, use the maximum speed from the current and
|
||||
// upcomming speeds for the island.
|
||||
adaptive_PA_speed = std::max(m_max_next_feedrate,m_current_feedrate);
|
||||
}
|
||||
|
||||
// Calculate the adaptive PA value
|
||||
predicted_pa = (*interpolator)(mm3mm_value * adaptive_PA_speed, accel_value);
|
||||
|
||||
// This is a bridge, use the dedicated PA setting.
|
||||
if(isBridge && m_config.adaptive_pressure_advance_bridges.get_at(m_last_extruder_id) > EPSILON)
|
||||
predicted_pa = m_config.adaptive_pressure_advance_bridges.get_at(m_last_extruder_id);
|
||||
|
||||
if (predicted_pa < 0) { // If extrapolation fails, fall back to the default PA for the extruder.
|
||||
predicted_pa = m_config.enable_pressure_advance.get_at(m_last_extruder_id) ? m_config.pressure_advance.get_at(m_last_extruder_id) : 0;
|
||||
if(m_config.gcode_comments) output << "; APA: Interpolation failed, using fallback pressure advance value\n";
|
||||
}
|
||||
}
|
||||
if(m_config.gcode_comments) {
|
||||
// Output debug GCode comments
|
||||
output << pa_change_line << '\n'; // Output PA change command tag
|
||||
if(isBridge && m_config.adaptive_pressure_advance_bridges.get_at(m_last_extruder_id) > EPSILON)
|
||||
output << "; APA Model Override (bridge)\n";
|
||||
output << "; APA Current Speed: " << std::to_string(m_current_feedrate) << "\n";
|
||||
output << "; APA Next Speed: " << std::to_string(m_next_feedrate) << "\n";
|
||||
output << "; APA Max Next Speed: " << std::to_string(m_max_next_feedrate) << "\n";
|
||||
output << "; APA Speed Used: " << std::to_string(adaptive_PA_speed) << "\n";
|
||||
output << "; APA Flow rate: " << std::to_string(mm3mm_value * m_max_next_feedrate) << "\n";
|
||||
output << "; APA Prev PA: " << std::to_string(m_last_predicted_pa) << " New PA: " << std::to_string(predicted_pa) << "\n";
|
||||
}
|
||||
if (extruder_changed || std::fabs(predicted_pa - m_last_predicted_pa) > EPSILON) {
|
||||
output << m_gcodegen.writer().set_pressure_advance(predicted_pa); // Use m_writer to set pressure advance
|
||||
m_last_predicted_pa = predicted_pa; // Update the last predicted PA value
|
||||
}
|
||||
}
|
||||
}else {
|
||||
// Output the current line as this isn't a PA change tag
|
||||
output << line << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
85
src/libslic3r/GCode/AdaptivePAProcessor.hpp
Normal file
85
src/libslic3r/GCode/AdaptivePAProcessor.hpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
// AdaptivePAProcessor.hpp
|
||||
// OrcaSlicer
|
||||
//
|
||||
// Header file for the AdaptivePAProcessor class, responsible for processing G-code layers for the purposes of applying adaptive pressure advance.
|
||||
|
||||
#ifndef ADAPTIVEPAPROCESSOR_H
|
||||
#define ADAPTIVEPAPROCESSOR_H
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "AdaptivePAInterpolator.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Forward declaration of GCode class
|
||||
class GCode;
|
||||
|
||||
/**
|
||||
* @brief Class for processing G-code layers with adaptive pressure advance.
|
||||
*/
|
||||
class AdaptivePAProcessor {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for AdaptivePAProcessor.
|
||||
*
|
||||
* This constructor initializes the AdaptivePAProcessor with a reference to a GCode object.
|
||||
* It also initializes the configuration reference, pressure advance interpolation object,
|
||||
* and regular expression patterns used for processing the G-code.
|
||||
*
|
||||
* @param gcodegen A reference to the GCode object that generates the G-code.
|
||||
*/
|
||||
AdaptivePAProcessor(GCode &gcodegen, const std::vector<unsigned int> &tools_used);
|
||||
|
||||
/**
|
||||
* @brief Processes a layer of G-code and applies adaptive pressure advance.
|
||||
*
|
||||
* This method processes the G-code for a single layer, identifying the appropriate
|
||||
* pressure advance settings and applying them based on the current state and configurations.
|
||||
*
|
||||
* @param gcode A string containing the G-code for the layer.
|
||||
* @return A string containing the processed G-code with adaptive pressure advance applied.
|
||||
*/
|
||||
std::string process_layer(std::string &&gcode);
|
||||
|
||||
/**
|
||||
* @brief Manually sets adaptive PA internal value.
|
||||
*
|
||||
* This method manually sets the adaptive PA internally held value.
|
||||
* Call this when changing tools or in any other case where the internally assumed last PA value may be incorrect
|
||||
*/
|
||||
void resetPreviousPA(double PA){ m_last_predicted_pa = PA; };
|
||||
|
||||
private:
|
||||
GCode &m_gcodegen; ///< Reference to the GCode object.
|
||||
std::unordered_map<unsigned int, std::unique_ptr<AdaptivePAInterpolator>> m_AdaptivePAInterpolators; ///< Map between Interpolator objects and tool ID's
|
||||
const PrintConfig &m_config; ///< Reference to the print configuration.
|
||||
double m_last_predicted_pa; ///< Last predicted pressure advance value.
|
||||
double m_max_next_feedrate; ///< Maximum feed rate (speed) for the upcomming island. If no speed is found, the previous island speed is used.
|
||||
double m_next_feedrate; ///< First feed rate (speed) for the upcomming island.
|
||||
double m_current_feedrate; ///< Current, latest feedrate.
|
||||
int m_last_extruder_id; ///< Last used extruder ID.
|
||||
|
||||
std::regex m_pa_change_pattern; ///< Regular expression to detect PA_CHANGE pattern.
|
||||
std::regex m_g1_f_pattern; ///< Regular expression to detect G1 F pattern.
|
||||
std::smatch m_match; ///< Match results for regular expressions.
|
||||
|
||||
/**
|
||||
* @brief Get the PA interpolator attached to the specified tool ID.
|
||||
*
|
||||
* This method manually sets the adaptive PA internally held value.
|
||||
* Call this when changing tools or in any other case where the internally assumed last PA value may be incorrect
|
||||
*
|
||||
* @param An integer with the tool ID for which the PA interpolation model is to be returned.
|
||||
* @return The Adaptive PA Interpolator object corresponding to that tool.
|
||||
*/
|
||||
AdaptivePAInterpolator* getInterpolator(unsigned int tool_id);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // ADAPTIVEPAPROCESSOR_H
|
|
@ -28,7 +28,6 @@ inline Grids line_rasterization(const Line &line, int64_t xdist = scale_(1), int
|
|||
Point rayStart = line.a;
|
||||
Point rayEnd = line.b;
|
||||
IndexPair currentVoxel = point_map_grid_index(rayStart, xdist, ydist);
|
||||
IndexPair firstVoxel = currentVoxel;
|
||||
IndexPair lastVoxel = point_map_grid_index(rayEnd, xdist, ydist);
|
||||
|
||||
Point ray = rayEnd - rayStart;
|
||||
|
|
|
@ -70,7 +70,8 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
|
|||
" MANUAL_TOOL_CHANGE ",
|
||||
"_DURING_PRINT_EXHAUST_FAN",
|
||||
" WIPE_TOWER_START",
|
||||
" WIPE_TOWER_END"
|
||||
" WIPE_TOWER_END",
|
||||
" PA_CHANGE:"
|
||||
};
|
||||
|
||||
const std::vector<std::string> GCodeProcessor::Reserved_Tags_compatible = {
|
||||
|
@ -90,7 +91,8 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags_compatible = {
|
|||
" MANUAL_TOOL_CHANGE ",
|
||||
"_DURING_PRINT_EXHAUST_FAN",
|
||||
" WIPE_TOWER_START",
|
||||
" WIPE_TOWER_END"
|
||||
" WIPE_TOWER_END",
|
||||
" PA_CHANGE:"
|
||||
};
|
||||
|
||||
|
||||
|
@ -695,7 +697,9 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
|
|||
if (!disable_m73 && !processed &&!is_temporary_decoration(gcode_line) &&
|
||||
(GCodeReader::GCodeLine::cmd_is(gcode_line, "G1") ||
|
||||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G2") ||
|
||||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G3"))) {
|
||||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G3") ||
|
||||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G10")||
|
||||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G11"))) {
|
||||
// remove temporary lines, add lines M73 where needed
|
||||
unsigned int extra_lines_count = process_line_move(g1_lines_counter ++);
|
||||
if (extra_lines_count > 0)
|
||||
|
@ -3477,7 +3481,6 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
|||
arc_length = ((int)line.p()) * 2 * PI * (start_point - m_arc_center).norm();
|
||||
//BBS: Attention! arc_onterpolation does not support P mode while P is not 1.
|
||||
arc_interpolation(start_point, end_point, m_arc_center, (m_move_path_type == EMovePathType::Arc_move_ccw));
|
||||
float radian = ArcSegment::calc_arc_radian(start_point, end_point, m_arc_center, (m_move_path_type == EMovePathType::Arc_move_ccw));
|
||||
Vec3f start_dir = Circle::calc_tangential_vector(start_point, m_arc_center, (m_move_path_type == EMovePathType::Arc_move_ccw));
|
||||
Vec3f end_dir = Circle::calc_tangential_vector(end_point, m_arc_center, (m_move_path_type == EMovePathType::Arc_move_ccw));
|
||||
|
||||
|
@ -3838,14 +3841,18 @@ void GCodeProcessor::process_G29(const GCodeReader::GCodeLine& line)
|
|||
|
||||
void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
// stores retract move
|
||||
store_move_vertex(EMoveType::Retract);
|
||||
GCodeReader::GCodeLine g10;
|
||||
g10.set(Axis::E, -this->m_parser.config().retraction_length.get_at(m_extruder_id));
|
||||
g10.set(Axis::F, this->m_parser.config().retraction_speed.get_at(m_extruder_id) * 60);
|
||||
process_G1(g10);
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_G11(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
// stores unretract move
|
||||
store_move_vertex(EMoveType::Unretract);
|
||||
GCodeReader::GCodeLine g11;
|
||||
g11.set(Axis::E, this->m_parser.config().retraction_length.get_at(m_extruder_id) + this->m_parser.config().retract_restart_extra.get_at(m_extruder_id));
|
||||
g11.set(Axis::F, this->m_parser.config().deretraction_speed.get_at(m_extruder_id) * 60);
|
||||
process_G1(g11);
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_G20(const GCodeReader::GCodeLine& line)
|
||||
|
|
|
@ -294,6 +294,7 @@ class Print;
|
|||
During_Print_Exhaust_Fan,
|
||||
Wipe_Tower_Start,
|
||||
Wipe_Tower_End,
|
||||
PA_Change,
|
||||
};
|
||||
|
||||
static const std::string& reserved_tag(ETags tag) { return s_IsBBLPrinter ? Reserved_Tags[static_cast<unsigned char>(tag)] : Reserved_Tags_compatible[static_cast<unsigned char>(tag)]; }
|
||||
|
|
100
src/libslic3r/GCode/PchipInterpolatorHelper.cpp
Normal file
100
src/libslic3r/GCode/PchipInterpolatorHelper.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
// PchipInterpolatorHelper.cpp
|
||||
// OrcaSlicer
|
||||
//
|
||||
// Implementation file for the PchipInterpolatorHelper class
|
||||
|
||||
#include "PchipInterpolatorHelper.hpp"
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* @brief Constructs the PCHIP interpolator with given data points.
|
||||
* @param x The x-coordinates of the data points.
|
||||
* @param y The y-coordinates of the data points.
|
||||
*/
|
||||
PchipInterpolatorHelper::PchipInterpolatorHelper(const std::vector<double>& x, const std::vector<double>& y) {
|
||||
setData(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the data points for the interpolator.
|
||||
* @param x The x-coordinates of the data points.
|
||||
* @param y The y-coordinates of the data points.
|
||||
* @throw std::invalid_argument if x and y have different sizes or if they contain fewer than two points.
|
||||
*/
|
||||
void PchipInterpolatorHelper::setData(const std::vector<double>& x, const std::vector<double>& y) {
|
||||
if (x.size() != y.size() || x.size() < 2) {
|
||||
throw std::invalid_argument("Input vectors must have the same size and contain at least two points.");
|
||||
}
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
sortData();
|
||||
computePCHIP();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sorts the data points by x-coordinate.
|
||||
*/
|
||||
void PchipInterpolatorHelper::sortData() {
|
||||
std::vector<std::pair<double, double>> data;
|
||||
for (size_t i = 0; i < x_.size(); ++i) {
|
||||
data.emplace_back(x_[i], y_[i]);
|
||||
}
|
||||
std::sort(data.begin(), data.end());
|
||||
|
||||
for (size_t i = 0; i < data.size(); ++i) {
|
||||
x_[i] = data[i].first;
|
||||
y_[i] = data[i].second;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Computes the PCHIP coefficients.
|
||||
*/
|
||||
void PchipInterpolatorHelper::computePCHIP() {
|
||||
size_t n = x_.size() - 1;
|
||||
h_.resize(n);
|
||||
delta_.resize(n);
|
||||
d_.resize(n+1);
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
h_[i] = h(i);
|
||||
delta_[i] = delta(i);
|
||||
}
|
||||
|
||||
d_[0] = delta_[0];
|
||||
d_[n] = delta_[n-1];
|
||||
for (size_t i = 1; i < n; ++i) {
|
||||
if (delta_[i-1] * delta_[i] > 0) {
|
||||
double w1 = 2 * h_[i] + h_[i-1];
|
||||
double w2 = h_[i] + 2 * h_[i-1];
|
||||
d_[i] = (w1 + w2) / (w1 / delta_[i-1] + w2 / delta_[i]);
|
||||
} else {
|
||||
d_[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Interpolates the value at a given point.
|
||||
*/
|
||||
double PchipInterpolatorHelper::interpolate(double xi) const {
|
||||
if (xi <= x_.front()) return y_.front();
|
||||
if (xi >= x_.back()) return y_.back();
|
||||
|
||||
auto it = std::lower_bound(x_.begin(), x_.end(), xi);
|
||||
size_t i = std::distance(x_.begin(), it) - 1;
|
||||
|
||||
double h_i = h_[i];
|
||||
double t = (xi - x_[i]) / h_i;
|
||||
double t2 = t * t;
|
||||
double t3 = t2 * t;
|
||||
|
||||
double h00 = 2 * t3 - 3 * t2 + 1;
|
||||
double h10 = t3 - 2 * t2 + t;
|
||||
double h01 = -2 * t3 + 3 * t2;
|
||||
double h11 = t3 - t2;
|
||||
|
||||
return h00 * y_[i] + h10 * h_i * d_[i] + h01 * y_[i+1] + h11 * h_i * d_[i+1];
|
||||
}
|
76
src/libslic3r/GCode/PchipInterpolatorHelper.hpp
Normal file
76
src/libslic3r/GCode/PchipInterpolatorHelper.hpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
// PchipInterpolatorHelper.hpp
|
||||
// OrcaSlicer
|
||||
//
|
||||
// Header file for the PchipInterpolatorHelper class, responsible for performing Piecewise Cubic Hermite Interpolating Polynomial (PCHIP) interpolation on given data points.
|
||||
|
||||
#ifndef PCHIPINTERPOLATORHELPER_HPP
|
||||
#define PCHIPINTERPOLATORHELPER_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @class PchipInterpolatorHelper
|
||||
* @brief A helper class to perform Piecewise Cubic Hermite Interpolating Polynomial (PCHIP) interpolation.
|
||||
*/
|
||||
class PchipInterpolatorHelper {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
PchipInterpolatorHelper() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructs the PCHIP interpolator with given data points.
|
||||
* @param x The x-coordinates of the data points.
|
||||
* @param y The y-coordinates of the data points.
|
||||
*/
|
||||
PchipInterpolatorHelper(const std::vector<double>& x, const std::vector<double>& y);
|
||||
|
||||
/**
|
||||
* @brief Sets the data points for the interpolator.
|
||||
* @param x The x-coordinates of the data points.
|
||||
* @param y The y-coordinates of the data points.
|
||||
* @throw std::invalid_argument if x and y have different sizes or if they contain fewer than two points.
|
||||
*/
|
||||
void setData(const std::vector<double>& x, const std::vector<double>& y);
|
||||
|
||||
/**
|
||||
* @brief Interpolates the value at a given point.
|
||||
* @param xi The x-coordinate at which to interpolate.
|
||||
* @return The interpolated y-coordinate.
|
||||
*/
|
||||
double interpolate(double xi) const;
|
||||
|
||||
private:
|
||||
std::vector<double> x_; ///< The x-coordinates of the data points.
|
||||
std::vector<double> y_; ///< The y-coordinates of the data points.
|
||||
std::vector<double> h_; ///< The differences between successive x-coordinates.
|
||||
std::vector<double> delta_; ///< The slopes of the segments between successive data points.
|
||||
std::vector<double> d_; ///< The derivatives at the data points.
|
||||
|
||||
/**
|
||||
* @brief Computes the PCHIP coefficients.
|
||||
*/
|
||||
void computePCHIP();
|
||||
|
||||
/**
|
||||
* @brief Sorts the data points by x-coordinate.
|
||||
*/
|
||||
void sortData();
|
||||
|
||||
/**
|
||||
* @brief Computes the difference between successive x-coordinates.
|
||||
* @param i The index of the x-coordinate.
|
||||
* @return The difference between x_[i+1] and x_[i].
|
||||
*/
|
||||
double h(int i) const { return x_[i+1] - x_[i]; }
|
||||
|
||||
/**
|
||||
* @brief Computes the slope of the segment between successive data points.
|
||||
* @param i The index of the segment.
|
||||
* @return The slope of the segment between y_[i] and y_[i+1].
|
||||
*/
|
||||
double delta(int i) const { return (y_[i+1] - y_[i]) / h(i); }
|
||||
};
|
||||
|
||||
#endif // PCHIPINTERPOLATORHELPER_HPP
|
|
@ -1,6 +1,4 @@
|
|||
#include "../ClipperUtils.hpp"
|
||||
#include "../Layer.hpp"
|
||||
#include "../Polyline.hpp"
|
||||
|
||||
#include "RetractWhenCrossingPerimeters.hpp"
|
||||
|
||||
|
|
|
@ -9,6 +9,14 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
#ifndef _WIN32
|
||||
// Currently on Linux/macOS, this class spits out large amounts of subobject linkage
|
||||
// warnings because of the flowModel field. tk::spline is in an anonymous namespace which
|
||||
// causes this issue. Until the issue can be solved, this is a temporary solution.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsubobject-linkage"
|
||||
#endif
|
||||
|
||||
class SmallAreaInfillFlowCompensator
|
||||
{
|
||||
public:
|
||||
|
@ -31,6 +39,10 @@ private:
|
|||
double max_modified_length() { return eLengths.back(); }
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_GCode_SmallAreaInfillFlowCompensator_hpp_ */
|
||||
|
|
|
@ -131,7 +131,7 @@ std::string SpiralVase::process_layer(const std::string &gcode, bool last_layer)
|
|||
if (line.has_z() && !line.retracting(reader)) {
|
||||
// If this is the initial Z move of the layer, replace it with a
|
||||
// (redundant) move to the last Z of previous layer.
|
||||
line.set(reader, Z, z);
|
||||
line.set(Z, z);
|
||||
new_gcode += line.raw() + '\n';
|
||||
return;
|
||||
} else {
|
||||
|
@ -142,17 +142,17 @@ std::string SpiralVase::process_layer(const std::string &gcode, bool last_layer)
|
|||
float factor = len / total_layer_length;
|
||||
if (transition_in)
|
||||
// Transition layer, interpolate the amount of extrusion from zero to the final value.
|
||||
line.set(reader, E, line.e() * factor, 5 /*decimal_digits*/);
|
||||
line.set(E, line.e() * factor, 5 /*decimal_digits*/);
|
||||
else if (transition_out) {
|
||||
// We want the last layer to ramp down extrusion, but without changing z height!
|
||||
// So clone the line before we mess with its Z and duplicate it into a new layer that ramps down E
|
||||
// We add this new layer at the very end
|
||||
GCodeReader::GCodeLine transitionLine(line);
|
||||
transitionLine.set(reader, E, line.e() * (1 - factor), 5 /*decimal_digits*/);
|
||||
transitionLine.set(E, line.e() * (1 - factor), 5 /*decimal_digits*/);
|
||||
transition_gcode += transitionLine.raw() + '\n';
|
||||
}
|
||||
// This line is the core of Spiral Vase mode, ramp up the Z smoothly
|
||||
line.set(reader, Z, z + factor * layer_height);
|
||||
line.set(Z, z + factor * layer_height);
|
||||
if (smooth_spiral) {
|
||||
// Now we also need to try to interpolate X and Y
|
||||
SpiralVase::SpiralPoint p(line.x(), line.y()); // Get current x/y coordinates
|
||||
|
@ -171,10 +171,10 @@ std::string SpiralVase::process_layer(const std::string &gcode, bool last_layer)
|
|||
if (modified_dist_XY < 0.001)
|
||||
line.clear();
|
||||
else {
|
||||
line.set(reader, X, target.x);
|
||||
line.set(reader, Y, target.y);
|
||||
line.set(X, target.x);
|
||||
line.set(Y, target.y);
|
||||
// Scale the extrusion amount according to change in length
|
||||
line.set(reader, E, line.e() * modified_dist_XY / dist_XY, 5 /*decimal_digits*/);
|
||||
line.set(E, line.e() * modified_dist_XY / dist_XY, 5 /*decimal_digits*/);
|
||||
last_point = target;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -307,7 +307,6 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
|||
std::vector<unsigned int> ToolOrdering::generate_first_layer_tool_order(const Print& print)
|
||||
{
|
||||
std::vector<unsigned int> tool_order;
|
||||
int initial_extruder_id = -1;
|
||||
std::map<int, double> min_areas_per_extruder;
|
||||
|
||||
for (auto object : print.objects()) {
|
||||
|
@ -336,7 +335,6 @@ std::vector<unsigned int> ToolOrdering::generate_first_layer_tool_order(const Pr
|
|||
}
|
||||
}
|
||||
|
||||
double max_minimal_area = 0.;
|
||||
for (auto ape : min_areas_per_extruder) {
|
||||
auto iter = tool_order.begin();
|
||||
for (; iter != tool_order.end(); iter++) {
|
||||
|
@ -369,7 +367,6 @@ std::vector<unsigned int> ToolOrdering::generate_first_layer_tool_order(const Pr
|
|||
std::vector<unsigned int> ToolOrdering::generate_first_layer_tool_order(const PrintObject& object)
|
||||
{
|
||||
std::vector<unsigned int> tool_order;
|
||||
int initial_extruder_id = -1;
|
||||
std::map<int, double> min_areas_per_extruder;
|
||||
auto first_layer = object.get_layer(0);
|
||||
for (auto layerm : first_layer->regions()) {
|
||||
|
@ -394,7 +391,6 @@ std::vector<unsigned int> ToolOrdering::generate_first_layer_tool_order(const Pr
|
|||
}
|
||||
}
|
||||
|
||||
double max_minimal_area = 0.;
|
||||
for (auto ape : min_areas_per_extruder) {
|
||||
auto iter = tool_order.begin();
|
||||
for (; iter != tool_order.end(); iter++) {
|
||||
|
|
|
@ -1072,8 +1072,6 @@ void WipeTower::toolchange_Wipe(
|
|||
const float target_speed = is_first_layer() ? std::min(m_first_layer_speed * 60.f, 4800.f) : 4800.f;
|
||||
float wipe_speed = 0.33f * target_speed;
|
||||
|
||||
float start_y = writer.y();
|
||||
|
||||
#if 0
|
||||
// if there is less than 2.5*m_perimeter_width to the edge, advance straightaway (there is likely a blob anyway)
|
||||
if ((m_left_to_right ? xr-writer.x() : writer.x()-xl) < 2.5f*m_perimeter_width) {
|
||||
|
@ -1132,8 +1130,6 @@ void WipeTower::toolchange_Wipe(
|
|||
m_left_to_right = !m_left_to_right;
|
||||
}
|
||||
|
||||
float end_y = writer.y();
|
||||
|
||||
// We may be going back to the model - wipe the nozzle. If this is followed
|
||||
// by finish_layer, this wipe path will be overwritten.
|
||||
//writer.add_wipe_point(writer.x(), writer.y())
|
||||
|
@ -1422,7 +1418,6 @@ void WipeTower::plan_tower()
|
|||
// If wipe tower height is between the current and next member, set the min_depth as linear interpolation between them
|
||||
auto next_height_to_depth = *iter;
|
||||
if (next_height_to_depth.first > m_wipe_tower_height) {
|
||||
float height_base = curr_height_to_depth.first;
|
||||
float height_diff = next_height_to_depth.first - curr_height_to_depth.first;
|
||||
float min_depth_base = curr_height_to_depth.second;
|
||||
float depth_diff = next_height_to_depth.second - curr_height_to_depth.second;
|
||||
|
|
|
@ -275,7 +275,7 @@ bool GCodeReader::GCodeLine::has_value(char axis, float &value) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void GCodeReader::GCodeLine::set(const GCodeReader &reader, const Axis axis, const float new_value, const int decimal_digits)
|
||||
void GCodeReader::GCodeLine::set(const Axis axis, const float new_value, const int decimal_digits)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << std::fixed << std::setprecision(decimal_digits) << new_value;
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
bool extruding(const GCodeReader &reader) const { return (this->cmd_is("G1") || this->cmd_is("G2") || this->cmd_is("G3")) && this->dist_E(reader) > 0; }
|
||||
bool retracting(const GCodeReader &reader) const { return (this->cmd_is("G1") || this->cmd_is("G2") || this->cmd_is("G3")) && this->dist_E(reader) < 0; }
|
||||
bool travel() const { return (this->cmd_is("G1") || this->cmd_is("G2") || this->cmd_is("G3")) && ! this->has(E); }
|
||||
void set(const GCodeReader &reader, const Axis axis, const float new_value, const int decimal_digits = 3);
|
||||
void set(const Axis axis, const float new_value, const int decimal_digits = 3);
|
||||
|
||||
bool has_x() const { return this->has(X); }
|
||||
bool has_y() const { return this->has(Y); }
|
||||
|
@ -103,6 +103,7 @@ public:
|
|||
void reset() { memset(m_position, 0, sizeof(m_position)); }
|
||||
void apply_config(const GCodeConfig &config);
|
||||
void apply_config(const DynamicPrintConfig &config);
|
||||
const GCodeConfig& config() { return m_config; };
|
||||
|
||||
template<typename Callback>
|
||||
void parse_buffer(const std::string &buffer, Callback callback)
|
||||
|
|
|
@ -4,21 +4,14 @@
|
|||
#include "ClipperUtils.hpp"
|
||||
#include "ExPolygon.hpp"
|
||||
#include "Line.hpp"
|
||||
#include "clipper.hpp"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#if defined(_MSC_VER) && defined(__clang__)
|
||||
#define BOOST_NO_CXX17_HDR_STRING_VIEW
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "Circle.hpp"
|
||||
|
||||
#include "../Polygon.hpp"
|
||||
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp"
|
||||
#include "libslic3r/Geometry/VoronoiUtils.hpp"
|
||||
#include "libslic3r/Geometry/VoronoiUtilsCgal.hpp"
|
||||
#include "libslic3r/MultiMaterialSegmentation.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include <boost/next_prior.hpp>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Surface_sweep_2_algorithms.h>
|
||||
|
|
|
@ -1,26 +1,18 @@
|
|||
#include "JumpPointSearch.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "ExPolygon.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "libslic3r/AStar.hpp"
|
||||
#include "libslic3r/KDTreeIndirect.hpp"
|
||||
#include "libslic3r/Polygon.hpp"
|
||||
#include "libslic3r/Polyline.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <oneapi/tbb/scalable_allocator.h>
|
||||
|
||||
//#define DEBUG_FILES
|
||||
#ifdef DEBUG_FILES
|
||||
#include "libslic3r/SVG.hpp"
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#include "Geometry.hpp"
|
||||
#include "Line.hpp"
|
||||
#include "Polyline.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
|
@ -330,7 +330,7 @@ void segment(CGALMesh& src, std::vector<CGALMesh>& dst, double smoothing_alpha =
|
|||
|
||||
// fill holes
|
||||
typedef boost::graph_traits<_EpicMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef boost::graph_traits<_EpicMesh>::vertex_descriptor vertex_descriptor;
|
||||
// typedef boost::graph_traits<_EpicMesh>::vertex_descriptor vertex_descriptor;
|
||||
std::vector<halfedge_descriptor> border_cycles;
|
||||
CGAL::Polygon_mesh_processing::extract_boundary_cycles(out, std::back_inserter(border_cycles));
|
||||
for (halfedge_descriptor h : border_cycles)
|
||||
|
@ -693,7 +693,7 @@ bool do_boolean_single(McutMesh &srcMesh, const McutMesh &cutMesh, const std::st
|
|||
McutMesh outMesh;
|
||||
int N_vertices = 0;
|
||||
// traversal of all connected components
|
||||
for (int n = 0; n < numConnComps; ++n) {
|
||||
for (unsigned int n = 0; n < numConnComps; ++n) {
|
||||
// query the data of each connected component from MCUT
|
||||
McConnectedComponent connComp = connectedComponents[n];
|
||||
|
||||
|
|
|
@ -442,7 +442,7 @@ ModelObject* Model::add_object(const ModelObject &other)
|
|||
this->objects.push_back(new_object);
|
||||
// BBS: backup
|
||||
if (need_backup) {
|
||||
if (auto model = other.get_model()) {
|
||||
if (other.get_model()) {
|
||||
auto iter = object_backup_id_map.find(other.id().id);
|
||||
if (iter != object_backup_id_map.end()) {
|
||||
object_backup_id_map.emplace(new_object->id().id, iter->second);
|
||||
|
@ -2615,7 +2615,7 @@ size_t ModelVolume::split(unsigned int max_extruders)
|
|||
size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin();
|
||||
const std::string name = this->name;
|
||||
|
||||
unsigned int extruder_counter = 0;
|
||||
// unsigned int extruder_counter = 0;
|
||||
const Vec3d offset = this->get_offset();
|
||||
|
||||
for (TriangleMesh &mesh : meshes) {
|
||||
|
@ -2930,9 +2930,6 @@ bool Model::obj_import_vertex_color_deal(const std::vector<unsigned char> &verte
|
|||
std::cout << "error";
|
||||
}
|
||||
};
|
||||
auto calc_tri_area = [](const Vec3f &v0, const Vec3f &v1, const Vec3f &v2) {
|
||||
return std::abs((v0 - v1).cross(v0 - v2).norm()) / 2;
|
||||
};
|
||||
auto volume = obj->volumes[0];
|
||||
volume->config.set("extruder", first_extruder_id);
|
||||
auto face_count = volume->mesh().its.indices.size();
|
||||
|
@ -3032,7 +3029,6 @@ bool Model::obj_import_face_color_deal(const std::vector<unsigned char> &face_fi
|
|||
volume->mmu_segmentation_facets.reserve(face_count);
|
||||
if (volume->mesh().its.indices.size() != face_filament_ids.size()) { return false; }
|
||||
for (size_t i = 0; i < volume->mesh().its.indices.size(); i++) {
|
||||
auto face = volume->mesh().its.indices[i];
|
||||
auto filament_id = face_filament_ids[i];
|
||||
if (filament_id <= 1) { continue; }
|
||||
std::string result;
|
||||
|
|
|
@ -167,7 +167,6 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::
|
|||
auto support_type_ptr = obj->get_config_value<ConfigOptionEnum<SupportType>>(config, "support_type");
|
||||
auto support_type = support_type_ptr->value;
|
||||
auto enable_support = supp_type_ptr->getBool();
|
||||
int support_int = support_type_ptr->getInt();
|
||||
|
||||
if (enable_support && (support_type == stNormalAuto || support_type == stNormal))
|
||||
ap.brim_width = 6.0;
|
||||
|
|
|
@ -338,7 +338,6 @@ static std::vector<std::vector<const MMU_Graph::Arc *>> get_all_next_arcs(
|
|||
|
||||
if (arc.type == MMU_Graph::ARC_TYPE::BORDER && arc.color != color) continue;
|
||||
|
||||
Vec2d arc_line = graph.nodes[arc.to_idx].point - graph.nodes[arc.from_idx].point;
|
||||
next_continue_arc.emplace_back(&arc);
|
||||
all_next_arcs.emplace_back(next_continue_arc);
|
||||
}
|
||||
|
@ -1286,7 +1285,6 @@ static void cut_segmented_layers(const std::vector<ExPolygons> &input_exp
|
|||
const std::function<void()> &throw_on_cancel_callback)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "MM segmentation - cutting segmented layers in parallel - begin";
|
||||
const float interlocking_cut_width = interlocking_depth > 0.f ? std::max(cut_width - interlocking_depth, 0.f) : 0.f;
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()),
|
||||
[&segmented_regions, &input_expolygons, &cut_width, &interlocking_depth, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
||||
|
|
|
@ -138,8 +138,6 @@ public:
|
|||
|
||||
auto cost_items = get_features(orientation, params.min_volume);
|
||||
|
||||
float unprintability = target_function(cost_items, params.min_volume);
|
||||
|
||||
results[orientation] = cost_items;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << std::fixed << std::setprecision(4) << "orientation:" << orientation.transpose() << ", cost:" << std::fixed << std::setprecision(4) << cost_items.field_values();
|
||||
|
@ -230,10 +228,10 @@ public:
|
|||
{
|
||||
std::unordered_map<stl_normal, float, VecHash> alignments;
|
||||
// init to 0
|
||||
for (size_t i = 0; i < areas_.size(); i++)
|
||||
for (Eigen::Index i = 0; i < areas_.size(); i++)
|
||||
alignments.insert(std::pair(normals_.row(i), 0));
|
||||
// cumulate areas
|
||||
for (size_t i = 0; i < areas_.size(); i++)
|
||||
for (Eigen::Index i = 0; i < areas_.size(); i++)
|
||||
{
|
||||
alignments[normals_.row(i)] += areas_(i);
|
||||
}
|
||||
|
@ -257,11 +255,11 @@ public:
|
|||
Vec3f n1 = { 0, 0, 0 };
|
||||
std::vector<float> current_areas = {0, 0};
|
||||
// init to 0
|
||||
for (size_t i = 0; i < areas_.size(); i++) {
|
||||
for (Eigen::Index i = 0; i < areas_.size(); i++) {
|
||||
alignments_.insert(std::pair(quantize_normals_.row(i), std::pair(current_areas, n1)));
|
||||
}
|
||||
// cumulate areas
|
||||
for (size_t i = 0; i < areas_.size(); i++)
|
||||
for (Eigen::Index i = 0; i < areas_.size(); i++)
|
||||
{
|
||||
alignments_[quantize_normals_.row(i)].first[1] += areas_(i);
|
||||
if (areas_(i) > alignments_[quantize_normals_.row(i)].first[0]){
|
||||
|
@ -339,7 +337,7 @@ public:
|
|||
|
||||
z_max_hull.resize(mesh_convex_hull.facets_count(), 1);
|
||||
its = mesh_convex_hull.its;
|
||||
for (size_t i = 0; i < z_max_hull.rows(); i++)
|
||||
for (Eigen::Index i = 0; i < z_max_hull.rows(); i++)
|
||||
{
|
||||
float z0 = its.get_vertex(i,0).dot(orientation);
|
||||
float z1 = its.get_vertex(i,1).dot(orientation);
|
||||
|
@ -393,7 +391,7 @@ public:
|
|||
|
||||
// filter overhang
|
||||
Eigen::VectorXf normal_projection(normals.rows(), 1);// = this->normals.dot(orientation);
|
||||
for (size_t i = 0; i < normals.rows(); i++)
|
||||
for (Eigen::Index i = 0; i < normals.rows(); i++)
|
||||
{
|
||||
normal_projection(i) = normals.row(i).dot(orientation);
|
||||
}
|
||||
|
@ -459,7 +457,6 @@ public:
|
|||
cost = params.TAR_A * (overhang + params.TAR_B) + params.RELATIVE_F * (/*costs.volume/100*/overhang*params.TAR_C + params.TAR_D + params.TAR_LAF * costs.area_laf * params.use_low_angle_face) / (params.TAR_D + params.CONTOUR_F * costs.contour + params.BOTTOM_F * bottom + params.BOTTOM_HULL_F * bottom_hull + params.TAR_E * overhang + params.TAR_PROJ_AREA * costs.area_projected);
|
||||
}
|
||||
else {
|
||||
float overhang = costs.overhang;
|
||||
cost = params.RELATIVE_F * (costs.overhang * params.TAR_C + params.TAR_D + params.TAR_LAF * costs.area_laf * params.use_low_angle_face) / (params.TAR_D + params.CONTOUR_F * costs.contour + params.BOTTOM_F * bottom + params.BOTTOM_HULL_F * bottom_hull + params.TAR_PROJ_AREA * costs.area_projected);
|
||||
}
|
||||
cost += (costs.bottom < params.BOTTOM_MIN) * 100;// +(costs.height_to_bottom_hull_ratio > params.height_to_bottom_hull_ratio_MIN) * 110;
|
||||
|
|
|
@ -242,12 +242,10 @@ static std::deque<PolylineWithDegree> split_polyline_by_degree(const Polyline &p
|
|||
Polyline right;
|
||||
Polyline temp_copy = polyline_with_insert_points;
|
||||
|
||||
size_t poly_size = polyline_with_insert_points.size();
|
||||
// BBS: merge degree in limited range
|
||||
//find first degee base
|
||||
double degree_base = int(points_overhang[points_overhang.size() - 1] / min_degree_gap) * min_degree_gap + min_degree_gap;
|
||||
degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base;
|
||||
double short_poly_len = 0;
|
||||
for (int point_idx = points_overhang.size() - 2; point_idx > 0; --point_idx) {
|
||||
|
||||
double degree = points_overhang[point_idx];
|
||||
|
@ -940,7 +938,6 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
|
|||
|
||||
if (perimeter_generator.config->overhang_speed_classic && perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None) {
|
||||
|
||||
Flow flow = is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow;
|
||||
std::map<double, std::vector<Polygons>> clipper_serise;
|
||||
|
||||
std::map<double,ExtrusionPaths> recognization_paths;
|
||||
|
@ -2253,7 +2250,6 @@ void PerimeterGenerator::process_no_bridge(Surfaces& all_surfaces, coord_t perim
|
|||
if (!unsupported.empty()) {
|
||||
//only consider the part that can be bridged (really, by the bridge algorithm)
|
||||
//first, separate into islands (ie, each ExPlolygon)
|
||||
int numploy = 0;
|
||||
//only consider the bottom layer that intersect unsupported, to be sure it's only on our island.
|
||||
ExPolygonCollection lower_island(support);
|
||||
//a detector per island
|
||||
|
@ -2371,7 +2367,6 @@ void PerimeterGenerator::process_no_bridge(Surfaces& all_surfaces, coord_t perim
|
|||
//ExPolygons no_bridge = diff_ex(offset_ex(unbridgeable, ext_perimeter_width * 3 / 2), last);
|
||||
//bridges_temp = diff_ex(bridges_temp, no_bridge);
|
||||
coordf_t offset_to_do = bridged_infill_margin;
|
||||
bool first = true;
|
||||
unbridgeable = diff_ex(unbridgeable, offset_ex(bridges_temp, ext_perimeter_width));
|
||||
while (offset_to_do > ext_perimeter_width * 1.5) {
|
||||
unbridgeable = offset2_ex(unbridgeable, -ext_perimeter_width / 4, ext_perimeter_width * 2.25, ClipperLib::jtSquare);
|
||||
|
@ -2379,7 +2374,6 @@ void PerimeterGenerator::process_no_bridge(Surfaces& all_surfaces, coord_t perim
|
|||
bridges_temp = offset_ex(bridges_temp, ext_perimeter_width, ClipperLib::jtMiter, 6.);
|
||||
unbridgeable = diff_ex(unbridgeable, offset_ex(bridges_temp, ext_perimeter_width));
|
||||
offset_to_do -= ext_perimeter_width;
|
||||
first = false;
|
||||
}
|
||||
unbridgeable = offset_ex(unbridgeable, ext_perimeter_width + offset_to_do, ClipperLib::jtSquare);
|
||||
bridges_temp = diff_ex(bridges_temp, unbridgeable);
|
||||
|
|
|
@ -355,8 +355,6 @@ Polygon Polygon::transform(const Transform3d& trafo) const
|
|||
if (vertices_count == 0)
|
||||
return dstpoly;
|
||||
|
||||
unsigned int data_size = 3 * vertices_count * sizeof(float);
|
||||
|
||||
Eigen::MatrixXd src(3, vertices_count);
|
||||
for (size_t i = 0; i < vertices_count; i++)
|
||||
{
|
||||
|
|
|
@ -51,7 +51,6 @@ void Polyline::reverse()
|
|||
// removes the given distance from the end of the polyline
|
||||
void Polyline::clip_end(double distance)
|
||||
{
|
||||
bool last_point_inserted = false;
|
||||
size_t remove_after_index = MultiPoint::size();
|
||||
while (distance > 0) {
|
||||
Vec2d last_point = this->last_point().cast<double>();
|
||||
|
@ -65,7 +64,6 @@ void Polyline::clip_end(double distance)
|
|||
double lsqr = v.squaredNorm();
|
||||
if (lsqr > distance * distance) {
|
||||
this->points.emplace_back((last_point + v * (distance / sqrt(lsqr))).cast<coord_t>());
|
||||
last_point_inserted = true;
|
||||
break;
|
||||
}
|
||||
distance -= sqrt(lsqr);
|
||||
|
|
|
@ -840,7 +840,7 @@ static std::vector<std::string> s_Preset_filament_options {
|
|||
"filament_wipe_distance", "additional_cooling_fan_speed",
|
||||
"nozzle_temperature_range_low", "nozzle_temperature_range_high",
|
||||
//SoftFever
|
||||
"enable_pressure_advance", "pressure_advance","chamber_temperature", "filament_shrink", "support_material_interface_fan_speed", "filament_notes" /*,"filament_seam_gap"*/,
|
||||
"enable_pressure_advance", "pressure_advance","adaptive_pressure_advance","adaptive_pressure_advance_model","adaptive_pressure_advance_overhangs", "adaptive_pressure_advance_bridges","chamber_temperature", "filament_shrink", "support_material_interface_fan_speed", "filament_notes" /*,"filament_seam_gap"*/,
|
||||
"filament_loading_speed", "filament_loading_speed_start", "filament_load_time",
|
||||
"filament_unloading_speed", "filament_unloading_speed_start", "filament_unload_time", "filament_toolchange_delay", "filament_cooling_moves", "filament_stamping_loading_speed", "filament_stamping_distance",
|
||||
"filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters",
|
||||
|
@ -1572,7 +1572,6 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
// Store the loaded presets into a new vector, otherwise the binary search for already existing presets would be broken.
|
||||
// (see the "Preset already present, not loading" message).
|
||||
//std::deque<Preset> presets_loaded;
|
||||
int count = 0;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, name %1% , total value counts %2%")%name %preset_values.size();
|
||||
|
||||
|
|
|
@ -1853,7 +1853,7 @@ void PresetBundle::export_selections(AppConfig &config)
|
|||
// BBS
|
||||
void PresetBundle::set_num_filaments(unsigned int n, std::string new_color)
|
||||
{
|
||||
int old_filament_count = this->filament_presets.size();
|
||||
size_t old_filament_count = this->filament_presets.size();
|
||||
if (n > old_filament_count && old_filament_count != 0)
|
||||
filament_presets.resize(n, filament_presets.back());
|
||||
else {
|
||||
|
@ -1867,7 +1867,7 @@ void PresetBundle::set_num_filaments(unsigned int n, std::string new_color)
|
|||
//BBS set new filament color to new_color
|
||||
if (old_filament_count < n) {
|
||||
if (!new_color.empty()) {
|
||||
for (int i = old_filament_count; i < n; i++) {
|
||||
for (size_t i = old_filament_count; i < n; i++) {
|
||||
filament_color->values[i] = new_color;
|
||||
}
|
||||
}
|
||||
|
@ -2054,7 +2054,7 @@ bool PresetBundle::check_filament_temp_equation_by_printer_type_and_nozzle_for_m
|
|||
//BBS: check whether this is the only edited filament
|
||||
bool PresetBundle::is_the_only_edited_filament(unsigned int filament_index)
|
||||
{
|
||||
int n = this->filament_presets.size();
|
||||
size_t n = this->filament_presets.size();
|
||||
if (filament_index >= n)
|
||||
return false;
|
||||
|
||||
|
@ -2117,7 +2117,6 @@ DynamicPrintConfig PresetBundle::full_fff_config() const
|
|||
|
||||
// BBS
|
||||
size_t num_filaments = this->filament_presets.size();
|
||||
auto* extruder_diameter = dynamic_cast<const ConfigOptionFloats*>(out.option("nozzle_diameter"));
|
||||
// Collect the "compatible_printers_condition" and "inherits" values over all presets (print, filaments, printers) into a single vector.
|
||||
std::vector<std::string> compatible_printers_condition;
|
||||
std::vector<std::string> compatible_prints_condition;
|
||||
|
@ -2472,7 +2471,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
std::vector<std::string> filament_ids = std::move(config.option<ConfigOptionStrings>("filament_ids", true)->values);
|
||||
std::vector<std::string> print_compatible_printers = std::move(config.option<ConfigOptionStrings>("print_compatible_printers", true)->values);
|
||||
//BBS: add different settings check logic
|
||||
bool has_different_settings_to_system = config.option("different_settings_to_system")?true:false;
|
||||
// bool has_different_settings_to_system = config.option("different_settings_to_system")?true:false;
|
||||
std::vector<std::string> different_values = std::move(config.option<ConfigOptionStrings>("different_settings_to_system", true)->values);
|
||||
std::string &compatible_printers_condition = Preset::compatible_printers_condition(config);
|
||||
std::string &compatible_prints_condition = Preset::compatible_prints_condition(config);
|
||||
|
|
|
@ -832,7 +832,6 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
|
|||
|
||||
for (int i = k+1; i < print_instance_count; i++)
|
||||
{
|
||||
auto& p = print_instance_with_bounding_box[i].print_instance;
|
||||
auto bbox2 = print_instance_with_bounding_box[i].bounding_box;
|
||||
auto py1 = bbox2.min.y();
|
||||
auto py2 = bbox2.max.y();
|
||||
|
@ -1403,32 +1402,30 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
|||
const ConfigOptionDef* bed_type_def = print_config_def.get("curr_bed_type");
|
||||
assert(bed_type_def != nullptr);
|
||||
|
||||
if (is_BBL_printer()) {
|
||||
if (is_BBL_printer()) {
|
||||
const t_config_enum_values* bed_type_keys_map = bed_type_def->enum_keys_map;
|
||||
const ConfigOptionInts* bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
|
||||
for (unsigned int extruder_id : extruders) {
|
||||
const ConfigOptionInts* bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
|
||||
for (unsigned int extruder_id : extruders) {
|
||||
int curr_bed_temp = bed_temp_opt->get_at(extruder_id);
|
||||
if (curr_bed_temp == 0 && bed_type_keys_map != nullptr) {
|
||||
std::string bed_type_name;
|
||||
for (auto item : *bed_type_keys_map) {
|
||||
if (item.second == m_config.curr_bed_type) {
|
||||
bed_type_name = item.first;
|
||||
break;
|
||||
}
|
||||
int curr_bed_temp = bed_temp_opt->get_at(extruder_id);
|
||||
if (curr_bed_temp == 0 && bed_type_keys_map != nullptr) {
|
||||
std::string bed_type_name;
|
||||
for (auto item : *bed_type_keys_map) {
|
||||
if (item.second == m_config.curr_bed_type) {
|
||||
bed_type_name = item.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
StringObjectException except;
|
||||
except.string = Slic3r::format(L("Plate %d: %s does not support filament %s"), this->get_plate_index() + 1, L(bed_type_name), extruder_id + 1);
|
||||
except.string += "\n";
|
||||
except.type = STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE;
|
||||
except.params.push_back(std::to_string(this->get_plate_index() + 1));
|
||||
except.params.push_back(L(bed_type_name));
|
||||
except.params.push_back(std::to_string(extruder_id+1));
|
||||
except.object = nullptr;
|
||||
return except;
|
||||
}
|
||||
}
|
||||
StringObjectException except;
|
||||
except.string = Slic3r::format(L("Plate %d: %s does not support filament %s"), this->get_plate_index() + 1, L(bed_type_name), extruder_id + 1);
|
||||
except.string += "\n";
|
||||
except.type = STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE;
|
||||
except.params.push_back(std::to_string(this->get_plate_index() + 1));
|
||||
except.params.push_back(L(bed_type_name));
|
||||
except.params.push_back(std::to_string(extruder_id+1));
|
||||
except.object = nullptr;
|
||||
return except;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1445,7 +1442,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
|||
}
|
||||
return warning_key;
|
||||
};
|
||||
auto check_motion_ability_region_setting = [&](const std::vector<std::string>& keys_to_check, double limit) -> std::string {
|
||||
/* auto check_motion_ability_region_setting = [&](const std::vector<std::string>& keys_to_check, double limit) -> std::string {
|
||||
std::string warning_key;
|
||||
for (const auto& key : keys_to_check) {
|
||||
if (m_default_region_config.get_abs_value(key) > limit) {
|
||||
|
@ -1454,7 +1451,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
|||
}
|
||||
}
|
||||
return warning_key;
|
||||
};
|
||||
}; */
|
||||
std::string warning_key;
|
||||
|
||||
// check jerk
|
||||
|
@ -2047,7 +2044,6 @@ void Print::process(long long *time_cost_with_cache, bool use_cache)
|
|||
//BBS: get the objects' indices when GCodes are generated
|
||||
ToolOrdering tool_ordering;
|
||||
unsigned int initial_extruder_id = (unsigned int)-1;
|
||||
unsigned int final_extruder_id = (unsigned int)-1;
|
||||
bool has_wipe_tower = false;
|
||||
std::vector<const PrintInstance*> print_object_instances_ordering;
|
||||
std::vector<const PrintInstance*>::const_iterator print_object_instance_sequential_active;
|
||||
|
@ -2661,7 +2657,7 @@ void Print::_make_wipe_tower()
|
|||
for (auto &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers
|
||||
if (!layer_tools.has_wipe_tower)
|
||||
continue;
|
||||
bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
|
||||
// bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
|
||||
wipe_tower.plan_toolchange((float) layer_tools.print_z, (float) layer_tools.wipe_tower_layer_height, current_extruder_id,
|
||||
current_extruder_id);
|
||||
|
||||
|
|
|
@ -1681,6 +1681,60 @@ void PrintConfigDef::init_fff_params()
|
|||
def->max = 2;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0.02 });
|
||||
|
||||
// Orca: Adaptive pressure advance option and calibration values
|
||||
def = this->add("adaptive_pressure_advance", coBools);
|
||||
def->label = L("Enable adaptive pressure advance (beta)");
|
||||
def->tooltip = L("With increasing print speeds (and hence increasing volumetric flow through the nozzle) and increasing accelerations, "
|
||||
"it has been observed that the effective PA value typically decreases. "
|
||||
"This means that a single PA value is not always 100% optimal for all features and a compromise value is usually used "
|
||||
"that does not cause too much bulging on features with lower flow speed and accelerations while also not causing gaps on faster features.\n\n"
|
||||
"This feature aims to address this limitation by modeling the response of your printer's extrusion system depending "
|
||||
"on the volumetric flow speed and acceleration it is printing at. Internally, it generates a fitted model that can extrapolate the needed pressure "
|
||||
"advance for any given volumetric flow speed and acceleration, which is then emmited to the printer depending on the current print conditions.\n\n"
|
||||
"When enabled, the pressure advance value above is overriden. However, a reasonable default value above is "
|
||||
"strongly recomended to act as a fallback and for when tool changing.\n\n");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBools{ false });
|
||||
|
||||
// Orca: Adaptive pressure advance option and calibration values
|
||||
def = this->add("adaptive_pressure_advance_model", coStrings);
|
||||
def->label = L("Adaptive pressure advance measurements (beta)");
|
||||
def->tooltip = L("Add sets of pressure advance (PA) values, the volumetric flow speeds and accelerations they were measured at, separated by a comma. "
|
||||
"One set of values per line. For example\n"
|
||||
"0.04,3.96,3000\n0.033,3.96,10000\n0.029,7.91,3000\n0.026,7.91,10000\n\n"
|
||||
"How to calibrate:\n"
|
||||
"1. Run the pressure advance test for at least 3 speeds per acceleration value. It is recommended that the test is run "
|
||||
"for at least the speed of the external perimeters, the speed of the internal perimeters and the fastest feature "
|
||||
"print speed in your profile (usually its the sparse or solid infill). Then run them for the same speeds for the slowest and fastest print accelerations,"
|
||||
"and no faster than the recommended maximum acceleration as given by the klipper input shaper.\n"
|
||||
"2. Take note of the optimal PA value for each volumetric flow speed and acceleration. You can find the flow number by selecting "
|
||||
"flow from the color scheme drop down and move the horizontal slider over the PA pattern lines. The number should be visible "
|
||||
"at the bottom of the page. The ideal PA value should be decreasing the higher the volumetric flow is. If it is not, confirm that your extruder is functioning correctly."
|
||||
"The slower and with less acceleration you print, the larger the range of acceptable PA values. If no difference is visible, use the PA value from the faster test."
|
||||
"3. Enter the triplets of PA values, Flow and Accelerations in the text box here and save your filament profile\n\n"
|
||||
"");
|
||||
def->mode = comAdvanced;
|
||||
//def->gui_flags = "serialized";
|
||||
def->multiline = true;
|
||||
def->full_width = true;
|
||||
def->height = 15;
|
||||
def->set_default_value(new ConfigOptionStrings{"0,0,0\n0,0,0"});
|
||||
|
||||
def = this->add("adaptive_pressure_advance_overhangs", coBools);
|
||||
def->label = L("Enable adaptive pressure advance for overhangs (beta)");
|
||||
def->tooltip = L("Enable adaptive PA for overhangs as well as when flow changes within the same feature. This is an experimental option, "
|
||||
"as if the PA profile is not set accurately, it will cause uniformity issues on the external surfaces before and after overhangs.\n");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBools{ false });
|
||||
|
||||
def = this->add("adaptive_pressure_advance_bridges", coFloats);
|
||||
def->label = L("Pressure advance for bridges");
|
||||
def->tooltip = L("Pressure advance value for bridges. Set to 0 to disable. \n\n A lower PA value when printing bridges helps reduce the appearance of slight under extrusion "
|
||||
"immediately after bridges. This is caused by the pressure drop in the nozzle when printing in the air and a lower PA helps counteract this.");
|
||||
def->max = 2;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0.0 });
|
||||
|
||||
def = this->add("line_width", coFloatOrPercent);
|
||||
def->label = L("Default");
|
||||
|
|
|
@ -1031,6 +1031,12 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloats, filament_flow_ratio))
|
||||
((ConfigOptionBools, enable_pressure_advance))
|
||||
((ConfigOptionFloats, pressure_advance))
|
||||
// Orca: adaptive pressure advance and calibration model
|
||||
((ConfigOptionBools, adaptive_pressure_advance))
|
||||
((ConfigOptionBools, adaptive_pressure_advance_overhangs))
|
||||
((ConfigOptionStrings, adaptive_pressure_advance_model))
|
||||
((ConfigOptionFloats, adaptive_pressure_advance_bridges))
|
||||
//
|
||||
((ConfigOptionFloat, fan_kickstart))
|
||||
((ConfigOptionBool, fan_speedup_overhangs))
|
||||
((ConfigOptionFloat, fan_speedup_time))
|
||||
|
|
|
@ -677,7 +677,6 @@ void PrintObject::estimate_curled_extrusions()
|
|||
[](const PrintRegion *region) { return region->config().enable_overhang_speed.getBool(); })) {
|
||||
|
||||
// Estimate curling of support material and add it to the malformaition lines of each layer
|
||||
float support_flow_width = support_material_flow(this, this->config().layer_height).width();
|
||||
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values,
|
||||
float(this->print()->default_object_config().inner_wall_acceleration.getFloat()),
|
||||
this->config().raft_layers.getInt(), this->config().brim_type.value,
|
||||
|
@ -2949,16 +2948,16 @@ struct POProfiler
|
|||
|
||||
void PrintObject::generate_support_preview()
|
||||
{
|
||||
POProfiler profiler;
|
||||
// POProfiler profiler;
|
||||
|
||||
boost::posix_time::ptime ts1 = boost::posix_time::microsec_clock::local_time();
|
||||
// boost::posix_time::ptime ts1 = boost::posix_time::microsec_clock::local_time();
|
||||
this->slice();
|
||||
boost::posix_time::ptime ts2 = boost::posix_time::microsec_clock::local_time();
|
||||
profiler.duration1 = (ts2 - ts1).total_milliseconds();
|
||||
// boost::posix_time::ptime ts2 = boost::posix_time::microsec_clock::local_time();
|
||||
// profiler.duration1 = (ts2 - ts1).total_milliseconds();
|
||||
|
||||
this->generate_support_material();
|
||||
boost::posix_time::ptime ts3 = boost::posix_time::microsec_clock::local_time();
|
||||
profiler.duration2 = (ts3 - ts2).total_milliseconds();
|
||||
// boost::posix_time::ptime ts3 = boost::posix_time::microsec_clock::local_time();
|
||||
// profiler.duration2 = (ts3 - ts2).total_milliseconds();
|
||||
}
|
||||
|
||||
void PrintObject::update_slicing_parameters()
|
||||
|
@ -3668,7 +3667,6 @@ template void PrintObject::remove_bridges_from_contacts<Polygons>(
|
|||
|
||||
SupportNecessaryType PrintObject::is_support_necessary()
|
||||
{
|
||||
static const double super_overhang_area_threshold = SQ(scale_(5.0));
|
||||
const double cantilevel_dist_thresh = scale_(6);
|
||||
#if 0
|
||||
double threshold_rad = (m_config.support_threshold_angle.value < EPSILON ? 30 : m_config.support_threshold_angle.value + 1) * M_PI / 180.;
|
||||
|
|
|
@ -151,8 +151,8 @@ static std::vector<VolumeSlices> slice_volumes_inner(
|
|||
params_base.mode_below = params_base.mode;
|
||||
|
||||
// BBS
|
||||
const size_t num_extruders = print_config.filament_diameter.size();
|
||||
const bool is_mm_painted = num_extruders > 1 && std::any_of(model_volumes.cbegin(), model_volumes.cend(), [](const ModelVolume *mv) { return mv->is_mm_painted(); });
|
||||
// const size_t num_extruders = print_config.filament_diameter.size();
|
||||
// const bool is_mm_painted = num_extruders > 1 && std::any_of(model_volumes.cbegin(), model_volumes.cend(), [](const ModelVolume *mv) { return mv->is_mm_painted(); });
|
||||
// BBS: don't do size compensation when slice volume.
|
||||
// Will handle contour and hole size compensation seperately later.
|
||||
//const auto extra_offset = is_mm_painted ? 0.f : std::max(0.f, float(print_object_config.xy_contour_compensation.value));
|
||||
|
@ -336,7 +336,8 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
|||
};
|
||||
|
||||
// BBS
|
||||
auto trim_overlap = [](ExPolygons& expolys_a, ExPolygons& expolys_b) {
|
||||
// Orca: unused
|
||||
/* auto trim_overlap = [](ExPolygons& expolys_a, ExPolygons& expolys_b) {
|
||||
ExPolygons trimming_a;
|
||||
ExPolygons trimming_b;
|
||||
|
||||
|
@ -361,7 +362,7 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
|||
|
||||
expolys_a = diff_ex(expolys_a, trimming_a);
|
||||
expolys_b = diff_ex(expolys_b, trimming_b);
|
||||
};
|
||||
}; */
|
||||
|
||||
std::vector<RegionSlice> temp_slices;
|
||||
for (size_t zs_complex_idx = range.begin(); zs_complex_idx < range.end(); ++ zs_complex_idx) {
|
||||
|
|
|
@ -99,8 +99,6 @@ std::vector<std::string> init_occt_fonts()
|
|||
|
||||
static bool TextToBRep(const char* text, const char* font, const float theTextHeight, Font_FontAspect& theFontAspect, TopoDS_Shape& theShape, double& text_width)
|
||||
{
|
||||
Standard_Integer anArgIt = 1;
|
||||
Standard_CString aName = "text_shape";
|
||||
Standard_CString aText = text;
|
||||
|
||||
Font_BRepFont aFont;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include "libslic3r/NormalUtils.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#include <numeric>
|
||||
|
||||
#include "SlicesToTriangleMesh.hpp"
|
||||
|
||||
//#include "libslic3r/MTUtils.hpp"
|
||||
#include "libslic3r/Execution/ExecutionTBB.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/Tesselate.hpp"
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
#include "OrganicSupport.hpp"
|
||||
#include "SupportCommon.hpp"
|
||||
|
||||
#include "../AABBTreeLines.hpp"
|
||||
#include "../ClipperUtils.hpp"
|
||||
#include "../Polygon.hpp"
|
||||
#include "../Polyline.hpp"
|
||||
#include "../MutablePolygon.hpp"
|
||||
#include "../TriangleMeshSlicer.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "../Print.hpp"
|
||||
#include "../PrintConfig.hpp"
|
||||
#include "../Slicing.hpp"
|
||||
#include "SupportParameters.hpp"
|
||||
|
||||
namespace Slic3r::FFFSupport {
|
||||
|
|
|
@ -338,7 +338,7 @@ static std::string get_svg_filename(std::string layer_nr_or_z, std::string tag
|
|||
rand_init = true;
|
||||
}
|
||||
|
||||
int rand_num = rand() % 1000000;
|
||||
// int rand_num = rand() % 1000000;
|
||||
//makedir("./SVG");
|
||||
std::string prefix = "./SVG/";
|
||||
std::string suffix = ".svg";
|
||||
|
@ -1554,7 +1554,6 @@ static inline ExPolygons detect_overhangs(
|
|||
double thresh_angle = object_config.support_threshold_angle.value > 0 ? object_config.support_threshold_angle.value + 1 : 0;
|
||||
thresh_angle = std::min(thresh_angle, 89.); // BBS should be smaller than 90
|
||||
const double threshold_rad = Geometry::deg2rad(thresh_angle);
|
||||
const coordf_t max_bridge_length = scale_(object_config.max_bridge_length.value);
|
||||
const bool bridge_no_support = object_config.bridge_no_support.value;
|
||||
const coordf_t xy_expansion = scale_(object_config.support_expansion.value);
|
||||
|
||||
|
@ -1577,7 +1576,6 @@ static inline ExPolygons detect_overhangs(
|
|||
{
|
||||
// Generate overhang / contact_polygons for non-raft layers.
|
||||
const Layer &lower_layer = *layer.lower_layer;
|
||||
const bool has_enforcer = !annotations.enforcers_layers.empty() && !annotations.enforcers_layers[layer_id].empty();
|
||||
// Can't directly use lower_layer.lslices, or we'll miss some very sharp tails.
|
||||
// Filter out areas whose diameter that is smaller than extrusion_width. Do not use offset2() for this purpose!
|
||||
// FIXME if there are multiple regions with different extrusion width, the following code may not be right.
|
||||
|
@ -1689,7 +1687,6 @@ static inline ExPolygons detect_overhangs(
|
|||
// check cantilever
|
||||
if (layer.lower_layer) {
|
||||
for (ExPolygon& poly : overhang_areas) {
|
||||
float fw = float(layer.regions().front()->flow(frExternalPerimeter).scaled_width());
|
||||
auto cluster_boundary_ex = intersection_ex(poly, offset_ex(layer.lower_layer->lslices, scale_(0.5)));
|
||||
Polygons cluster_boundary = to_polygons(cluster_boundary_ex);
|
||||
if (cluster_boundary.empty()) continue;
|
||||
|
@ -1734,7 +1731,6 @@ static inline std::tuple<Polygons, Polygons, double> detect_contacts(
|
|||
Polygons enforcer_polygons;
|
||||
|
||||
// BBS.
|
||||
const bool auto_normal_support = object_config.support_type.value == stNormalAuto;
|
||||
const bool buildplate_only = !annotations.buildplate_covered.empty();
|
||||
float no_interface_offset = 0.f;
|
||||
|
||||
|
@ -1748,8 +1744,6 @@ static inline std::tuple<Polygons, Polygons, double> detect_contacts(
|
|||
// Generate overhang / contact_polygons for non-raft layers.
|
||||
const Layer& lower_layer = *layer.lower_layer;
|
||||
const bool has_enforcer = !annotations.enforcers_layers.empty() && !annotations.enforcers_layers[layer_id].empty();
|
||||
const ExPolygons& lower_layer_expolys = lower_layer.lslices;
|
||||
const ExPolygons& lower_layer_sharptails = lower_layer.sharp_tails;
|
||||
|
||||
// Cache support trimming polygons derived from lower layer polygons, possible merged with "on build plate only" trimming polygons.
|
||||
auto slices_margin_update =
|
||||
|
@ -2187,7 +2181,6 @@ struct OverhangCluster {
|
|||
|
||||
static OverhangCluster* add_overhang(std::vector<OverhangCluster>& clusters, ExPolygon* overhang, int layer_nr, coordf_t offset_scaled) {
|
||||
OverhangCluster* cluster = nullptr;
|
||||
bool found = false;
|
||||
for (int i = 0; i < clusters.size(); i++) {
|
||||
auto cluster_i = &clusters[i];
|
||||
if (cluster_i->intersects(*overhang, layer_nr)) {
|
||||
|
@ -3546,13 +3539,13 @@ std::pair<PrintObjectSupportMaterial::MyLayersPtr, PrintObjectSupportMaterial::M
|
|||
// distinguish between interface and base interface layers
|
||||
// Contact layer is considered an interface layer, therefore run the following block only if support_interface_top_layers > 1.
|
||||
// Contact layer needs a base_interface layer, therefore run the following block if support_interface_top_layers > 0, has soluble support and extruders are different.
|
||||
bool soluble_interface_non_soluble_base =
|
||||
// Zero z-gap between the overhangs and the support interface.
|
||||
m_slicing_params.soluble_interface &&
|
||||
// Interface extruder soluble.
|
||||
m_object_config->support_interface_filament.value > 0 && m_print_config->filament_soluble.get_at(m_object_config->support_interface_filament.value - 1) &&
|
||||
// Base extruder: Either "print with active extruder" not soluble.
|
||||
(m_object_config->support_filament.value == 0 || ! m_print_config->filament_soluble.get_at(m_object_config->support_filament.value - 1));
|
||||
// bool soluble_interface_non_soluble_base =
|
||||
// // Zero z-gap between the overhangs and the support interface.
|
||||
// m_slicing_params.soluble_interface &&
|
||||
// // Interface extruder soluble.
|
||||
// m_object_config->support_interface_filament.value > 0 && m_print_config->filament_soluble.get_at(m_object_config->support_interface_filament.value - 1) &&
|
||||
// // Base extruder: Either "print with active extruder" not soluble.
|
||||
// (m_object_config->support_filament.value == 0 || ! m_print_config->filament_soluble.get_at(m_object_config->support_filament.value - 1));
|
||||
bool snug_supports = m_object_config->support_style.value == smsSnug;
|
||||
// BBS: if support interface and support base do not use the same filament, add a base layer to improve their adhesion
|
||||
bool differnt_support_interface_filament = m_object_config->support_interface_filament.value != m_object_config->support_filament.value;
|
||||
|
@ -4628,7 +4621,6 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
|
||||
if (object_layer != nullptr) {
|
||||
float biggest_bridge_area = 0.f;
|
||||
const Polygons& top_contact_polys = top_contact_layer.polygons_to_extrude();
|
||||
for (auto layerm : object_layer->regions()) {
|
||||
for (auto bridge_surface : layerm->fill_surfaces.filter_by_type(stBottomBridge)) {
|
||||
float bs_area = bridge_surface->area();
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "Print.hpp"
|
||||
#include "Layer.hpp"
|
||||
#include "Fill/FillBase.hpp"
|
||||
#include "Fill/FillConcentric.hpp"
|
||||
#include "CurveAnalyzer.hpp"
|
||||
#include "SVG.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
|
@ -13,7 +12,6 @@
|
|||
#include <libnest2d/backends/libslic3r/geometries.hpp>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <tbb/blocked_range.h>
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#define _L(s) Slic3r::I18N::translate(s)
|
||||
|
@ -469,7 +467,6 @@ static bool move_inside_expolys(const ExPolygons& polygons, Point& from, double
|
|||
Point ret = from;
|
||||
std::vector<Point> valid_pts;
|
||||
double bestDist2 = std::numeric_limits<double>::max();
|
||||
unsigned int bestPoly = NO_INDEX;
|
||||
bool is_already_on_correct_side_of_boundary = false; // whether [from] is already on the right side of the boundary
|
||||
Point inward_dir;
|
||||
for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
|
||||
|
@ -510,7 +507,6 @@ static bool move_inside_expolys(const ExPolygons& polygons, Point& from, double
|
|||
if (dist2 < bestDist2)
|
||||
{
|
||||
bestDist2 = dist2;
|
||||
bestPoly = poly_idx;
|
||||
if (distance == 0) { ret = x; }
|
||||
else
|
||||
{
|
||||
|
@ -547,7 +543,6 @@ static bool move_inside_expolys(const ExPolygons& polygons, Point& from, double
|
|||
if (dist2 < bestDist2)
|
||||
{
|
||||
bestDist2 = dist2;
|
||||
bestPoly = poly_idx;
|
||||
if (distance == 0) { ret = x; }
|
||||
else
|
||||
{
|
||||
|
@ -632,7 +627,6 @@ static bool is_inside_ex(const ExPolygons &polygons, const Point &pt)
|
|||
|
||||
static bool move_out_expolys(const ExPolygons& polygons, Point& from, double distance, double max_move_distance)
|
||||
{
|
||||
Point from0 = from;
|
||||
ExPolygons polys_dilated = union_ex(offset_ex(polygons, scale_(distance)));
|
||||
Point pt = projection_onto(polys_dilated, from);// find_closest_ex(from, polys_dilated);
|
||||
Point outward_dir = pt - from;
|
||||
|
@ -734,16 +728,12 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
|||
const coordf_t extrusion_width = config.get_abs_value("line_width", nozzle_diameter);
|
||||
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
|
||||
const coordf_t max_bridge_length = scale_(config.max_bridge_length.value);
|
||||
const bool bridge_no_support = max_bridge_length > 0;
|
||||
const bool support_critical_regions_only = config.support_critical_regions_only.value;
|
||||
const bool config_remove_small_overhangs = config.support_remove_small_overhang.value;
|
||||
const int enforce_support_layers = config.enforce_support_layers.value;
|
||||
const double area_thresh_well_supported = SQ(scale_(6));
|
||||
const double length_thresh_well_supported = scale_(6);
|
||||
static const double sharp_tail_max_support_height = 16.f;
|
||||
// a region is considered well supported if the number of layers below it exceeds this threshold
|
||||
const int thresh_layers_below = 10 / config.layer_height;
|
||||
double obj_height = m_object->size().z();
|
||||
// +1 makes the threshold inclusive
|
||||
double thresh_angle = config.support_threshold_angle.value > EPSILON ? config.support_threshold_angle.value + 1 : 30;
|
||||
thresh_angle = std::min(thresh_angle, 89.); // should be smaller than 90
|
||||
|
@ -1406,7 +1396,6 @@ void TreeSupport::generate_toolpaths()
|
|||
const PrintObjectConfig &object_config = m_object->config();
|
||||
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
|
||||
coordf_t nozzle_diameter = print_config.nozzle_diameter.get_at(object_config.support_filament - 1);
|
||||
coordf_t layer_height = object_config.layer_height.value;
|
||||
const size_t wall_count = object_config.tree_support_wall_count.value;
|
||||
|
||||
// Check if set to zero, use default if so.
|
||||
|
@ -1420,8 +1409,6 @@ void TreeSupport::generate_toolpaths()
|
|||
coordf_t interface_density = std::min(1., m_support_material_interface_flow.spacing() / interface_spacing);
|
||||
coordf_t bottom_interface_density = std::min(1., m_support_material_interface_flow.spacing() / bottom_interface_spacing);
|
||||
|
||||
const coordf_t branch_radius = object_config.tree_support_branch_diameter.value / 2;
|
||||
const coordf_t branch_radius_scaled = scale_(branch_radius);
|
||||
|
||||
if (m_object->support_layers().empty())
|
||||
return;
|
||||
|
@ -2126,7 +2113,6 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
|||
|
||||
const bool with_lightning_infill = m_support_params.base_fill_pattern == ipLightning;
|
||||
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
|
||||
const size_t wall_count = config.tree_support_wall_count.value;
|
||||
|
||||
const PrintObjectConfig& object_config = m_object->config();
|
||||
BOOST_LOG_TRIVIAL(info) << "draw_circles for object: " << m_object->model_object()->name;
|
||||
|
@ -2377,7 +2363,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
|||
ExPolygons& base_areas = ts_layer->base_areas;
|
||||
|
||||
int layer_nr_lower = layer_nr - 1;
|
||||
for (layer_nr_lower; layer_nr_lower >= 0; layer_nr_lower--) {
|
||||
for (;layer_nr_lower >= 0; layer_nr_lower--) {
|
||||
if (!m_object->get_support_layer(layer_nr_lower + m_raft_layers)->area_groups.empty()) break;
|
||||
}
|
||||
if (layer_nr_lower <= 0) continue;
|
||||
|
@ -2467,7 +2453,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
|||
if (ts_layer->area_groups.empty()) continue;
|
||||
|
||||
int layer_nr_lower = layer_nr - 1;
|
||||
for (layer_nr_lower; layer_nr_lower >= 0; layer_nr_lower--) {
|
||||
for (;layer_nr_lower >= 0; layer_nr_lower--) {
|
||||
if (!m_object->get_support_layer(layer_nr_lower + m_raft_layers)->area_groups.empty()) break;
|
||||
}
|
||||
if (layer_nr_lower < 0) continue;
|
||||
|
@ -2582,15 +2568,10 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
|||
const coordf_t radius_sample_resolution = m_ts_data->m_radius_sample_resolution;
|
||||
const bool support_on_buildplate_only = config.support_on_build_plate_only.value;
|
||||
const size_t bottom_interface_layers = config.support_interface_bottom_layers.value;
|
||||
const size_t top_interface_layers = config.support_interface_top_layers.value;
|
||||
float DO_NOT_MOVER_UNDER_MM = is_slim ? 0 : 5; // do not move contact points under 5mm
|
||||
const auto nozzle_diameter = m_object->print()->config().nozzle_diameter.get_at(m_object->config().support_interface_filament-1);
|
||||
const auto support_line_width = config.support_line_width.get_abs_value(nozzle_diameter);
|
||||
|
||||
auto get_branch_angle = [this,&config](coordf_t radius) {
|
||||
if (config.tree_support_branch_angle.value < 30.0) return config.tree_support_branch_angle.value;
|
||||
return (radius - MIN_BRANCH_RADIUS) / (MAX_BRANCH_RADIUS - MIN_BRANCH_RADIUS) * (config.tree_support_branch_angle.value - 30.0) + 30.0;
|
||||
};
|
||||
auto get_max_move_dist = [this, &config, branch_radius, tip_layers, diameter_angle_scale_factor, wall_count, support_extrusion_width, support_line_width](const Node *node, int power = 1) {
|
||||
double move_dist = node->max_move_dist;
|
||||
if (node->max_move_dist == 0) {
|
||||
|
@ -3202,7 +3183,6 @@ void TreeSupport::adjust_layer_heights(std::vector<std::vector<Node*>>& contact_
|
|||
const coordf_t layer_height = config.layer_height.value;
|
||||
const coordf_t max_layer_height = m_slicing_params.max_layer_height;
|
||||
const size_t bot_intf_layers = config.support_interface_bottom_layers.value;
|
||||
const size_t top_intf_layers = config.support_interface_top_layers.value;
|
||||
|
||||
// if already using max layer height, no need to adjust
|
||||
if (layer_height == max_layer_height) return;
|
||||
|
@ -3324,7 +3304,6 @@ std::vector<LayerHeightData> TreeSupport::plan_layer_heights(std::vector<std::ve
|
|||
|
||||
// Insert intermediate layers.
|
||||
size_t n_layers_extra = size_t(ceil(dist / (m_slicing_params.max_suport_layer_height + EPSILON)));
|
||||
int actual_internel_layers = extr2_layer_nr - extr1_layer_nr - 1;
|
||||
int extr_layers_left = extr2_layer_nr - extr1_layer_nr - n_layers_extra - 1;
|
||||
if (n_layers_extra < 1)
|
||||
continue;
|
||||
|
|
|
@ -173,7 +173,7 @@ static FacetSliceType slice_facet(
|
|||
// (external on the right of the line)
|
||||
for (int j = 0; j < 3; ++ j) { // loop through facet edges
|
||||
int edge_id;
|
||||
const stl_vertex *a, *b, *c;
|
||||
const stl_vertex *a, *b/* , *c */;
|
||||
int a_id, b_id;
|
||||
{
|
||||
int k = (idx_vertex_lowest + j) % 3;
|
||||
|
@ -183,7 +183,7 @@ static FacetSliceType slice_facet(
|
|||
a = vertices + k;
|
||||
b_id = indices[l];
|
||||
b = vertices + l;
|
||||
c = vertices + (k + 2) % 3;
|
||||
// c = vertices + (k + 2) % 3;
|
||||
}
|
||||
|
||||
// Is edge or face aligned with the cutting plane?
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include <map>
|
||||
#include <random>
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/blocked_range.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "TriangulateWall.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
//#include "TriangulateWall.hpp"
|
||||
//#include "MTUtils.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include "Triangulation.hpp"
|
||||
#include "IntersectionPoints.hpp"
|
||||
|
||||
#ifndef _WIN32
|
||||
// On linux and macOS, this include is required
|
||||
#include <boost/next_prior.hpp>
|
||||
#endif // _WIN32
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
|
||||
|
|
|
@ -465,8 +465,9 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star
|
|||
|
||||
const double e_per_mm = CalibPressureAdvance::e_per_mm(m_line_width, m_height_layer, m_nozzle_diameter, filament_diameter,
|
||||
print_flow_ratio);
|
||||
const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(m_thin_line_width, m_height_layer, m_nozzle_diameter, filament_diameter,
|
||||
print_flow_ratio);
|
||||
// Orca: Unused due to skip drawing indicator lines
|
||||
// const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(m_thin_line_width, m_height_layer, m_nozzle_diameter, filament_diameter,
|
||||
// print_flow_ratio);
|
||||
const double number_e_per_mm = CalibPressureAdvance::e_per_mm(m_number_line_width, m_height_layer, m_nozzle_diameter, filament_diameter,
|
||||
print_flow_ratio);
|
||||
|
||||
|
|
|
@ -3,19 +3,12 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <locale>
|
||||
#include <ctime>
|
||||
#include <cstdarg>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "format.hpp"
|
||||
#include "Platform.hpp"
|
||||
#include "Time.hpp"
|
||||
#include "libslic3r.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "MacUtils.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
|
@ -32,6 +25,7 @@
|
|||
#ifdef __APPLE__
|
||||
#include <mach/mach.h>
|
||||
#include <libproc.h>
|
||||
#include "MacUtils.hpp"
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/stat.h>
|
||||
|
@ -39,6 +33,7 @@
|
|||
#include <sys/sendfile.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include "Platform.hpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -59,7 +54,6 @@
|
|||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
// We are using quite an old TBB 2017 U7, which does not support global control API officially.
|
||||
// Before we update our build servers, let's use the old API, which is deprecated in up to date TBB.
|
||||
|
@ -1489,8 +1483,6 @@ bool bbl_calc_md5(std::string &filename, std::string &md5_out)
|
|||
MD5_Init(&ctx);
|
||||
boost::nowide::ifstream ifs(filename, std::ios::binary);
|
||||
std::string buf(64 * 1024, 0);
|
||||
const std::size_t & size = boost::filesystem::file_size(filename);
|
||||
std::size_t left_size = size;
|
||||
while (ifs) {
|
||||
ifs.read(buf.data(), buf.size());
|
||||
int read_bytes = ifs.gcount();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue