mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 01:07:57 -06:00
New feature: Bridging angle override through a bridge_angle config
variable. When set to zero, the usual automatic bridge detection applies. The bridging angle override may be set at the Infill->Advanced settings, or through a modifier mesh.
This commit is contained in:
parent
75c72bc59b
commit
71f99423c5
7 changed files with 27 additions and 13 deletions
|
@ -532,7 +532,7 @@ sub build {
|
||||||
seam_position external_perimeters_first
|
seam_position external_perimeters_first
|
||||||
fill_density fill_pattern external_fill_pattern
|
fill_density fill_pattern external_fill_pattern
|
||||||
infill_every_layers infill_only_where_needed
|
infill_every_layers infill_only_where_needed
|
||||||
solid_infill_every_layers fill_angle solid_infill_below_area
|
solid_infill_every_layers fill_angle bridge_angle solid_infill_below_area
|
||||||
only_retract_when_crossing_perimeters infill_first
|
only_retract_when_crossing_perimeters infill_first
|
||||||
max_print_speed max_volumetric_speed
|
max_print_speed max_volumetric_speed
|
||||||
max_volumetric_extrusion_rate_slope_positive max_volumetric_extrusion_rate_slope_negative
|
max_volumetric_extrusion_rate_slope_positive max_volumetric_extrusion_rate_slope_negative
|
||||||
|
@ -622,6 +622,7 @@ sub build {
|
||||||
$optgroup->append_single_option_line('solid_infill_every_layers');
|
$optgroup->append_single_option_line('solid_infill_every_layers');
|
||||||
$optgroup->append_single_option_line('fill_angle');
|
$optgroup->append_single_option_line('fill_angle');
|
||||||
$optgroup->append_single_option_line('solid_infill_below_area');
|
$optgroup->append_single_option_line('solid_infill_below_area');
|
||||||
|
$optgroup->append_single_option_line('bridge_angle');
|
||||||
$optgroup->append_single_option_line('only_retract_when_crossing_perimeters');
|
$optgroup->append_single_option_line('only_retract_when_crossing_perimeters');
|
||||||
$optgroup->append_single_option_line('infill_first');
|
$optgroup->append_single_option_line('infill_first');
|
||||||
}
|
}
|
||||||
|
@ -977,7 +978,7 @@ sub _update {
|
||||||
solid_infill_speed);
|
solid_infill_speed);
|
||||||
|
|
||||||
$self->get_field($_)->toggle($have_infill || $have_solid_infill)
|
$self->get_field($_)->toggle($have_infill || $have_solid_infill)
|
||||||
for qw(fill_angle infill_extrusion_width infill_speed bridge_speed);
|
for qw(fill_angle bridge_angle infill_extrusion_width infill_speed bridge_speed);
|
||||||
|
|
||||||
$self->get_field('gap_fill_speed')->toggle($have_perimeters && $have_infill);
|
$self->get_field('gap_fill_speed')->toggle($have_perimeters && $have_infill);
|
||||||
|
|
||||||
|
|
|
@ -68,20 +68,20 @@ void BridgeDetector::initialize()
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool BridgeDetector::detect_angle(double bridge_direction_override)
|
||||||
BridgeDetector::detect_angle()
|
|
||||||
{
|
{
|
||||||
if (this->_edges.empty() || this->_anchor_regions.empty())
|
if (this->_edges.empty() || this->_anchor_regions.empty())
|
||||||
// The bridging region is completely in the air, there are no anchors available at the layer below.
|
// The bridging region is completely in the air, there are no anchors available at the layer below.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::vector<BridgeDirection> candidates;
|
std::vector<BridgeDirection> candidates;
|
||||||
{
|
if (bridge_direction_override == 0.) {
|
||||||
std::vector<double> angles = bridge_direction_candidates();
|
std::vector<double> angles = bridge_direction_candidates();
|
||||||
candidates.reserve(angles.size());
|
candidates.reserve(angles.size());
|
||||||
for (size_t i = 0; i < angles.size(); ++ i)
|
for (size_t i = 0; i < angles.size(); ++ i)
|
||||||
candidates.push_back(BridgeDirection(angles[i]));
|
candidates.emplace_back(BridgeDirection(angles[i]));
|
||||||
}
|
} else
|
||||||
|
candidates.emplace_back(BridgeDirection(bridge_direction_override));
|
||||||
|
|
||||||
/* Outset the bridge expolygon by half the amount we used for detecting anchors;
|
/* Outset the bridge expolygon by half the amount we used for detecting anchors;
|
||||||
we'll use this one to clip our test lines and be sure that their endpoints
|
we'll use this one to clip our test lines and be sure that their endpoints
|
||||||
|
|
|
@ -31,7 +31,8 @@ public:
|
||||||
|
|
||||||
BridgeDetector(ExPolygon _expolygon, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
|
BridgeDetector(ExPolygon _expolygon, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
|
||||||
BridgeDetector(const ExPolygons &_expolygons, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
|
BridgeDetector(const ExPolygons &_expolygons, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
|
||||||
bool detect_angle();
|
// If bridge_direction_override != 0, then the angle is used instead of auto-detect.
|
||||||
|
bool detect_angle(double bridge_direction_override = 0.);
|
||||||
Polygons coverage(double angle = -1) const;
|
Polygons coverage(double angle = -1) const;
|
||||||
void unsupported_edges(double angle, Polylines* unsupported) const;
|
void unsupported_edges(double angle, Polylines* unsupported) const;
|
||||||
Polylines unsupported_edges(double angle = -1) const;
|
Polylines unsupported_edges(double angle = -1) const;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Layer.hpp"
|
#include "Layer.hpp"
|
||||||
#include "BridgeDetector.hpp"
|
#include "BridgeDetector.hpp"
|
||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
|
#include "Geometry.hpp"
|
||||||
#include "PerimeterGenerator.hpp"
|
#include "PerimeterGenerator.hpp"
|
||||||
#include "Print.hpp"
|
#include "Print.hpp"
|
||||||
#include "Surface.hpp"
|
#include "Surface.hpp"
|
||||||
|
@ -87,8 +88,7 @@ LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection*
|
||||||
//#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 1.5
|
//#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 1.5
|
||||||
#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtSquare, 0.
|
#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtSquare, 0.
|
||||||
|
|
||||||
void
|
void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||||
LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
|
||||||
{
|
{
|
||||||
const Surfaces &surfaces = this->fill_surfaces.surfaces;
|
const Surfaces &surfaces = this->fill_surfaces.surfaces;
|
||||||
const double margin = scale_(EXTERNAL_INFILL_MARGIN);
|
const double margin = scale_(EXTERNAL_INFILL_MARGIN);
|
||||||
|
@ -260,7 +260,7 @@ LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
|
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
|
||||||
#endif
|
#endif
|
||||||
if (bd.detect_angle()) {
|
if (bd.detect_angle(Geometry::deg2rad(this->region()->config.bridge_angle))) {
|
||||||
bridges[idx_last].bridge_angle = bd.angle;
|
bridges[idx_last].bridge_angle = bd.angle;
|
||||||
if (this->layer()->object()->config.support_material) {
|
if (this->layer()->object()->config.support_material) {
|
||||||
polygons_append(this->bridged, bd.coverage());
|
polygons_append(this->bridged, bd.coverage());
|
||||||
|
|
|
@ -65,6 +65,15 @@ PrintConfigDef::PrintConfigDef()
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->default_value = new ConfigOptionFloat(0);
|
def->default_value = new ConfigOptionFloat(0);
|
||||||
|
|
||||||
|
def = this->add("bridge_angle", coFloat);
|
||||||
|
def->label = "Bridging angle";
|
||||||
|
def->category = "Infill";
|
||||||
|
def->tooltip = "Bridging angle override. If left to zero, the bridging angle will be calculated automatically. Otherwise the provided angle will be used for all bridges, use 180° for zero angle.";
|
||||||
|
def->sidetext = "°";
|
||||||
|
def->cli = "bridge-angle=f";
|
||||||
|
def->min = 0;
|
||||||
|
def->default_value = new ConfigOptionFloat(0.);
|
||||||
|
|
||||||
def = this->add("bridge_fan_speed", coInts);
|
def = this->add("bridge_fan_speed", coInts);
|
||||||
def->label = "Bridges fan speed";
|
def->label = "Bridges fan speed";
|
||||||
def->tooltip = "This fan speed is enforced during all bridges and overhangs.";
|
def->tooltip = "This fan speed is enforced during all bridges and overhangs.";
|
||||||
|
|
|
@ -243,7 +243,8 @@ public:
|
||||||
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
|
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
|
||||||
class PrintRegionConfig : public virtual StaticPrintConfig
|
class PrintRegionConfig : public virtual StaticPrintConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ConfigOptionFloat bridge_angle;
|
||||||
ConfigOptionInt bottom_solid_layers;
|
ConfigOptionInt bottom_solid_layers;
|
||||||
ConfigOptionFloat bridge_flow_ratio;
|
ConfigOptionFloat bridge_flow_ratio;
|
||||||
ConfigOptionFloat bridge_speed;
|
ConfigOptionFloat bridge_speed;
|
||||||
|
@ -285,6 +286,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
|
||||||
|
|
||||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||||
UNUSED(create);
|
UNUSED(create);
|
||||||
|
OPT_PTR(bridge_angle);
|
||||||
OPT_PTR(bottom_solid_layers);
|
OPT_PTR(bottom_solid_layers);
|
||||||
OPT_PTR(bridge_flow_ratio);
|
OPT_PTR(bridge_flow_ratio);
|
||||||
OPT_PTR(bridge_speed);
|
OPT_PTR(bridge_speed);
|
||||||
|
|
|
@ -195,7 +195,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||||
|| opt_key == "infill_extruder"
|
|| opt_key == "infill_extruder"
|
||||||
|| opt_key == "solid_infill_extruder"
|
|| opt_key == "solid_infill_extruder"
|
||||||
|| opt_key == "infill_extrusion_width"
|
|| opt_key == "infill_extrusion_width"
|
||||||
|| opt_key == "ensure_vertical_shell_thickness") {
|
|| opt_key == "ensure_vertical_shell_thickness"
|
||||||
|
|| opt_key == "bridge_angle") {
|
||||||
steps.emplace_back(posPrepareInfill);
|
steps.emplace_back(posPrepareInfill);
|
||||||
} else if (
|
} else if (
|
||||||
opt_key == "external_fill_pattern"
|
opt_key == "external_fill_pattern"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue