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:
bubnikv 2017-02-14 12:36:04 +01:00
parent ce8973b33a
commit 420e387055
7 changed files with 50 additions and 41 deletions

View File

@ -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');

View File

@ -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);
}
}

View File

@ -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})

View File

@ -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.";

View File

@ -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);

View File

@ -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.) {
float delta = float(scale_(this->config.xy_size_compensation.value));
if (layer->regions.size() == 1) {
// single region
// 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) {
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);
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)
// 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;
}
polygons_append(processed, slices);
layerm->slices.set(std::move(slices), stInternal);
}
}
}
} 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];
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 (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();
}

View File

@ -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;