#399 add an other pattern for brim ear: rectilinear with perimeter.

If you have problem with adhesion of the ear.
also some fixes about brim invalidation.
This commit is contained in:
supermerill 2020-08-20 01:57:54 +02:00
parent c36681147d
commit 3ec2f077e5
11 changed files with 137 additions and 58 deletions

View File

@ -154,6 +154,7 @@ group:Brim
line:Brim ears
setting:brim_ears
setting:width$3:brim_ears_max_angle
setting:brim_ears_pattern
end_line
setting:brim_offset

View File

@ -898,7 +898,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
surface->expolygon,
- rotate_vector.first,
scale_(0 /*this->overlap*/ - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing),
scale_(0 /*this->overlap*/ - 0.5 * this->spacing));
scale_(0 /*this->overlap*/ - (params.full_infill() && params.fill_exactly ? 0.5 + INFILL_OVERLAP_OVER_SPACING : 0.5) * this->spacing));
if (poly_with_offset.n_contours_inner == 0) {
// Not a single infill line fits.
//Prusa: maybe one shall trigger the gap fill here?
@ -909,7 +909,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
// define flow spacing according to requested density
if (params.full_infill() && !params.dont_adjust) {
if (params.full_infill() && !params.dont_adjust || line_spacing == 0 ) {
//it's == this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing) because of the init_spacing
line_spacing = scale_(this->spacing);
} else {

View File

@ -5,6 +5,7 @@
#include "ClipperUtils.hpp"
#include "Extruder.hpp"
#include "Flow.hpp"
#include "Fill/FillBase.hpp"
#include "Geometry.hpp"
#include "I18N.hpp"
#include "ShortestPath.hpp"
@ -196,8 +197,11 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
} else if (
opt_key == "brim_inside_holes"
|| opt_key == "brim_width"
|| opt_key == "brim_width_interior"
|| opt_key == "brim_offset"
|| opt_key == "brim_ears"
|| opt_key == "brim_ears_max_angle") {
|| opt_key == "brim_ears_max_angle"
|| opt_key == "brim_ears_pattern") {
steps.emplace_back(psBrim);
steps.emplace_back(psSkirt);
} else if (
@ -1712,6 +1716,7 @@ void Print::process()
for (std::vector<PrintObject*> &obj_group : obj_groups) {
if (obj_group.front()->config().brim_ears.value == obj->config().brim_ears.value
&& obj_group.front()->config().brim_ears_max_angle.value == obj->config().brim_ears_max_angle.value
&& obj_group.front()->config().brim_ears_pattern.value == obj->config().brim_ears_pattern.value
&& obj_group.front()->config().brim_inside_holes.value == obj->config().brim_inside_holes.value
&& obj_group.front()->config().brim_offset.value == obj->config().brim_offset.value
&& obj_group.front()->config().brim_width.value == obj->config().brim_width.value
@ -2281,61 +2286,102 @@ void Print::_make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, Ex
brimmable_areas = diff_ex(brimmable_areas, unbrimmable, true);
this->throw_if_canceled();
//create loops (same as standard brim)
Polygons loops;
islands = offset_ex(islands, -0.5f * double(flow.scaled_spacing()));
for (size_t i = 0; i < num_loops; ++i) {
this->throw_if_canceled();
islands = offset_ex(islands, double(flow.scaled_spacing()), jtSquare);
for (ExPolygon &expoly : islands) {
Polygon poly = expoly.contour;
poly.points.push_back(poly.points.front());
Points p = MultiPoint::_douglas_peucker(poly.points, SCALED_RESOLUTION);
p.pop_back();
poly.points = std::move(p);
loops.push_back(poly);
if (brim_config.brim_ears_pattern.value == InfillPattern::ipConcentric) {
//create loops (same as standard brim)
Polygons loops;
islands = offset_ex(islands, -0.5f * double(flow.scaled_spacing()));
for (size_t i = 0; i < num_loops; ++i) {
this->throw_if_canceled();
islands = offset_ex(islands, double(flow.scaled_spacing()), jtSquare);
for (ExPolygon &expoly : islands) {
Polygon poly = expoly.contour;
poly.points.push_back(poly.points.front());
Points p = MultiPoint::_douglas_peucker(poly.points, SCALED_RESOLUTION);
p.pop_back();
poly.points = std::move(p);
loops.push_back(poly);
}
}
}
//order path with least travel possible
loops = union_pt_chained(loops, false);
//order path with least travel possible
loops = union_pt_chained(loops, false);
//create ear pattern
coord_t size_ear = (scale_((brim_config.brim_width.value - brim_config.brim_offset.value)) - flow.scaled_spacing());
Polygon point_round;
for (size_t i = 0; i < POLY_SIDES; i++) {
double angle = (2.0 * PI * i) / POLY_SIDES;
point_round.points.emplace_back(size_ear * cos(angle), size_ear * sin(angle));
//create ear pattern
coord_t size_ear = (scale_((brim_config.brim_width.value - brim_config.brim_offset.value)) - flow.scaled_spacing());
Polygon point_round;
for (size_t i = 0; i < POLY_SIDES; i++) {
double angle = (2.0 * PI * i) / POLY_SIDES;
point_round.points.emplace_back(size_ear * cos(angle), size_ear * sin(angle));
}
//create ears
Polygons mouse_ears;
ExPolygons mouse_ears_ex;
for (Point pt : pt_ears) {
mouse_ears.push_back(point_round);
mouse_ears.back().translate(pt);
mouse_ears_ex.emplace_back();
mouse_ears_ex.back().contour = mouse_ears.back();
}
//intersection
Polylines lines = intersection_pl(loops, mouse_ears);
this->throw_if_canceled();
//reorder & extrude them
Polylines lines_sorted = _reorder_brim_polyline(lines, out, flow);
//push into extrusions
extrusion_entities_append_paths(
out.entities,
lines_sorted,
erSkirt,
float(flow.mm3_per_mm()),
float(flow.width),
float(this->skirt_first_layer_height())
);
ExPolygons new_brim_area = intersection_ex(brimmable_areas, mouse_ears_ex);
unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end());
} else {
//create ear pattern
coord_t size_ear = (scale_((brim_config.brim_width.value - brim_config.brim_offset.value)) - flow.scaled_spacing());
Polygon point_round;
for (size_t i = 0; i < POLY_SIDES; i++) {
double angle = (2.0 * PI * i) / POLY_SIDES;
point_round.points.emplace_back(size_ear * cos(angle), size_ear * sin(angle));
}
//create ears
ExPolygons mouse_ears_ex;
for (Point pt : pt_ears) {
mouse_ears_ex.emplace_back();
mouse_ears_ex.back().contour = point_round;
mouse_ears_ex.back().contour.translate(pt);
}
ExPolygons new_brim_area = intersection_ex(brimmable_areas, mouse_ears_ex);
std::unique_ptr<Fill> filler = std::unique_ptr<Fill>(Fill::new_from_type(ipRectiWithPerimeter));
filler->angle = 0;
FillParams fill_params;
fill_params.density = 1.f;
fill_params.fill_exactly = true;
fill_params.flow = &flow;
fill_params.role = erSkirt;
filler->init_spacing(flow.spacing(), fill_params);
for (const ExPolygon &expoly : new_brim_area) {
Surface surface(stPosInternal | stDensSparse, expoly);
filler->fill_surface_extrusion(&surface, fill_params, out.entities);
}
unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end());
}
//create ears
Polygons mouse_ears;
ExPolygons mouse_ears_ex;
for (Point pt : pt_ears) {
mouse_ears.push_back(point_round);
mouse_ears.back().translate(pt);
mouse_ears_ex.emplace_back();
mouse_ears_ex.back().contour = mouse_ears.back();
}
//intersection
Polylines lines = intersection_pl(loops, mouse_ears);
this->throw_if_canceled();
//reorder & extrude them
Polylines lines_sorted = _reorder_brim_polyline(lines, out, flow);
//push into extrusions
extrusion_entities_append_paths(
out.entities,
lines_sorted,
erSkirt,
float(flow.mm3_per_mm()),
float(flow.width),
float(this->skirt_first_layer_height())
);
ExPolygons new_brim_area = intersection_ex(brimmable_areas, mouse_ears_ex);
unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end());
}
void Print::_make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable_areas, ExtrusionEntityCollection &out) {

View File

@ -352,6 +352,19 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(125));
def = this->add("brim_ears_pattern", coEnum);
def->label = L("Pattern");
def->full_label = L("Ear pattern");
def->category = OptionCategory::infill;
def->tooltip = L("Pattern for the ear. The concentric id the default one."
" The rectilinear has a perimeter around it, you can try it if the concentric has too many problems to stick to the build plate.");
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
def->enum_values.push_back("concentric");
def->enum_values.push_back("rectilinear");
def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Rectilinear"));
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipConcentric));
def = this->add("brim_offset", coFloat);
def->label = L("brim offset");
def->category = OptionCategory::skirtBrim;
@ -4736,6 +4749,10 @@ std::string FullPrintConfig::validate()
if (!print_config_def.get("solid_fill_pattern")->has_enum_value(this->solid_fill_pattern.serialize()))
return "Invalid value for --solid-fill-pattern";
// --brim-ears-pattern
if (!print_config_def.get("brim_ears_pattern")->has_enum_value(this->brim_ears_pattern.serialize()))
return "Invalid value for --brim-ears-pattern";
// --fill-density
if (fabs(this->fill_density.value - 100.) < EPSILON &&
(! print_config_def.get("top_fill_pattern")->has_enum_value(this->fill_pattern.serialize())

View File

@ -490,6 +490,7 @@ public:
ConfigOptionFloat brim_width_interior;
ConfigOptionBool brim_ears;
ConfigOptionFloat brim_ears_max_angle;
ConfigOptionEnum<InfillPattern> brim_ears_pattern;
ConfigOptionFloat brim_offset;
ConfigOptionBool clip_multipart_objects;
ConfigOptionBool dont_support_bridges;
@ -555,6 +556,7 @@ protected:
OPT_PTR(brim_width_interior);
OPT_PTR(brim_ears);
OPT_PTR(brim_ears_max_angle);
OPT_PTR(brim_ears_pattern);
OPT_PTR(brim_offset);
OPT_PTR(clip_multipart_objects);
OPT_PTR(dont_support_bridges);

View File

@ -757,6 +757,15 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|| opt_key == "wipe_into_objects") {
invalidated |= m_print->invalidate_step(psWipeTower);
invalidated |= m_print->invalidate_step(psGCodeExport);
} else if (
opt_key == "brim_inside_holes"
|| opt_key == "brim_width"
|| opt_key == "brim_width_interior"
|| opt_key == "brim_offset"
|| opt_key == "brim_ears"
|| opt_key == "brim_ears_max_angle"
|| opt_key == "brim_ears_pattern") {
invalidated |= m_print->invalidate_step(psBrim);
} else {
// for legacy, if we can't handle this option let's invalidate all steps
this->invalidate_all_steps();

View File

@ -376,6 +376,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
toggle_field("brim_ears", config->opt_float("brim_width") > 0);
toggle_field("brim_inside_holes", config->opt_float("brim_width") > 0 && config->opt_float("brim_width_interior") == 0);
toggle_field("brim_ears_max_angle", have_brim && config->opt_bool("brim_ears"));
toggle_field("brim_ears_pattern", have_brim && config->opt_bool("brim_ears"));
bool have_raft = config->opt_int("raft_layers") > 0;
bool have_support_material = config->opt_bool("support_material") || have_raft;

View File

@ -986,7 +986,7 @@ void Choice::set_value(const boost::any& value, bool change_event)
case coEnum: {
int val = boost::any_cast<int>(value);
if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern"
|| m_opt_id == "fill_pattern" || m_opt_id == "support_material_interface_pattern")
|| m_opt_id == "fill_pattern" || m_opt_id == "support_material_interface_pattern" || m_opt_id == "brim_ears_pattern")
{
val = idx_from_enum_value<InfillPattern>(val);
} else if (m_opt_id.compare("perimeter_loop_seam") == 0) {
@ -1073,7 +1073,7 @@ boost::any& Choice::get_value()
{
int ret_enum = field->GetSelection();
if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern"
|| m_opt_id == "support_material_interface_pattern" || m_opt_id == "fill_pattern")
|| m_opt_id == "support_material_interface_pattern" || m_opt_id == "fill_pattern" || m_opt_id == "brim_ears_pattern")
convert_to_enum_value<InfillPattern>(ret_enum);
else if (m_opt_id.compare("gcode_flavor") == 0)
convert_to_enum_value<GCodeFlavor>(ret_enum);

View File

@ -187,7 +187,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
if (opt_key == "top_fill_pattern" ||
opt_key == "bottom_fill_pattern" ||
opt_key == "solid_fill_pattern" ||
opt_key == "fill_pattern")
opt_key == "fill_pattern" ||
opt_key == "brim_ears_pattern")
config.set_key_value(opt_key, new ConfigOptionEnum<InfillPattern>(boost::any_cast<InfillPattern>(value)));
else if (opt_key.compare("complete_objects_sort") == 0)
config.set_key_value(opt_key, new ConfigOptionEnum<CompleteObjectSort>(boost::any_cast<CompleteObjectSort>(value)));

View File

@ -746,7 +746,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
if (opt_key == "top_fill_pattern" ||
opt_key == "bottom_fill_pattern" ||
opt_key == "solid_fill_pattern" ||
opt_key == "fill_pattern" ) {
opt_key == "fill_pattern" ||
opt_key == "brim_ears_pattern" ) {
ret = static_cast<int>(config.option<ConfigOptionEnum<InfillPattern>>(opt_key)->value);
}
else if (opt_key.compare("complete_objects_sort") == 0 ) {

View File

@ -485,6 +485,7 @@ const std::vector<std::string>& Preset::print_options()
"brim_width_interior",
"brim_ears",
"brim_ears_max_angle",
"brim_ears_pattern",
"brim_offset",
"support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers",
"raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing",