mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 10:51:22 +00:00
Merge branch 'main' into dev/ams-heat
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
@@ -930,6 +934,77 @@ Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r
|
||||
Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip)
|
||||
{ return _clipper_pl_closed(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip)); }
|
||||
|
||||
// Orca: Sort and orient open polyline fragments produced by clipping `source` with
|
||||
// intersection_pl(), so that they run in the same order and direction as the source
|
||||
// polyline. Clipping creates new endpoints at the clip boundary, but it keeps the
|
||||
// interior source vertices intact, so a fragment's position on the source path is
|
||||
// recovered exactly by looking its vertices up in the source. Fragments without any
|
||||
// surviving source vertex lie on a single source segment, found by a nearest-segment
|
||||
// search.
|
||||
void restore_source_path_order(const Slic3r::Polyline &source, Slic3r::Polylines &fragments)
|
||||
{
|
||||
const Points &src = source.points;
|
||||
if (src.size() < 2 || fragments.empty())
|
||||
return;
|
||||
|
||||
std::unordered_map<Point, size_t, PointHash> source_index;
|
||||
source_index.reserve(src.size());
|
||||
for (size_t i = 0; i < src.size(); ++ i)
|
||||
source_index.emplace(src[i], i);
|
||||
|
||||
// Sort key: index of the source vertex where the fragment starts, then the signed
|
||||
// offset of the fragment's start from that vertex, to order multiple fragments cut
|
||||
// from one long source segment.
|
||||
std::vector<std::pair<size_t, double>> keys(fragments.size());
|
||||
for (size_t n = 0; n < fragments.size(); ++ n) {
|
||||
Polyline &pl = fragments[n];
|
||||
const size_t npos = size_t(-1);
|
||||
size_t front = npos;
|
||||
size_t back = npos;
|
||||
for (const Point &pt : pl.points)
|
||||
if (auto it = source_index.find(pt); it != source_index.end()) {
|
||||
front = it->second;
|
||||
break;
|
||||
}
|
||||
for (auto i = pl.points.rbegin(); i != pl.points.rend(); ++ i)
|
||||
if (auto it = source_index.find(*i); it != source_index.end()) {
|
||||
back = it->second;
|
||||
break;
|
||||
}
|
||||
Vec2crd source_dir;
|
||||
if (front == npos) {
|
||||
// All vertices were created by clipping, thus the whole fragment lies on a
|
||||
// single source segment. Find that segment.
|
||||
double best = std::numeric_limits<double>::max();
|
||||
for (size_t i = 0; i + 1 < src.size(); ++ i)
|
||||
if (double d = Line::distance_to_squared(pl.first_point(), src[i], src[i + 1]); d < best) {
|
||||
best = d;
|
||||
front = i;
|
||||
}
|
||||
back = front;
|
||||
source_dir = src[front + 1] - src[front];
|
||||
} else
|
||||
source_dir = src[std::min(back + 1, src.size() - 1)] - src[front > 0 ? front - 1 : 0];
|
||||
if (front > back) {
|
||||
pl.reverse();
|
||||
std::swap(front, back);
|
||||
} else if (front == back &&
|
||||
(pl.last_point() - pl.first_point()).cast<double>().dot(source_dir.cast<double>()) < 0.)
|
||||
pl.reverse();
|
||||
const Vec2crd seg = src[std::min(front + 1, src.size() - 1)] - src[front];
|
||||
keys[n] = { front, (pl.first_point() - src[front]).cast<double>().dot(seg.cast<double>()) };
|
||||
}
|
||||
|
||||
std::vector<size_t> order(fragments.size());
|
||||
std::iota(order.begin(), order.end(), size_t(0));
|
||||
std::sort(order.begin(), order.end(), [&keys](size_t a, size_t b) { return keys[a] < keys[b]; });
|
||||
Polylines sorted;
|
||||
sorted.reserve(fragments.size());
|
||||
for (size_t n : order)
|
||||
sorted.emplace_back(std::move(fragments[n]));
|
||||
fragments = std::move(sorted);
|
||||
}
|
||||
|
||||
Lines _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons &clip)
|
||||
{
|
||||
// convert Lines to Polylines
|
||||
|
||||
@@ -528,6 +528,10 @@ Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r
|
||||
Slic3r::Polylines3 intersection_pl(const Slic3r::Polylines3 &subject, const Slic3r::Polygon &clip);
|
||||
Slic3r::Polylines3 intersection_pl(const Slic3r::Polylines3 &subject, const Slic3r::ExPolygon &clip);
|
||||
|
||||
// Orca: Sort and orient open polyline fragments produced by clipping `source` with
|
||||
// intersection_pl(), so that they run in the same order and direction as the source polyline.
|
||||
void restore_source_path_order(const Slic3r::Polyline &source, Slic3r::Polylines &fragments);
|
||||
|
||||
inline Slic3r::Lines intersection_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip)
|
||||
{
|
||||
return _clipper_ln(ClipperLib::ctIntersection, subject, clip);
|
||||
|
||||
@@ -177,7 +177,14 @@ double Extruder::filament_flow_ratio() const
|
||||
// Return a "retract_before_wipe" percentage as a factor clamped to <0, 1>
|
||||
double Extruder::retract_before_wipe() const
|
||||
{
|
||||
return std::min(1., std::max(0., m_config->retract_before_wipe.get_at(m_config_index) * 0.01));
|
||||
return std::clamp(m_config->retract_before_wipe.get_at(m_config_index) * 0.01, 0., 1.);
|
||||
}
|
||||
|
||||
// Orca:
|
||||
// Return a "retract_after_wipe" percentage as a factor clamped to <0, 1>
|
||||
double Extruder::retract_after_wipe() const
|
||||
{
|
||||
return std::min(std::clamp(m_config->retract_after_wipe.get_at(m_config_index) * 0.01, 0., 1.), 1. - retract_before_wipe());
|
||||
}
|
||||
|
||||
double Extruder::retraction_length() const
|
||||
|
||||
@@ -74,6 +74,8 @@ public:
|
||||
double filament_cost() const;
|
||||
double filament_flow_ratio() const;
|
||||
double retract_before_wipe() const;
|
||||
// Orca:
|
||||
double retract_after_wipe() const;
|
||||
double retraction_length() const;
|
||||
double retract_lift() const;
|
||||
int retract_speed() const;
|
||||
|
||||
@@ -352,8 +352,7 @@ namespace Slic3r
|
||||
int k,
|
||||
const std::vector<unsigned int>& used_filaments,
|
||||
const std::unordered_map<int, std::vector<int>>& unplaceable_limits,
|
||||
int* cost,
|
||||
int timeout_ms)
|
||||
int* cost)
|
||||
{
|
||||
auto distance_evaluator = std::make_shared<FlushDistanceEvaluator>(ctx.model_info.flush_matrix, used_filaments, ctx.model_info.layer_filaments);
|
||||
KMediods PAM(k, (int)used_filaments.size(), distance_evaluator, ctx.machine_info.master_extruder_id);
|
||||
@@ -369,7 +368,7 @@ namespace Slic3r
|
||||
}
|
||||
PAM.set_cluster_group_size(cluster_size_limit);
|
||||
|
||||
PAM.do_clustering(ctx, timeout_ms, 30);
|
||||
PAM.do_clustering(ctx, m_clustering_budget);
|
||||
|
||||
m_memoryed_heap = PAM.get_memoryed_groups();
|
||||
|
||||
@@ -793,7 +792,7 @@ namespace Slic3r
|
||||
2.1 In each cluster, make the point that minimizes the sum of distances within the cluster the medoid
|
||||
2.2 Reassign each point to the cluster defined by the closest medoid determined in the previous step
|
||||
*/
|
||||
void KMediods::do_clustering(const FilamentGroupContext &context, int timeout_ms, int retry)
|
||||
void KMediods::do_clustering(const FilamentGroupContext& context, const ClusteringBudget& budget)
|
||||
{
|
||||
FlushTimeMachine T;
|
||||
T.time_machine_start();
|
||||
@@ -817,7 +816,11 @@ namespace Slic3r
|
||||
double best_cluster_cost = std::numeric_limits<double>::max();
|
||||
int retry_count = 0;
|
||||
|
||||
while (retry_count < retry && T.time_machine_end() < timeout_ms) {
|
||||
// Run at least one restart; otherwise every filament would stay in the default group.
|
||||
const int retry = std::max(1, budget.max_restarts);
|
||||
auto within_budget = [&]() { return budget.timeout_ms <= 0 || T.time_machine_end() < budget.timeout_ms; };
|
||||
|
||||
while (retry_count < retry && within_budget()) {
|
||||
std::vector<int> curr_cluster_centers = init_cluster_center(m_placeable_limits, m_unplaceable_limits, m_max_cluster_size, m_cluster_group_size, retry_count);
|
||||
std::vector<int> curr_cluster_labels = assign_cluster_label(curr_cluster_centers, m_placeable_limits, m_unplaceable_limits, m_max_cluster_size, m_cluster_group_size);
|
||||
double curr_cluster_cost = evaluate_labels(curr_cluster_labels);
|
||||
@@ -826,7 +829,7 @@ namespace Slic3r
|
||||
update_memoryed_groups(g, memory_threshold, memoryed_groups);
|
||||
|
||||
bool mediods_changed = true;
|
||||
while (mediods_changed && T.time_machine_end() < timeout_ms) {
|
||||
while (mediods_changed && within_budget()) {
|
||||
mediods_changed = false;
|
||||
double best_swap_cost = curr_cluster_cost;
|
||||
int best_swap_cluster = -1;
|
||||
@@ -889,7 +892,7 @@ namespace Slic3r
|
||||
if (estimated < ENUM_THRESHOLD)
|
||||
result = calc_group_by_enum(k, used_filaments, unplaceable_limits, cost);
|
||||
else
|
||||
result = calc_group_by_kmedoids(k, used_filaments, unplaceable_limits, cost, 3000);
|
||||
result = calc_group_by_kmedoids(k, used_filaments, unplaceable_limits, cost);
|
||||
|
||||
change_memoryed_heaps_to_arrays(m_memoryed_heap, ctx.group_info.total_filament_num, used_filaments, m_memoryed_groups);
|
||||
|
||||
|
||||
@@ -142,6 +142,16 @@ namespace Slic3r
|
||||
FilamentGroupContext::SpeedInfo m_speed_info;
|
||||
};
|
||||
|
||||
// Search budget for the k-medoids clustering, an anytime search. Each restart is seeded from its
|
||||
// own index, so what it returns depends on how many restarts complete before the clock expires,
|
||||
// and therefore on the speed of the machine. A timeout_ms <= 0 removes the clock and bounds the
|
||||
// search by max_restarts alone.
|
||||
struct ClusteringBudget
|
||||
{
|
||||
int timeout_ms = 3000;
|
||||
int max_restarts = 30;
|
||||
};
|
||||
|
||||
class FilamentGroup
|
||||
{
|
||||
using MemoryedGroup = FilamentGroupUtils::MemoryedGroup;
|
||||
@@ -149,6 +159,8 @@ namespace Slic3r
|
||||
public:
|
||||
explicit FilamentGroup(const FilamentGroupContext& ctx_) :ctx(ctx_) {}
|
||||
public:
|
||||
void set_clustering_budget(const ClusteringBudget& budget) { m_clustering_budget = budget; }
|
||||
|
||||
std::vector<int> calc_filament_group(int * cost = nullptr);
|
||||
std::vector<std::vector<int>> get_memoryed_groups()const { return m_memoryed_groups; }
|
||||
|
||||
@@ -162,7 +174,7 @@ namespace Slic3r
|
||||
std::vector<int> calc_group_by_enum(int k, const std::vector<unsigned int>& used_filaments,
|
||||
const std::unordered_map<int, std::vector<int>>& unplaceable_limits, int* cost = nullptr);
|
||||
std::vector<int> calc_group_by_kmedoids(int k, const std::vector<unsigned int>& used_filaments,
|
||||
const std::unordered_map<int, std::vector<int>>& unplaceable_limits, int* cost = nullptr, int timeout_ms = 500);
|
||||
const std::unordered_map<int, std::vector<int>>& unplaceable_limits, int* cost = nullptr);
|
||||
|
||||
std::map<int, int> rebuild_unprintables(const std::vector<unsigned int>& used_filaments, const std::map<int,int>& extruder_unprintables);
|
||||
std::unordered_map<int, std::vector<int>> rebuild_nozzle_unprintables(const std::vector<unsigned int>& used_filaments, const std::unordered_map<int, std::vector<int>>& extruder_unprintables, const std::vector<int>& filament_volume_map);
|
||||
@@ -175,6 +187,7 @@ namespace Slic3r
|
||||
FilamentGroupContext ctx;
|
||||
MemoryedGroupHeap m_memoryed_heap;
|
||||
std::vector<std::vector<int>> m_memoryed_groups;
|
||||
ClusteringBudget m_clustering_budget;
|
||||
public:
|
||||
std::optional<std::function<bool(int, std::vector<int>&)>> get_custom_seq;
|
||||
};
|
||||
@@ -220,7 +233,7 @@ namespace Slic3r
|
||||
void set_memory_threshold(double threshold) { memory_threshold = threshold; }
|
||||
MemoryedGroupHeap get_memoryed_groups()const { return memoryed_groups; }
|
||||
|
||||
void do_clustering(const FilamentGroupContext& context, int timeout_ms = 100, int retry = 10);
|
||||
void do_clustering(const FilamentGroupContext& context, const ClusteringBudget& budget);
|
||||
std::vector<int> get_cluster_labels()const { return m_cluster_labels; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -272,10 +272,12 @@ struct SurfaceFillParams
|
||||
// For Gyroid: when true, use the parameterized "optimized" wave.
|
||||
bool gyroid_optimized = false;
|
||||
|
||||
bool anisotropic_surfaces{false};
|
||||
CenterOfSurfacePattern center_of_surface_pattern{CenterOfSurfacePattern::Each_Surface};
|
||||
bool separated_infills{false};
|
||||
|
||||
// Orca: forced print order of surface fill loops/fragments for center-based patterns.
|
||||
SurfaceFillOrder fill_order = SurfaceFillOrder::Default;
|
||||
|
||||
bool operator<(const SurfaceFillParams &rhs) const {
|
||||
#define RETURN_COMPARE_NON_EQUAL(KEY) if (this->KEY < rhs.KEY) return true; if (this->KEY > rhs.KEY) return false;
|
||||
#define RETURN_COMPARE_NON_EQUAL_TYPED(TYPE, KEY) if (TYPE(this->KEY) < TYPE(rhs.KEY)) return true; if (TYPE(this->KEY) > TYPE(rhs.KEY)) return false;
|
||||
@@ -308,9 +310,9 @@ struct SurfaceFillParams
|
||||
RETURN_COMPARE_NON_EQUAL(skin_infill_depth);
|
||||
RETURN_COMPARE_NON_EQUAL(infill_overhang_angle);
|
||||
RETURN_COMPARE_NON_EQUAL(gyroid_optimized);
|
||||
RETURN_COMPARE_NON_EQUAL(anisotropic_surfaces);
|
||||
RETURN_COMPARE_NON_EQUAL(center_of_surface_pattern);
|
||||
RETURN_COMPARE_NON_EQUAL(separated_infills);
|
||||
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, fill_order);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -337,10 +339,10 @@ struct SurfaceFillParams
|
||||
this->infill_lock_depth == rhs.infill_lock_depth &&
|
||||
this->skin_infill_depth == rhs.skin_infill_depth &&
|
||||
this->infill_overhang_angle == rhs.infill_overhang_angle &&
|
||||
this->anisotropic_surfaces == rhs.anisotropic_surfaces &&
|
||||
this->center_of_surface_pattern == rhs.center_of_surface_pattern &&
|
||||
this->separated_infills == rhs.separated_infills &&
|
||||
this->gyroid_optimized == rhs.gyroid_optimized;
|
||||
this->gyroid_optimized == rhs.gyroid_optimized &&
|
||||
this->fill_order == rhs.fill_order;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -879,7 +881,6 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
||||
params.lateral_lattice_angle_1 = region_config.lateral_lattice_angle_1;
|
||||
params.lateral_lattice_angle_2 = region_config.lateral_lattice_angle_2;
|
||||
params.infill_overhang_angle = region_config.infill_overhang_angle;
|
||||
params.anisotropic_surfaces = region_config.anisotropic_surfaces;
|
||||
params.center_of_surface_pattern = region_config.center_of_surface_pattern;
|
||||
params.separated_infills = region_config.separated_infills;
|
||||
if (params.pattern == ipLockedZag) {
|
||||
@@ -936,6 +937,14 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
||||
params.extruder = region_config.bottom_surface_filament_id;
|
||||
else if (params.extrusion_role == erSolidInfill)
|
||||
params.extruder = region_config.internal_solid_filament_id;
|
||||
// Orca: forced fill order applies only to top/bottom surfaces filled with a
|
||||
// center-based pattern; everything else stays at Default to keep batching together.
|
||||
if (params.pattern == ipConcentric || params.pattern == ipArchimedeanChords || params.pattern == ipOctagramSpiral) {
|
||||
if (params.extrusion_role == erTopSolidInfill)
|
||||
params.fill_order = region_config.top_surface_fill_order.value;
|
||||
else if (params.extrusion_role == erBottomSurface)
|
||||
params.fill_order = region_config.bottom_surface_fill_order.value;
|
||||
}
|
||||
// Orca: apply fill multiline only for sparse infill
|
||||
params.multiline = params.extrusion_role == erInternalInfill ? int(region_config.fill_multiline) : 1;
|
||||
|
||||
@@ -1322,12 +1331,12 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||
auto ®ion_config = layerm->region().config();
|
||||
params.config = ®ion_config;
|
||||
params.pattern = surface_fill.params.pattern;
|
||||
params.fill_order = surface_fill.params.fill_order;
|
||||
|
||||
// Orca: Checking the filling of a centered surface by drawing for each model parts
|
||||
bool is_top_or_bottom = params.extrusion_role == erTopSolidInfill || params.extrusion_role == erBottomSurface;
|
||||
bool is_centered_infill = surface_fill.params.pattern == ipArchimedeanChords || surface_fill.params.pattern == ipOctagramSpiral;
|
||||
if (is_top_or_bottom) {
|
||||
params.is_anisotropic = surface_fill.params.anisotropic_surfaces; // Orca: anisotropic surfaces
|
||||
params.center_of_surface_pattern = surface_fill.params.center_of_surface_pattern; // Orca: center of surface pattern
|
||||
}
|
||||
// Orca: Each_Model centers the pattern on each model part's bbox; Each_Surface / Each_Assembly
|
||||
|
||||
@@ -162,10 +162,11 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
|
||||
out.push_back(eec = new ExtrusionEntityCollection());
|
||||
// Only concentric fills are not sorted.
|
||||
eec->no_sort = this->no_sort();
|
||||
// ORCA: special flag for flow rate calibration
|
||||
auto is_flow_calib = params.extrusion_role == erTopSolidInfill && this->print_object_config->has("calib_flowrate_topinfill_special_order") &&
|
||||
this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool();
|
||||
if (is_flow_calib || params.is_anisotropic) { // Orca: disable sorting while anisotropic surfaces
|
||||
// Orca: a forced surface fill order must survive the G-code path planner, which would
|
||||
// otherwise re-chain and possibly reverse the paths. This also covers the flow rate
|
||||
// calibration, which forces an outward fill order on its top surfaces.
|
||||
const bool keep_fill_order = params.fill_order != SurfaceFillOrder::Default;
|
||||
if (keep_fill_order) {
|
||||
eec->no_sort = true;
|
||||
}
|
||||
size_t idx = eec->entities.size();
|
||||
@@ -180,14 +181,13 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
|
||||
params.extrusion_role,
|
||||
flow_mm3_per_mm, float(flow_width), params.flow.height());
|
||||
}
|
||||
if (!params.can_reverse || is_flow_calib) {
|
||||
if (!params.can_reverse || keep_fill_order) {
|
||||
for (size_t i = idx; i < eec->entities.size(); i++)
|
||||
eec->entities[i]->set_reverse();
|
||||
}
|
||||
|
||||
// Orca: run gap fill
|
||||
if (!(params.is_anisotropic)) // Orca: Disable gap filling while anisotropic
|
||||
this->_create_gap_fill(surface, params, eec);
|
||||
this->_create_gap_fill(surface, params, eec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,13 +100,16 @@ struct FillParams
|
||||
bool dont_sort{ false }; // do not sort the lines, just simply connect them
|
||||
bool can_reverse{true};
|
||||
|
||||
// Orca: forced print order of surface fill loops/fragments for center-based patterns
|
||||
// (Concentric, Archimedean Chords, Octagram Spiral). Default keeps shortest-path ordering.
|
||||
SurfaceFillOrder fill_order { SurfaceFillOrder::Default };
|
||||
|
||||
float horiz_move{0.0}; //move infill to get cross zag pattern
|
||||
bool symmetric_infill_y_axis{false};
|
||||
coord_t symmetric_y_axis{0};
|
||||
bool locked_zag{false};
|
||||
float infill_lock_depth{0.0};
|
||||
float skin_infill_depth{0.0};
|
||||
bool is_anisotropic{false};
|
||||
CenterOfSurfacePattern center_of_surface_pattern{CenterOfSurfacePattern::Each_Surface};
|
||||
};
|
||||
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
||||
|
||||
@@ -41,6 +41,10 @@ void FillConcentric::_fill_surface_single(
|
||||
// generate paths from the outermost to the innermost, to avoid
|
||||
// adhesion problems of the first central tiny loops
|
||||
loops = union_pt_chained_outside_in(loops);
|
||||
|
||||
// Orca: an outward fill order prints the innermost loops first instead.
|
||||
if (params.fill_order == SurfaceFillOrder::Outward)
|
||||
std::reverse(loops.begin(), loops.end());
|
||||
|
||||
// split paths using a nearest neighbor search
|
||||
size_t iPathFirst = polylines_out.size();
|
||||
@@ -108,6 +112,17 @@ void FillConcentric::_fill_surface_single(const FillParams& params,
|
||||
all_extrusions.emplace_back(&wall);
|
||||
}
|
||||
|
||||
// Orca: a forced fill order prints the loops in strictly monotonic depth order so
|
||||
// that surfaces broken up by holes or slots cannot hop outward and back inward.
|
||||
const bool forced_fill_order = params.fill_order != SurfaceFillOrder::Default;
|
||||
if (forced_fill_order) {
|
||||
const bool outward = params.fill_order == SurfaceFillOrder::Outward;
|
||||
std::stable_sort(all_extrusions.begin(), all_extrusions.end(),
|
||||
[outward](const Arachne::ExtrusionLine *a, const Arachne::ExtrusionLine *b) {
|
||||
return outward ? a->inset_idx > b->inset_idx : a->inset_idx < b->inset_idx;
|
||||
});
|
||||
}
|
||||
|
||||
// Split paths using a nearest neighbor search.
|
||||
size_t firts_poly_idx = thick_polylines_out.size();
|
||||
Point last_pos(0, 0);
|
||||
@@ -136,7 +151,8 @@ void FillConcentric::_fill_surface_single(const FillParams& params,
|
||||
if (j < thick_polylines_out.size())
|
||||
thick_polylines_out.erase(thick_polylines_out.begin() + int(j), thick_polylines_out.end());
|
||||
|
||||
reorder_by_shortest_traverse(thick_polylines_out);
|
||||
if (!forced_fill_order)
|
||||
reorder_by_shortest_traverse(thick_polylines_out);
|
||||
}
|
||||
else {
|
||||
Polylines polylines;
|
||||
|
||||
@@ -133,49 +133,26 @@ void FillPlanePath::_fill_surface_single(
|
||||
polylines = intersection_pl(std::move(polylines), expolygon);
|
||||
if (!polylines.empty()) {
|
||||
Polylines chained;
|
||||
if (!params.is_anisotropic) { // Orca: not anisotropic surface
|
||||
if ((params.dont_connect() || params.density > 0.5)) {
|
||||
// ORCA: special flag for flow rate calibration
|
||||
auto is_flow_calib = params.extrusion_role == erTopSolidInfill &&
|
||||
this->print_object_config->has("calib_flowrate_topinfill_special_order") &&
|
||||
this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool() &&
|
||||
dynamic_cast<FillArchimedeanChords*>(this);
|
||||
if (is_flow_calib) {
|
||||
// We want the spiral part to be printed inside-out
|
||||
// Find the center spiral line first, by looking for the longest one
|
||||
auto it = std::max_element(polylines.begin(), polylines.end(),
|
||||
[](const Polyline& a, const Polyline& b) { return a.length() < b.length(); });
|
||||
Polyline center_spiral = std::move(*it);
|
||||
|
||||
// Ensure the spiral is printed from inside to out
|
||||
if ((center_spiral.first_point().squaredNorm() > center_spiral.last_point().squaredNorm())) {
|
||||
center_spiral.reverse();
|
||||
}
|
||||
|
||||
// Chain the other polylines
|
||||
polylines.erase(it);
|
||||
chained = chain_polylines(std::move(polylines), nullptr);
|
||||
|
||||
// Then add the center spiral back
|
||||
chained.push_back(std::move(center_spiral));
|
||||
} else {
|
||||
chained = chain_polylines(std::move(polylines), nullptr);
|
||||
if (params.dont_connect() || params.density > 0.5) {
|
||||
if (params.fill_order != SurfaceFillOrder::Default) {
|
||||
// Orca: print the fragments in the order they appear along the generated
|
||||
// path, which runs from the center outwards. The Euclidean distance from
|
||||
// the center cannot be used for this: along the Octagram Spiral the radius
|
||||
// oscillates by far more than the ring spacing, so fragments of different
|
||||
// rings would interleave.
|
||||
restore_source_path_order(polyline, polylines);
|
||||
chained = std::move(polylines);
|
||||
if (params.fill_order == SurfaceFillOrder::Inward) {
|
||||
// The source path runs from the center outwards; flip everything for inward.
|
||||
std::reverse(chained.begin(), chained.end());
|
||||
for (Polyline &pl : chained)
|
||||
pl.reverse();
|
||||
}
|
||||
} else
|
||||
connect_infill(std::move(polylines), expolygon, chained, this->spacing, params);
|
||||
} else { // Orca: anisotropic surface
|
||||
const Point _center(0., 0.);
|
||||
for (Polyline& segment : polylines) { // sort paths by its direction
|
||||
if (segment.size() > 1) { // need at least two points to evaluate direction
|
||||
if (segment.first_point().ccw(segment.points[1], _center) < 0)
|
||||
segment.reverse();
|
||||
}
|
||||
chained.emplace_back(std::move(segment));
|
||||
} else {
|
||||
chained = chain_polylines(std::move(polylines), nullptr);
|
||||
}
|
||||
std::sort(chained.begin(), chained.end(), [&_center](const Polyline& a, const Polyline& b) { // just sort polylines from center to outside
|
||||
return a.distance_to(_center) < b.distance_to(_center);
|
||||
});
|
||||
}
|
||||
} else
|
||||
connect_infill(std::move(polylines), expolygon, chained, this->spacing, params);
|
||||
// paths must be repositioned and rotated back
|
||||
for (Polyline& pl : chained) {
|
||||
pl.translate(shift.x(), shift.y());
|
||||
|
||||
+40
-21
@@ -441,22 +441,30 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
|
||||
// Declare & initialize retraction lengths
|
||||
double retraction_length_remaining = 0,
|
||||
retractionBeforeWipe = 0,
|
||||
retractionDuringWipe = 0;
|
||||
retraction_length_before_wipe = 0,
|
||||
retraction_length_during_wipe = 0,
|
||||
retraction_length_after_wipe = 0;
|
||||
|
||||
// initialise the remaining retraction amount with the full retraction amount.
|
||||
retraction_length_remaining = toolchange ? extruder->retract_length_toolchange() : extruder->retraction_length();
|
||||
// Initialise the remaining retraction amount with the full retraction amount.
|
||||
retraction_length_remaining = toolchange ?
|
||||
extruder->retract_length_toolchange() : extruder->retraction_length();
|
||||
|
||||
// nothing to retract - return early
|
||||
if(retraction_length_remaining <=EPSILON) return {0.f,0.f};
|
||||
// Nothing to retract - return early
|
||||
if (retraction_length_remaining <= EPSILON)
|
||||
return { 0.f, 0.f, 0.f };
|
||||
|
||||
// calculate retraction before wipe distance from the user setting. Keep adding to this variable any excess retraction needed
|
||||
// to be performed before the wipe.
|
||||
retractionBeforeWipe = retraction_length_remaining * extruder->retract_before_wipe();
|
||||
retraction_length_remaining -= retractionBeforeWipe; // subtract it from the remaining retraction length
|
||||
|
||||
// all of the retraction is to be done before the wipe
|
||||
if(retraction_length_remaining <=EPSILON) return {retractionBeforeWipe,0.f};
|
||||
// Calculate retraction before and after wipe distances from the user setting.
|
||||
// Keep adding to the for retraction before wipe variable any excess retraction
|
||||
// needed to be performed before the wipe.
|
||||
retraction_length_before_wipe = retraction_length_remaining * extruder->retract_before_wipe();
|
||||
retraction_length_after_wipe = retraction_length_remaining * extruder->retract_after_wipe();
|
||||
|
||||
// Subtract it from the remaining retraction length
|
||||
retraction_length_remaining -= retraction_length_before_wipe + retraction_length_after_wipe;
|
||||
|
||||
// All of the retraction is to be done before the wipe
|
||||
if (retraction_length_remaining <= EPSILON)
|
||||
return { retraction_length_before_wipe, 0., retraction_length_after_wipe };
|
||||
|
||||
// Calculate wipe speed
|
||||
// Orca: resolve the travel_speed slot via the Print-side per-layer resolver; the writer's
|
||||
@@ -471,18 +479,25 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
double wipe_path_length = std::min(wipe_path.length(), wipe_dist);
|
||||
|
||||
// Calculate the maximum retraction amount during wipe
|
||||
retractionDuringWipe = config.retraction_speed.get_at(extruder_id) * unscale_(wipe_path_length) / wipe_speed;
|
||||
// If the maximum retraction amount during wipe is too small, return 0 and retract everything prior to the wipe.
|
||||
if(retractionDuringWipe <= EPSILON) return {retractionBeforeWipe,0.f};
|
||||
retraction_length_during_wipe = config.retraction_speed.get_at(extruder_id) *
|
||||
unscale_(wipe_path_length) / wipe_speed;
|
||||
|
||||
// If the maximum retraction amount during wipe is too small,
|
||||
// disable wipe-time retraction and leave any remaining retract amount
|
||||
// to the subsequent standard retract flow.
|
||||
if (retraction_length_during_wipe <= EPSILON)
|
||||
return { retraction_length_before_wipe, 0., retraction_length_after_wipe };
|
||||
|
||||
// If the maximum retraction amount during wipe is greater than any remaining retraction length
|
||||
// return the remaining retraction length to be retracted during the wipe
|
||||
if (retractionDuringWipe - retraction_length_remaining > EPSILON) return {retractionBeforeWipe,retraction_length_remaining};
|
||||
if (retraction_length_during_wipe - retraction_length_remaining > EPSILON)
|
||||
return { retraction_length_before_wipe, retraction_length_remaining, retraction_length_after_wipe };
|
||||
|
||||
// We will always proceed with incrementing the retraction amount before wiping with the difference
|
||||
// and return the maximum allowed wipe amount to be retracted during the wipe move
|
||||
retractionBeforeWipe += retraction_length_remaining - retractionDuringWipe;
|
||||
return {retractionBeforeWipe, retractionDuringWipe};
|
||||
retraction_length_before_wipe += retraction_length_remaining - retraction_length_during_wipe;
|
||||
|
||||
return { retraction_length_before_wipe, retraction_length_during_wipe, retraction_length_after_wipe };
|
||||
}
|
||||
|
||||
std::string transform_gcode(const std::string &gcode, Vec2f pos, const Vec2f &translation, float angle)
|
||||
@@ -8507,8 +8522,12 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
|
||||
// wipe (if it's enabled for this extruder and we have a stored wipe path and no-zero wipe distance)
|
||||
if (FILAMENT_CONFIG(wipe) && m_wipe.has_path() && scale_(FILAMENT_CONFIG(wipe_distance)) > SCALED_EPSILON) {
|
||||
Wipe::RetractionValues wipeRetractions = m_wipe.calculateWipeRetractionLengths(*this, toolchange);
|
||||
gcode += toolchange ? m_writer.retract_for_toolchange(true,wipeRetractions.retractLengthBeforeWipe) : m_writer.retract(true, wipeRetractions.retractLengthBeforeWipe);
|
||||
gcode += m_wipe.wipe(*this,wipeRetractions.retractLengthDuringWipe, toolchange, is_last_retraction);
|
||||
gcode += toolchange ? m_writer.retract_for_toolchange(true, wipeRetractions.retraction_length_before_wipe) :
|
||||
m_writer.retract(true, wipeRetractions.retraction_length_before_wipe);
|
||||
gcode += m_wipe.wipe(*this, wipeRetractions.retraction_length_during_wipe, toolchange, is_last_retraction);
|
||||
|
||||
// Orca: wipeRetractions.retraction_length_after_wipe is not being used explicitly,
|
||||
// the remaining retraction after wipe is handled by the subsequent m_writer.retract() call
|
||||
}
|
||||
|
||||
/* The parent class will decide whether we need to perform an actual retraction
|
||||
|
||||
@@ -60,15 +60,20 @@ class Wipe {
|
||||
public:
|
||||
bool enable;
|
||||
Polyline path;
|
||||
|
||||
// Orca:
|
||||
struct RetractionValues{
|
||||
double retractLengthBeforeWipe;
|
||||
double retractLengthDuringWipe;
|
||||
double retraction_length_before_wipe = 0.;
|
||||
double retraction_length_during_wipe = 0.;
|
||||
double retraction_length_after_wipe = 0.;
|
||||
};
|
||||
|
||||
Wipe() : enable(false) {}
|
||||
bool has_path() const { return !this->path.points.empty(); }
|
||||
void reset_path() { this->path = Polyline(); }
|
||||
std::string wipe(GCode &gcodegen, double length, bool toolchange = false, bool is_last = false);
|
||||
|
||||
// Orca:
|
||||
RetractionValues calculateWipeRetractionLengths(GCode& gcodegen, bool toolchange);
|
||||
};
|
||||
|
||||
|
||||
@@ -6551,8 +6551,11 @@ void GCodeProcessor::process_T(const std::string_view command, int nozzle_id)
|
||||
if (command.length() > 1) {
|
||||
if (eid < 0 || eid > 254) {
|
||||
//BBS: T255, T1000 and T1100 is used as special command for BBL machine and does not cost time. return directly
|
||||
// Orca: T1001 (hotend-type detection) and T65535/T65279 (AMS unload virtual-tool selects, paired with
|
||||
// M620/M621 S65535/S65279) are firmware opcodes emitted verbatim by BBL machine start/end g-code, not
|
||||
// real tool changes - whitelist them so the time estimator stops flagging these valid lines.
|
||||
if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) && (command == "Tx" || command == "Tc" || command == "T?" ||
|
||||
eid == 1000 || eid == 1100 || eid == 255))
|
||||
eid == 1000 || eid == 1100 || eid == 255 || eid == 1001 || eid == 65279 || eid == 65535))
|
||||
return;
|
||||
|
||||
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools)
|
||||
|
||||
@@ -1048,6 +1048,8 @@ static std::vector<std::string> s_Preset_print_options{
|
||||
"top_surface_expansion_margin",
|
||||
"top_surface_expansion_direction",
|
||||
"bottom_surface_pattern",
|
||||
"top_surface_fill_order",
|
||||
"bottom_surface_fill_order",
|
||||
"infill_direction",
|
||||
"solid_infill_direction",
|
||||
"top_layer_direction",
|
||||
@@ -1063,7 +1065,6 @@ static std::vector<std::string> s_Preset_print_options{
|
||||
"skin_infill_density",
|
||||
"align_infill_direction_to_model",
|
||||
"extra_solid_infills",
|
||||
"anisotropic_surfaces",
|
||||
"center_of_surface_pattern",
|
||||
"separated_infills",
|
||||
"minimum_sparse_infill_area",
|
||||
@@ -1309,7 +1310,6 @@ static std::vector<std::string> s_Preset_print_options{
|
||||
"interlocking_depth",
|
||||
"interlocking_boundary_avoidance",
|
||||
"interlocking_beam_width",
|
||||
"calib_flowrate_topinfill_special_order",
|
||||
// Z Anti-Aliasing (ZAA)
|
||||
"zaa_enabled",
|
||||
"zaa_minimize_perimeter_height",
|
||||
@@ -1335,8 +1335,20 @@ static std::vector<std::string> s_Preset_filament_options {/*"filament_colour",
|
||||
//exhaust fan control
|
||||
"activate_air_filtration","activate_air_filtration_during_print","activate_air_filtration_on_completion","during_print_exhaust_fan_speed","complete_print_exhaust_fan_speed",
|
||||
// Retract overrides
|
||||
"filament_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_lift_enforce", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel",
|
||||
"filament_retract_when_changing_layer", "filament_wipe", "filament_retract_before_wipe",
|
||||
"filament_deretraction_speed",
|
||||
"filament_retract_after_wipe", // Orca
|
||||
"filament_retract_before_wipe",
|
||||
"filament_retract_lift_above",
|
||||
"filament_retract_lift_below",
|
||||
"filament_retract_lift_enforce",
|
||||
"filament_retract_restart_extra",
|
||||
"filament_retract_when_changing_layer",
|
||||
"filament_retraction_length",
|
||||
"filament_retraction_minimum_travel",
|
||||
"filament_retraction_speed",
|
||||
"filament_wipe",
|
||||
"filament_z_hop",
|
||||
"filament_z_hop_types",
|
||||
// Profile compatibility
|
||||
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||
//BBS
|
||||
|
||||
+16
-7
@@ -177,6 +177,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
"filename_format",
|
||||
"retraction_minimum_travel",
|
||||
"retract_before_wipe",
|
||||
// Orca:
|
||||
"retract_after_wipe",
|
||||
"retract_when_changing_layer",
|
||||
"retraction_length",
|
||||
"retract_length_toolchange",
|
||||
@@ -210,7 +212,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
"chamber_minimal_temperature",
|
||||
"thumbnails",
|
||||
"thumbnails_format",
|
||||
"anisotropic_surfaces",
|
||||
"center_of_surface_pattern",
|
||||
"separated_infills",
|
||||
"seam_gap",
|
||||
@@ -3676,6 +3677,8 @@ int Print::get_filament_config_indx(int filament_id, int layer_id)
|
||||
|
||||
void Print::update_filament_self_index_cache()
|
||||
{
|
||||
m_missing_nozzle_group_logged.clear(); // reset the per-slice get_config_index log dedupe
|
||||
|
||||
std::vector<int> values;
|
||||
if (m_full_print_config.has("filament_self_index")) {
|
||||
values = m_full_print_config.option<ConfigOptionInts>("filament_self_index")->values;
|
||||
@@ -3721,9 +3724,12 @@ int Print::get_config_index(int filament_id, int layer_id, const std::vector<std
|
||||
return filament_id;
|
||||
auto nozzle_info = group_result->get_nozzle_for_filament(filament_id, layer_id);
|
||||
if (!nozzle_info.has_value()) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__
|
||||
<< boost::format(", Line %1%: could not found group_nozzle_info corresponding to filament_id %2%, layer_id %3%") % __LINE__ % filament_id %
|
||||
layer_id;
|
||||
// Orca: this fallback runs per-filament/per-layer in the g-code hot path — log once per filament
|
||||
// (reset each slice) instead of flooding thousands of identical lines that bury the real error.
|
||||
if (m_missing_nozzle_group_logged.insert(filament_id).second)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__
|
||||
<< boost::format(", Line %1%: could not found group_nozzle_info corresponding to filament_id %2%, layer_id %3% (further occurrences for this filament suppressed)") % __LINE__ % filament_id %
|
||||
layer_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3750,9 +3756,12 @@ int Print::get_config_index(int filament_id, int layer_id, const std::vector<std
|
||||
return (int)get_extruder_id(filament_id);
|
||||
auto nozzle_info = group_result->get_nozzle_for_filament(filament_id, layer_id);
|
||||
if (!nozzle_info.has_value()) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__
|
||||
<< boost::format(", Line %1%: could not found group_nozzle_info corresponding to filament_id %2%, layer_id %3%") % __LINE__ % filament_id %
|
||||
layer_id;
|
||||
// Orca: this fallback runs per-filament/per-layer in the g-code hot path — log once per filament
|
||||
// (reset each slice) instead of flooding thousands of identical lines that bury the real error.
|
||||
if (m_missing_nozzle_group_logged.insert(filament_id).second)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__
|
||||
<< boost::format(", Line %1%: could not found group_nozzle_info corresponding to filament_id %2%, layer_id %3% (further occurrences for this filament suppressed)") % __LINE__ % filament_id %
|
||||
layer_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1303,6 +1303,10 @@ private:
|
||||
FilamentIndexMap m_filament_index_map;
|
||||
// Used to cache printer and process parameter information
|
||||
PrintIndexMap m_nozzle_index_map;
|
||||
// Orca: filament ids already reported as missing a nozzle-group entry this slice. get_config_index()
|
||||
// falls back per-filament/per-layer in the g-code hot path, so this dedupes its log to once per
|
||||
// filament instead of flooding thousands of identical error lines. Cleared with the caches each slice.
|
||||
std::set<int> m_missing_nozzle_group_logged;
|
||||
// save the config value of "filament_self_index"
|
||||
std::vector<int> m_filament_self_index;
|
||||
|
||||
|
||||
+122
-27
@@ -79,6 +79,9 @@ const std::vector<std::string> filament_extruder_override_keys = {
|
||||
"filament_wipe",
|
||||
// percents
|
||||
"filament_retract_before_wipe",
|
||||
// Orca
|
||||
"filament_retract_after_wipe",
|
||||
// BBS
|
||||
"filament_long_retractions_when_cut",
|
||||
"filament_retraction_distances_when_cut"
|
||||
};
|
||||
@@ -310,6 +313,14 @@ static t_config_enum_values s_keys_map_WallDirection{
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallDirection)
|
||||
|
||||
//Orca
|
||||
static t_config_enum_values s_keys_map_SurfaceFillOrder{
|
||||
{ "default", int(SurfaceFillOrder::Default) },
|
||||
{ "outward", int(SurfaceFillOrder::Outward) },
|
||||
{ "inward", int(SurfaceFillOrder::Inward) },
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SurfaceFillOrder)
|
||||
|
||||
//BBS
|
||||
static t_config_enum_values s_keys_map_PrintSequence {
|
||||
{ "by layer", int(PrintSequence::ByLayer) },
|
||||
@@ -2319,6 +2330,40 @@ void PrintConfigDef::init_fff_params()
|
||||
def->max = 100;
|
||||
def->set_default_value(new ConfigOptionPercent(100));
|
||||
|
||||
auto def_top_fill_order = def = this->add("top_surface_fill_order", coEnum);
|
||||
def->label = L("Top surface fill order");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Direction in which top surfaces are filled when using a center-based pattern "
|
||||
"(Concentric, Archimedean Chords, Octagram Spiral).\n"
|
||||
"Outward starts at the center of the surface, so any excess material is pushed "
|
||||
"towards the edge where it is least visible. Inward starts at the edge and ends "
|
||||
"with the tight curves at the center.\n"
|
||||
"Default uses shortest-path ordering, which may run in either direction.");
|
||||
def->enum_keys_map = &ConfigOptionEnum<SurfaceFillOrder>::get_enum_values();
|
||||
def->enum_values.push_back("default");
|
||||
def->enum_values.push_back("outward");
|
||||
def->enum_values.push_back("inward");
|
||||
def->enum_labels.push_back(L("Default"));
|
||||
def->enum_labels.push_back(L("Outward"));
|
||||
def->enum_labels.push_back(L("Inward"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<SurfaceFillOrder>(SurfaceFillOrder::Default));
|
||||
|
||||
def = this->add("bottom_surface_fill_order", coEnum);
|
||||
def->label = L("Bottom surface fill order");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Direction in which bottom surfaces are filled when using a center-based pattern "
|
||||
"(Concentric, Archimedean Chords, Octagram Spiral).\n"
|
||||
"Inward starts each surface with the wider outer curves, which improves first layer "
|
||||
"adhesion on build plates where the tight curves at the center may not stick. "
|
||||
"Outward starts at the center, pushing any excess material towards the edge.\n"
|
||||
"Default uses shortest-path ordering, which may run in either direction.");
|
||||
def->enum_keys_map = &ConfigOptionEnum<SurfaceFillOrder>::get_enum_values();
|
||||
def->enum_values = def_top_fill_order->enum_values;
|
||||
def->enum_labels = def_top_fill_order->enum_labels;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<SurfaceFillOrder>(SurfaceFillOrder::Default));
|
||||
|
||||
def = this->add("internal_solid_infill_pattern", coEnum);
|
||||
def->label = L("Internal solid infill pattern");
|
||||
def->category = L("Strength");
|
||||
@@ -4602,11 +4647,6 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(2));
|
||||
|
||||
// ORCA: special flag for flow rate calibration
|
||||
def = this->add("calib_flowrate_topinfill_special_order", coBool);
|
||||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("ironing_type", coEnum);
|
||||
def->label = L("Ironing type");
|
||||
def->category = L("Quality");
|
||||
@@ -5546,6 +5586,15 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPercents { 100 });
|
||||
|
||||
// Orca:
|
||||
def = this->add("retract_after_wipe", coPercents);
|
||||
def->label = L("Retract amount after wipe");
|
||||
def->tooltip = L("The length of fast retraction after wipe, relative to retraction length.\n"
|
||||
"The value will be clamped by 100% minus the retract amount before the wipe value.");
|
||||
def->sidetext = "%";
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionPercents { 0 });
|
||||
|
||||
def = this->add("retract_when_changing_layer", coBools);
|
||||
def->label = L("Retract on layer change");
|
||||
def->tooltip = L("This forces a retraction on layer changes.");
|
||||
@@ -7186,17 +7235,6 @@ void PrintConfigDef::init_fff_params()
|
||||
def->min = 0;
|
||||
def->set_default_value(new ConfigOptionFloat(0.6));
|
||||
|
||||
def = this->add("anisotropic_surfaces", coBool);
|
||||
def->label = L("Anisotropic surfaces");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Anisotropic patterns on the top and bottom surfaces.\n"
|
||||
"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color "
|
||||
"dispersion when using multi-colored or silk plastics.\n"
|
||||
"This option disable the gap fill.\n"
|
||||
"This option can increase a printing time.");
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("separated_infills", coBool);
|
||||
def->label = L("Separated infills");
|
||||
def->category = L("Strength");
|
||||
@@ -7987,17 +8025,44 @@ void PrintConfigDef::init_extruder_option_keys()
|
||||
{
|
||||
// ConfigOptionFloats, ConfigOptionPercents, ConfigOptionBools, ConfigOptionStrings
|
||||
m_extruder_option_keys = {
|
||||
"extruder_type", "nozzle_diameter", "default_nozzle_volume_type", "min_layer_height", "max_layer_height", "extruder_offset",
|
||||
"extruder_printable_height", "nozzle_volume", "nozzle_type", "nozzle_flush_dataset",
|
||||
"retraction_length", "z_hop", "z_hop_types", "travel_slope", "retract_lift_above", "retract_lift_below", "retract_lift_enforce", "retraction_speed", "deretraction_speed",
|
||||
"retract_before_wipe", "retract_restart_extra", "retraction_minimum_travel", "wipe", "wipe_distance",
|
||||
"retract_when_changing_layer", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour",
|
||||
"default_filament_profile","retraction_distances_when_cut","long_retractions_when_cut"
|
||||
"default_filament_profile",
|
||||
"default_nozzle_volume_type",
|
||||
"deretraction_speed",
|
||||
"extruder_colour",
|
||||
"extruder_offset",
|
||||
"extruder_printable_height",
|
||||
"extruder_type",
|
||||
"long_retractions_when_cut",
|
||||
"max_layer_height",
|
||||
"min_layer_height",
|
||||
"nozzle_diameter",
|
||||
"nozzle_flush_dataset",
|
||||
"nozzle_type",
|
||||
"nozzle_volume",
|
||||
"retract_after_wipe",
|
||||
"retract_before_wipe",
|
||||
"retract_length_toolchange",
|
||||
"retract_lift_above",
|
||||
"retract_lift_below",
|
||||
"retract_lift_enforce",
|
||||
"retract_restart_extra",
|
||||
"retract_restart_extra_toolchange",
|
||||
"retract_when_changing_layer",
|
||||
"retraction_distances_when_cut",
|
||||
"retraction_length",
|
||||
"retraction_minimum_travel",
|
||||
"retraction_speed",
|
||||
"travel_slope",
|
||||
"wipe",
|
||||
"wipe_distance",
|
||||
"z_hop",
|
||||
"z_hop_types"
|
||||
};
|
||||
|
||||
m_extruder_retract_keys = {
|
||||
"deretraction_speed",
|
||||
"long_retractions_when_cut",
|
||||
"retract_after_wipe",
|
||||
"retract_before_wipe",
|
||||
"retract_lift_above",
|
||||
"retract_lift_below",
|
||||
@@ -8020,17 +8085,40 @@ void PrintConfigDef::init_extruder_option_keys()
|
||||
void PrintConfigDef::init_filament_option_keys()
|
||||
{
|
||||
m_filament_option_keys = {
|
||||
"filament_diameter", "min_layer_height", "max_layer_height","volumetric_speed_coefficients",
|
||||
"retraction_length", "z_hop", "z_hop_types", "retract_lift_above", "retract_lift_below", "retract_lift_enforce", "retraction_speed", "deretraction_speed",
|
||||
"retract_before_wipe", "filament_retract_length_nc", "retract_restart_extra", "retraction_minimum_travel", "wipe", "wipe_distance",
|
||||
"retract_when_changing_layer", "retract_length_toolchange", "retract_restart_extra_toolchange", "filament_colour",
|
||||
"default_filament_profile","retraction_distances_when_cut","long_retractions_when_cut"/*,"filament_seam_gap"*/
|
||||
"default_filament_profile",
|
||||
"deretraction_speed",
|
||||
"filament_colour",
|
||||
"filament_diameter",
|
||||
"filament_retract_length_nc",
|
||||
// "filament_seam_gap",
|
||||
"long_retractions_when_cut",
|
||||
"max_layer_height",
|
||||
"min_layer_height",
|
||||
"retract_after_wipe",
|
||||
"retract_before_wipe",
|
||||
"retract_length_toolchange",
|
||||
"retract_lift_above",
|
||||
"retract_lift_below",
|
||||
"retract_lift_enforce",
|
||||
"retract_restart_extra",
|
||||
"retract_restart_extra_toolchange",
|
||||
"retract_when_changing_layer",
|
||||
"retraction_distances_when_cut",
|
||||
"retraction_length",
|
||||
"retraction_minimum_travel",
|
||||
"retraction_speed",
|
||||
"volumetric_speed_coefficients",
|
||||
"wipe",
|
||||
"wipe_distance",
|
||||
"z_hop",
|
||||
"z_hop_types",
|
||||
};
|
||||
|
||||
m_filament_retract_keys = {
|
||||
"deretraction_speed",
|
||||
"filament_retract_length_nc",
|
||||
"long_retractions_when_cut",
|
||||
"retract_after_wipe",
|
||||
"retract_before_wipe",
|
||||
"retract_lift_above",
|
||||
"retract_lift_below",
|
||||
@@ -8928,6 +9016,8 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
"internal_bridge_support_thickness", "top_area_threshold", "reduce_wall_solid_infill","filament_load_time","filament_unload_time",
|
||||
"smooth_coefficient", "overhang_totally_speed", "silent_mode",
|
||||
"overhang_speed_classic", "filament_prime_volume",
|
||||
"calib_flowrate_topinfill_special_order",
|
||||
"anisotropic_surfaces", // superseded by top_surface_fill_order / bottom_surface_fill_order
|
||||
};
|
||||
|
||||
if (ignore.find(opt_key) != ignore.end()) {
|
||||
@@ -9074,6 +9164,9 @@ std::set<std::string> filament_options_with_variant = {
|
||||
//BBS
|
||||
"filament_wipe_distance",
|
||||
"filament_retract_before_wipe",
|
||||
// Orca
|
||||
"filament_retract_after_wipe",
|
||||
//BBS
|
||||
"filament_long_retractions_when_cut",
|
||||
"filament_retraction_distances_when_cut",
|
||||
"long_retractions_when_ec",
|
||||
@@ -9124,6 +9217,8 @@ std::set<std::string> printer_options_with_variant_1 = {
|
||||
"wipe",
|
||||
"wipe_distance",
|
||||
"retract_before_wipe",
|
||||
// Orca:
|
||||
"retract_after_wipe",
|
||||
"retract_length_toolchange",
|
||||
"retract_restart_extra",
|
||||
"retract_restart_extra_toolchange",
|
||||
|
||||
@@ -193,6 +193,15 @@ enum class WallDirection
|
||||
Count,
|
||||
};
|
||||
|
||||
// Orca: print order of surface fill loops/fragments for center-based fill patterns
|
||||
// (Concentric, Archimedean Chords, Octagram Spiral).
|
||||
enum class SurfaceFillOrder {
|
||||
Default,
|
||||
Outward,
|
||||
Inward,
|
||||
Count,
|
||||
};
|
||||
|
||||
//BBS
|
||||
enum class PrintSequence {
|
||||
ByLayer,
|
||||
@@ -660,6 +669,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(WipeTowerWallType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ToolChangeOrderingType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PowerLossRecoveryMode)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SurfaceFillOrder)
|
||||
|
||||
#undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS
|
||||
|
||||
@@ -1211,9 +1221,6 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionInt, interlocking_beam_layer_count))
|
||||
((ConfigOptionInt, interlocking_depth))
|
||||
((ConfigOptionInt, interlocking_boundary_avoidance))
|
||||
|
||||
// Orca: internal use only
|
||||
((ConfigOptionBool, calib_flowrate_topinfill_special_order)) // ORCA: special flag for flow rate calibration
|
||||
)
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
|
||||
@@ -1237,6 +1244,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionPercent, bottom_surface_density))
|
||||
((ConfigOptionEnum<InfillPattern>, top_surface_pattern))
|
||||
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
|
||||
((ConfigOptionEnum<SurfaceFillOrder>, top_surface_fill_order))
|
||||
((ConfigOptionEnum<SurfaceFillOrder>, bottom_surface_fill_order))
|
||||
((ConfigOptionEnum<InfillPattern>, internal_solid_infill_pattern))
|
||||
((ConfigOptionFloatOrPercent, outer_wall_line_width))
|
||||
((ConfigOptionFloatsNullable, outer_wall_speed))
|
||||
@@ -1257,7 +1266,6 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloat, lightning_prune_angle))
|
||||
((ConfigOptionFloat, lightning_straightening_angle))
|
||||
((ConfigOptionBool, align_infill_direction_to_model))
|
||||
((ConfigOptionBool, anisotropic_surfaces))
|
||||
((ConfigOptionEnum<CenterOfSurfacePattern>, center_of_surface_pattern))
|
||||
((ConfigOptionBool, separated_infills))
|
||||
((ConfigOptionString, extra_solid_infills))
|
||||
@@ -1544,6 +1552,9 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
|
||||
|
||||
((ConfigOptionPercents, retract_before_wipe))
|
||||
// Orca
|
||||
((ConfigOptionPercents, retract_after_wipe))
|
||||
|
||||
((ConfigOptionFloats, retraction_length))
|
||||
((ConfigOptionFloats, retract_length_toolchange))
|
||||
((ConfigOptionInt, enable_long_retraction_when_cut))
|
||||
|
||||
@@ -1393,6 +1393,8 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
} else if (
|
||||
opt_key == "top_surface_pattern"
|
||||
|| opt_key == "bottom_surface_pattern"
|
||||
|| opt_key == "top_surface_fill_order"
|
||||
|| opt_key == "bottom_surface_fill_order"
|
||||
|| opt_key == "internal_solid_infill_pattern"
|
||||
|| opt_key == "external_fill_link_max_length"
|
||||
|| opt_key == "infill_anchor"
|
||||
@@ -1400,7 +1402,6 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
|| opt_key == "top_surface_line_width"
|
||||
|| opt_key == "top_surface_density"
|
||||
|| opt_key == "bottom_surface_density"
|
||||
|| opt_key == "anisotropic_surfaces"
|
||||
|| opt_key == "center_of_surface_pattern"
|
||||
|| opt_key == "separated_infills"
|
||||
|| opt_key == "initial_layer_line_width"
|
||||
|
||||
@@ -22,7 +22,7 @@ struct Params
|
||||
: /*max_acceleration(max_acceleration), */raft_layers_count(raft_layers_count), brim_type(brim_type), brim_width(brim_width)
|
||||
{
|
||||
if (filament_types.size() > 1) {
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "SupportSpotsGenerator does not currently handle different materials properly, only first will be used";
|
||||
}
|
||||
if (filament_types.empty() || filament_types[0].empty()) {
|
||||
|
||||
Reference in New Issue
Block a user