mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2026-02-21 03:52:15 -07:00
Merge branch 'main' into feature/show-extruder-values-on-filament-overrides-tab
This commit is contained in:
commit
b34ac2bda3
336 changed files with 14249 additions and 11440 deletions
|
|
@ -358,7 +358,7 @@ void CBaseException::ShowExceptionInformation()
|
|||
|
||||
OutputString(_T("Exception Flag :0x%x "), m_pEp->ExceptionRecord->ExceptionFlags);
|
||||
OutputString(_T("NumberParameters :%ld \n"), m_pEp->ExceptionRecord->NumberParameters);
|
||||
for (unsigned int i = 0; i < m_pEp->ExceptionRecord->NumberParameters; i++)
|
||||
for (int i = 0; i < m_pEp->ExceptionRecord->NumberParameters; i++)
|
||||
{
|
||||
OutputString(_T("Param %d :0x%x \n"), i, m_pEp->ExceptionRecord->ExceptionInformation[i]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1191,7 +1191,7 @@ int CLI::run(int argc, char **argv)
|
|||
PlateDataPtrs plate_data_src;
|
||||
std::vector<plate_obj_size_info_t> plate_obj_size_infos;
|
||||
int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0;
|
||||
bool first_file = true, is_bbl_3mf = false, need_arrange = true, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false;
|
||||
bool first_file = true, is_bbl_3mf = false, need_arrange = true, has_thumbnails = false, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false;
|
||||
bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false;
|
||||
Semver file_version;
|
||||
std::map<size_t, bool> orients_requirement;
|
||||
|
|
@ -1545,7 +1545,7 @@ int CLI::run(int argc, char **argv)
|
|||
{
|
||||
ModelObject* object = model.objects[obj_index];
|
||||
|
||||
for (int clone_index = 1; clone_index < clone_count; clone_index++)
|
||||
for (unsigned int clone_index = 1; clone_index < clone_count; clone_index++)
|
||||
{
|
||||
ModelObject* newObj = model.add_object(*object);
|
||||
newObj->name = object->name +"_"+ std::to_string(clone_index+1);
|
||||
|
|
@ -1618,7 +1618,7 @@ int CLI::run(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
boost::nowide::cerr << "construct_assemble_list: " << e.what() << std::endl;
|
||||
boost::nowide::cerr << construct_assemble_list << ": " << e.what() << std::endl;
|
||||
record_exit_reson(outfile_dir, CLI_DATA_FILE_ERROR, 0, cli_errors[CLI_DATA_FILE_ERROR], sliced_info);
|
||||
flush_and_exit(CLI_DATA_FILE_ERROR);
|
||||
}
|
||||
|
|
@ -2102,7 +2102,7 @@ int CLI::run(int argc, char **argv)
|
|||
record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, 0, cli_errors[CLI_INVALID_PARAMS], sliced_info);
|
||||
flush_and_exit(CLI_INVALID_PARAMS);
|
||||
}
|
||||
for (int index = 0; index < filament_count; index ++)
|
||||
for (unsigned int index = 0; index < filament_count; index ++)
|
||||
{
|
||||
std::string file = uptodate_filaments[index];
|
||||
DynamicPrintConfig config;
|
||||
|
|
@ -2219,7 +2219,7 @@ int CLI::run(int argc, char **argv)
|
|||
}
|
||||
|
||||
//upwards check
|
||||
bool process_compatible = false, /* machine_upwards = false, */ machine_switch = false;
|
||||
bool process_compatible = false, machine_upwards = false, machine_switch = false;
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("current printer %1%, new printer %2%, current process %3%, new process %4%")%current_printer_name %new_printer_name %current_process_name %new_process_name;
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("current printer inherits %1%, new printer inherits %2%, current process inherits %3%, new process inherits %4%")
|
||||
%current_printer_system_name %new_printer_system_name %current_process_system_name %new_process_system_name;
|
||||
|
|
@ -2289,7 +2289,7 @@ int CLI::run(int argc, char **argv)
|
|||
for (int index = 0; index < upward_compatible_printers.size(); index++) {
|
||||
if (upward_compatible_printers[index] == new_printer_system_name) {
|
||||
process_compatible = true;
|
||||
// machine_upwards = true;
|
||||
machine_upwards = true;
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("new printer is upward_compatible");
|
||||
break;
|
||||
}
|
||||
|
|
@ -2899,8 +2899,7 @@ int CLI::run(int argc, char **argv)
|
|||
for (auto& model : m_models)
|
||||
for (ModelObject* o : model.objects)
|
||||
{
|
||||
/* ModelObject* new_object = */
|
||||
m.add_object(*o);
|
||||
ModelObject* new_object = m.add_object(*o);
|
||||
//BOOST_LOG_TRIVIAL(info) << "object "<<o->name <<", id :" << o->id().id << "\n";
|
||||
//orients_requirement.emplace(new_object->id().id, orients_requirement[o->id().id]);
|
||||
//orients_requirement.erase(o->id().id);
|
||||
|
|
@ -3343,6 +3342,7 @@ int CLI::run(int argc, char **argv)
|
|||
BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: all failed, size %1%")%downward_check_size;
|
||||
break;
|
||||
}
|
||||
Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate *)partplate_list.get_plate(index);
|
||||
Vec3d size = plate_obj_size_infos[index].obj_bbox.size();
|
||||
|
||||
for (int index2 = 0; index2 < downward_check_size; index2 ++)
|
||||
|
|
@ -3392,6 +3392,7 @@ int CLI::run(int argc, char **argv)
|
|||
}
|
||||
|
||||
// Loop through transform options.
|
||||
bool user_center_specified = false;
|
||||
Points beds = get_bed_shape(m_print_config);
|
||||
ArrangeParams arrange_cfg;
|
||||
|
||||
|
|
@ -3415,6 +3416,7 @@ int CLI::run(int argc, char **argv)
|
|||
ModelObject* new_object = m.add_object();
|
||||
new_object->name = _u8L("Assembly");
|
||||
new_object->add_instance();
|
||||
int idx = 0;
|
||||
for (auto& model : m_models)
|
||||
for (ModelObject* o : model.objects) {
|
||||
for (auto volume : o->volumes) {
|
||||
|
|
@ -3516,6 +3518,7 @@ int CLI::run(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
} else if (opt_key == "center") {
|
||||
user_center_specified = true;
|
||||
for (auto &model : m_models) {
|
||||
model.add_default_instances();
|
||||
// this affects instances:
|
||||
|
|
@ -3815,6 +3818,7 @@ int CLI::run(int argc, char **argv)
|
|||
{
|
||||
//do arrange for plate
|
||||
ArrangePolygons selected, unselected;
|
||||
Model& model = m_models[0];
|
||||
arrange_cfg = ArrangeParams(); // reset all params
|
||||
get_print_sequence(cur_plate, m_print_config, arrange_cfg.is_seq_print);
|
||||
|
||||
|
|
@ -3840,6 +3844,7 @@ int CLI::run(int argc, char **argv)
|
|||
if (!arrange_cfg.is_seq_print && assemble_plate.filaments_count > 1)
|
||||
{
|
||||
//prepare the wipe tower
|
||||
int plate_count = partplate_list.get_plate_count();
|
||||
|
||||
auto printer_structure_opt = m_print_config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure");
|
||||
const float tower_brim_width = m_print_config.option<ConfigOptionFloat>("prime_tower_width", true)->value;
|
||||
|
|
@ -4225,6 +4230,7 @@ int CLI::run(int argc, char **argv)
|
|||
//float depth = v * (filaments_cnt - 1) / (layer_height * w);
|
||||
|
||||
Vec3d wipe_tower_size = cur_plate->estimate_wipe_tower_size(m_print_config, w, v, filaments_cnt);
|
||||
Vec3d plate_origin = cur_plate->get_origin();
|
||||
int plate_width, plate_depth, plate_height;
|
||||
partplate_list.get_plate_size(plate_width, plate_depth, plate_height);
|
||||
float depth = wipe_tower_size(1);
|
||||
|
|
@ -4603,7 +4609,7 @@ int CLI::run(int argc, char **argv)
|
|||
}
|
||||
|
||||
// loop through action options
|
||||
bool export_to_3mf = false, load_slicedata = false, export_slicedata = false;
|
||||
bool export_to_3mf = false, load_slicedata = false, export_slicedata = false, export_slicedata_error = false;
|
||||
bool no_check = false;
|
||||
std::string export_3mf_file, load_slice_data_dir, export_slice_data_dir, export_stls_dir;
|
||||
std::vector<ThumbnailData*> calibration_thumbnails;
|
||||
|
|
@ -5092,6 +5098,7 @@ int CLI::run(int argc, char **argv)
|
|||
int ret = print->export_cached_data(plate_dir, with_space);
|
||||
if (ret) {
|
||||
BOOST_LOG_TRIVIAL(error) << "plate "<< index+1<< ": export Slicing data error, ret=" << ret;
|
||||
export_slicedata_error = true;
|
||||
if (fs::exists(plate_dir))
|
||||
fs::remove_all(plate_dir);
|
||||
record_exit_reson(outfile_dir, ret, index+1, cli_errors[ret], sliced_info);
|
||||
|
|
@ -5218,7 +5225,8 @@ int CLI::run(int argc, char **argv)
|
|||
bool need_regenerate_top_thumbnail = oriented_or_arranged || regenerate_thumbnails;
|
||||
bool need_create_thumbnail_group = false, need_create_no_light_group = false, need_create_top_group = false;
|
||||
|
||||
// get color for platedata
|
||||
// get type and color for platedata
|
||||
auto* filament_types = dynamic_cast<const ConfigOptionStrings*>(m_print_config.option("filament_type"));
|
||||
const ConfigOptionStrings* filament_color = dynamic_cast<const ConfigOptionStrings *>(m_print_config.option("filament_colour"));
|
||||
auto* filament_id = dynamic_cast<const ConfigOptionStrings*>(m_print_config.option("filament_ids"));
|
||||
const ConfigOptionFloats* nozzle_diameter_option = dynamic_cast<const ConfigOptionFloats *>(m_print_config.option("nozzle_diameter"));
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ private:
|
|||
// This is a match. Record result in neighbors list.
|
||||
match_neighbors(edge, *link->next);
|
||||
// Delete the matched edge from the list.
|
||||
// HashEdge *temp = link->next;
|
||||
HashEdge *temp = link->next;
|
||||
link->next = link->next->next;
|
||||
// pool.destroy(temp);
|
||||
#ifndef NDEBUG
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ void stl_fix_normal_directions(stl_file *stl)
|
|||
norm_sw[facet_num] = 1; // Record this one as being fixed.
|
||||
++ checked;
|
||||
}
|
||||
// stl_normal *temp = head->next; // Delete this facet from the list.
|
||||
stl_normal *temp = head->next; // Delete this facet from the list.
|
||||
head->next = head->next->next;
|
||||
// pool.destroy(temp);
|
||||
} else { // If we ran out of facets to fix: All of the facets in this part have been fixed.
|
||||
|
|
|
|||
|
|
@ -768,9 +768,11 @@ bool ImGui::BBLButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFl
|
|||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||
|
||||
bool b_hover = false;
|
||||
if (hovered)
|
||||
{
|
||||
PushStyleColor(ImGuiCol_Text,GetColorU32(ImGuiCol_CheckMark));
|
||||
b_hover = true;
|
||||
}
|
||||
|
||||
// Render
|
||||
|
|
@ -4165,6 +4167,8 @@ bool ImGui::BBLInputScalar(const char *label, ImGuiDataType data_type, void *p_d
|
|||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
|
||||
// Tabbing or CTRL-clicking on Drag turns it into an InputText
|
||||
const bool hovered = ItemHoverable(frame_bb, id);
|
||||
// We are only allowed to access the state if we are already the active widget.
|
||||
ImGuiInputTextState *state = GetInputTextState(id);
|
||||
|
||||
bool push_color_count = 0;
|
||||
if (hovered || g.ActiveId == id) {
|
||||
|
|
@ -6294,9 +6298,9 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
|||
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
||||
else
|
||||
#ifdef __APPLE__
|
||||
window->DrawList->AddRect(bb.Min - ImVec2(3, 3), bb.Max + ImVec2(3, 3), GetColorU32(ImGuiCol_FrameBg), rounding * 2,0,4.0f);; // Color button are often in need of some sort of border
|
||||
window->DrawList->AddRect(bb.Min - ImVec2(3, 3), bb.Max + ImVec2(3, 3), GetColorU32(ImGuiCol_FrameBg), rounding * 2,NULL,4.0f);; // Color button are often in need of some sort of border
|
||||
#else
|
||||
window->DrawList->AddRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2), GetColorU32(ImGuiCol_FrameBg), rounding * 2,0,3.0f); // Color button are often in need of some sort of border
|
||||
window->DrawList->AddRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2), GetColorU32(ImGuiCol_FrameBg), rounding * 2,NULL,3.0f); // Color button are often in need of some sort of border
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -7093,6 +7097,7 @@ bool ImGui::BBLImageSelectable(ImTextureID user_texture_id, const ImVec2& size_a
|
|||
|
||||
// Text stays at the submission position, but bounding box may be extended on both sides
|
||||
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
|
||||
const ImVec2 text_min = ImVec2(pos.x + arrow_size, pos.y);
|
||||
const ImVec2 text_max(min_x + size.x, pos.y + size.y);
|
||||
|
||||
// Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
|
||||
|
|
@ -7204,6 +7209,7 @@ bool ImGui::BBLImageSelectable(ImTextureID user_texture_id, const ImVec2& size_a
|
|||
if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
|
||||
|
||||
// Render
|
||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
ImVec2 p_min = bb.Min + ImVec2(style.ItemInnerSpacing.x, (bb.Max.y - bb.Min.y - font_size.y) / 2);
|
||||
ImVec2 p_max = p_min + font_size;
|
||||
window->DrawList->AddImage(user_texture_id, p_min, p_max, uv0, uv1, selected || (held && hovered) ? GetColorU32(ImVec4(1.f, 1.f, 1.f, 1.f)) : GetColorU32(tint_col));
|
||||
|
|
|
|||
|
|
@ -2807,6 +2807,7 @@ namespace IMGUIZMO_NAMESPACE
|
|||
{
|
||||
static bool isDraging = false;
|
||||
static bool isClicking = false;
|
||||
static bool isInside = false;
|
||||
static vec_t interpolationUp;
|
||||
static vec_t interpolationDir;
|
||||
static int interpolationFrames = 0;
|
||||
|
|
@ -3054,6 +3055,7 @@ namespace IMGUIZMO_NAMESPACE
|
|||
LookAt(&newEye.x, &camTarget.x, &newUp.x, view);
|
||||
viewUpdated = true;
|
||||
}
|
||||
isInside = gContext.mbMouseOver && ImRect(position, position + size).Contains(io.MousePos);
|
||||
|
||||
if (io.MouseDown[0] && (fabsf(io.MouseDelta[0]) || fabsf(io.MouseDelta[1])) && isClicking)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ inline TPoint<RawShape> referenceVertex(const RawShape& sh)
|
|||
template<class RawBox, class RawShape, class Ratio = double> inline NfpResult<RawShape> nfpInnerRectBed(const RawBox &bed, const RawShape &other)
|
||||
{
|
||||
using Vertex = TPoint<RawShape>;
|
||||
using Edge = _Segment<Vertex>;
|
||||
namespace sl = shapelike;
|
||||
|
||||
auto sbox = sl::boundingBox(other);
|
||||
|
|
|
|||
|
|
@ -1119,6 +1119,7 @@ private:
|
|||
for (const Item& item : items_) {
|
||||
if (!item.is_virt_object) { extruders.insert(item.extrude_ids.begin(), item.extrude_ids.end()); }
|
||||
}
|
||||
bool need_wipe_tower = extruders.size() > 1;
|
||||
|
||||
std::vector<RawShape> objs,excludes;
|
||||
for (const Item &item : items_) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
#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,6 +1,7 @@
|
|||
//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,6 +9,7 @@
|
|||
#include "RedistributeBeadingStrategy.hpp"
|
||||
#include "OuterWallInsetBeadingStrategy.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "RedistributeBeadingStrategy.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
|
|
|
|||
|
|
@ -1595,6 +1595,7 @@ 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;
|
||||
|
|
@ -1611,7 +1612,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;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,15 @@
|
|||
//CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
#include "SkeletalTrapezoidationGraph.hpp"
|
||||
#include "../Line.hpp"
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "utils/linearAlg2D.hpp"
|
||||
#include "../Line.hpp"
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "ExtrusionLine.hpp"
|
||||
#include "linearAlg2D.hpp"
|
||||
#include "../../VariableWidth.hpp"
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
|
|
|
|||
|
|
@ -245,6 +245,15 @@ static inline Polygon to_polygon(const ExtrusionLine &line)
|
|||
return out;
|
||||
}
|
||||
|
||||
static Points to_points(const ExtrusionLine &extrusion_line)
|
||||
{
|
||||
Points points;
|
||||
points.reserve(extrusion_line.junctions.size());
|
||||
for (const ExtrusionJunction &junction : extrusion_line.junctions)
|
||||
points.emplace_back(junction.p);
|
||||
return points;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static BoundingBox get_extents(const ExtrusionLine &extrusion_line)
|
||||
{
|
||||
|
|
@ -272,15 +281,6 @@ static BoundingBox get_extents(const std::vector<const ExtrusionLine *> &extrusi
|
|||
return bbox;
|
||||
}
|
||||
|
||||
static Points to_points(const ExtrusionLine &extrusion_line)
|
||||
{
|
||||
Points points;
|
||||
points.reserve(extrusion_line.junctions.size());
|
||||
for (const ExtrusionJunction &junction : extrusion_line.junctions)
|
||||
points.emplace_back(junction.p);
|
||||
return points;
|
||||
}
|
||||
|
||||
static std::vector<Points> to_points(const std::vector<const ExtrusionLine *> &extrusion_lines)
|
||||
{
|
||||
std::vector<Points> points;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
//CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
#include "SquareGrid.hpp"
|
||||
#include "../../Point.hpp"
|
||||
|
||||
using namespace Slic3r::Arachne;
|
||||
|
||||
|
|
|
|||
|
|
@ -199,19 +199,23 @@ void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPr
|
|||
}
|
||||
|
||||
if (std::abs(a00) > EPSILON) {
|
||||
double db1_2, db1_6, db1_12, db1_24;
|
||||
double m00, m10, m01, m20, m11, m02;
|
||||
double db1_2, db1_6, db1_12, db1_24, db1_20, db1_60;
|
||||
double m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;
|
||||
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;
|
||||
|
|
@ -219,6 +223,10 @@ 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,5 +1,6 @@
|
|||
#include "BlacklistedLibraryCheck.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
|
|||
|
|
@ -576,6 +576,7 @@ 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()) {
|
||||
|
|
@ -1583,6 +1584,7 @@ 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();
|
||||
|
|
@ -1657,6 +1659,7 @@ 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Clipper2Lib::Paths64 Slic3rPoints_to_Paths64(const std::vector<T>& in)
|
|||
{
|
||||
Clipper2Lib::Paths64 out;
|
||||
out.reserve(in.size());
|
||||
for (const T item: in) {
|
||||
for (const T& item: in) {
|
||||
Clipper2Lib::Path64 path;
|
||||
path.reserve(item.size());
|
||||
for (const Slic3r::Point& point : item.points)
|
||||
|
|
|
|||
|
|
@ -775,9 +775,10 @@ 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);
|
||||
|
||||
load_from_json(file, substitutions_ctxt, true, key_values, reason);
|
||||
ret = load_from_json(file, substitutions_ctxt, true, key_values, reason);
|
||||
return std::move(substitutions_ctxt.substitutions);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -334,8 +334,8 @@ bool Emboss::divide_segments_for_close_point(ExPolygons &expolygons, double dist
|
|||
const Points &poly_pts = poly.points;
|
||||
const Point &line_a = poly_pts[id.point_index];
|
||||
const Point &line_b = (!ids.is_last_point(id)) ? poly_pts[id.point_index + 1] : poly_pts.front();
|
||||
assert(line_a == lines[index].a.cast<int>());
|
||||
assert(line_b == lines[index].b.cast<int>());
|
||||
assert(line_a == lines[index].a.cast<coord_t>());
|
||||
assert(line_b == lines[index].b.cast<coord_t>());
|
||||
if (p == line_a || p == line_b) continue;
|
||||
|
||||
divs.emplace_back(p, index);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "ShortestPath.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,25 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
template<typename LINE_T>
|
||||
int stagger_seam_index(int ind, LINE_T line, double shift, bool dir)
|
||||
{
|
||||
Point const *point = &line.points[ind];
|
||||
double dist = 0;
|
||||
while (dist < shift / SCALING_FACTOR) {
|
||||
if (dir)
|
||||
ind = (ind + 1) % line.points.size();
|
||||
else
|
||||
ind = ind > 0 ? --ind : line.points.size() - 1;
|
||||
Point const &next = line.points[ind];
|
||||
dist += point->distance_to(next);
|
||||
point = &next;
|
||||
};
|
||||
return ind;
|
||||
}
|
||||
|
||||
#define STAGGER_SEAM_THRESHOLD 0.9
|
||||
|
||||
void FillConcentric::_fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
|
|
@ -41,8 +60,20 @@ void FillConcentric::_fill_surface_single(
|
|||
// split paths using a nearest neighbor search
|
||||
size_t iPathFirst = polylines_out.size();
|
||||
Point last_pos(0, 0);
|
||||
|
||||
double min_nozzle_diameter;
|
||||
bool dir;
|
||||
if (this->print_config != nullptr && params.density >= STAGGER_SEAM_THRESHOLD) {
|
||||
min_nozzle_diameter = *std::min_element(print_config->nozzle_diameter.values.begin(), print_config->nozzle_diameter.values.end());
|
||||
dir = rand() % 2;
|
||||
}
|
||||
|
||||
for (const Polygon &loop : loops) {
|
||||
polylines_out.emplace_back(loop.split_at_index(last_pos.nearest_point_index(loop.points)));
|
||||
int ind = (this->print_config != nullptr && params.density > STAGGER_SEAM_THRESHOLD) ?
|
||||
stagger_seam_index(last_pos.nearest_point_index(loop.points), loop, min_nozzle_diameter / 2, dir) :
|
||||
last_pos.nearest_point_index(loop.points);
|
||||
|
||||
polylines_out.emplace_back(loop.split_at_index(ind));
|
||||
last_pos = polylines_out.back().last_point();
|
||||
}
|
||||
|
||||
|
|
@ -104,13 +135,18 @@ void FillConcentric::_fill_surface_single(const FillParams& params,
|
|||
// Split paths using a nearest neighbor search.
|
||||
size_t firts_poly_idx = thick_polylines_out.size();
|
||||
Point last_pos(0, 0);
|
||||
bool dir = rand() % 2;
|
||||
for (const Arachne::ExtrusionLine* extrusion : all_extrusions) {
|
||||
if (extrusion->empty())
|
||||
continue;
|
||||
|
||||
ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion);
|
||||
if (extrusion->is_closed)
|
||||
thick_polyline.start_at_index(last_pos.nearest_point_index(thick_polyline.points));
|
||||
|
||||
if (extrusion->is_closed) {
|
||||
int ind = (params.density >= STAGGER_SEAM_THRESHOLD) ?
|
||||
stagger_seam_index(last_pos.nearest_point_index(thick_polyline.points), thick_polyline, min_nozzle_diameter / 2, dir) :
|
||||
last_pos.nearest_point_index(thick_polyline.points);
|
||||
thick_polyline.start_at_index(ind);
|
||||
}
|
||||
thick_polylines_out.emplace_back(std::move(thick_polyline));
|
||||
last_pos = thick_polylines_out.back().last_point();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
#include "../ClipperUtils.hpp"
|
||||
#include "../ExPolygon.hpp"
|
||||
#include "../Surface.hpp"
|
||||
#include "../VariableWidth.hpp"
|
||||
#include "Arachne/WallToolPaths.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "../ClipperUtils.hpp"
|
||||
#include "../ShortestPath.hpp"
|
||||
#include "../Surface.hpp"
|
||||
#include <cmath>
|
||||
|
||||
#include "FillCrossHatch.hpp"
|
||||
|
|
@ -64,6 +65,7 @@ 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);
|
||||
|
|
@ -150,6 +152,7 @@ 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,6 +4,7 @@
|
|||
#include "Generator.hpp"
|
||||
#include "TreeNode.hpp"
|
||||
|
||||
#include "../../ClipperUtils.hpp"
|
||||
#include "../../Layer.hpp"
|
||||
#include "../../Print.hpp"
|
||||
|
||||
|
|
@ -34,7 +35,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,4 +1,5 @@
|
|||
#include <cmath>
|
||||
#include <assert.h>
|
||||
#include "slic3r/Utils/ColorSpaceConvert.hpp"
|
||||
|
||||
#include "FlushVolCalc.hpp"
|
||||
|
|
|
|||
|
|
@ -298,6 +298,7 @@ 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,6 +100,7 @@ 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]);
|
||||
|
|
|
|||
|
|
@ -1616,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);
|
||||
|
|
@ -2218,6 +2218,7 @@ 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);
|
||||
|
|
@ -3317,9 +3318,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())
|
||||
|
|
@ -4620,7 +4621,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
its.vertices.assign(sub_object->geometry.vertices.begin(), sub_object->geometry.vertices.end());
|
||||
|
||||
// BBS
|
||||
for (const std::string prop_str : sub_object->geometry.face_properties) {
|
||||
for (const std::string& prop_str : sub_object->geometry.face_properties) {
|
||||
FaceProperty face_prop;
|
||||
face_prop.from_string(prop_str);
|
||||
its.properties.push_back(face_prop);
|
||||
|
|
@ -4992,9 +4993,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)
|
||||
|
|
@ -5989,6 +5990,8 @@ 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();
|
||||
|
|
@ -6226,6 +6229,7 @@ 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();
|
||||
|
|
@ -6615,6 +6619,7 @@ 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);
|
||||
|
|
@ -7531,7 +7536,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
if (!m_skip_model && instance_size > 0)
|
||||
{
|
||||
for (int j = 0; j < instance_size; ++j)
|
||||
for (unsigned int j = 0; j < instance_size; ++j)
|
||||
{
|
||||
stream << " <" << INSTANCE_TAG << ">\n";
|
||||
int obj_id = plate_data->objects_and_instances[j].first;
|
||||
|
|
|
|||
|
|
@ -113,6 +113,9 @@ 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;
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +137,8 @@ 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);
|
||||
|
||||
|
|
@ -379,6 +384,7 @@ 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,6 +116,7 @@ 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();
|
||||
|
|
@ -2491,6 +2492,7 @@ 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;
|
||||
|
|
@ -3275,17 +3277,14 @@ 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.
|
||||
|
|
@ -3297,7 +3296,8 @@ 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)
|
||||
{
|
||||
|
|
@ -3360,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
|
||||
|
|
@ -3717,8 +3717,7 @@ 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
|
||||
// Orca: Left unused due to removed code below
|
||||
/* auto get_next_extruder = [&](int current_extruder,const std::vector<unsigned int>&extruders) {
|
||||
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:
|
||||
|
|
@ -3736,7 +3735,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) {
|
||||
|
|
@ -4494,8 +4493,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||
float seam_overhang = std::numeric_limits<float>::lowest();
|
||||
if (!m_config.spiral_mode && description == "perimeter") {
|
||||
assert(m_layer != nullptr);
|
||||
bool is_outer_wall_first = m_config.wall_sequence == WallSequence::OuterInner;
|
||||
m_seam_placer.place_seam(m_layer, loop, is_outer_wall_first, this->last_pos(), seam_overhang);
|
||||
m_seam_placer.place_seam(m_layer, loop, this->last_pos(), seam_overhang);
|
||||
} else
|
||||
loop.split_at(last_pos, false);
|
||||
|
||||
|
|
@ -4871,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);
|
||||
|
|
@ -5570,6 +5568,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
size_t start_index = fitting_result[fitting_index].start_point_index;
|
||||
size_t end_index = fitting_result[fitting_index].end_point_index;
|
||||
for (size_t point_index = start_index + 1; point_index < end_index + 1; point_index++) {
|
||||
tempDescription = description;
|
||||
const Line line = Line(path.polyline.points[point_index - 1], path.polyline.points[point_index]);
|
||||
const double line_length = line.length() * SCALING_FACTOR;
|
||||
if (line_length < EPSILON)
|
||||
|
|
@ -5893,8 +5892,10 @@ std::string GCode::travel_to(const Point& point, ExtrusionRole role, std::string
|
|||
|
||||
// generate G-code for the travel move
|
||||
if (needs_retraction) {
|
||||
if (m_config.reduce_crossing_wall && could_be_wipe_disabled)
|
||||
m_wipe.reset_path();
|
||||
// ORCA: Fix scenario where wipe is disabled when avoid crossing perimeters was enabled even though a retraction move was performed.
|
||||
// This replicates the existing behaviour of always wiping when retracting
|
||||
/*if (m_config.reduce_crossing_wall && could_be_wipe_disabled)
|
||||
m_wipe.reset_path();*/
|
||||
|
||||
Point last_post_before_retract = this->last_pos();
|
||||
gcode += this->retract(false, false, lift_type);
|
||||
|
|
@ -6041,6 +6042,7 @@ 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]));
|
||||
|
|
@ -6142,6 +6144,7 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ 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;
|
||||
|
|
|
|||
|
|
@ -521,62 +521,6 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
|
|||
return per_extruder_adjustments;
|
||||
}
|
||||
|
||||
// Slow down an extruder range proportionally down to slow_down_layer_time.
|
||||
// Return the total time for the complete layer.
|
||||
static inline float extruder_range_slow_down_proportional(
|
||||
std::vector<PerExtruderAdjustments*>::iterator it_begin,
|
||||
std::vector<PerExtruderAdjustments*>::iterator it_end,
|
||||
// Elapsed time for the extruders already processed.
|
||||
float elapsed_time_total0,
|
||||
// Initial total elapsed time before slow down.
|
||||
float elapsed_time_before_slowdown,
|
||||
// Target time for the complete layer (all extruders applied).
|
||||
float slow_down_layer_time)
|
||||
{
|
||||
// Total layer time after the slow down has been applied.
|
||||
float total_after_slowdown = elapsed_time_before_slowdown;
|
||||
// Now decide, whether the external perimeters shall be slowed down as well.
|
||||
float max_time_nep = elapsed_time_total0;
|
||||
for (auto it = it_begin; it != it_end; ++ it)
|
||||
max_time_nep += (*it)->maximum_time_after_slowdown(false);
|
||||
if (max_time_nep > slow_down_layer_time) {
|
||||
// It is sufficient to slow down the non-external perimeter moves to reach the target layer time.
|
||||
// Slow down the non-external perimeters proportionally.
|
||||
float non_adjustable_time = elapsed_time_total0;
|
||||
for (auto it = it_begin; it != it_end; ++ it)
|
||||
non_adjustable_time += (*it)->non_adjustable_time(false);
|
||||
// The following step is a linear programming task due to the minimum movement speeds of the print moves.
|
||||
// Run maximum 5 iterations until a good enough approximation is reached.
|
||||
for (size_t iter = 0; iter < 5; ++ iter) {
|
||||
float factor = (slow_down_layer_time - non_adjustable_time) / (total_after_slowdown - non_adjustable_time);
|
||||
assert(factor > 1.f);
|
||||
total_after_slowdown = elapsed_time_total0;
|
||||
for (auto it = it_begin; it != it_end; ++ it)
|
||||
total_after_slowdown += (*it)->slow_down_proportional(factor, false);
|
||||
if (total_after_slowdown > 0.95f * slow_down_layer_time)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Slow down everything. First slow down the non-external perimeters to maximum.
|
||||
for (auto it = it_begin; it != it_end; ++ it)
|
||||
(*it)->slowdown_to_minimum_feedrate(false);
|
||||
// Slow down the external perimeters proportionally.
|
||||
float non_adjustable_time = elapsed_time_total0;
|
||||
for (auto it = it_begin; it != it_end; ++ it)
|
||||
non_adjustable_time += (*it)->non_adjustable_time(true);
|
||||
for (size_t iter = 0; iter < 5; ++ iter) {
|
||||
float factor = (slow_down_layer_time - non_adjustable_time) / (total_after_slowdown - non_adjustable_time);
|
||||
assert(factor > 1.f);
|
||||
total_after_slowdown = elapsed_time_total0;
|
||||
for (auto it = it_begin; it != it_end; ++ it)
|
||||
total_after_slowdown += (*it)->slow_down_proportional(factor, true);
|
||||
if (total_after_slowdown > 0.95f * slow_down_layer_time)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return total_after_slowdown;
|
||||
}
|
||||
|
||||
// Slow down an extruder range to slow_down_layer_time.
|
||||
// Return the total time for the complete layer.
|
||||
static inline void extruder_range_slow_down_non_proportional(
|
||||
|
|
@ -674,9 +618,8 @@ float CoolingBuffer::calculate_layer_slowdown(std::vector<PerExtruderAdjustments
|
|||
adj.time_maximum = adj.maximum_time_after_slowdown(true);
|
||||
if (adj.cooling_slow_down_enabled && adj.lines.size() > 0) {
|
||||
by_slowdown_time.emplace_back(&adj);
|
||||
if (! m_cooling_logic_proportional)
|
||||
// sorts the lines, also sets adj.time_non_adjustable
|
||||
adj.sort_lines_by_decreasing_feedrate();
|
||||
// sorts the lines, also sets adj.time_non_adjustable
|
||||
adj.sort_lines_by_decreasing_feedrate();
|
||||
} else
|
||||
elapsed_time_total0 += adj.elapsed_time_total();
|
||||
}
|
||||
|
|
@ -700,10 +643,7 @@ float CoolingBuffer::calculate_layer_slowdown(std::vector<PerExtruderAdjustments
|
|||
for (auto it = cur_begin; it != by_slowdown_time.end(); ++ it)
|
||||
max_time += (*it)->time_maximum;
|
||||
if (max_time > slow_down_layer_time) {
|
||||
if (m_cooling_logic_proportional)
|
||||
extruder_range_slow_down_proportional(cur_begin, by_slowdown_time.end(), elapsed_time_total0, total, slow_down_layer_time);
|
||||
else
|
||||
extruder_range_slow_down_non_proportional(cur_begin, by_slowdown_time.end(), slow_down_layer_time - total);
|
||||
extruder_range_slow_down_non_proportional(cur_begin, by_slowdown_time.end(), slow_down_layer_time - total);
|
||||
} else {
|
||||
// Slow down to maximum possible.
|
||||
for (auto it = cur_begin; it != by_slowdown_time.end(); ++ it)
|
||||
|
|
|
|||
|
|
@ -54,9 +54,6 @@ private:
|
|||
// the PrintConfig slice of FullPrintConfig is constant, thus no thread synchronization is required.
|
||||
const PrintConfig &m_config;
|
||||
unsigned int m_current_extruder;
|
||||
|
||||
// Old logic: proportional.
|
||||
bool m_cooling_logic_proportional = false;
|
||||
//BBS: current fan speed
|
||||
int m_current_fan_speed;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ static const float DEFAULT_FILAMENT_DIAMETER = 1.75f;
|
|||
static const int DEFAULT_FILAMENT_HRC = 0;
|
||||
static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
|
||||
static const float DEFAULT_FILAMENT_COST = 29.99f;
|
||||
static const float DEFAULT_FILAMENT_FLOW_RATIOS = 1.0f;
|
||||
static const int DEFAULT_FILAMENT_VITRIFICATION_TEMPERATURE = 0;
|
||||
static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
|
||||
|
||||
|
|
@ -392,8 +391,10 @@ void GCodeProcessor::TimeProcessor::reset()
|
|||
extruder_unloaded = true;
|
||||
machine_envelope_processing_enabled = false;
|
||||
machine_limits = MachineEnvelopeConfig();
|
||||
filament_load_times = std::vector<float>();
|
||||
filament_unload_times = std::vector<float>();
|
||||
filament_load_times = 0.0f;
|
||||
filament_unload_times = 0.0f;
|
||||
machine_tool_change_time = 0.0f;
|
||||
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
machines[i].reset();
|
||||
|
|
@ -953,7 +954,6 @@ void GCodeProcessorResult::reset() {
|
|||
required_nozzle_HRC = std::vector<int>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_HRC);
|
||||
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
|
||||
filament_costs = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_COST);
|
||||
filament_flow_ratios = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_FLOW_RATIOS);
|
||||
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
|
||||
spiral_vase_layers = std::vector<std::pair<float, std::pair<size_t, size_t>>>();
|
||||
bed_match_result = BedMatchResult(true);
|
||||
|
|
@ -1076,7 +1076,6 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
m_result.filament_densities.resize(extruders_count);
|
||||
m_result.filament_vitrification_temperature.resize(extruders_count);
|
||||
m_result.filament_costs.resize(extruders_count);
|
||||
m_result.filament_flow_ratios.resize(extruders_count);
|
||||
m_extruder_temps.resize(extruders_count);
|
||||
m_extruder_temps_config.resize(extruders_count);
|
||||
m_extruder_temps_first_layer_config.resize(extruders_count);
|
||||
|
|
@ -1096,7 +1095,6 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
m_result.filament_densities[i] = static_cast<float>(config.filament_density.get_at(i));
|
||||
m_result.filament_vitrification_temperature[i] = static_cast<float>(config.temperature_vitrification.get_at(i));
|
||||
m_result.filament_costs[i] = static_cast<float>(config.filament_cost.get_at(i));
|
||||
m_result.filament_flow_ratios[i] = static_cast<float>(config.filament_flow_ratio.get_at(i));
|
||||
}
|
||||
|
||||
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfKlipper || m_flavor == gcfRepRapFirmware) {
|
||||
|
|
@ -1115,23 +1113,9 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
// Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful.
|
||||
// As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
|
||||
// are considered to be active for the single extruder multi-material printers only.
|
||||
if(s_IsBBLPrinter){
|
||||
// BBL printers use machine_load_filament_time and machine_unload_filament_time
|
||||
m_time_processor.filament_load_times.resize(1);
|
||||
m_time_processor.filament_load_times[0] = static_cast<float>(config.machine_load_filament_time.value);
|
||||
m_time_processor.filament_unload_times.resize(1);
|
||||
m_time_processor.filament_unload_times[0] = static_cast<float>(config.machine_unload_filament_time.value);
|
||||
} else {
|
||||
// for non-BBL printers use the filament_load_time and filament_unload_time
|
||||
m_time_processor.filament_load_times.resize(config.filament_load_time.values.size());
|
||||
for (size_t i = 0; i < config.filament_load_time.values.size(); ++i) {
|
||||
m_time_processor.filament_load_times[i] = static_cast<float>(config.filament_load_time.values[i]);
|
||||
}
|
||||
m_time_processor.filament_unload_times.resize(config.filament_unload_time.values.size());
|
||||
for (size_t i = 0; i < config.filament_unload_time.values.size(); ++i) {
|
||||
m_time_processor.filament_unload_times[i] = static_cast<float>(config.filament_unload_time.values[i]);
|
||||
}
|
||||
}
|
||||
m_time_processor.filament_load_times = static_cast<float>(config.machine_load_filament_time.value);
|
||||
m_time_processor.filament_unload_times = static_cast<float>(config.machine_unload_filament_time.value);
|
||||
m_time_processor.machine_tool_change_time = static_cast<float>(config.machine_tool_change_time.value);
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
|
||||
|
|
@ -1274,15 +1258,6 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
|||
m_result.filament_costs.emplace_back(DEFAULT_FILAMENT_COST);
|
||||
}
|
||||
|
||||
// Orca: filament flow ratio
|
||||
const ConfigOptionFloats* filament_flow_ratios = config.option<ConfigOptionFloats>("filament_flow_ratio");
|
||||
if (filament_flow_ratios != nullptr) {
|
||||
m_result.filament_flow_ratios.clear();
|
||||
m_result.filament_flow_ratios.resize(filament_flow_ratios->values.size());
|
||||
for (size_t i = 0; i < filament_flow_ratios->values.size(); ++i)
|
||||
m_result.filament_flow_ratios[i]=static_cast<float>(filament_flow_ratios->values[i]);
|
||||
}
|
||||
|
||||
//BBS
|
||||
const ConfigOptionInts* filament_vitrification_temperature = config.option<ConfigOptionInts>("temperature_vitrification");
|
||||
if (filament_vitrification_temperature != nullptr) {
|
||||
|
|
@ -1352,36 +1327,18 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
|||
|
||||
m_extruder_temps.resize(m_result.extruders_count);
|
||||
|
||||
if(s_IsBBLPrinter){
|
||||
// BBL printers use machine_load_filament_time and machine_unload_filament_time
|
||||
const ConfigOptionFloat* machine_load_filament_time = config.option<ConfigOptionFloat>("machine_load_filament_time");
|
||||
if (machine_load_filament_time != nullptr){
|
||||
m_time_processor.filament_load_times.resize(1);
|
||||
m_time_processor.filament_load_times[0] = static_cast<float>(machine_load_filament_time->value);
|
||||
}
|
||||
const ConfigOptionFloat* machine_load_filament_time = config.option<ConfigOptionFloat>("machine_load_filament_time");
|
||||
if (machine_load_filament_time != nullptr)
|
||||
m_time_processor.filament_load_times = static_cast<float>(machine_load_filament_time->value);
|
||||
|
||||
const ConfigOptionFloat* machine_unload_filament_time = config.option<ConfigOptionFloat>("machine_unload_filament_time");
|
||||
if (machine_unload_filament_time != nullptr)
|
||||
m_time_processor.filament_unload_times = static_cast<float>(machine_unload_filament_time->value);
|
||||
|
||||
const ConfigOptionFloat* machine_tool_change_time = config.option<ConfigOptionFloat>("machine_tool_change_time");
|
||||
if (machine_tool_change_time != nullptr)
|
||||
m_time_processor.machine_tool_change_time = static_cast<float>(machine_tool_change_time->value);
|
||||
|
||||
const ConfigOptionFloat* machine_unload_filament_time = config.option<ConfigOptionFloat>("machine_unload_filament_time");
|
||||
if (machine_unload_filament_time != nullptr){
|
||||
m_time_processor.filament_unload_times.resize(1);
|
||||
m_time_processor.filament_unload_times[0] = static_cast<float>(machine_unload_filament_time->value);
|
||||
}
|
||||
} else {
|
||||
// non-BBL printers use filament_load_time and filament_unload_time
|
||||
const ConfigOptionFloats* filament_load_time = config.option<ConfigOptionFloats>("filament_load_time");
|
||||
if (filament_load_time != nullptr) {
|
||||
m_time_processor.filament_load_times.resize(filament_load_time->values.size());
|
||||
for (size_t i = 0; i < filament_load_time->values.size(); ++i) {
|
||||
m_time_processor.filament_load_times[i] = static_cast<float>(filament_load_time->values[i]);
|
||||
}
|
||||
}
|
||||
const ConfigOptionFloats* filament_unload_time = config.option<ConfigOptionFloats>("filament_unload_time");
|
||||
if (filament_unload_time != nullptr) {
|
||||
m_time_processor.filament_unload_times.resize(filament_unload_time->values.size());
|
||||
for (size_t i = 0; i < filament_unload_time->values.size(); ++i) {
|
||||
m_time_processor.filament_unload_times[i] = static_cast<float>(filament_unload_time->values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfKlipper) {
|
||||
const ConfigOptionFloats* machine_max_acceleration_x = config.option<ConfigOptionFloats>("machine_max_acceleration_x");
|
||||
|
|
@ -2960,7 +2917,6 @@ void GCodeProcessor::process_G0(const GCodeReader::GCodeLine& line)
|
|||
void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line, const std::optional<unsigned int>& remaining_internal_g1_lines)
|
||||
{
|
||||
float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
|
||||
float filament_flowratio = (static_cast<size_t>(m_extruder_id) < m_result.filament_flow_ratios.size()) ? m_result.filament_flow_ratios[m_extruder_id] : m_result.filament_flow_ratios.back();
|
||||
float filament_radius = 0.5f * filament_diameter;
|
||||
float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
|
||||
auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) {
|
||||
|
|
@ -3038,7 +2994,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line, const std::o
|
|||
m_used_filaments.increase_model_caches(volume_extruded_filament);
|
||||
}
|
||||
// volume extruded filament / tool displacement = area toolpath cross section
|
||||
m_mm3_per_mm = area_toolpath_cross_section * filament_flowratio;
|
||||
m_mm3_per_mm = area_toolpath_cross_section;
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role);
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
|
@ -3389,7 +3345,6 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line, const std::o
|
|||
void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
|
||||
float filament_flowratio = (static_cast<size_t>(m_extruder_id) < m_result.filament_flow_ratios.size()) ? m_result.filament_flow_ratios[m_extruder_id] : m_result.filament_flow_ratios.back();
|
||||
float filament_radius = 0.5f * filament_diameter;
|
||||
float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
|
||||
auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG2_3) {
|
||||
|
|
@ -3481,6 +3436,7 @@ 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));
|
||||
|
||||
|
|
@ -3517,7 +3473,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
|||
m_used_filaments.increase_model_caches(volume_extruded_filament);
|
||||
}
|
||||
//BBS: volume extruded filament / tool displacement = area toolpath cross section
|
||||
m_mm3_per_mm = area_toolpath_cross_section * filament_flowratio;
|
||||
m_mm3_per_mm = area_toolpath_cross_section;
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role);
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
|
@ -4373,6 +4329,7 @@ void GCodeProcessor::process_T(const std::string_view command)
|
|||
float extra_time = get_filament_unload_time(static_cast<size_t>(m_last_extruder_id));
|
||||
m_time_processor.extruder_unloaded = false;
|
||||
extra_time += get_filament_load_time(static_cast<size_t>(m_extruder_id));
|
||||
extra_time += m_time_processor.machine_tool_change_time;
|
||||
simulate_st_synchronize(extra_time);
|
||||
}
|
||||
|
||||
|
|
@ -5277,32 +5234,14 @@ void GCodeProcessor::set_travel_acceleration(PrintEstimatedStatistics::ETimeMode
|
|||
|
||||
float GCodeProcessor::get_filament_load_time(size_t extruder_id)
|
||||
{
|
||||
if (s_IsBBLPrinter) {
|
||||
// BBL printers
|
||||
// BBS: change load time to machine config and all extruder has same value
|
||||
return m_time_processor.extruder_unloaded ? 0.0f : m_time_processor.filament_load_times[0];
|
||||
} else {
|
||||
// non-BBL printers
|
||||
return (m_time_processor.filament_load_times.empty() || m_time_processor.extruder_unloaded) ?
|
||||
0.0f :
|
||||
((extruder_id < m_time_processor.filament_load_times.size()) ? m_time_processor.filament_load_times[extruder_id] :
|
||||
m_time_processor.filament_load_times.front());
|
||||
}
|
||||
//BBS: change load time to machine config and all extruder has same value
|
||||
return m_time_processor.extruder_unloaded ? 0.0f : m_time_processor.filament_load_times;
|
||||
}
|
||||
|
||||
float GCodeProcessor::get_filament_unload_time(size_t extruder_id)
|
||||
{
|
||||
if (s_IsBBLPrinter) {
|
||||
// BBL printers
|
||||
// BBS: change unload time to machine config and all extruder has same value
|
||||
return m_time_processor.extruder_unloaded ? 0.0f : m_time_processor.filament_unload_times[0];
|
||||
} else {
|
||||
// non-BBL printers
|
||||
return (m_time_processor.filament_unload_times.empty() || m_time_processor.extruder_unloaded) ?
|
||||
0.0f :
|
||||
((extruder_id < m_time_processor.filament_unload_times.size()) ? m_time_processor.filament_unload_times[extruder_id] :
|
||||
m_time_processor.filament_unload_times.front());
|
||||
}
|
||||
//BBS: change unload time to machine config and all extruder has same value
|
||||
return m_time_processor.extruder_unloaded ? 0.0f : m_time_processor.filament_unload_times;
|
||||
}
|
||||
|
||||
//BBS
|
||||
|
|
|
|||
|
|
@ -215,7 +215,6 @@ class Print;
|
|||
std::vector<int> required_nozzle_HRC;
|
||||
std::vector<float> filament_densities;
|
||||
std::vector<float> filament_costs;
|
||||
std::vector<float> filament_flow_ratios;
|
||||
std::vector<int> filament_vitrification_temperature;
|
||||
PrintEstimatedStatistics print_statistics;
|
||||
std::vector<CustomGCode::Item> custom_gcode_per_print_z;
|
||||
|
|
@ -251,7 +250,6 @@ class Print;
|
|||
filament_diameters = other.filament_diameters;
|
||||
filament_densities = other.filament_densities;
|
||||
filament_costs = other.filament_costs;
|
||||
filament_flow_ratios = other.filament_flow_ratios;
|
||||
print_statistics = other.print_statistics;
|
||||
custom_gcode_per_print_z = other.custom_gcode_per_print_z;
|
||||
spiral_vase_layers = other.spiral_vase_layers;
|
||||
|
|
@ -492,8 +490,10 @@ class Print;
|
|||
bool machine_envelope_processing_enabled;
|
||||
MachineEnvelopeConfig machine_limits;
|
||||
// Additional load / unload times for a filament exchange sequence.
|
||||
std::vector<float> filament_load_times;
|
||||
std::vector<float> filament_unload_times;
|
||||
float filament_load_times;
|
||||
float filament_unload_times;
|
||||
//Orca: time for tool change
|
||||
float machine_tool_change_time;
|
||||
bool disable_m73;
|
||||
|
||||
std::array<TimeMachine, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> machines;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "../ClipperUtils.hpp"
|
||||
#include "../Layer.hpp"
|
||||
#include "../Polyline.hpp"
|
||||
|
||||
#include "RetractWhenCrossingPerimeters.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -1486,7 +1486,7 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
|
|||
}
|
||||
}
|
||||
|
||||
void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first,
|
||||
void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop,
|
||||
const Point &last_pos, float& overhang) const {
|
||||
using namespace SeamPlacerImpl;
|
||||
const PrintObject *po = layer->object();
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ public:
|
|||
|
||||
void init(const Print &print, std::function<void(void)> throw_if_canceled_func);
|
||||
|
||||
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos, float& overhang) const;
|
||||
void place_seam(const Layer *layer, ExtrusionLoop &loop, const Point &last_pos, float& overhang) const;
|
||||
private:
|
||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_candidates_visibility(const PrintObject *po,
|
||||
|
|
|
|||
|
|
@ -325,6 +325,7 @@ 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()) {
|
||||
|
|
@ -353,6 +354,7 @@ 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++) {
|
||||
|
|
@ -385,6 +387,7 @@ 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()) {
|
||||
|
|
@ -409,6 +412,7 @@ 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,6 +1072,8 @@ 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) {
|
||||
|
|
@ -1130,6 +1132,8 @@ 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())
|
||||
|
|
@ -1418,6 +1422,7 @@ 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;
|
||||
|
|
|
|||
|
|
@ -34,8 +34,10 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config)
|
|||
std::round((use_mach_limits && supports_separate_travel_acceleration(print_config.gcode_flavor.value)) ?
|
||||
print_config.machine_max_acceleration_travel.values.front() :
|
||||
0));
|
||||
m_max_jerk = std::lrint(
|
||||
use_mach_limits ? std::min(print_config.machine_max_jerk_x.values.front(), print_config.machine_max_jerk_y.values.front()) : 0);
|
||||
if (use_mach_limits) {
|
||||
m_max_jerk_x = std::lrint(print_config.machine_max_jerk_x.values.front());
|
||||
m_max_jerk_y = std::lrint(print_config.machine_max_jerk_y.values.front());
|
||||
};
|
||||
m_max_jerk_z = print_config.machine_max_jerk_z.values.front();
|
||||
m_max_jerk_e = print_config.machine_max_jerk_e.values.front();
|
||||
}
|
||||
|
|
@ -230,20 +232,31 @@ std::string GCodeWriter::set_acceleration_internal(Acceleration type, unsigned i
|
|||
|
||||
std::string GCodeWriter::set_jerk_xy(double jerk)
|
||||
{
|
||||
// Clamp the jerk to the allowed maximum.
|
||||
if (m_max_jerk > 0 && jerk > m_max_jerk)
|
||||
jerk = m_max_jerk;
|
||||
|
||||
if (jerk < 0.01 || is_approx(jerk, m_last_jerk))
|
||||
return std::string();
|
||||
|
||||
m_last_jerk = jerk;
|
||||
|
||||
|
||||
std::ostringstream gcode;
|
||||
if(FLAVOR_IS(gcfKlipper))
|
||||
if (FLAVOR_IS(gcfKlipper)) {
|
||||
// Clamp the jerk to the allowed maximum.
|
||||
if (m_max_jerk_x > 0 && jerk > m_max_jerk_x)
|
||||
jerk = m_max_jerk_x;
|
||||
if (m_max_jerk_y > 0 && jerk > m_max_jerk_y)
|
||||
jerk = m_max_jerk_y;
|
||||
|
||||
gcode << "SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=" << jerk;
|
||||
else
|
||||
gcode << "M205 X" << jerk << " Y" << jerk;
|
||||
} else {
|
||||
double jerk_x = jerk;
|
||||
double jerk_y = jerk;
|
||||
// Clamp the axis jerk to the allowed maximum.
|
||||
if (m_max_jerk_x > 0 && jerk > m_max_jerk_x)
|
||||
jerk_x = m_max_jerk_x;
|
||||
if (m_max_jerk_y > 0 && jerk > m_max_jerk_y)
|
||||
jerk_y = m_max_jerk_y;
|
||||
|
||||
gcode << "M205 X" << jerk_x << " Y" << jerk_y;
|
||||
}
|
||||
|
||||
if (m_is_bbl_printers)
|
||||
gcode << std::setprecision(2) << " Z" << m_max_jerk_z << " E" << m_max_jerk_e;
|
||||
|
|
@ -277,8 +290,10 @@ std::string GCodeWriter::set_accel_and_jerk(unsigned int acceleration, double je
|
|||
is_empty = false;
|
||||
}
|
||||
// Clamp the jerk to the allowed maximum.
|
||||
if (m_max_jerk > 0 && jerk > m_max_jerk)
|
||||
jerk = m_max_jerk;
|
||||
if (m_max_jerk_x > 0 && jerk > m_max_jerk_x)
|
||||
jerk = m_max_jerk_x;
|
||||
if (m_max_jerk_y > 0 && jerk > m_max_jerk_y)
|
||||
jerk = m_max_jerk_y;
|
||||
|
||||
if (jerk > 0.01 && !is_approx(jerk, m_last_jerk)) {
|
||||
gcode << " SQUARE_CORNER_VELOCITY=" << jerk;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public:
|
|||
multiple_extruders(false), m_extruder(nullptr),
|
||||
m_single_extruder_multi_material(false),
|
||||
m_last_acceleration(0), m_max_acceleration(0),m_last_travel_acceleration(0), m_max_travel_acceleration(0),
|
||||
m_last_jerk(0), m_max_jerk(0),
|
||||
m_last_jerk(0), m_max_jerk_x(0), m_max_jerk_y(0),
|
||||
m_last_bed_temperature(0), m_last_bed_temperature_reached(true),
|
||||
m_lifted(0),
|
||||
m_to_lift(0),
|
||||
|
|
@ -130,7 +130,8 @@ public:
|
|||
// Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware.
|
||||
// If set to zero, the limit is not in action.
|
||||
unsigned int m_max_acceleration;
|
||||
double m_max_jerk;
|
||||
double m_max_jerk_x;
|
||||
double m_max_jerk_y;
|
||||
double m_last_jerk;
|
||||
double m_max_jerk_z;
|
||||
double m_max_jerk_e;
|
||||
|
|
|
|||
|
|
@ -4,14 +4,21 @@
|
|||
#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,5 +1,7 @@
|
|||
#include "Circle.hpp"
|
||||
|
||||
#include "../Polygon.hpp"
|
||||
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include <boost/log/trivial.hpp>
|
||||
#include "MedialAxis.hpp"
|
||||
|
||||
#include "clipper.hpp"
|
||||
#include "VoronoiOffset.hpp"
|
||||
#include "../ClipperUtils.hpp"
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
namespace boost { namespace polygon {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#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,3 +1,5 @@
|
|||
// Needed since the CGAL headers are not self-contained.
|
||||
#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,18 +1,26 @@
|
|||
#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,7 +1,9 @@
|
|||
#include "Geometry.hpp"
|
||||
#include "Line.hpp"
|
||||
#include "Polyline.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
|
|||
|
|
@ -201,12 +201,12 @@ indexed_triangle_set cgal_to_indexed_triangle_set(const _Mesh &cgalmesh)
|
|||
const auto &vertices = cgalmesh.vertices();
|
||||
int vsize = int(vertices.size());
|
||||
|
||||
for (auto &vi : vertices) {
|
||||
for (const auto &vi : vertices) {
|
||||
auto &v = cgalmesh.point(vi); // Don't ask...
|
||||
its.vertices.emplace_back(to_vec3f(v));
|
||||
}
|
||||
|
||||
for (auto &face : faces) {
|
||||
for (const auto &face : faces) {
|
||||
auto vtc = cgalmesh.vertices_around_face(cgalmesh.halfedge(face));
|
||||
|
||||
int i = 0;
|
||||
|
|
@ -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 (unsigned int n = 0; n < numConnComps; ++n) {
|
||||
for (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 (other.get_model()) {
|
||||
if (auto model = 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,6 +2930,9 @@ 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();
|
||||
|
|
@ -3029,6 +3032,7 @@ 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;
|
||||
|
|
@ -3293,7 +3297,7 @@ bool FacetsAnnotation::has_facets(const ModelVolume& mv, EnforcerBlockerType typ
|
|||
|
||||
bool FacetsAnnotation::set(const TriangleSelector& selector)
|
||||
{
|
||||
std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> sel_map = selector.serialize();
|
||||
TriangleSelector::TriangleSplittingData sel_map = selector.serialize();
|
||||
if (sel_map != m_data) {
|
||||
m_data = std::move(sel_map);
|
||||
this->touch();
|
||||
|
|
@ -3304,8 +3308,8 @@ bool FacetsAnnotation::set(const TriangleSelector& selector)
|
|||
|
||||
void FacetsAnnotation::reset()
|
||||
{
|
||||
m_data.first.clear();
|
||||
m_data.second.clear();
|
||||
m_data.triangles_to_split.clear();
|
||||
m_data.bitstream.clear();
|
||||
this->touch();
|
||||
}
|
||||
|
||||
|
|
@ -3316,15 +3320,15 @@ std::string FacetsAnnotation::get_triangle_as_string(int triangle_idx) const
|
|||
{
|
||||
std::string out;
|
||||
|
||||
auto triangle_it = std::lower_bound(m_data.first.begin(), m_data.first.end(), triangle_idx, [](const std::pair<int, int> &l, const int r) { return l.first < r; });
|
||||
if (triangle_it != m_data.first.end() && triangle_it->first == triangle_idx) {
|
||||
int offset = triangle_it->second;
|
||||
int end = ++ triangle_it == m_data.first.end() ? int(m_data.second.size()) : triangle_it->second;
|
||||
auto triangle_it = std::lower_bound(m_data.triangles_to_split.begin(), m_data.triangles_to_split.end(), triangle_idx, [](const TriangleSelector::TriangleBitStreamMapping &l, const int r) { return l.triangle_idx < r; });
|
||||
if (triangle_it != m_data.triangles_to_split.end() && triangle_it->triangle_idx == triangle_idx) {
|
||||
int offset = triangle_it->bitstream_start_idx;
|
||||
int end = ++ triangle_it == m_data.triangles_to_split.end() ? int(m_data.bitstream.size()) : triangle_it->bitstream_start_idx;
|
||||
while (offset < end) {
|
||||
int next_code = 0;
|
||||
for (int i=3; i>=0; --i) {
|
||||
next_code = next_code << 1;
|
||||
next_code |= int(m_data.second[offset + i]);
|
||||
next_code |= int(m_data.bitstream[offset + i]);
|
||||
}
|
||||
offset += 4;
|
||||
|
||||
|
|
@ -3341,9 +3345,10 @@ std::string FacetsAnnotation::get_triangle_as_string(int triangle_idx) const
|
|||
void FacetsAnnotation::set_triangle_from_string(int triangle_id, const std::string& str)
|
||||
{
|
||||
assert(! str.empty());
|
||||
assert(m_data.first.empty() || m_data.first.back().first < triangle_id);
|
||||
m_data.first.emplace_back(triangle_id, int(m_data.second.size()));
|
||||
assert(m_data.triangles_to_split.empty() || m_data.triangles_to_split.back().triangle_idx < triangle_id);
|
||||
m_data.triangles_to_split.emplace_back(triangle_id, int(m_data.bitstream.size()));
|
||||
|
||||
const size_t bitstream_start_idx = m_data.bitstream.size();
|
||||
for (auto it = str.crbegin(); it != str.crend(); ++it) {
|
||||
const char ch = *it;
|
||||
int dec = 0;
|
||||
|
|
@ -3355,14 +3360,16 @@ void FacetsAnnotation::set_triangle_from_string(int triangle_id, const std::stri
|
|||
assert(false);
|
||||
|
||||
// Convert to binary and append into code.
|
||||
for (int i=0; i<4; ++i)
|
||||
m_data.second.insert(m_data.second.end(), bool(dec & (1 << i)));
|
||||
for (int i = 0; i < 4; ++i)
|
||||
m_data.bitstream.insert(m_data.bitstream.end(), bool(dec & (1 << i)));
|
||||
}
|
||||
|
||||
m_data.update_used_states(bitstream_start_idx);
|
||||
}
|
||||
|
||||
bool FacetsAnnotation::equals(const FacetsAnnotation &other) const
|
||||
{
|
||||
const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>>& data = other.get_data();
|
||||
const auto& data = other.get_data();
|
||||
return (m_data == data);
|
||||
}
|
||||
|
||||
|
|
@ -3531,7 +3538,7 @@ void check_model_ids_validity(const Model &model)
|
|||
for (const ModelInstance *model_instance : model_object->instances)
|
||||
check(model_instance->id());
|
||||
}
|
||||
for (const auto mm : model.materials) {
|
||||
for (const auto& mm : model.materials) {
|
||||
check(mm.second->id());
|
||||
check(mm.second->config.id());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "enum_bitmask.hpp"
|
||||
#include "TextConfiguration.hpp"
|
||||
#include "EmbossShape.hpp"
|
||||
#include "TriangleSelector.hpp"
|
||||
|
||||
//BBS: add bbs 3mf
|
||||
#include "Format/bbs_3mf.hpp"
|
||||
|
|
@ -704,31 +705,6 @@ private:
|
|||
void update_min_max_z();
|
||||
};
|
||||
|
||||
enum class EnforcerBlockerType : int8_t {
|
||||
// Maximum is 3. The value is serialized in TriangleSelector into 2 bits.
|
||||
NONE = 0,
|
||||
ENFORCER = 1,
|
||||
BLOCKER = 2,
|
||||
// Maximum is 15. The value is serialized in TriangleSelector into 6 bits using a 2 bit prefix code.
|
||||
Extruder1 = ENFORCER,
|
||||
Extruder2 = BLOCKER,
|
||||
Extruder3,
|
||||
Extruder4,
|
||||
Extruder5,
|
||||
Extruder6,
|
||||
Extruder7,
|
||||
Extruder8,
|
||||
Extruder9,
|
||||
Extruder10,
|
||||
Extruder11,
|
||||
Extruder12,
|
||||
Extruder13,
|
||||
Extruder14,
|
||||
Extruder15,
|
||||
Extruder16,
|
||||
ExtruderMax = Extruder16
|
||||
};
|
||||
|
||||
enum class ConversionType : int {
|
||||
CONV_TO_INCH,
|
||||
CONV_FROM_INCH,
|
||||
|
|
@ -745,9 +721,9 @@ enum class En3mfType : int {
|
|||
class FacetsAnnotation final : public ObjectWithTimestamp {
|
||||
public:
|
||||
// Assign the content if the timestamp differs, don't assign an ObjectID.
|
||||
void assign(const FacetsAnnotation& rhs) { if (! this->timestamp_matches(rhs)) { m_data = rhs.m_data; this->copy_timestamp(rhs); } }
|
||||
void assign(FacetsAnnotation&& rhs) { if (! this->timestamp_matches(rhs)) { m_data = std::move(rhs.m_data); this->copy_timestamp(rhs); } }
|
||||
const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>>& get_data() const throw() { return m_data; }
|
||||
void assign(const FacetsAnnotation &rhs) { if (! this->timestamp_matches(rhs)) { m_data = rhs.m_data; this->copy_timestamp(rhs); } }
|
||||
void assign(FacetsAnnotation &&rhs) { if (! this->timestamp_matches(rhs)) { m_data = std::move(rhs.m_data); this->copy_timestamp(rhs); } }
|
||||
const TriangleSelector::TriangleSplittingData &get_data() const noexcept { return m_data; }
|
||||
bool set(const TriangleSelector& selector);
|
||||
indexed_triangle_set get_facets(const ModelVolume& mv, EnforcerBlockerType type) const;
|
||||
// BBS
|
||||
|
|
@ -755,7 +731,7 @@ public:
|
|||
void set_enforcer_block_type_limit(const ModelVolume& mv, EnforcerBlockerType max_type);
|
||||
indexed_triangle_set get_facets_strict(const ModelVolume& mv, EnforcerBlockerType type) const;
|
||||
bool has_facets(const ModelVolume& mv, EnforcerBlockerType type) const;
|
||||
bool empty() const { return m_data.first.empty(); }
|
||||
bool empty() const { return m_data.triangles_to_split.empty(); }
|
||||
|
||||
// Following method clears the config and increases its timestamp, so the deleted
|
||||
// state is considered changed from perspective of the undo/redo stack.
|
||||
|
|
@ -765,11 +741,11 @@ public:
|
|||
std::string get_triangle_as_string(int i) const;
|
||||
|
||||
// Before deserialization, reserve space for n_triangles.
|
||||
void reserve(int n_triangles) { m_data.first.reserve(n_triangles); }
|
||||
void reserve(int n_triangles) { m_data.triangles_to_split.reserve(n_triangles); }
|
||||
// Deserialize triangles one by one, with strictly increasing triangle_id.
|
||||
void set_triangle_from_string(int triangle_id, const std::string& str);
|
||||
// After deserializing the last triangle, shrink data to fit.
|
||||
void shrink_to_fit() { m_data.first.shrink_to_fit(); m_data.second.shrink_to_fit(); }
|
||||
void shrink_to_fit() { m_data.triangles_to_split.shrink_to_fit(); m_data.bitstream.shrink_to_fit(); }
|
||||
bool equals(const FacetsAnnotation &other) const;
|
||||
|
||||
private:
|
||||
|
|
@ -796,7 +772,7 @@ private:
|
|||
ar(cereal::base_class<ObjectWithTimestamp>(this), m_data);
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> m_data;
|
||||
TriangleSelector::TriangleSplittingData m_data;
|
||||
|
||||
// To access set_new_unique_id() when copy / pasting a ModelVolume.
|
||||
friend class ModelVolume;
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ 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,6 +338,7 @@ 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);
|
||||
}
|
||||
|
|
@ -1285,6 +1286,7 @@ 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) {
|
||||
|
|
|
|||
|
|
@ -370,6 +370,59 @@ Points MultiPoint::concave_hull_2d(const Points& pts, const double tolerence)
|
|||
}
|
||||
|
||||
|
||||
//Orca: Distancing function used by IOI wall ordering algorithm for arachne
|
||||
/**
|
||||
* @brief Calculates the squared distance between a point and a line segment defined by two points.
|
||||
*
|
||||
* @param p The point.
|
||||
* @param v The starting point of the line segment.
|
||||
* @param w The ending point of the line segment.
|
||||
* @return double The squared distance between the point and the line segment.
|
||||
*/
|
||||
double MultiPoint::squaredDistanceToLineSegment(const Point& p, const Point& v, const Point& w) {
|
||||
// Calculate the squared length of the line segment
|
||||
double l2 = (v - w).squaredNorm();
|
||||
// If the segment is a single point, return the squared distance to that point
|
||||
if (l2 == 0.0) return (p - v).squaredNorm();
|
||||
// Project point p onto the line defined by v and w, and clamp the projection to the segment
|
||||
double t = std::max(0.0, std::min(1.0, ((p - v).dot(w - v)) / l2));
|
||||
// Compute the projection point
|
||||
Point projection{v.x() + t * (w.x() - v.x()), v.y() + t * (w.y() - v.y())};
|
||||
// Return the squared distance between the point and the projection
|
||||
return (p - projection).squaredNorm();
|
||||
}
|
||||
|
||||
//Orca: Distancing function used by IOI wall ordering algorithm for arachne
|
||||
/**
|
||||
* @brief Calculates the minimum distance between two lines defined by sets of points.
|
||||
*
|
||||
* @param A The first set of points defining a polyline.
|
||||
* @param B The second set of points defining a polyline.
|
||||
* @return double The minimum distance between the two polylines.
|
||||
*/
|
||||
double MultiPoint::minimumDistanceBetweenLinesDefinedByPoints(const Points& A, const Points& B) {
|
||||
double min_distance = std::numeric_limits<double>::infinity();
|
||||
|
||||
// Calculate the minimum distance between segments in A and points in B
|
||||
for (size_t i = 0; i < A.size() - 1; ++i) {
|
||||
for (const auto& b : B) {
|
||||
double distance = squaredDistanceToLineSegment(b, A[i], A[i + 1]);
|
||||
min_distance = std::min(min_distance, std::sqrt(distance));
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the minimum distance between segments in B and points in A
|
||||
for (size_t i = 0; i < B.size() - 1; ++i) {
|
||||
for (const auto& a : A) {
|
||||
double distance = squaredDistanceToLineSegment(a, B[i], B[i + 1]);
|
||||
min_distance = std::min(min_distance, std::sqrt(distance));
|
||||
}
|
||||
}
|
||||
|
||||
return min_distance;
|
||||
}
|
||||
|
||||
|
||||
void MultiPoint3::translate(double x, double y)
|
||||
{
|
||||
for (Vec3crd &p : points) {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,9 @@ public:
|
|||
static Points _douglas_peucker(const Points &points, const double tolerance);
|
||||
static Points visivalingam(const Points& pts, const double tolerance);
|
||||
static Points concave_hull_2d(const Points& pts, const double tolerence);
|
||||
|
||||
//Orca: Distancing function used by IOI wall ordering algorithm for arachne
|
||||
static double minimumDistanceBetweenLinesDefinedByPoints(const Points& A, const Points& B);
|
||||
|
||||
inline auto begin() { return points.begin(); }
|
||||
inline auto begin() const { return points.begin(); }
|
||||
|
|
@ -105,6 +108,10 @@ public:
|
|||
inline auto end() const { return points.end(); }
|
||||
inline auto cbegin() const { return points.begin(); }
|
||||
inline auto cend() const { return points.end(); }
|
||||
|
||||
private:
|
||||
//Orca: Distancing function used by IOI wall ordering algorithm for arachne
|
||||
static double squaredDistanceToLineSegment(const Point& p, const Point& v, const Point& w);
|
||||
};
|
||||
|
||||
class MultiPoint3
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ 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();
|
||||
|
|
@ -228,10 +230,10 @@ public:
|
|||
{
|
||||
std::unordered_map<stl_normal, float, VecHash> alignments;
|
||||
// init to 0
|
||||
for (Eigen::Index i = 0; i < areas_.size(); i++)
|
||||
for (size_t i = 0; i < areas_.size(); i++)
|
||||
alignments.insert(std::pair(normals_.row(i), 0));
|
||||
// cumulate areas
|
||||
for (Eigen::Index i = 0; i < areas_.size(); i++)
|
||||
for (size_t i = 0; i < areas_.size(); i++)
|
||||
{
|
||||
alignments[normals_.row(i)] += areas_(i);
|
||||
}
|
||||
|
|
@ -255,11 +257,11 @@ public:
|
|||
Vec3f n1 = { 0, 0, 0 };
|
||||
std::vector<float> current_areas = {0, 0};
|
||||
// init to 0
|
||||
for (Eigen::Index i = 0; i < areas_.size(); i++) {
|
||||
for (size_t i = 0; i < areas_.size(); i++) {
|
||||
alignments_.insert(std::pair(quantize_normals_.row(i), std::pair(current_areas, n1)));
|
||||
}
|
||||
// cumulate areas
|
||||
for (Eigen::Index i = 0; i < areas_.size(); i++)
|
||||
for (size_t 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]){
|
||||
|
|
@ -337,7 +339,7 @@ public:
|
|||
|
||||
z_max_hull.resize(mesh_convex_hull.facets_count(), 1);
|
||||
its = mesh_convex_hull.its;
|
||||
for (Eigen::Index i = 0; i < z_max_hull.rows(); i++)
|
||||
for (size_t 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);
|
||||
|
|
@ -391,7 +393,7 @@ public:
|
|||
|
||||
// filter overhang
|
||||
Eigen::VectorXf normal_projection(normals.rows(), 1);// = this->normals.dot(orientation);
|
||||
for (Eigen::Index i = 0; i < normals.rows(); i++)
|
||||
for (size_t i = 0; i < normals.rows(); i++)
|
||||
{
|
||||
normal_projection(i) = normals.row(i).dot(orientation);
|
||||
}
|
||||
|
|
@ -457,6 +459,7 @@ 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,10 +242,12 @@ 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];
|
||||
|
|
@ -938,6 +940,7 @@ 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;
|
||||
|
|
@ -2250,6 +2253,7 @@ 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
|
||||
|
|
@ -2367,6 +2371,7 @@ 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);
|
||||
|
|
@ -2374,6 +2379,7 @@ 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);
|
||||
|
|
@ -2436,6 +2442,166 @@ void PerimeterGenerator::process_no_bridge(Surfaces& all_surfaces, coord_t perim
|
|||
}
|
||||
}
|
||||
|
||||
// ORCA:
|
||||
// Inner Outer Inner wall ordering mode perimeter order optimisation functions
|
||||
/**
|
||||
* @brief Finds all perimeters touching a given set of reference lines, given as indexes.
|
||||
*
|
||||
* @param entities The list of PerimeterGeneratorArachneExtrusion entities.
|
||||
* @param referenceIndices A set of indices representing the reference points.
|
||||
* @param threshold_external The distance threshold to consider for proximity for a reference perimeter with inset index 0
|
||||
* @param threshold_internal The distance threshold to consider for proximity for a reference perimeter with inset index 1+
|
||||
* @param considered_inset_idx What perimeter inset index are we searching for (eg. if we are searching for first internal perimeters proximate to the current reference perimeter, this value should be set to 1 etc).
|
||||
* @return std::vector<int> A vector of indices representing the touching perimeters.
|
||||
*/
|
||||
std::vector<int> findAllTouchingPerimeters(const std::vector<PerimeterGeneratorArachneExtrusion>& entities, const std::unordered_set<int>& referenceIndices, size_t threshold_external, size_t threshold_internal , size_t considered_inset_idx) {
|
||||
std::unordered_set<int> touchingIndices;
|
||||
|
||||
for (const int refIdx : referenceIndices) {
|
||||
const auto& referenceEntity = entities[refIdx];
|
||||
Points referencePoints = Arachne::to_points(*referenceEntity.extrusion);
|
||||
for (size_t i = 0; i < entities.size(); ++i) {
|
||||
// Skip already considered references and the reference entity
|
||||
if (referenceIndices.count(i) > 0) continue;
|
||||
const auto& entity = entities[i];
|
||||
if (entity.extrusion->inset_idx == 0) continue; // Ignore inset index 0 (external) perimeters from the re-ordering even if they are touching
|
||||
|
||||
if (entity.extrusion->inset_idx != considered_inset_idx) { // Find Inset index perimeters that match the requested inset index
|
||||
continue; // skip if they dont match
|
||||
}
|
||||
|
||||
Points points = Arachne::to_points(*entity.extrusion);
|
||||
double distance = MultiPoint::minimumDistanceBetweenLinesDefinedByPoints(referencePoints, points);
|
||||
// Add to touchingIndices if within threshold distance
|
||||
size_t threshold=0;
|
||||
if(referenceEntity.extrusion->inset_idx == 0)
|
||||
threshold = threshold_external;
|
||||
else
|
||||
threshold = threshold_internal;
|
||||
if (distance <= threshold) {
|
||||
touchingIndices.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::vector<int>(touchingIndices.begin(), touchingIndices.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reorders perimeters based on proximity to the reference perimeter
|
||||
*
|
||||
* This approach finds all perimeters touching the external perimeter first and then finds all perimeters touching these new ones until none are left
|
||||
* It ensures a level-by-level traversal, similar to BFS in graph theory.
|
||||
*
|
||||
* @param entities The list of PerimeterGeneratorArachneExtrusion entities.
|
||||
* @param referenceIndex The index of the reference perimeter.
|
||||
* @param threshold_external The distance threshold to consider for proximity for a reference perimeter with inset index 0
|
||||
* @param threshold_internal The distance threshold to consider for proximity for a reference perimeter with inset index 1+
|
||||
* @return std::vector<PerimeterGeneratorArachneExtrusion> The reordered list of perimeters based on proximity.
|
||||
*/
|
||||
std::vector<PerimeterGeneratorArachneExtrusion> reorderPerimetersByProximity(std::vector<PerimeterGeneratorArachneExtrusion> entities, size_t threshold_external, size_t threshold_internal) {
|
||||
std::vector<PerimeterGeneratorArachneExtrusion> reordered;
|
||||
std::unordered_set<int> includedIndices;
|
||||
|
||||
// Function to reorder perimeters starting from a given reference index
|
||||
auto reorderFromReference = [&](int referenceIndex) {
|
||||
std::unordered_set<int> firstLevelIndices;
|
||||
firstLevelIndices.insert(referenceIndex);
|
||||
|
||||
// Find first level touching perimeters
|
||||
std::vector<int> firstLevelTouchingIndices = findAllTouchingPerimeters(entities, firstLevelIndices, threshold_external, threshold_internal, 1);
|
||||
// Bring the largest first level perimeter to the front
|
||||
// The longest first neighbour is most likely the dominant proximate perimeter
|
||||
// hence printing it immediately after the external perimeter should speed things up
|
||||
if (!firstLevelTouchingIndices.empty()) {
|
||||
auto maxIt = std::max_element(firstLevelTouchingIndices.begin(), firstLevelTouchingIndices.end(), [&entities](int a, int b) {
|
||||
return entities[a].extrusion->getLength() < entities[b].extrusion->getLength();
|
||||
});
|
||||
std::iter_swap(maxIt, firstLevelTouchingIndices.end() - 1);
|
||||
}
|
||||
// Insert first level perimeters into reordered list
|
||||
reordered.push_back(entities[referenceIndex]);
|
||||
includedIndices.insert(referenceIndex);
|
||||
|
||||
for (int idx : firstLevelTouchingIndices) {
|
||||
if (includedIndices.count(idx) == 0) {
|
||||
reordered.push_back(entities[idx]);
|
||||
includedIndices.insert(idx);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through all inset indices above 1
|
||||
size_t currentInsetIndex = 2;
|
||||
while (true) {
|
||||
std::unordered_set<int> currentLevelIndices(firstLevelTouchingIndices.begin(), firstLevelTouchingIndices.end());
|
||||
std::vector<int> currentLevelTouchingIndices = findAllTouchingPerimeters(entities, currentLevelIndices, threshold_external, threshold_internal, currentInsetIndex);
|
||||
|
||||
// Break if no more touching perimeters are found
|
||||
if (currentLevelTouchingIndices.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Exclude any already included indices from the current level touching indices
|
||||
currentLevelTouchingIndices.erase(
|
||||
std::remove_if(currentLevelTouchingIndices.begin(), currentLevelTouchingIndices.end(),
|
||||
[&](int idx) { return includedIndices.count(idx) > 0; }),
|
||||
currentLevelTouchingIndices.end());
|
||||
|
||||
// Bring the largest current level perimeter to the end
|
||||
if (!currentLevelTouchingIndices.empty()) {
|
||||
auto maxIt = std::max_element(currentLevelTouchingIndices.begin(), currentLevelTouchingIndices.end(), [&entities](int a, int b) {
|
||||
return entities[a].extrusion->getLength() < entities[b].extrusion->getLength();
|
||||
});
|
||||
std::iter_swap(maxIt, currentLevelTouchingIndices.begin());
|
||||
}
|
||||
|
||||
// Insert current level perimeters into reordered list
|
||||
for (int idx : currentLevelTouchingIndices) {
|
||||
if (includedIndices.count(idx) == 0) {
|
||||
reordered.push_back(entities[idx]);
|
||||
includedIndices.insert(idx);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare for the next level
|
||||
firstLevelTouchingIndices = currentLevelTouchingIndices;
|
||||
currentInsetIndex++;
|
||||
}
|
||||
};
|
||||
|
||||
// Loop through all perimeters and reorder starting from each inset index 0 perimeter
|
||||
for (size_t refIdx = 0; refIdx < entities.size(); ++refIdx) {
|
||||
if (entities[refIdx].extrusion->inset_idx == 0 && includedIndices.count(refIdx) == 0) {
|
||||
reorderFromReference(refIdx);
|
||||
}
|
||||
}
|
||||
|
||||
// Append any remaining entities that were not included
|
||||
for (size_t i = 0; i < entities.size(); ++i) {
|
||||
if (includedIndices.count(i) == 0) {
|
||||
reordered.push_back(entities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return reordered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reorders the vector to bring external perimeter (i.e. paths with inset index 0) that are also contours (i.e. external facing lines) to the front.
|
||||
*
|
||||
* This function uses a stable partition to move all external perimeter contour elements to the front of the vector,
|
||||
* while maintaining the relative order of non-contour elements.
|
||||
*
|
||||
* @param ordered_extrusions The vector of PerimeterGeneratorArachneExtrusion to reorder.
|
||||
*/
|
||||
void bringContoursToFront(std::vector<PerimeterGeneratorArachneExtrusion>& ordered_extrusions) {
|
||||
std::stable_partition(ordered_extrusions.begin(), ordered_extrusions.end(), [](const PerimeterGeneratorArachneExtrusion& extrusion) {
|
||||
return (extrusion.extrusion->is_contour() && extrusion.extrusion->inset_idx==0);
|
||||
});
|
||||
}
|
||||
// ORCA:
|
||||
// Inner Outer Inner wall ordering mode perimeter order optimisation functions ended
|
||||
|
||||
|
||||
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
||||
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
|
||||
void PerimeterGenerator::process_arachne()
|
||||
|
|
@ -2738,39 +2904,22 @@ void PerimeterGenerator::process_arachne()
|
|||
int arr_i, arr_j = 0; // indexes to run through the walls in the for loops
|
||||
int outer, first_internal, second_internal, max_internal, current_perimeter; // allocate index values
|
||||
|
||||
// Initiate reorder sequence to bring any index 1 (first internal) perimeters ahead of any second internal perimeters
|
||||
// Leaving these out of order will result in print defects on the external wall as they will be extruded prior to any
|
||||
// external wall. To do the re-ordering, we are creating two extrusion arrays - reordered_extrusions which will contain
|
||||
// the reordered extrusions and skipped_extrusions will contain the ones that were skipped in the scan
|
||||
std::vector<PerimeterGeneratorArachneExtrusion> reordered_extrusions, skipped_extrusions;
|
||||
bool found_second_internal = false; // helper variable to indicate the start of a new island
|
||||
// To address any remaining scenarios where the outer perimeter contour is not first on the list as arachne sometimes reorders the perimeters when clustering
|
||||
// for OI mode that is used the basis for IOI
|
||||
bringContoursToFront(ordered_extrusions);
|
||||
std::vector<PerimeterGeneratorArachneExtrusion> reordered_extrusions;
|
||||
|
||||
// Get searching thresholds. For an external perimeter we take the middle of the external perimeter width, split it in two, add the spacing to the internal perimeter and add half the internal perimeter width.
|
||||
// This should get us to the middle of the internal perimeter. We then scale by 10% up for safety margin.
|
||||
coord_t threshold_external = (this->ext_perimeter_flow.scaled_width()/2+this->ext_perimeter_flow.scaled_spacing()+this->perimeter_flow.scaled_width()/2) * 1.1;
|
||||
// For the intenal perimeter threshold, the distance is the perimeter width plus the spacing, scaled by 10% for safety margin.
|
||||
coord_t threshold_internal = (this->perimeter_flow.scaled_width()+this->perimeter_flow.scaled_spacing()) * 1.1;
|
||||
|
||||
// Re-order extrusions based on distance
|
||||
// Alorithm will aggresively optimise for the appearance of the outermost perimeter
|
||||
ordered_extrusions = reorderPerimetersByProximity(ordered_extrusions,threshold_external,threshold_internal );
|
||||
reordered_extrusions = ordered_extrusions; // copy them into the reordered extrusions vector to allow for IOI operations to be performed below without altering the base ordered extrusions list.
|
||||
|
||||
for(auto extrusion_to_reorder : ordered_extrusions){ //scan the perimeters to reorder
|
||||
switch (extrusion_to_reorder.extrusion->inset_idx) {
|
||||
case 0: // external perimeter
|
||||
if(found_second_internal){ //new island - move skipped extrusions to reordered array
|
||||
for(auto extrusion_skipped : skipped_extrusions)
|
||||
reordered_extrusions.emplace_back(extrusion_skipped);
|
||||
skipped_extrusions.clear();
|
||||
}
|
||||
reordered_extrusions.emplace_back(extrusion_to_reorder);
|
||||
break;
|
||||
case 1: // first internal perimeter
|
||||
reordered_extrusions.emplace_back(extrusion_to_reorder);
|
||||
break;
|
||||
default: // second internal+ perimeter -> put them in the skipped extrusions array
|
||||
skipped_extrusions.emplace_back(extrusion_to_reorder);
|
||||
found_second_internal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ordered_extrusions.size()>reordered_extrusions.size()){
|
||||
// we didnt find any more islands, so lets move the remaining skipped perimeters to the reordered extrusions list.
|
||||
for(auto extrusion_skipped : skipped_extrusions)
|
||||
reordered_extrusions.emplace_back(extrusion_skipped);
|
||||
skipped_extrusions.clear();
|
||||
}
|
||||
|
||||
// Now start the sandwich mode wall re-ordering using the reordered_extrusions as the basis
|
||||
// scan to find the external perimeter, first internal, second internal and last perimeter in the island.
|
||||
// We then advance the position index to move to the second island and continue until there are no more
|
||||
|
|
@ -2800,7 +2949,8 @@ void PerimeterGenerator::process_arachne()
|
|||
}
|
||||
break;
|
||||
}
|
||||
if(outer >-1 && first_internal>-1 && second_internal>-1 && reordered_extrusions[arr_i].extrusion->inset_idx == 0){ // found a new external perimeter after we've found all three perimeters to re-order -> this means we entered a new island.
|
||||
if(outer >-1 && first_internal>-1 && reordered_extrusions[arr_i].extrusion->inset_idx == 0){ // found a new external perimeter after we've found at least a first internal perimeter to re-order.
|
||||
// This means we entered a new island.
|
||||
arr_i=arr_i-1; //step back one perimeter
|
||||
max_internal = arr_i; // new maximum internal perimeter is now this as we have found a new external perimeter, hence a new island.
|
||||
break; // exit the for loop
|
||||
|
|
@ -2808,7 +2958,7 @@ void PerimeterGenerator::process_arachne()
|
|||
}
|
||||
|
||||
// printf("Layer ID %d, Outer index %d, inner index %d, second inner index %d, maximum internal perimeter %d \n",layer_id,outer,first_internal,second_internal, max_internal);
|
||||
if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order?
|
||||
if (outer > -1 && first_internal > -1 && second_internal > -1) { // found all three perimeters to re-order? If not the perimeters will be processed outside in.
|
||||
std::vector<PerimeterGeneratorArachneExtrusion> inner_outer_extrusions; // temporary array to hold extrusions for reordering
|
||||
inner_outer_extrusions.reserve(max_internal - position + 1); // reserve array containing the number of perimeters before a new island. Variables are array indexes hence need to add +1 to convert to position allocations
|
||||
// printf("Allocated array size %d, max_internal index %d, start position index %d \n",max_internal-position+1,max_internal,position);
|
||||
|
|
@ -2828,8 +2978,7 @@ void PerimeterGenerator::process_arachne()
|
|||
|
||||
for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array
|
||||
ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position];
|
||||
} else
|
||||
break;
|
||||
}
|
||||
// go to the next perimeter from the current position to continue scanning for external walls in the same island
|
||||
position = arr_i + 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,6 +355,8 @@ 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,6 +51,7 @@ 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>();
|
||||
|
|
@ -64,6 +65,7 @@ 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);
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ void Preset::normalize(DynamicPrintConfig &config)
|
|||
static_cast<ConfigOptionVectorBase*>(opt)->resize(n, defaults.option(key));
|
||||
}
|
||||
// The following keys are mandatory for the UI, but they are not part of FullPrintConfig, therefore they are handled separately.
|
||||
for (const std::string &key : { "filament_settings_id" }) {
|
||||
for (const std::string key : { "filament_settings_id" }) {
|
||||
auto *opt = config.option(key, false);
|
||||
assert(opt == nullptr || opt->type() == coStrings);
|
||||
if (opt != nullptr && opt->type() == coStrings)
|
||||
|
|
@ -841,8 +841,8 @@ static std::vector<std::string> s_Preset_filament_options {
|
|||
"nozzle_temperature_range_low", "nozzle_temperature_range_high",
|
||||
//SoftFever
|
||||
"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_loading_speed", "filament_loading_speed_start",
|
||||
"filament_unloading_speed", "filament_unloading_speed_start", "filament_toolchange_delay", "filament_cooling_moves", "filament_stamping_loading_speed", "filament_stamping_distance",
|
||||
"filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters",
|
||||
"filament_multitool_ramming", "filament_multitool_ramming_volume", "filament_multitool_ramming_flow", "activate_chamber_temp_control",
|
||||
"filament_long_retractions_when_cut","filament_retraction_distances_when_cut", "idle_temperature"
|
||||
|
|
@ -865,11 +865,9 @@ static std::vector<std::string> s_Preset_printer_options {
|
|||
"nozzle_height",
|
||||
"default_print_profile", "inherits",
|
||||
"silent_mode",
|
||||
// BBS
|
||||
"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time","time_cost", "machine_pause_gcode", "template_custom_gcode",
|
||||
"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "machine_tool_change_time", "time_cost", "machine_pause_gcode", "template_custom_gcode",
|
||||
"nozzle_type", "nozzle_hrc","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types", "travel_slope", "retract_lift_enforce","support_chamber_temp_control","support_air_filtration","printer_structure",
|
||||
"best_object_pos","head_wrap_detect_zone",
|
||||
//SoftFever
|
||||
"host_type", "print_host", "printhost_apikey", "bbl_use_printhost",
|
||||
"print_host_webui",
|
||||
"printhost_cafile","printhost_port","printhost_authorization_type",
|
||||
|
|
@ -1572,6 +1570,7 @@ 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)
|
||||
{
|
||||
size_t old_filament_count = this->filament_presets.size();
|
||||
int 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 (size_t i = old_filament_count; i < n; i++) {
|
||||
for (int 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)
|
||||
{
|
||||
size_t n = this->filament_presets.size();
|
||||
int n = this->filament_presets.size();
|
||||
if (filament_index >= n)
|
||||
return false;
|
||||
|
||||
|
|
@ -2117,6 +2117,7 @@ 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;
|
||||
|
|
@ -2479,7 +2480,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);
|
||||
|
|
|
|||
|
|
@ -831,6 +831,7 @@ 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();
|
||||
|
|
@ -1401,30 +1402,32 @@ 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) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1441,7 +1444,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) {
|
||||
|
|
@ -1450,7 +1453,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
|||
}
|
||||
}
|
||||
return warning_key;
|
||||
}; */
|
||||
};
|
||||
std::string warning_key;
|
||||
|
||||
// check jerk
|
||||
|
|
@ -2463,7 +2466,7 @@ FilamentTempType Print::get_filament_temp_type(const std::string& filament_type)
|
|||
in.close();
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": parse " << file_path.string() << " got a nlohmann::detail::parse_error, reason = " << err.what();
|
||||
filament_temp_type_map[HighTempFilamentStr] = {"ABS","ASA","PC","PA","PA-CF","PA-GF","PA6-CF","PET-CF","PPS","PPS-CF","PPA-GF","PPA-CF","ABS-Aero","ABS-GF"};
|
||||
filament_temp_type_map[LowTempFilamentStr] = {"PLA","TPU","PLA-CF","PLA-AERO","PVA","BVOH"};
|
||||
filament_temp_type_map[LowTempFilamentStr] = {"PLA","TPU","PLA-CF","PLA-AERO","PVA","BVOH","SBS"};
|
||||
filament_temp_type_map[HighLowCompatibleFilamentStr] = { "HIPS","PETG","PCTG","PE","PP","EVA","PE-CF","PP-CF","PP-GF","PHA"};
|
||||
}
|
||||
}
|
||||
|
|
@ -2666,7 +2669,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);
|
||||
|
||||
|
|
@ -2922,7 +2925,7 @@ DynamicConfig PrintStatistics::config() const
|
|||
DynamicConfig PrintStatistics::placeholders()
|
||||
{
|
||||
DynamicConfig config;
|
||||
for (const std::string &key : {
|
||||
for (const std::string key : {
|
||||
"print_time", "normal_print_time", "silent_print_time",
|
||||
"used_filament", "extruded_volume", "total_cost", "total_weight",
|
||||
"initial_tool", "total_toolchanges", "total_wipe_tower_cost", "total_wipe_tower_filament"})
|
||||
|
|
|
|||
|
|
@ -1498,11 +1498,22 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
}
|
||||
std::vector<unsigned int> painting_extruders;
|
||||
if (const auto &volumes = print_object.model_object()->volumes;
|
||||
num_extruders > 1 &&
|
||||
num_extruders > 1 &&
|
||||
std::find_if(volumes.begin(), volumes.end(), [](const ModelVolume *v) { return ! v->mmu_segmentation_facets.empty(); }) != volumes.end()) {
|
||||
//FIXME be more specific! Don't enumerate extruders that are not used for painting!
|
||||
painting_extruders.assign(num_extruders , 0);
|
||||
std::iota(painting_extruders.begin(), painting_extruders.end(), 1);
|
||||
|
||||
std::array<bool, static_cast<size_t>(EnforcerBlockerType::ExtruderMax)> used_facet_states{};
|
||||
for (const ModelVolume *volume : volumes) {
|
||||
const std::vector<bool> &volume_used_facet_states = volume->mmu_segmentation_facets.get_data().used_states;
|
||||
|
||||
assert(volume_used_facet_states.size() == used_facet_states.size());
|
||||
for (size_t state_idx = 0; state_idx < std::min(volume_used_facet_states.size(), used_facet_states.size()); ++state_idx)
|
||||
used_facet_states[state_idx] |= volume_used_facet_states[state_idx];
|
||||
}
|
||||
|
||||
for (size_t state_idx = static_cast<size_t>(EnforcerBlockerType::Extruder1); state_idx < used_facet_states.size(); ++state_idx) {
|
||||
if (used_facet_states[state_idx])
|
||||
painting_extruders.emplace_back(state_idx);
|
||||
}
|
||||
}
|
||||
if (model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::Valid) {
|
||||
// Verify that the trafo for regions & volume bounding boxes thus for regions is still applicable.
|
||||
|
|
|
|||
|
|
@ -817,12 +817,22 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("gap_fill_target", coEnum);
|
||||
def->label = L("Apply gap fill");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Enables gap fill for the selected surfaces. The minimum gap length that will be filled can be controlled "
|
||||
def->tooltip = L("Enables gap fill for the selected solid surfaces. The minimum gap length that will be filled can be controlled "
|
||||
"from the filter out tiny gaps option below.\n\n"
|
||||
"Options:\n"
|
||||
"1. Everywhere: Applies gap fill to top, bottom and internal solid surfaces\n"
|
||||
"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces only\n"
|
||||
"3. Nowhere: Disables gap fill\n");
|
||||
"1. Everywhere: Applies gap fill to top, bottom and internal solid surfaces for maximum strength\n"
|
||||
"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces only, balancing print speed, "
|
||||
"reducing potential over extrusion in the solid infill and making sure the top and bottom surfaces have "
|
||||
"no pin hole gaps\n"
|
||||
"3. Nowhere: Disables gap fill for all solid infill areas. \n\n"
|
||||
"Note that if using the classic perimeter generator, gap fill may also be generated between perimeters, "
|
||||
"if a full width line cannot fit between them. That perimeter gap fill is not controlled by this setting. \n\n"
|
||||
"If you would like all gap fill, including the classic perimeter generated one, removed, "
|
||||
"set the filter out tiny gaps value to a large number, like 999999. \n\n"
|
||||
"However this is not advised, as gap fill between perimeters is contributing to the model's strength. "
|
||||
"For models where excessive gap fill is generated between perimeters, a better option would be to "
|
||||
"switch to the arachne wall generator and use this option to control whether the cosmetic top and "
|
||||
"bottom surface gap fill is generated");
|
||||
def->enum_keys_map = &ConfigOptionEnum<GapFillTarget>::get_enum_values();
|
||||
def->enum_values.push_back("everywhere");
|
||||
def->enum_values.push_back("topbottom");
|
||||
|
|
@ -897,7 +907,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->label = L("Bridge flow ratio");
|
||||
def->category = L("Quality");
|
||||
def->tooltip = L("Decrease this value slightly(for example 0.9) to reduce the amount of material for bridge, "
|
||||
"to improve sag");
|
||||
"to improve sag. \n\nThe actual bridge flow used is calculated by multiplying this value with the filament flow ratio, and if set, the object's flow ratio.");
|
||||
def->min = 0;
|
||||
def->max = 2.0;
|
||||
def->mode = comAdvanced;
|
||||
|
|
@ -906,7 +916,8 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("internal_bridge_flow", coFloat);
|
||||
def->label = L("Internal bridge flow ratio");
|
||||
def->category = L("Quality");
|
||||
def->tooltip = L("This value governs the thickness of the internal bridge layer. This is the first layer over sparse infill. Decrease this value slightly (for example 0.9) to improve surface quality over sparse infill.");
|
||||
def->tooltip = L("This value governs the thickness of the internal bridge layer. This is the first layer over sparse infill. Decrease this value slightly (for example 0.9) to improve surface quality over sparse infill."
|
||||
"\n\nThe actual internal bridge flow used is calculated by multiplying this value with the bridge flow ratio, the filament flow ratio, and if set, the object's flow ratio.");
|
||||
def->min = 0;
|
||||
def->max = 2.0;
|
||||
def->mode = comAdvanced;
|
||||
|
|
@ -916,7 +927,8 @@ void PrintConfigDef::init_fff_params()
|
|||
def->label = L("Top surface flow ratio");
|
||||
def->category = L("Advanced");
|
||||
def->tooltip = L("This factor affects the amount of material for top solid infill. "
|
||||
"You can decrease it slightly to have smooth surface finish");
|
||||
"You can decrease it slightly to have smooth surface finish. "
|
||||
"\n\nThe actual top surface flow used is calculated by multiplying this value with the filament flow ratio, and if set, the object's flow ratio.");
|
||||
def->min = 0;
|
||||
def->max = 2;
|
||||
def->mode = comAdvanced;
|
||||
|
|
@ -925,7 +937,8 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("bottom_solid_infill_flow_ratio", coFloat);
|
||||
def->label = L("Bottom surface flow ratio");
|
||||
def->category = L("Advanced");
|
||||
def->tooltip = L("This factor affects the amount of material for bottom solid infill");
|
||||
def->tooltip = L("This factor affects the amount of material for bottom solid infill. "
|
||||
"\n\nThe actual bottom solid infill flow used is calculated by multiplying this value with the filament flow ratio, and if set, the object's flow ratio.");
|
||||
def->min = 0;
|
||||
def->max = 2;
|
||||
def->mode = comAdvanced;
|
||||
|
|
@ -1039,7 +1052,16 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("slowdown_for_curled_perimeters", coBool);
|
||||
def->label = L("Slow down for curled perimeters");
|
||||
def->category = L("Speed");
|
||||
def->tooltip = L("Enable this option to slow printing down in areas where potential curled perimeters may exist");
|
||||
def->tooltip = L("Enable this option to slow down printing in areas where perimeters may have curled upwards."
|
||||
"For example, additional slowdown will be applied when printing overhangs on sharp corners like the "
|
||||
"front of the Benchy hull, reducing curling which compounds over multiple layers.\n\n "
|
||||
"It is generally recommended to have this option switched on unless your printer cooling is powerful enough or the "
|
||||
"print speed slow enough that perimeter curling does not happen. If printing with a high external perimeter speed, "
|
||||
"this parameter may introduce slight artifacts when slowing down due to the large variance in print speeds. "
|
||||
"If you notice artifacts, ensure your pressure advance is tuned correctly.\n\n"
|
||||
"Note: When this option is enabled, overhang perimeters are treated like overhangs, meaning the overhang speed is "
|
||||
"applied even if the overhanging perimeter is part of a bridge. For example, when the perimeters are 100% overhanging"
|
||||
", with no wall supporting them from underneath, the 100% overhang speed will be applied.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool{ false });
|
||||
|
||||
|
|
@ -1092,7 +1114,10 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("bridge_speed", coFloat);
|
||||
def->label = L("External");
|
||||
def->category = L("Speed");
|
||||
def->tooltip = L("Speed of bridge and completely overhang wall");
|
||||
def->tooltip = L("Speed of the externally visible bridge extrusions. "
|
||||
"\n\nIn addition, if Slow down for curled perimeters is disabled or Classic overhang mode is enabled, "
|
||||
"it will be the print speed of overhang walls that are supported by less than 13%, whether they are part of a bridge "
|
||||
"or an overhang.");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 1;
|
||||
def->mode = comAdvanced;
|
||||
|
|
@ -1101,7 +1126,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("internal_bridge_speed", coFloatOrPercent);
|
||||
def->label = L("Internal");
|
||||
def->category = L("Speed");
|
||||
def->tooltip = L("Speed of internal bridge. If the value is expressed as a percentage, it will be calculated based on the bridge_speed. Default value is 150%.");
|
||||
def->tooltip = L("Speed of internal bridges. If the value is expressed as a percentage, it will be calculated based on the bridge_speed. Default value is 150%.");
|
||||
def->sidetext = L("mm/s or %");
|
||||
def->ratio_over = "bridge_speed";
|
||||
def->min = 1;
|
||||
|
|
@ -1664,7 +1689,8 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("The material may have volumetric change after switching between molten state and crystalline state. "
|
||||
"This setting changes all extrusion flow of this filament in gcode proportionally. "
|
||||
"Recommended value range is between 0.95 and 1.05. "
|
||||
"Maybe you can tune this value to get nice flat surface when there has slight overflow or underflow");
|
||||
"Maybe you can tune this value to get nice flat surface when there has slight overflow or underflow. "
|
||||
"\n\nThe final object flow ratio is this value multiplied by the filament flow ratio.");
|
||||
def->mode = comAdvanced;
|
||||
def->max = 2;
|
||||
def->min = 0.01;
|
||||
|
|
@ -1818,7 +1844,7 @@ void PrintConfigDef::init_fff_params()
|
|||
|
||||
def = this->add("machine_load_filament_time", coFloat);
|
||||
def->label = L("Filament load time");
|
||||
def->tooltip = L("Time to load new filament when switch filament. For statistics only");
|
||||
def->tooltip = L("Time to load new filament when switch filament. It's usually applicable for single-extruder multi-material machines. For tool changers or multi-tool machines, it's typically 0. For statistics only");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
|
|
@ -1826,12 +1852,21 @@ void PrintConfigDef::init_fff_params()
|
|||
|
||||
def = this->add("machine_unload_filament_time", coFloat);
|
||||
def->label = L("Filament unload time");
|
||||
def->tooltip = L("Time to unload old filament when switch filament. For statistics only");
|
||||
def->tooltip = L("Time to unload old filament when switch filament. It's usually applicable for single-extruder multi-material machines. For tool changers or multi-tool machines, it's typically 0. For statistics only");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.0));
|
||||
|
||||
def = this->add("machine_tool_change_time", coFloat);
|
||||
def->label = L("Tool change time");
|
||||
def->tooltip = L("Time taken to switch tools. It's usually applicable for tool changers or multi-tool machines. For single-extruder multi-material machines, it's typically 0. For statistics only");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat { 0. });
|
||||
|
||||
|
||||
def = this->add("filament_diameter", coFloats);
|
||||
def->label = L("Diameter");
|
||||
def->tooltip = L("Filament diameter is used to calculate extrusion in gcode, so it's important and should be accurate");
|
||||
|
|
@ -1978,14 +2013,6 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 3.4 });
|
||||
|
||||
def = this->add("filament_load_time", coFloats);
|
||||
def->label = L("Filament load time");
|
||||
def->tooltip = L("Time for the printer firmware (or the Multi Material Unit 2.0) to load a new filament during a tool change (when executing the T code). This time is added to the total print time by the G-code time estimator.");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0. });
|
||||
|
||||
def = this->add("filament_ramming_parameters", coStrings);
|
||||
def->label = L("Ramming parameters");
|
||||
def->tooltip = L("This string is edited by RammingDialog and contains ramming specific parameters.");
|
||||
|
|
@ -1993,14 +2020,6 @@ void PrintConfigDef::init_fff_params()
|
|||
def->set_default_value(new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0|"
|
||||
" 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" });
|
||||
|
||||
def = this->add("filament_unload_time", coFloats);
|
||||
def->label = L("Filament unload time");
|
||||
def->tooltip = L("Time for the printer firmware (or the Multi Material Unit 2.0) to unload a filament during a tool change (when executing the T code). This time is added to the total print time by the G-code time estimator.");
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0. });
|
||||
|
||||
def = this->add("filament_multitool_ramming", coBools);
|
||||
def->label = L("Enable ramming for multitool setups");
|
||||
def->tooltip = L("Perform ramming when using multitool printer (i.e. when the 'Single Extruder Multimaterial' in Printer Settings is unchecked). "
|
||||
|
|
@ -2073,6 +2092,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_values.push_back("PPS-CF");
|
||||
def->enum_values.push_back("PVA");
|
||||
def->enum_values.push_back("PVB");
|
||||
def->enum_values.push_back("SBS");
|
||||
def->enum_values.push_back("TPU");
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionStrings { "PLA" });
|
||||
|
|
@ -2541,7 +2561,8 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("filter_out_gap_fill", coFloat);
|
||||
def->label = L("Filter out tiny gaps");
|
||||
def->category = L("Layers and Perimeters");
|
||||
def->tooltip = L("Filter out gaps smaller than the threshold specified");
|
||||
def->tooltip = L("Don't print gap fill with a length is smaller than the threshold specified (in mm). This setting applies to top, "
|
||||
"bottom and solid infill and, if using the classic perimeter generator, to wall gap fill. ");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
|
@ -4734,15 +4755,21 @@ void PrintConfigDef::init_fff_params()
|
|||
|
||||
def = this->add("activate_chamber_temp_control",coBools);
|
||||
def->label = L("Activate temperature control");
|
||||
def->tooltip = L("Enable this option for chamber temperature control. An M191 command will be added before \"machine_start_gcode\"\nG-code commands: M141/M191 S(0-255)");
|
||||
def->tooltip = L("Enable this option for automated chamber temperature control. This option activates the emitting of an M191 command before the \"machine_start_gcode\"\n which sets the "
|
||||
"chamber temperature and waits until it is reached. In addition, it emits an M141 command at the end of the print to turn off the chamber heater, if present. \n\n"
|
||||
"This option relies on the firmware supporting the M191 and M141 commands either via macros or natively and is usually used when an active chamber heater is installed.");
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionBools{false});
|
||||
|
||||
def = this->add("chamber_temperature", coInts);
|
||||
def->label = L("Chamber temperature");
|
||||
def->tooltip = L("Higher chamber temperature can help suppress or reduce warping and potentially lead to higher interlayer bonding strength for high temperature materials like ABS, ASA, PC, PA and so on."
|
||||
"At the same time, the air filtration of ABS and ASA will get worse.While for PLA, PETG, TPU, PVA and other low temperature materials,"
|
||||
"the actual chamber temperature should not be high to avoid cloggings, so 0 which stands for turning off is highly recommended"
|
||||
def->tooltip = L("For high-temperature materials like ABS, ASA, PC, and PA, a higher chamber temperature can help suppress or reduce warping and potentially lead to higher interlayer bonding strength. "
|
||||
"However, at the same time, a higher chamber temperature will reduce the efficiency of air filtration for ABS and ASA. \n\n"
|
||||
"For PLA, PETG, TPU, PVA, and other low-temperature materials, this option should be disabled (set to 0) as the chamber temperature should be low to avoid extruder clogging caused "
|
||||
"by material softening at the heat break.\n\n"
|
||||
"If enabled, this parameter also sets a gcode variable named chamber_temperature, which can be used to pass the desired chamber temperature to your print start macro, "
|
||||
"or a heat soak macro like this: PRINT_START (other variables) CHAMBER_TEMP=[chamber_temperature]. This may be useful if your printer does not support M141/M191 commands, or if you desire "
|
||||
"to handle heat soaking in the print start macro if no active chamber heater is installed."
|
||||
);
|
||||
def->sidetext = L("°C");
|
||||
def->full_label = L("Chamber temperature");
|
||||
|
|
@ -5331,11 +5358,11 @@ void PrintConfigDef::init_extruder_option_keys()
|
|||
"retraction_length",
|
||||
"retraction_minimum_travel",
|
||||
"retraction_speed",
|
||||
"travel_slope",
|
||||
"wipe",
|
||||
"wipe_distance",
|
||||
"z_hop",
|
||||
"z_hop_types",
|
||||
"travel_slope"
|
||||
"z_hop_types"
|
||||
};
|
||||
assert(std::is_sorted(m_extruder_retract_keys.begin(), m_extruder_retract_keys.end()));
|
||||
}
|
||||
|
|
@ -6142,7 +6169,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
"z_hop_type", "z_lift_type", "bed_temperature_difference","long_retraction_when_cut",
|
||||
"retraction_distance_when_cut",
|
||||
"extruder_type",
|
||||
"internal_bridge_support_thickness","extruder_clearance_max_radius", "top_area_threshold", "reduce_wall_solid_infill"
|
||||
"internal_bridge_support_thickness","extruder_clearance_max_radius", "top_area_threshold", "reduce_wall_solid_infill","filament_load_time","filament_unload_time"
|
||||
};
|
||||
|
||||
if (ignore.find(opt_key) != ignore.end()) {
|
||||
|
|
|
|||
|
|
@ -1119,15 +1119,13 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloat, parking_pos_retraction))
|
||||
((ConfigOptionFloat, extra_loading_move))
|
||||
((ConfigOptionFloat, machine_load_filament_time))
|
||||
((ConfigOptionFloat, machine_tool_change_time))
|
||||
((ConfigOptionFloat, machine_unload_filament_time))
|
||||
((ConfigOptionFloats, filament_loading_speed))
|
||||
((ConfigOptionFloats, filament_loading_speed_start))
|
||||
((ConfigOptionFloats, filament_load_time))
|
||||
((ConfigOptionFloats, filament_unloading_speed))
|
||||
((ConfigOptionFloats, filament_unloading_speed_start))
|
||||
((ConfigOptionFloats, filament_toolchange_delay))
|
||||
// Orca todo: consolidate with machine_load_filament_time
|
||||
((ConfigOptionFloats, filament_unload_time))
|
||||
((ConfigOptionInts, filament_cooling_moves))
|
||||
((ConfigOptionFloats, filament_cooling_initial_speed))
|
||||
((ConfigOptionFloats, filament_minimal_purge_on_wipe_tower))
|
||||
|
|
|
|||
|
|
@ -680,6 +680,7 @@ 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,
|
||||
|
|
@ -2951,16 +2952,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()
|
||||
|
|
@ -3670,6 +3671,7 @@ 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,8 +336,7 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
|||
};
|
||||
|
||||
// BBS
|
||||
// Orca: unused
|
||||
/* auto trim_overlap = [](ExPolygons& expolys_a, ExPolygons& expolys_b) {
|
||||
auto trim_overlap = [](ExPolygons& expolys_a, ExPolygons& expolys_b) {
|
||||
ExPolygons trimming_a;
|
||||
ExPolygons trimming_b;
|
||||
|
||||
|
|
@ -362,7 +361,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,6 +99,8 @@ 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,6 +2,7 @@
|
|||
#include "libslic3r/NormalUtils.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ template<typename T> inline void reorder_by_shortest_traverse(std::vector<T> &po
|
|||
{
|
||||
Points start_point;
|
||||
start_point.reserve(polylines_out.size());
|
||||
for (const T contour : polylines_out) start_point.push_back(contour.points.front());
|
||||
for (const T& contour : polylines_out) start_point.push_back(contour.points.front());
|
||||
|
||||
std::vector<Points::size_type> order = chain_points(start_point);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include <numeric>
|
||||
|
||||
#include "SlicesToTriangleMesh.hpp"
|
||||
|
||||
//#include "libslic3r/MTUtils.hpp"
|
||||
#include "libslic3r/Execution/ExecutionTBB.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/Tesselate.hpp"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
#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,4 +1,6 @@
|
|||
#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,6 +1554,7 @@ 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);
|
||||
|
||||
|
|
@ -1576,6 +1577,7 @@ 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.
|
||||
|
|
@ -1687,6 +1689,7 @@ 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;
|
||||
|
|
@ -1731,6 +1734,7 @@ 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;
|
||||
|
||||
|
|
@ -1744,6 +1748,8 @@ 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 =
|
||||
|
|
@ -2181,6 +2187,7 @@ 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)) {
|
||||
|
|
@ -3539,13 +3546,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;
|
||||
|
|
@ -4621,6 +4628,7 @@ 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,6 +5,7 @@
|
|||
#include "Print.hpp"
|
||||
#include "Layer.hpp"
|
||||
#include "Fill/FillBase.hpp"
|
||||
#include "Fill/FillConcentric.hpp"
|
||||
#include "CurveAnalyzer.hpp"
|
||||
#include "SVG.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
|
|
@ -12,6 +13,7 @@
|
|||
#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)
|
||||
|
|
@ -467,6 +469,7 @@ 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++)
|
||||
|
|
@ -479,7 +482,7 @@ static bool move_inside_expolys(const ExPolygons& polygons, Point& from, double
|
|||
// because we compare with vsize2_with_unscale here (no division by zero), we also need to compare by vsize2_with_unscale inside the loop
|
||||
// to avoid integer rounding edge cases
|
||||
bool projected_p_beyond_prev_segment = dot_with_unscale(p1 - p0, from - p0) >= vsize2_with_unscale(p1 - p0);
|
||||
for(const Point p2 : poly.contour.points)
|
||||
for(const Point& p2 : poly.contour.points)
|
||||
{
|
||||
// X = A + Normal(B-A) * (((B-A) dot_with_unscale (P-A)) / VSize(B-A));
|
||||
// = A + (B-A) * ((B-A) dot_with_unscale (P-A)) / VSize2(B-A);
|
||||
|
|
@ -507,6 +510,7 @@ 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
|
||||
{
|
||||
|
|
@ -543,6 +547,7 @@ 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
|
||||
{
|
||||
|
|
@ -627,6 +632,7 @@ 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;
|
||||
|
|
@ -728,12 +734,16 @@ 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
|
||||
|
|
@ -1396,6 +1406,7 @@ 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.
|
||||
|
|
@ -1409,6 +1420,8 @@ 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;
|
||||
|
|
@ -1424,11 +1437,11 @@ void TreeSupport::generate_toolpaths()
|
|||
|
||||
if (m_object->support_layer_count() > m_raft_layers) {
|
||||
const SupportLayer *ts_layer = m_object->get_support_layer(m_raft_layers);
|
||||
for (const ExPolygon expoly : ts_layer->floor_areas)
|
||||
for (const ExPolygon& expoly : ts_layer->floor_areas)
|
||||
raft_areas.push_back(expoly);
|
||||
for (const ExPolygon expoly : ts_layer->roof_areas)
|
||||
for (const ExPolygon& expoly : ts_layer->roof_areas)
|
||||
raft_areas.push_back(expoly);
|
||||
for (const ExPolygon expoly : ts_layer->base_areas)
|
||||
for (const ExPolygon& expoly : ts_layer->base_areas)
|
||||
raft_areas.push_back(expoly);
|
||||
}
|
||||
|
||||
|
|
@ -2113,6 +2126,7 @@ 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;
|
||||
|
|
@ -2363,7 +2377,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 >= 0; layer_nr_lower--) {
|
||||
for (layer_nr_lower; 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;
|
||||
|
|
@ -2453,7 +2467,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 >= 0; layer_nr_lower--) {
|
||||
for (layer_nr_lower; 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;
|
||||
|
|
@ -2568,10 +2582,15 @@ 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) {
|
||||
|
|
@ -3183,6 +3202,7 @@ 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;
|
||||
|
|
@ -3304,6 +3324,7 @@ 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;
|
||||
|
|
@ -3607,7 +3628,7 @@ const ExPolygons& TreeSupportData::get_avoidance(coordf_t radius, size_t layer_n
|
|||
Polygons TreeSupportData::get_contours(size_t layer_nr) const
|
||||
{
|
||||
Polygons contours;
|
||||
for (const ExPolygon expoly : m_layer_outlines[layer_nr]) {
|
||||
for (const ExPolygon& expoly : m_layer_outlines[layer_nr]) {
|
||||
contours.push_back(expoly.contour);
|
||||
}
|
||||
|
||||
|
|
@ -3617,7 +3638,7 @@ Polygons TreeSupportData::get_contours(size_t layer_nr) const
|
|||
Polygons TreeSupportData::get_contours_with_holes(size_t layer_nr) const
|
||||
{
|
||||
Polygons contours;
|
||||
for (const ExPolygon expoly : m_layer_outlines[layer_nr]) {
|
||||
for (const ExPolygon& expoly : m_layer_outlines[layer_nr]) {
|
||||
for(int i=0;i<expoly.num_contours();i++)
|
||||
contours.push_back(expoly.contour_or_hole(i));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -1622,8 +1622,7 @@ void TriangleSelector::get_seed_fill_contour_recursive(const int facet_idx, cons
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> TriangleSelector::serialize() const
|
||||
{
|
||||
TriangleSelector::TriangleSplittingData TriangleSelector::serialize() const {
|
||||
// Each original triangle of the mesh is assigned a number encoding its state
|
||||
// or how it is split. Each triangle is encoded by 4 bits (xxyy) or 8 bits (zzzzxxyy):
|
||||
// leaf triangle: xx = EnforcerBlockerType (Only values 0, 1, and 2. Value 3 is used as an indicator for additional 4 bits.), yy = 0
|
||||
|
|
@ -1639,7 +1638,7 @@ std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> TriangleSelector:
|
|||
// (std::function calls using a pointer, while this implementation calls directly).
|
||||
struct Serializer {
|
||||
const TriangleSelector* triangle_selector;
|
||||
std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> data;
|
||||
TriangleSplittingData data;
|
||||
|
||||
void serialize(int facet_idx) {
|
||||
const Triangle& tr = triangle_selector->m_triangles[facet_idx];
|
||||
|
|
@ -1648,8 +1647,8 @@ std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> TriangleSelector:
|
|||
int split_sides = tr.number_of_split_sides();
|
||||
assert(split_sides >= 0 && split_sides <= 3);
|
||||
|
||||
data.second.push_back(split_sides & 0b01);
|
||||
data.second.push_back(split_sides & 0b10);
|
||||
data.bitstream.push_back(split_sides & 0b01);
|
||||
data.bitstream.push_back(split_sides & 0b10);
|
||||
|
||||
if (split_sides) {
|
||||
// If this triangle is split, save which side is split (in case
|
||||
|
|
@ -1657,8 +1656,8 @@ std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> TriangleSelector:
|
|||
// be ignored for 3-side split.
|
||||
assert(tr.is_split() && split_sides > 0);
|
||||
assert(tr.special_side() >= 0 && tr.special_side() <= 3);
|
||||
data.second.push_back(tr.special_side() & 0b01);
|
||||
data.second.push_back(tr.special_side() & 0b10);
|
||||
data.bitstream.push_back(tr.special_side() & 0b01);
|
||||
data.bitstream.push_back(tr.special_side() & 0b10);
|
||||
// Now save all children.
|
||||
// Serialized in reverse order for compatibility with PrusaSlicer 2.3.1.
|
||||
for (int child_idx = split_sides; child_idx >= 0; -- child_idx)
|
||||
|
|
@ -1666,45 +1665,48 @@ std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> TriangleSelector:
|
|||
} else {
|
||||
// In case this is leaf, we better save information about its state.
|
||||
int n = int(tr.get_state());
|
||||
if (n < static_cast<size_t>(EnforcerBlockerType::ExtruderMax))
|
||||
data.used_states[n] = true;
|
||||
|
||||
if (n >= 3) {
|
||||
assert(n <= 16);
|
||||
if (n <= 16) {
|
||||
// Store "11" plus 4 bits of (n-3).
|
||||
data.second.insert(data.second.end(), { true, true });
|
||||
data.bitstream.insert(data.bitstream.end(), { true, true });
|
||||
n -= 3;
|
||||
for (size_t bit_idx = 0; bit_idx < 4; ++bit_idx)
|
||||
data.second.push_back(n & (uint64_t(0b0001) << bit_idx));
|
||||
data.bitstream.push_back(n & (uint64_t(0b0001) << bit_idx));
|
||||
}
|
||||
} else {
|
||||
// Simple case, compatible with PrusaSlicer 2.3.1 and older for storing paint on supports and seams.
|
||||
// Store 2 bits of n.
|
||||
data.second.push_back(n & 0b01);
|
||||
data.second.push_back(n & 0b10);
|
||||
data.bitstream.push_back(n & 0b01);
|
||||
data.bitstream.push_back(n & 0b10);
|
||||
}
|
||||
}
|
||||
}
|
||||
} out { this };
|
||||
|
||||
out.data.first.reserve(m_orig_size_indices);
|
||||
out.data.triangles_to_split.reserve(m_orig_size_indices);
|
||||
for (int i=0; i<m_orig_size_indices; ++i)
|
||||
if (const Triangle& tr = m_triangles[i]; tr.is_split() || tr.get_state() != EnforcerBlockerType::NONE) {
|
||||
// Store index of the first bit assigned to ith triangle.
|
||||
out.data.first.emplace_back(i, int(out.data.second.size()));
|
||||
out.data.triangles_to_split.emplace_back(i, int(out.data.bitstream.size()));
|
||||
// out the triangle bits.
|
||||
out.serialize(i);
|
||||
}
|
||||
|
||||
// May be stored onto Undo / Redo stack, thus conserve memory.
|
||||
out.data.first.shrink_to_fit();
|
||||
out.data.second.shrink_to_fit();
|
||||
out.data.triangles_to_split.shrink_to_fit();
|
||||
out.data.bitstream.shrink_to_fit();
|
||||
return out.data;
|
||||
}
|
||||
|
||||
void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> &data, bool needs_reset, EnforcerBlockerType max_ebt)
|
||||
void TriangleSelector::deserialize(const TriangleSplittingData& data, bool needs_reset, EnforcerBlockerType max_ebt)
|
||||
{
|
||||
if (needs_reset)
|
||||
reset(); // dump any current state
|
||||
for (auto [triangle_id, ibit] : data.first) {
|
||||
for (auto [triangle_id, ibit] : data.triangles_to_split) {
|
||||
if (triangle_id >= int(m_triangles.size())) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "array bound:error:triangle_id >= int(m_triangles.size())";
|
||||
return;
|
||||
|
|
@ -1712,7 +1714,7 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
|
|||
}
|
||||
// Reserve number of triangles as if each triangle was saved with 4 bits.
|
||||
// With MMU painting this estimate may be somehow low, but better than nothing.
|
||||
m_triangles.reserve(std::max(m_mesh.its.indices.size(), data.second.size() / 4));
|
||||
m_triangles.reserve(std::max(m_mesh.its.indices.size(), data.bitstream.size() / 4));
|
||||
// Number of triangles is twice the number of vertices on a large manifold mesh of genus zero.
|
||||
// Here the triangles count account for both the nodes and leaves, thus the following line may overestimate.
|
||||
m_vertices.reserve(std::max(m_mesh.its.vertices.size(), m_triangles.size() / 2));
|
||||
|
|
@ -1728,13 +1730,13 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
|
|||
// kept outside of the loop to avoid re-allocating inside the loop.
|
||||
std::vector<ProcessingInfo> parents;
|
||||
|
||||
for (auto [triangle_id, ibit] : data.first) {
|
||||
for (auto [triangle_id, ibit] : data.triangles_to_split) {
|
||||
assert(triangle_id < int(m_triangles.size()));
|
||||
assert(ibit < int(data.second.size()));
|
||||
assert(ibit < int(data.bitstream.size()));
|
||||
auto next_nibble = [&data, &ibit = ibit]() {
|
||||
int n = 0;
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
n |= data.second[ibit ++] << i;
|
||||
n |= data.bitstream[ibit ++] << i;
|
||||
return n;
|
||||
};
|
||||
|
||||
|
|
@ -1811,21 +1813,53 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
|
|||
}
|
||||
}
|
||||
|
||||
void TriangleSelector::TriangleSplittingData::update_used_states(const size_t bitstream_start_idx) {
|
||||
assert(bitstream_start_idx < this->bitstream.size());
|
||||
assert(!this->bitstream.empty() && this->bitstream.size() != bitstream_start_idx);
|
||||
assert((this->bitstream.size() - bitstream_start_idx) % 4 == 0);
|
||||
|
||||
if (this->bitstream.empty() || this->bitstream.size() == bitstream_start_idx)
|
||||
return;
|
||||
|
||||
size_t nibble_idx = bitstream_start_idx;
|
||||
|
||||
auto read_next_nibble = [&data_bitstream = std::as_const(this->bitstream), &nibble_idx]() -> uint8_t {
|
||||
assert(nibble_idx + 3 < data_bitstream.size());
|
||||
uint8_t code = 0;
|
||||
for (size_t bit_idx = 0; bit_idx < 4; ++bit_idx)
|
||||
code |= data_bitstream[nibble_idx++] << bit_idx;
|
||||
return code;
|
||||
};
|
||||
|
||||
while (nibble_idx < this->bitstream.size()) {
|
||||
const uint8_t code = read_next_nibble();
|
||||
|
||||
if (const bool is_split = (code & 0b11) != 0; is_split)
|
||||
continue;
|
||||
|
||||
const uint8_t facet_state = (code & 0b1100) == 0b1100 ? read_next_nibble() + 3 : code >> 2;
|
||||
assert(facet_state < this->used_states.size());
|
||||
if (facet_state >= this->used_states.size())
|
||||
continue;
|
||||
|
||||
this->used_states[facet_state] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Lightweight variant of deserialization, which only tests whether a face of test_state exists.
|
||||
bool TriangleSelector::has_facets(const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> &data, const EnforcerBlockerType test_state)
|
||||
{
|
||||
bool TriangleSelector::has_facets(const TriangleSplittingData &data, const EnforcerBlockerType test_state) {
|
||||
// Depth-first queue of a number of unvisited children.
|
||||
// Kept outside of the loop to avoid re-allocating inside the loop.
|
||||
std::vector<int> parents_children;
|
||||
parents_children.reserve(64);
|
||||
|
||||
for (const std::pair<int, int> &triangle_id_and_ibit : data.first) {
|
||||
int ibit = triangle_id_and_ibit.second;
|
||||
assert(ibit < int(data.second.size()));
|
||||
for (const TriangleBitStreamMapping &triangle_id_and_ibit : data.triangles_to_split) {
|
||||
int ibit = triangle_id_and_ibit.bitstream_start_idx;
|
||||
assert(ibit < int(data.bitstream.size()));
|
||||
auto next_nibble = [&data, &ibit = ibit]() {
|
||||
int n = 0;
|
||||
for (int i = 0; i < 4; ++ i)
|
||||
n |= data.second[ibit ++] << i;
|
||||
n |= data.bitstream[ibit ++] << i;
|
||||
return n;
|
||||
};
|
||||
// < 0 -> negative of a number of children
|
||||
|
|
|
|||
|
|
@ -7,10 +7,34 @@
|
|||
#include <cfloat>
|
||||
#include "Point.hpp"
|
||||
#include "TriangleMesh.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class EnforcerBlockerType : int8_t {
|
||||
// Maximum is 3. The value is serialized in TriangleSelector into 2 bits.
|
||||
NONE = 0,
|
||||
ENFORCER = 1,
|
||||
BLOCKER = 2,
|
||||
// Maximum is 15. The value is serialized in TriangleSelector into 6 bits using a 2 bit prefix code.
|
||||
Extruder1 = ENFORCER,
|
||||
Extruder2 = BLOCKER,
|
||||
Extruder3,
|
||||
Extruder4,
|
||||
Extruder5,
|
||||
Extruder6,
|
||||
Extruder7,
|
||||
Extruder8,
|
||||
Extruder9,
|
||||
Extruder10,
|
||||
Extruder11,
|
||||
Extruder12,
|
||||
Extruder13,
|
||||
Extruder14,
|
||||
Extruder15,
|
||||
Extruder16,
|
||||
ExtruderMax = Extruder16
|
||||
};
|
||||
|
||||
// Following class holds information about selected triangles. It also has power
|
||||
// to recursively subdivide the triangles and make the selection finer.
|
||||
class TriangleSelector
|
||||
|
|
@ -208,6 +232,56 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct TriangleBitStreamMapping
|
||||
{
|
||||
// Index of the triangle to which we assign the bitstream containing splitting information.
|
||||
int triangle_idx = -1;
|
||||
// Index of the first bit of the bitstream assigned to this triangle.
|
||||
int bitstream_start_idx = -1;
|
||||
|
||||
TriangleBitStreamMapping() = default;
|
||||
explicit TriangleBitStreamMapping(int triangleIdx, int bitstreamStartIdx) : triangle_idx(triangleIdx), bitstream_start_idx(bitstreamStartIdx) {}
|
||||
|
||||
friend bool operator==(const TriangleBitStreamMapping &lhs, const TriangleBitStreamMapping &rhs) { return lhs.triangle_idx == rhs.triangle_idx && lhs.bitstream_start_idx == rhs.bitstream_start_idx; }
|
||||
friend bool operator!=(const TriangleBitStreamMapping &lhs, const TriangleBitStreamMapping &rhs) { return !(lhs == rhs); }
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(triangle_idx, bitstream_start_idx); }
|
||||
};
|
||||
|
||||
struct TriangleSplittingData {
|
||||
// Vector of triangles and its indexes to the bitstream.
|
||||
std::vector<TriangleBitStreamMapping> triangles_to_split;
|
||||
// Bit stream containing splitting information.
|
||||
std::vector<bool> bitstream;
|
||||
// Array indicating which triangle state types are used (encoded inside bitstream).
|
||||
std::vector<bool> used_states { std::vector<bool>(static_cast<size_t>(EnforcerBlockerType::ExtruderMax), false) };
|
||||
|
||||
TriangleSplittingData() = default;
|
||||
|
||||
friend bool operator==(const TriangleSplittingData &lhs, const TriangleSplittingData &rhs) {
|
||||
return lhs.triangles_to_split == rhs.triangles_to_split
|
||||
&& lhs.bitstream == rhs.bitstream
|
||||
&& lhs.used_states == rhs.used_states;
|
||||
}
|
||||
|
||||
friend bool operator!=(const TriangleSplittingData &lhs, const TriangleSplittingData &rhs) { return !(lhs == rhs); }
|
||||
|
||||
// Reset all used states before they are recomputed based on the bitstream.
|
||||
void reset_used_states() {
|
||||
used_states.resize(static_cast<size_t>(EnforcerBlockerType::ExtruderMax), false);
|
||||
std::fill(used_states.begin(), used_states.end(), false);
|
||||
}
|
||||
|
||||
// Update used states based on the bitstream. It just iterated over the bitstream from the bitstream_start_idx till the end.
|
||||
void update_used_states(size_t bitstream_start_idx);
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(triangles_to_split, bitstream, used_states); }
|
||||
};
|
||||
|
||||
std::pair<std::vector<Vec3i32>, std::vector<Vec3i32>> precompute_all_neighbors() const;
|
||||
void precompute_all_neighbors_recursive(int facet_idx, const Vec3i32 &neighbors, const Vec3i32 &neighbors_propagated, std::vector<Vec3i32> &neighbors_out, std::vector<Vec3i32> &neighbors_normal_out) const;
|
||||
|
||||
|
|
@ -247,7 +321,7 @@ public:
|
|||
bool force_reselection = false); // force reselection of the triangle mesh even in cases that mouse is pointing on the selected triangle
|
||||
|
||||
bool has_facets(EnforcerBlockerType state) const;
|
||||
static bool has_facets(const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> &data, EnforcerBlockerType test_state);
|
||||
static bool has_facets(const TriangleSplittingData &data, EnforcerBlockerType test_state);
|
||||
int num_facets(EnforcerBlockerType state) const;
|
||||
// Get facets at a given state. Don't triangulate T-joints.
|
||||
indexed_triangle_set get_facets(EnforcerBlockerType state) const;
|
||||
|
|
@ -270,10 +344,15 @@ public:
|
|||
|
||||
// Store the division trees in compact form (a long stream of bits for each triangle of the original mesh).
|
||||
// First vector contains pairs of (triangle index, first bit in the second vector).
|
||||
std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> serialize() const;
|
||||
TriangleSplittingData serialize() const;
|
||||
|
||||
// Load serialized data. Assumes that correct mesh is loaded.
|
||||
void deserialize(const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>>& data, bool needs_reset = true, EnforcerBlockerType max_ebt = EnforcerBlockerType::ExtruderMax);
|
||||
void deserialize(const TriangleSplittingData& data,
|
||||
bool needs_reset = true,
|
||||
EnforcerBlockerType max_ebt = EnforcerBlockerType::ExtruderMax);
|
||||
|
||||
// Extract all used facet states from the given TriangleSplittingData.
|
||||
static std::vector<EnforcerBlockerType> extract_used_facet_states(const TriangleSplittingData &data);
|
||||
|
||||
// For all triangles, remove the flag indicating that the triangle was selected by seed fill.
|
||||
void seed_fill_unselect_all_triangles();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#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,10 +1,6 @@
|
|||
#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>
|
||||
|
|
|
|||
|
|
@ -471,9 +471,8 @@ 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);
|
||||
// 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 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,12 +3,19 @@
|
|||
|
||||
#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>
|
||||
|
|
@ -25,7 +32,6 @@
|
|||
#ifdef __APPLE__
|
||||
#include <mach/mach.h>
|
||||
#include <libproc.h>
|
||||
#include "MacUtils.hpp"
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -33,7 +39,6 @@
|
|||
#include <sys/sendfile.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include "Platform.hpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
@ -54,6 +59,7 @@
|
|||
#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.
|
||||
|
|
@ -1483,6 +1489,8 @@ 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();
|
||||
|
|
|
|||
|
|
@ -19,7 +19,11 @@ if(Qhull_FOUND)
|
|||
message(STATUS "Using qhull from system.")
|
||||
if(SLIC3R_STATIC)
|
||||
slic3r_remap_configs("Qhull::qhullcpp;Qhull::qhullstatic_r" RelWithDebInfo Release)
|
||||
target_link_libraries(qhull INTERFACE Qhull::qhullcpp Qhull::qhullstatic_r)
|
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
target_link_libraries(qhull INTERFACE Qhull::qhullcpp_d Qhull::qhullstatic_rd)
|
||||
else()
|
||||
target_link_libraries(qhull INTERFACE Qhull::qhullcpp Qhull::qhullstatic_r)
|
||||
endif()
|
||||
else()
|
||||
slic3r_remap_configs("Qhull::qhullcpp;Qhull::qhull_r" RelWithDebInfo Release)
|
||||
target_link_libraries(qhull INTERFACE Qhull::qhullcpp Qhull::qhull_r)
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ float GLVolume::last_explosion_ratio = 1.0;
|
|||
|
||||
void GLVolume::set_render_color()
|
||||
{
|
||||
// bool outside = is_outside || is_below_printbed();
|
||||
bool outside = is_outside || is_below_printbed();
|
||||
|
||||
if (force_native_color || force_neutral_color) {
|
||||
#ifdef ENABBLE_OUTSIDE_COLOR
|
||||
|
|
@ -859,6 +859,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
|||
return;
|
||||
|
||||
GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat");
|
||||
GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat");
|
||||
|
||||
if (type == ERenderType::Transparent) {
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
|
|
@ -1022,6 +1023,7 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
|||
GUI::PartPlate* curr_plate = GUI::wxGetApp().plater()->get_partplate_list().get_selected_plate();
|
||||
const Pointfs& pp_bed_shape = curr_plate->get_shape();
|
||||
BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height());
|
||||
const std::vector<BoundingBoxf3>& exclude_areas = curr_plate->get_exclude_areas();
|
||||
|
||||
for (GLVolume* volume : this->volumes)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@ void AMSMaterialsSetting::create_panel_kn(wxWindow* parent)
|
|||
kn_val_sizer->Add(m_input_k_val, 0, wxALL | wxEXPAND | wxALIGN_CENTER_VERTICAL, FromDIP(0));
|
||||
|
||||
// n params input
|
||||
wxBoxSizer* n_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_n_param = new wxStaticText(parent, wxID_ANY, _L("Factor N"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_n_param->SetFont(::Label::Body_13);
|
||||
m_n_param->SetForegroundColour(wxColour(50, 58, 61));
|
||||
|
|
@ -356,7 +357,7 @@ void AMSMaterialsSetting::paintEvent(wxPaintEvent &evt)
|
|||
{
|
||||
auto size = GetSize();
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour("#000000")), 1, wxPENSTYLE_SOLID));
|
||||
dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour("#000000")), 1, wxSOLID));
|
||||
dc.SetBrush(wxBrush(*wxTRANSPARENT_BRUSH));
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ void MaterialItem::doRender(wxDC &dc)
|
|||
|
||||
wxString out_txt = m_msg;
|
||||
wxString count_txt = "";
|
||||
int new_line_pos = 0;
|
||||
|
||||
for (int i = 0; i < m_msg.length(); i++) {
|
||||
auto text_size = m_warning_text->GetTextExtent(count_txt);
|
||||
|
|
@ -401,6 +402,7 @@ void AmsMapingPopup::on_left_down(wxMouseEvent &evt)
|
|||
auto pos = ClientToScreen(evt.GetPosition());
|
||||
for (MappingItem *item : m_mapping_item_list) {
|
||||
auto p_rect = item->ClientToScreen(wxPoint(0, 0));
|
||||
auto left = item->GetSize();
|
||||
|
||||
if (pos.x > p_rect.x && pos.y > p_rect.y && pos.x < (p_rect.x + item->GetSize().x) && pos.y < (p_rect.y + item->GetSize().y)) {
|
||||
if (item->m_tray_data.type == TrayType::NORMAL && !is_match_material(item->m_tray_data.filament_type)) return;
|
||||
|
|
@ -1522,6 +1524,9 @@ void AmsRMGroup::on_mouse_move(wxMouseEvent& evt)
|
|||
std::string tray_name = iter->first;
|
||||
wxColour tray_color = iter->second;
|
||||
|
||||
int x = size.x / 2;
|
||||
int y = size.y / 2;
|
||||
int radius = size.x / 2;
|
||||
endAngle += ev_angle;
|
||||
|
||||
if (click_angle >= startAngle && click_angle < endAngle) {
|
||||
|
|
|
|||
|
|
@ -989,7 +989,7 @@ void AuxiliaryPanel::create_folder(wxString name)
|
|||
fs::path bfs_path((m_root_dir + "/" + folder_name).ToStdWstring());
|
||||
if (fs::exists(bfs_path)) {
|
||||
try {
|
||||
fs::remove_all(bfs_path);
|
||||
bool is_done = fs::remove_all(bfs_path);
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory " << m_root_dir.c_str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ wxDataViewItemArray AuxiliaryModel::ImportFile(AuxiliaryModelNode* sel, wxArrayS
|
|||
dir_path += "\\" + src_bfs_path.filename().generic_wstring();
|
||||
|
||||
boost::system::error_code ec;
|
||||
if (!fs::copy_file(src_bfs_path, fs::path(dir_path.ToStdWstring()), fs::copy_options::overwrite_existing, ec))
|
||||
if (!fs::copy_file(src_bfs_path, fs::path(dir_path.ToStdWstring()), fs::copy_option::overwrite_if_exists, ec))
|
||||
continue;
|
||||
|
||||
// Update model data
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include <wx/timer.h>
|
||||
#include <wx/gauge.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/statusbr.h>
|
||||
#include <wx/frame.h>
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ void BBLTopbar::Init(wxFrame* parent)
|
|||
this->AddSpacer(FromDIP(10));
|
||||
|
||||
wxBitmap save_bitmap = create_scaled_bitmap("topbar_save", nullptr, TOPBAR_ICON_SIZE);
|
||||
this->AddTool(wxID_SAVE, "", save_bitmap);
|
||||
wxAuiToolBarItem* save_btn = this->AddTool(wxID_SAVE, "", save_bitmap);
|
||||
|
||||
this->AddSpacer(FromDIP(10));
|
||||
|
||||
|
|
@ -278,7 +278,7 @@ void BBLTopbar::Init(wxFrame* parent)
|
|||
this->AddSpacer(FromDIP(4));
|
||||
|
||||
wxBitmap iconize_bitmap = create_scaled_bitmap("topbar_min", nullptr, TOPBAR_ICON_SIZE);
|
||||
this->AddTool(wxID_ICONIZE_FRAME, "", iconize_bitmap);
|
||||
wxAuiToolBarItem* iconize_btn = this->AddTool(wxID_ICONIZE_FRAME, "", iconize_bitmap);
|
||||
|
||||
this->AddSpacer(FromDIP(4));
|
||||
|
||||
|
|
@ -294,7 +294,7 @@ void BBLTopbar::Init(wxFrame* parent)
|
|||
this->AddSpacer(FromDIP(4));
|
||||
|
||||
wxBitmap close_bitmap = create_scaled_bitmap("topbar_close", nullptr, TOPBAR_ICON_SIZE);
|
||||
this->AddTool(wxID_CLOSE_FRAME, "", close_bitmap);
|
||||
wxAuiToolBarItem* close_btn = this->AddTool(wxID_CLOSE_FRAME, "", close_bitmap);
|
||||
|
||||
Realize();
|
||||
// m_toolbar_h = this->GetSize().GetHeight();
|
||||
|
|
@ -466,6 +466,7 @@ void BBLTopbar::UpdateToolbarWidth(int width)
|
|||
}
|
||||
|
||||
void BBLTopbar::Rescale() {
|
||||
int em = em_unit(this);
|
||||
wxAuiToolBarItem* item;
|
||||
|
||||
/*item = this->FindTool(ID_LOGO);
|
||||
|
|
@ -495,7 +496,7 @@ void BBLTopbar::Rescale() {
|
|||
item->SetBitmap(create_scaled_bitmap("calib_sf", nullptr, TOPBAR_ICON_SIZE));
|
||||
item->SetDisabledBitmap(create_scaled_bitmap("calib_sf_inactive", nullptr, TOPBAR_ICON_SIZE));
|
||||
|
||||
// item = this->FindTool(ID_TITLE);
|
||||
item = this->FindTool(ID_TITLE);
|
||||
|
||||
/*item = this->FindTool(ID_PUBLISH);
|
||||
item->SetBitmap(create_scaled_bitmap("topbar_publish", this, TOPBAR_ICON_SIZE));
|
||||
|
|
@ -547,14 +548,14 @@ void BBLTopbar::OnCloseFrame(wxAuiToolBarEvent& event)
|
|||
|
||||
void BBLTopbar::OnMouseLeftDClock(wxMouseEvent& mouse)
|
||||
{
|
||||
wxPoint mouse_pos = ::wxGetMousePosition();
|
||||
// check whether mouse is not on any tool item
|
||||
if (this->FindToolByCurrentPosition() != NULL &&
|
||||
this->FindToolByCurrentPosition() != m_title_item) {
|
||||
mouse.Skip();
|
||||
return;
|
||||
}
|
||||
#ifdef __WXMSW__
|
||||
wxPoint mouse_pos = ::wxGetMousePosition();
|
||||
#ifdef __W1XMSW__
|
||||
::PostMessage((HWND) m_frame->GetHandle(), WM_NCLBUTTONDBLCLK, HTCAPTION, MAKELPARAM(mouse_pos.x, mouse_pos.y));
|
||||
return;
|
||||
#endif // __WXMSW__
|
||||
|
|
@ -636,6 +637,7 @@ void BBLTopbar::OnMouseLeftDown(wxMouseEvent& event)
|
|||
|
||||
void BBLTopbar::OnMouseLeftUp(wxMouseEvent& event)
|
||||
{
|
||||
wxPoint mouse_pos = ::wxGetMousePosition();
|
||||
if (HasCapture())
|
||||
{
|
||||
ReleaseMouse();
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@
|
|||
#include "format.hpp"
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
// For zipped archive creation
|
||||
#include <wx/stdstream.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/zipstrm.h>
|
||||
|
||||
#include <miniz.h>
|
||||
|
||||
|
|
@ -16,18 +20,23 @@
|
|||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/GCode/PostProcessor.hpp"
|
||||
#include "libslic3r/Format/SL1.hpp"
|
||||
#include "libslic3r/Thread.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <cctype>
|
||||
|
||||
#include <boost/format/format_fwd.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include "I18N.hpp"
|
||||
//#include "RemovableDriveManager.hpp"
|
||||
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
bool SlicingProcessCompletedEvent::critical_error() const
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ PingCodeBindDialog::PingCodeBindDialog(Plater* plater /*= nullptr*/)
|
|||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
|
||||
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ SelectMObjectPopup::SelectMObjectPopup(wxWindow* parent)
|
|||
m_refresh_timer = new wxTimer();
|
||||
m_refresh_timer->SetOwner(this);
|
||||
Bind(EVT_UPDATE_USER_MLIST, &SelectMObjectPopup::update_machine_list, this);
|
||||
Bind(wxEVT_TIMER, [this](wxTimerEvent&) { on_timer(); });
|
||||
Bind(wxEVT_TIMER, &SelectMObjectPopup::on_timer, this);
|
||||
Bind(EVT_DISSMISS_MACHINE_LIST, &SelectMObjectPopup::on_dissmiss_win, this);
|
||||
}
|
||||
|
||||
|
|
@ -265,7 +265,7 @@ void SelectMObjectPopup::Popup(wxWindow* WXUNUSED(focus))
|
|||
}
|
||||
}
|
||||
|
||||
on_timer();
|
||||
wxPostEvent(this, wxTimerEvent());
|
||||
PopupWindow::Popup();
|
||||
}
|
||||
|
||||
|
|
@ -304,7 +304,7 @@ bool SelectMObjectPopup::Show(bool show) {
|
|||
return PopupWindow::Show(show);
|
||||
}
|
||||
|
||||
void SelectMObjectPopup::on_timer()
|
||||
void SelectMObjectPopup::on_timer(wxTimerEvent& event)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(trace) << "SelectMObjectPopup on_timer";
|
||||
wxGetApp().reset_to_active();
|
||||
|
|
@ -459,7 +459,7 @@ CalibrationPanel::CalibrationPanel(wxWindow* parent, wxWindowID id, const wxPoin
|
|||
Layout();
|
||||
|
||||
init_timer();
|
||||
Bind(wxEVT_TIMER, [this](wxTimerEvent&) { on_timer(); });
|
||||
Bind(wxEVT_TIMER, &CalibrationPanel::on_timer, this);
|
||||
}
|
||||
|
||||
void CalibrationPanel::init_tabpanel() {
|
||||
|
|
@ -502,10 +502,10 @@ void CalibrationPanel::init_timer()
|
|||
m_refresh_timer = new wxTimer();
|
||||
m_refresh_timer->SetOwner(this);
|
||||
m_refresh_timer->Start(REFRESH_INTERVAL);
|
||||
on_timer();
|
||||
wxPostEvent(this, wxTimerEvent());
|
||||
}
|
||||
|
||||
void CalibrationPanel::on_timer() {
|
||||
void CalibrationPanel::on_timer(wxTimerEvent& event) {
|
||||
update_all();
|
||||
}
|
||||
|
||||
|
|
@ -644,7 +644,7 @@ bool CalibrationPanel::Show(bool show) {
|
|||
m_refresh_timer->Stop();
|
||||
m_refresh_timer->SetOwner(this);
|
||||
m_refresh_timer->Start(REFRESH_INTERVAL);
|
||||
on_timer();
|
||||
wxPostEvent(this, wxTimerEvent());
|
||||
|
||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (dev) {
|
||||
|
|
@ -670,6 +670,9 @@ bool CalibrationPanel::Show(bool show) {
|
|||
|
||||
void CalibrationPanel::on_printer_clicked(wxMouseEvent& event)
|
||||
{
|
||||
auto mouse_pos = ClientToScreen(event.GetPosition());
|
||||
wxPoint rect = m_side_tools->ClientToScreen(wxPoint(0, 0));
|
||||
|
||||
if (!m_side_tools->is_in_interval()) {
|
||||
wxPoint pos = m_side_tools->ClientToScreen(wxPoint(0, 0));
|
||||
pos.y += m_side_tools->GetRect().height;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue