new feature: Clip multi-part objects one by the other.
This works the same way as if the XY compensation was set to a tiny value before, but without the overhead of an offset.
This commit is contained in:
parent
ce8973b33a
commit
420e387055
@ -557,7 +557,7 @@ sub build {
|
||||
external_perimeter_extrusion_width infill_extrusion_width solid_infill_extrusion_width
|
||||
top_infill_extrusion_width support_material_extrusion_width
|
||||
infill_overlap bridge_flow_ratio
|
||||
xy_size_compensation threads resolution
|
||||
clip_multipart_objects xy_size_compensation threads resolution
|
||||
));
|
||||
$self->{config}->set('print_settings_id', '');
|
||||
|
||||
@ -750,6 +750,7 @@ sub build {
|
||||
}
|
||||
{
|
||||
my $optgroup = $page->new_optgroup('Other');
|
||||
$optgroup->append_single_option_line('clip_multipart_objects');
|
||||
$optgroup->append_single_option_line('xy_size_compensation');
|
||||
$optgroup->append_single_option_line('threads') if $Slic3r::have_threads;
|
||||
$optgroup->append_single_option_line('resolution');
|
||||
|
@ -425,7 +425,7 @@ sub write_gcode {
|
||||
# Wait for 1/4 seconds and try to rename once again.
|
||||
select(undef, undef, undef, 0.25);
|
||||
}
|
||||
Slic3r::debugf "Faild to remove the output G-code file from $tempfile to $file. Is $tempfile locked?\n" if ($i == 5);
|
||||
Slic3r::debugf "Failed to remove the output G-code file from $tempfile to $file. Is $tempfile locked?\n" if ($i == 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,6 +497,9 @@ $j
|
||||
--dont-arrange Don't arrange the objects on the build plate. The model coordinates
|
||||
define the absolute positions on the build plate.
|
||||
The option --print-center will be ignored.
|
||||
--clip_multipart_objects When printing multi-material objects, this settings will make slic3r to clip the overlapping
|
||||
object parts one by the other (2nd part will be clipped by the 1st, 3rd part will be clipped
|
||||
by the 1st and 2nd etc). (default: $config->{clip_multipart_objects})";
|
||||
--xy-size-compensation
|
||||
Grow/shrink objects by the configured absolute distance (mm, default: $config->{xy_size_compensation})
|
||||
|
||||
|
@ -96,6 +96,12 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(0);
|
||||
|
||||
def = this->add("clip_multipart_objects", coBool);
|
||||
def->label = "Clip multi-part objects";
|
||||
def->tooltip = "When printing multi-material objects, this settings will make slic3r to clip the overlapping object parts one by the other (2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc).";
|
||||
def->cli = "clip-multipart-objects!";
|
||||
def->default_value = new ConfigOptionBool(false);
|
||||
|
||||
def = this->add("complete_objects", coBool);
|
||||
def->label = "Complete individual objects";
|
||||
def->tooltip = "When printing multiple objects or copies, this feature will complete each object before moving onto next one (and starting it from its bottom layer). This feature is useful to avoid the risk of ruined prints. Slic3r should warn and prevent you from extruder collisions, but beware.";
|
||||
|
@ -138,6 +138,7 @@ class StaticPrintConfig : public PrintConfigBase, public StaticConfig
|
||||
class PrintObjectConfig : public virtual StaticPrintConfig
|
||||
{
|
||||
public:
|
||||
ConfigOptionBool clip_multipart_objects;
|
||||
ConfigOptionBool dont_support_bridges;
|
||||
ConfigOptionFloatOrPercent extrusion_width;
|
||||
ConfigOptionFloatOrPercent first_layer_height;
|
||||
@ -175,6 +176,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
||||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
OPT_PTR(clip_multipart_objects);
|
||||
OPT_PTR(dont_support_bridges);
|
||||
OPT_PTR(extrusion_width);
|
||||
OPT_PTR(first_layer_height);
|
||||
|
@ -221,7 +221,8 @@ PrintObject::invalidate_state_by_config_options(const std::vector<t_config_optio
|
||||
steps.insert(posSlice);
|
||||
this->reset_layer_height_profile();
|
||||
}
|
||||
else if (*opt_key == "xy_size_compensation") {
|
||||
else if (*opt_key == "clip_multipart_objects"
|
||||
|| *opt_key == "xy_size_compensation") {
|
||||
steps.insert(posSlice);
|
||||
} else if (*opt_key == "support_material"
|
||||
|| *opt_key == "support_material_angle"
|
||||
@ -1091,48 +1092,34 @@ end:
|
||||
|
||||
for (size_t layer_id = 0; layer_id < layers.size(); ++ layer_id) {
|
||||
Layer *layer = this->layers[layer_id];
|
||||
// apply size compensation
|
||||
if (this->config.xy_size_compensation.value != 0.) {
|
||||
// Apply size compensation and perform clipping of multi-part objects.
|
||||
float delta = float(scale_(this->config.xy_size_compensation.value));
|
||||
bool scale = delta != 0.f;
|
||||
bool clip = this->config.clip_multipart_objects.value || delta > 0.f;
|
||||
if (layer->regions.size() == 1) {
|
||||
// single region
|
||||
if (scale) {
|
||||
// Single region, growing or shrinking.
|
||||
LayerRegion *layerm = layer->regions.front();
|
||||
layerm->slices.set(offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta), stInternal);
|
||||
} else {
|
||||
if (delta < 0) {
|
||||
// multiple regions, shrinking
|
||||
// we apply the offset to the combined shape, then intersect it
|
||||
// with the original slices for each region
|
||||
Polygons region_slices;
|
||||
for (size_t region_id = 0; region_id < layer->regions.size(); ++ region_id)
|
||||
polygons_append(region_slices, layer->regions[region_id]->slices.surfaces);
|
||||
Polygons slices = offset(union_(region_slices), delta);
|
||||
}
|
||||
} else if (scale || clip) {
|
||||
// Multiple regions, growing, shrinking or just clipping one region by the other.
|
||||
// When clipping the regions, priority is given to the first regions.
|
||||
Polygons processed;
|
||||
for (size_t region_id = 0; region_id < layer->regions.size(); ++ region_id) {
|
||||
LayerRegion *layerm = layer->regions[region_id];
|
||||
layerm->slices.set(std::move(intersection_ex(slices, to_polygons(std::move(layerm->slices.surfaces)))), stInternal);
|
||||
}
|
||||
} else {
|
||||
// multiple regions, growing
|
||||
// this is an ambiguous case, since it's not clear how to grow regions where they are going to overlap
|
||||
// so we give priority to the first one and so on
|
||||
Polygons processed;
|
||||
for (size_t region_id = 0;; ++ region_id) {
|
||||
LayerRegion *layerm = layer->regions[region_id];
|
||||
ExPolygons slices = offset_ex(to_expolygons(layerm->slices.surfaces), delta);
|
||||
if (region_id > 0)
|
||||
ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces));
|
||||
if (scale)
|
||||
slices = offset_ex(slices, delta);
|
||||
if (region_id > 0 && clip)
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
if (region_id + 1 == layer->regions.size()) {
|
||||
layerm->slices.set(std::move(slices), stInternal);
|
||||
break;
|
||||
}
|
||||
if (clip && region_id + 1 < layer->regions.size())
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
layerm->slices.set(std::move(slices), stInternal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge all regions' slices to get islands, chain them by a shortest path.
|
||||
layer->make_slices();
|
||||
}
|
||||
|
@ -107,6 +107,16 @@ inline ExPolygons to_expolygons(const Surfaces &src)
|
||||
return expolygons;
|
||||
}
|
||||
|
||||
inline ExPolygons to_expolygons(Surfaces &&src)
|
||||
{
|
||||
ExPolygons expolygons;
|
||||
expolygons.reserve(src.size());
|
||||
for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it)
|
||||
expolygons.emplace_back(ExPolygon(std::move(it->expolygon)));
|
||||
src.clear();
|
||||
return expolygons;
|
||||
}
|
||||
|
||||
inline ExPolygons to_expolygons(const SurfacesPtr &src)
|
||||
{
|
||||
ExPolygons expolygons;
|
||||
|
Loading…
Reference in New Issue
Block a user