mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-12-24 00:28:38 -07:00
Enforce Archimedean chords direction on top / bottom surface
This commit is contained in:
parent
59ad126b48
commit
199721cf28
7 changed files with 158 additions and 30 deletions
|
|
@ -167,6 +167,24 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
|
|||
if (is_flow_calib) {
|
||||
eec->no_sort = true;
|
||||
}
|
||||
|
||||
// ORCA: When Archimedean Chords direction is explicitly set, prevent path reversal
|
||||
// to preserve the intended spiral direction. Settings are in PrintRegionConfig (params.config).
|
||||
bool has_archimedean_direction = false;
|
||||
auto* archimedean_fill = dynamic_cast<FillArchimedeanChords*>(this);
|
||||
if (archimedean_fill != nullptr && params.config != nullptr) {
|
||||
ArchimedeanChordsDirection direction = ArchimedeanChordsDirection::Default;
|
||||
if (params.extrusion_role == erTopSolidInfill) {
|
||||
direction = params.config->top_surface_archimedean_direction.value;
|
||||
} else if (params.extrusion_role == erBottomSurface) {
|
||||
direction = params.config->bottom_surface_archimedean_direction.value;
|
||||
}
|
||||
|
||||
has_archimedean_direction = (direction != ArchimedeanChordsDirection::Default);
|
||||
if (has_archimedean_direction) {
|
||||
eec->no_sort = true;
|
||||
}
|
||||
}
|
||||
size_t idx = eec->entities.size();
|
||||
if (params.use_arachne) {
|
||||
Flow new_flow = params.flow.with_spacing(float(this->spacing));
|
||||
|
|
@ -179,7 +197,7 @@ 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 || is_flow_calib || has_archimedean_direction) {
|
||||
for (size_t i = idx; i < eec->entities.size(); i++)
|
||||
eec->entities[i]->set_reverse();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,71 @@ void InfillPolylineClipper::add_point(const Vec2d &fpt)
|
|||
}
|
||||
}
|
||||
|
||||
// ORCA: Helper function to chain Archimedean chord polylines with proper spiral direction.
|
||||
// Handles flow calibration mode and user-specified spiral direction (FromCenter/ToCenter).
|
||||
// For non-Archimedean fills or default direction, simply chains the polylines.
|
||||
static Polylines chain_archimedean_polylines(
|
||||
Polylines polylines,
|
||||
bool is_archimedean_fill,
|
||||
bool is_flow_calib,
|
||||
const FillParams& params)
|
||||
{
|
||||
if (polylines.empty()) {
|
||||
return Polylines();
|
||||
}
|
||||
|
||||
// Get Archimedean direction setting based on extrusion role
|
||||
ArchimedeanChordsDirection spiral_direction = ArchimedeanChordsDirection::Default;
|
||||
if (is_archimedean_fill && params.config) {
|
||||
if (params.extrusion_role == erTopSolidInfill) {
|
||||
spiral_direction = params.config->top_surface_archimedean_direction.value;
|
||||
} else if (params.extrusion_role == erBottomSurface) {
|
||||
spiral_direction = params.config->bottom_surface_archimedean_direction.value;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if special spiral direction handling is needed
|
||||
bool apply_spiral_direction = is_flow_calib ||
|
||||
(is_archimedean_fill && spiral_direction != ArchimedeanChordsDirection::Default);
|
||||
|
||||
if (!apply_spiral_direction) {
|
||||
return chain_polylines(std::move(polylines));
|
||||
}
|
||||
|
||||
// Find the center spiral (longest polyline)
|
||||
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);
|
||||
|
||||
// Spiral is generated centered at (0,0), so squaredNorm gives distance from center
|
||||
bool is_inside_out = center_spiral.first_point().squaredNorm() < center_spiral.last_point().squaredNorm();
|
||||
|
||||
// Flow calibration needs inside-out (from center), same as FromCenter direction
|
||||
if (is_flow_calib || spiral_direction == ArchimedeanChordsDirection::FromCenter) {
|
||||
if (!is_inside_out) {
|
||||
center_spiral.reverse();
|
||||
}
|
||||
} else if (spiral_direction == ArchimedeanChordsDirection::ToCenter) {
|
||||
if (is_inside_out) {
|
||||
center_spiral.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
// Chain the other polylines
|
||||
polylines.erase(it);
|
||||
Polylines chained = chain_polylines(std::move(polylines));
|
||||
|
||||
// Flow calibration and ToCenter: add spiral at end
|
||||
// FromCenter: add spiral at beginning
|
||||
if (spiral_direction == ArchimedeanChordsDirection::FromCenter) {
|
||||
chained.insert(chained.begin(), std::move(center_spiral));
|
||||
} else {
|
||||
chained.push_back(std::move(center_spiral));
|
||||
}
|
||||
|
||||
return chained;
|
||||
}
|
||||
|
||||
void FillPlanePath::_fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
|
|
@ -122,32 +187,13 @@ void FillPlanePath::_fill_surface_single(
|
|||
if (!polylines.empty()) {
|
||||
Polylines chained;
|
||||
if (params.dont_connect() || params.density > 0.5) {
|
||||
// ORCA: special flag for flow rate calibration
|
||||
auto is_flow_calib = params.extrusion_role == erTopSolidInfill &&
|
||||
// ORCA: Check for Archimedean fill and flow calibration mode
|
||||
bool is_archimedean_fill = dynamic_cast<FillArchimedeanChords*>(this) != nullptr;
|
||||
bool is_flow_calib = is_archimedean_fill &&
|
||||
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));
|
||||
|
||||
// Then add the center spiral back
|
||||
chained.push_back(std::move(center_spiral));
|
||||
} else {
|
||||
chained = chain_polylines(std::move(polylines));
|
||||
}
|
||||
this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool();
|
||||
chained = chain_archimedean_polylines(std::move(polylines), is_archimedean_fill, is_flow_calib, params);
|
||||
} else
|
||||
connect_infill(std::move(polylines), expolygon, chained, this->spacing, params);
|
||||
// paths must be repositioned and rotated back
|
||||
|
|
|
|||
|
|
@ -884,10 +884,11 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "spiral_starting_flow_ratio", "spiral_finishing_flow_ratio", "slicing_mode",
|
||||
"top_shell_layers", "top_shell_thickness", "top_surface_density", "bottom_surface_density", "bottom_shell_layers", "bottom_shell_thickness",
|
||||
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction",
|
||||
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density","fill_multiline", "sparse_infill_pattern", "lateral_lattice_angle_1", "lateral_lattice_angle_2", "infill_overhang_angle", "top_surface_pattern", "bottom_surface_pattern",
|
||||
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density","fill_multiline", "sparse_infill_pattern", "lateral_lattice_angle_1", "lateral_lattice_angle_2", "infill_overhang_angle",
|
||||
"top_surface_pattern", "top_surface_archimedean_direction", "bottom_surface_pattern", "bottom_surface_archimedean_direction",
|
||||
"infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density",
|
||||
"align_infill_direction_to_model", "extra_solid_infills",
|
||||
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target",
|
||||
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern", "gap_fill_target",
|
||||
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_angle_fixed", "ironing_inset",
|
||||
"support_ironing", "support_ironing_pattern", "support_ironing_flow", "support_ironing_spacing",
|
||||
"max_travel_detour_distance",
|
||||
|
|
|
|||
|
|
@ -253,6 +253,14 @@ static t_config_enum_values s_keys_map_WallDirection{
|
|||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallDirection)
|
||||
|
||||
// Orca: Archimedean chords direction
|
||||
static t_config_enum_values s_keys_map_ArchimedeanChordsDirection{
|
||||
{ "default", int(ArchimedeanChordsDirection::Default) },
|
||||
{ "from_center", int(ArchimedeanChordsDirection::FromCenter) },
|
||||
{ "to_center", int(ArchimedeanChordsDirection::ToCenter) }
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(ArchimedeanChordsDirection)
|
||||
|
||||
//BBS
|
||||
static t_config_enum_values s_keys_map_PrintSequence {
|
||||
{ "by layer", int(PrintSequence::ByLayer) },
|
||||
|
|
@ -1901,7 +1909,39 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_labels = def_top_fill_pattern->enum_labels;
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipMonotonic));
|
||||
|
||||
def = this->add("internal_solid_infill_pattern", coEnum);
|
||||
def = this->add("top_surface_archimedean_direction", coEnum);
|
||||
def->label = L("Top surface chord direction");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Controls the direction of the Archimedean chords spiral pattern for top surface. "
|
||||
"'Default' keeps the current behavior without forcing direction. "
|
||||
"'From center' forces the spiral to go from center toward edges. "
|
||||
"'To center' forces the spiral to go from edges toward center.");
|
||||
def->enum_keys_map = &ConfigOptionEnum<ArchimedeanChordsDirection>::get_enum_values();
|
||||
def->enum_values.push_back("default");
|
||||
def->enum_values.push_back("from_center");
|
||||
def->enum_values.push_back("to_center");
|
||||
def->enum_labels.push_back(L("Default"));
|
||||
def->enum_labels.push_back(L("From center"));
|
||||
def->enum_labels.push_back(L("To center"));
|
||||
def->set_default_value(new ConfigOptionEnum<ArchimedeanChordsDirection>(ArchimedeanChordsDirection::Default));
|
||||
|
||||
def = this->add("bottom_surface_archimedean_direction", coEnum);
|
||||
def->label = L("Bottom surface chord direction");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Controls the direction of the Archimedean chords spiral pattern for bottom surface. "
|
||||
"'Default' keeps the current behavior without forcing direction. "
|
||||
"'From center' forces the spiral to go from center toward edges. "
|
||||
"'To center' forces the spiral to go from edges toward center.");
|
||||
def->enum_keys_map = &ConfigOptionEnum<ArchimedeanChordsDirection>::get_enum_values();
|
||||
def->enum_values.push_back("default");
|
||||
def->enum_values.push_back("from_center");
|
||||
def->enum_values.push_back("to_center");
|
||||
def->enum_labels.push_back(L("Default"));
|
||||
def->enum_labels.push_back(L("From center"));
|
||||
def->enum_labels.push_back(L("To center"));
|
||||
def->set_default_value(new ConfigOptionEnum<ArchimedeanChordsDirection>(ArchimedeanChordsDirection::Default));
|
||||
|
||||
def = this->add("internal_solid_infill_pattern", coEnum);
|
||||
def->label = L("Internal solid infill pattern");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Line pattern of internal solid infill. if the detect narrow internal solid infill be enabled, the concentric pattern will be used for the small area.");
|
||||
|
|
@ -1909,7 +1949,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_values = def_top_fill_pattern->enum_values;
|
||||
def->enum_labels = def_top_fill_pattern->enum_labels;
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipMonotonic));
|
||||
|
||||
|
||||
def = this->add("outer_wall_line_width", coFloatOrPercent);
|
||||
def->label = L("Outer wall");
|
||||
def->category = L("Quality");
|
||||
|
|
|
|||
|
|
@ -119,6 +119,17 @@ enum class WallDirection
|
|||
Count,
|
||||
};
|
||||
|
||||
// Orca: Archimedean chords direction
|
||||
enum class ArchimedeanChordsDirection
|
||||
{
|
||||
// Keep current behavior without forcing direction
|
||||
Default,
|
||||
// Force spiral from center to edges (inner-out)
|
||||
FromCenter,
|
||||
// Force spiral from edges toward center (outer-in)
|
||||
ToCenter,
|
||||
};
|
||||
|
||||
//BBS
|
||||
enum class PrintSequence {
|
||||
ByLayer,
|
||||
|
|
@ -1034,7 +1045,9 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionPercent, top_surface_density))
|
||||
((ConfigOptionPercent, bottom_surface_density))
|
||||
((ConfigOptionEnum<InfillPattern>, top_surface_pattern))
|
||||
((ConfigOptionEnum<ArchimedeanChordsDirection>, top_surface_archimedean_direction))
|
||||
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
|
||||
((ConfigOptionEnum<ArchimedeanChordsDirection>, bottom_surface_archimedean_direction))
|
||||
((ConfigOptionEnum<InfillPattern>, internal_solid_infill_pattern))
|
||||
((ConfigOptionFloatOrPercent, outer_wall_line_width))
|
||||
((ConfigOptionFloat, outer_wall_speed))
|
||||
|
|
|
|||
|
|
@ -652,6 +652,14 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
toggle_field("top_surface_density", has_top_shell);
|
||||
toggle_field("bottom_surface_density", has_bottom_shell);
|
||||
|
||||
// Orca: Show Archimedean direction only when the pattern is Archimedean Chords
|
||||
bool has_top_archimedean = has_top_shell &&
|
||||
config->opt_enum<InfillPattern>("top_surface_pattern") == ipArchimedeanChords;
|
||||
bool has_bottom_archimedean = has_bottom_shell &&
|
||||
config->opt_enum<InfillPattern>("bottom_surface_pattern") == ipArchimedeanChords;
|
||||
toggle_line("top_surface_archimedean_direction", has_top_archimedean);
|
||||
toggle_line("bottom_surface_archimedean_direction", has_bottom_archimedean);
|
||||
|
||||
for (auto el : { "infill_direction", "sparse_infill_line_width", "gap_fill_target","filter_out_gap_fill","infill_wall_overlap",
|
||||
"sparse_infill_speed", "bridge_speed", "internal_bridge_speed", "bridge_angle", "internal_bridge_angle",
|
||||
"solid_infill_direction", "solid_infill_rotate_template", "internal_solid_infill_pattern", "solid_infill_filament",
|
||||
|
|
|
|||
|
|
@ -2416,10 +2416,12 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("top_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
|
||||
optgroup->append_single_option_line("top_surface_density", "strength_settings_top_bottom_shells#surface-density");
|
||||
optgroup->append_single_option_line("top_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern");
|
||||
optgroup->append_single_option_line("top_surface_archimedean_direction", "strength_settings_top_bottom_shells#spiral-direction");
|
||||
optgroup->append_single_option_line("bottom_shell_layers", "strength_settings_top_bottom_shells#shell-layers");
|
||||
optgroup->append_single_option_line("bottom_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
|
||||
optgroup->append_single_option_line("bottom_surface_density", "strength_settings_top_bottom_shells#surface-density");
|
||||
optgroup->append_single_option_line("bottom_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern");
|
||||
optgroup->append_single_option_line("bottom_surface_archimedean_direction", "strength_settings_top_bottom_shells#spiral-direction");
|
||||
optgroup->append_single_option_line("top_bottom_infill_wall_overlap", "strength_settings_top_bottom_shells#infillwall-overlap");
|
||||
|
||||
optgroup = page->new_optgroup(L("Infill"), L"param_infill");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue