polyholes are rotated on each layer.

supermerill/SuperSlicer#1396
This commit is contained in:
supermerill 2021-08-22 20:50:37 +02:00
parent 201cf90b97
commit 37a6688174
6 changed files with 50 additions and 19 deletions

View File

@ -106,6 +106,7 @@ group:Modifying slices
line:Convert round vertical holes to polyholes line:Convert round vertical holes to polyholes
setting:label$_:hole_to_polyhole setting:label$_:hole_to_polyhole
setting:hole_to_polyhole_threshold setting:hole_to_polyhole_threshold
setting:hole_to_polyhole_twisted
end_line end_line
group:Other group:Other
setting:clip_multipart_objects setting:clip_multipart_objects

View File

@ -597,6 +597,7 @@ const std::vector<std::string>& Preset::print_options()
"hole_size_threshold", "hole_size_threshold",
"hole_to_polyhole", "hole_to_polyhole",
"hole_to_polyhole_threshold", "hole_to_polyhole_threshold",
"hole_to_polyhole_twisted",
"threads", "threads",
// wipe tower // wipe tower
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging",

View File

@ -4440,13 +4440,21 @@ void PrintConfigDef::init_fff_params()
def->full_label = L("Polyhole detection margin"); def->full_label = L("Polyhole detection margin");
def->category = OptionCategory::slicing; def->category = OptionCategory::slicing;
def->tooltip = L("Maximum defection of a point to the estimated radius of the circle." def->tooltip = L("Maximum defection of a point to the estimated radius of the circle."
"\nAs cylinders are often exported as triangles of varying size, points may not be on the circle circumference." "\nAs cylinders are often exported as triangles of varying size, points may not be on the circle circumference."
" This setting allows you some leway to broaden the detection." " This setting allows you some leway to broaden the detection."
"\nIn mm or in % of the radius."); "\nIn mm or in % of the radius.");
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloatOrPercent(0.01, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0.01, false));
def = this->add("hole_to_polyhole_twisted", coBool);
def->label = L("Twisting");
def->full_label = L("Polyhole twist");
def->category = OptionCategory::slicing;
def->tooltip = L("Rotate the polyhole every layer.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("z_offset", coFloat); def = this->add("z_offset", coFloat);
def->label = L("Z offset"); def->label = L("Z offset");
def->category = OptionCategory::general; def->category = OptionCategory::general;
@ -5596,6 +5604,7 @@ void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value,
"hole_size_threshold", "hole_size_threshold",
"hole_to_polyhole", "hole_to_polyhole",
"hole_to_polyhole_threshold", "hole_to_polyhole_threshold",
"hole_to_polyhole_twisted",
"z_step", "z_step",
"milling_cutter", "milling_cutter",
"milling_diameter", "milling_diameter",

View File

@ -798,6 +798,7 @@ public:
ConfigOptionFloatOrPercent infill_anchor_max; ConfigOptionFloatOrPercent infill_anchor_max;
ConfigOptionBool hole_to_polyhole; ConfigOptionBool hole_to_polyhole;
ConfigOptionFloatOrPercent hole_to_polyhole_threshold; ConfigOptionFloatOrPercent hole_to_polyhole_threshold;
ConfigOptionBool hole_to_polyhole_twisted;
ConfigOptionInt infill_extruder; ConfigOptionInt infill_extruder;
ConfigOptionFloatOrPercent infill_extrusion_width; ConfigOptionFloatOrPercent infill_extrusion_width;
ConfigOptionInt infill_every_layers; ConfigOptionInt infill_every_layers;
@ -914,6 +915,7 @@ protected:
OPT_PTR(infill_anchor_max); OPT_PTR(infill_anchor_max);
OPT_PTR(hole_to_polyhole); OPT_PTR(hole_to_polyhole);
OPT_PTR(hole_to_polyhole_threshold); OPT_PTR(hole_to_polyhole_threshold);
OPT_PTR(hole_to_polyhole_twisted);
OPT_PTR(infill_extruder); OPT_PTR(infill_extruder);
OPT_PTR(infill_extrusion_width); OPT_PTR(infill_extrusion_width);
OPT_PTR(infill_every_layers); OPT_PTR(infill_every_layers);

View File

@ -151,25 +151,41 @@ namespace Slic3r {
} }
Polygon create_polyhole(const Point center, const coord_t radius, const coord_t nozzle_diameter)
Polygons create_polyholes(const Point center, const coord_t radius, const coord_t nozzle_diameter, bool multiple)
{ {
// n = max(round(2 * d), 3); // for 0.4mm nozzle // n = max(round(2 * d), 3); // for 0.4mm nozzle
size_t nb_polygons = (int)std::max(3, (int)std::round(4.0 * unscaled(radius) * 0.4 / unscaled(nozzle_diameter))); size_t nb_edges = (int)std::max(3, (int)std::round(4.0 * unscaled(radius) * 0.4 / unscaled(nozzle_diameter)));
// cylinder(h = h, r = d / cos (180 / n), $fn = n); // cylinder(h = h, r = d / cos (180 / n), $fn = n);
Points pts; //create x polyholes by rotation if multiple
const float new_radius = radius / std::cos(PI / nb_polygons); int nb_polyhole = 1;
for (int i = 0; i < nb_polygons; ++i) { float rotation = 0;
float angle = (PI * 2 * i) / nb_polygons; if (multiple) {
pts.emplace_back(center.x() + new_radius * cos(angle), center.y() + new_radius * sin(angle)); nb_polyhole = 5;
rotation = 2 * float(PI) / (nb_edges * nb_polyhole);
} }
return Polygon{ pts }; Polygons list;
for (int i_poly = 0; i_poly < nb_polyhole; i_poly++)
list.emplace_back();
for (int i_poly = 0; i_poly < nb_polyhole; i_poly++) {
Polygon& pts = (((i_poly % 2) == 0) ? list[i_poly / 2] : list[(nb_polyhole + 1) / 2 + i_poly / 2]);
const float new_radius = radius / float(std::cos(PI / nb_edges));
for (int i_edge = 0; i_edge < nb_edges; ++i_edge) {
float angle = rotation * i_poly + (float(PI) * 2 * i_edge) / nb_edges;
pts.points.emplace_back(center.x() + new_radius * cos(angle), center.y() + new_radius * sin(angle));
}
pts.make_clockwise();
}
//alternate
return list;
} }
void PrintObject::_transform_hole_to_polyholes() void PrintObject::_transform_hole_to_polyholes()
{ {
// get all circular holes for each layer // get all circular holes for each layer
// the id is center-diameter-extruderid // the id is center-diameter-extruderid
std::vector<std::vector<std::pair<std::tuple<Point, float, int, coord_t>, Polygon*>>> layerid2center; //the tuple is Point center; float diameter_max; int extruder_id; coord_t max_variation; bool twist;
std::vector<std::vector<std::pair<std::tuple<Point, float, int, coord_t, bool>, Polygon*>>> layerid2center;
for (size_t i = 0; i < this->m_layers.size(); i++) layerid2center.emplace_back(); for (size_t i = 0; i < this->m_layers.size(); i++) layerid2center.emplace_back();
tbb::parallel_for( tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()), tbb::blocked_range<size_t>(0, m_layers.size()),
@ -196,9 +212,10 @@ namespace Slic3r {
} }
// SCALED_EPSILON was a bit too harsh. Now using a config, as some may want some harsh setting and some don't. // SCALED_EPSILON was a bit too harsh. Now using a config, as some may want some harsh setting and some don't.
coord_t max_variation = std::max(SCALED_EPSILON, scale_(this->m_layers[layer_idx]->m_regions[region_idx]->region()->config().hole_to_polyhole_threshold.get_abs_value(unscaled(diameter_sum / hole.points.size())))); coord_t max_variation = std::max(SCALED_EPSILON, scale_(this->m_layers[layer_idx]->m_regions[region_idx]->region()->config().hole_to_polyhole_threshold.get_abs_value(unscaled(diameter_sum / hole.points.size()))));
bool twist = this->m_layers[layer_idx]->m_regions[region_idx]->region()->config().hole_to_polyhole_twisted.value;
if (diameter_max - diameter_min < max_variation * 2) { if (diameter_max - diameter_min < max_variation * 2) {
layerid2center[layer_idx].emplace_back( layerid2center[layer_idx].emplace_back(
std::tuple<Point, float, int, coord_t>{center, diameter_max, layer->m_regions[region_idx]->region()->config().perimeter_extruder.value, max_variation}, & hole); std::tuple<Point, float, int, coord_t, bool>{center, diameter_max, layer->m_regions[region_idx]->region()->config().perimeter_extruder.value, max_variation, twist}, & hole);
} }
} }
} }
@ -209,7 +226,7 @@ namespace Slic3r {
} }
}); });
//sort holes per center-diameter //sort holes per center-diameter
std::map<std::tuple<Point, float, int, coord_t>, std::vector<std::pair<Polygon*, int>>> id2layerz2hole; std::map<std::tuple<Point, float, int, coord_t, bool>, std::vector<std::pair<Polygon*, int>>> id2layerz2hole;
//search & find hole that span at least X layers //search & find hole that span at least X layers
const size_t min_nb_layers = 2; const size_t min_nb_layers = 2;
@ -217,7 +234,7 @@ namespace Slic3r {
for (size_t layer_idx = 0; layer_idx < this->m_layers.size(); ++layer_idx) { for (size_t layer_idx = 0; layer_idx < this->m_layers.size(); ++layer_idx) {
for (size_t hole_idx = 0; hole_idx < layerid2center[layer_idx].size(); ++hole_idx) { for (size_t hole_idx = 0; hole_idx < layerid2center[layer_idx].size(); ++hole_idx) {
//get all other same polygons //get all other same polygons
std::tuple<Point, float, int, coord_t>& id = layerid2center[layer_idx][hole_idx].first; std::tuple<Point, float, int, coord_t, bool>& id = layerid2center[layer_idx][hole_idx].first;
float max_z = layers()[layer_idx]->print_z; float max_z = layers()[layer_idx]->print_z;
std::vector<std::pair<Polygon*, int>> holes; std::vector<std::pair<Polygon*, int>> holes;
holes.emplace_back(layerid2center[layer_idx][hole_idx].second, layer_idx); holes.emplace_back(layerid2center[layer_idx][hole_idx].second, layer_idx);
@ -225,7 +242,7 @@ namespace Slic3r {
if (layers()[search_layer_idx]->print_z - layers()[search_layer_idx]->height - max_z > EPSILON) break; if (layers()[search_layer_idx]->print_z - layers()[search_layer_idx]->height - max_z > EPSILON) break;
//search an other polygon with same id //search an other polygon with same id
for (size_t search_hole_idx = 0; search_hole_idx < layerid2center[search_layer_idx].size(); ++search_hole_idx) { for (size_t search_hole_idx = 0; search_hole_idx < layerid2center[search_layer_idx].size(); ++search_hole_idx) {
std::tuple<Point, float, int, coord_t>& search_id = layerid2center[search_layer_idx][search_hole_idx].first; std::tuple<Point, float, int, coord_t, bool>& search_id = layerid2center[search_layer_idx][search_hole_idx].first;
if (std::get<2>(id) == std::get<2>(search_id) if (std::get<2>(id) == std::get<2>(search_id)
&& std::get<0>(id).distance_to(std::get<0>(search_id)) < std::get<3>(id) && std::get<0>(id).distance_to(std::get<0>(search_id)) < std::get<3>(id)
&& std::abs(std::get<1>(id) - std::get<1>(search_id)) < std::get<3>(id) && std::abs(std::get<1>(id) - std::get<1>(search_id)) < std::get<3>(id)
@ -246,9 +263,9 @@ namespace Slic3r {
} }
//create a polyhole per id and replace holes points by it. //create a polyhole per id and replace holes points by it.
for (auto entry : id2layerz2hole) { for (auto entry : id2layerz2hole) {
Polygon polyhole = create_polyhole(std::get<0>(entry.first), std::get<1>(entry.first), scale_(print()->config().nozzle_diameter.get_at(std::get<2>(entry.first) - 1))); Polygons polyholes = create_polyholes(std::get<0>(entry.first), std::get<1>(entry.first), scale_(print()->config().nozzle_diameter.get_at(std::get<2>(entry.first) - 1)), std::get<4>(entry.first));
polyhole.make_clockwise();
for (auto& poly_to_replace : entry.second) { for (auto& poly_to_replace : entry.second) {
Polygon polyhole = polyholes[poly_to_replace.second % polyholes.size()];
//search the clone in layers->slices //search the clone in layers->slices
for (ExPolygon& explo_slice : m_layers[poly_to_replace.second]->lslices) { for (ExPolygon& explo_slice : m_layers[poly_to_replace.second]->lslices) {
for (Polygon& poly_slice : explo_slice.holes) { for (Polygon& poly_slice : explo_slice.holes) {

View File

@ -430,7 +430,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
for (auto el : { "solid_fill_pattern", "infill_connection_solid" }) for (auto el : { "solid_fill_pattern", "infill_connection_solid" })
toggle_field(el, has_solid_infill); // should be top_solid_layers") > 1 || bottom_solid_layers") > 1 toggle_field(el, has_solid_infill); // should be top_solid_layers") > 1 || bottom_solid_layers") > 1
toggle_field("hole_to_polyhole_threshold", config->opt_bool("hole_to_polyhole")); for (auto el : { "hole_to_polyhole_threshold", "hole_to_polyhole_twisted" })
toggle_field(el, config->opt_bool("hole_to_polyhole"));
bool have_default_acceleration = config->option<ConfigOptionFloatOrPercent>("default_acceleration")->value > 0; bool have_default_acceleration = config->option<ConfigOptionFloatOrPercent>("default_acceleration")->value > 0;
for (auto el : { "perimeter_acceleration", "infill_acceleration", for (auto el : { "perimeter_acceleration", "infill_acceleration",