mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-22 16:21:24 -06:00
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
7 changed files with 50 additions and 41 deletions
|
@ -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.) {
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue