Skip to content

Commit

Permalink
Fix ext_peri_spacing, scripted widget improvements, other little fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Jan 23, 2024
2 parents 2053c1b + 0621b6f commit 8b5bbe0
Show file tree
Hide file tree
Showing 18 changed files with 327 additions and 159 deletions.
48 changes: 48 additions & 0 deletions src/libslic3r/ExtrusionEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ double ExtrusionLoop::length() const
return len;
}

ExtrusionRole ExtrusionLoop::role() const
{
if (this->paths.empty())
return erNone;
ExtrusionRole role = this->paths.front().role();
for (const ExtrusionPath &path : this->paths)
if (role != path.role()) {
return erMixed;
}
return role;
}

bool ExtrusionLoop::split_at_vertex(const Point &point, const double scaled_epsilon)
{
for (ExtrusionPaths::iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
Expand Down Expand Up @@ -544,6 +556,42 @@ void ExtrusionVisitorRecursive::use(ExtrusionEntityCollection& collection) {
}
}

void HasRoleVisitor::use(const ExtrusionMultiPath& multipath) {
for (const ExtrusionPath& path : multipath.paths) {
path.visit(*this);
if(found) return;
}
}
void HasRoleVisitor::use(const ExtrusionMultiPath3D& multipath3D) {
for (const ExtrusionPath3D& path3D : multipath3D.paths) {
path3D.visit(*this);
if(found) return;
}
}
void HasRoleVisitor::use(const ExtrusionLoop& loop) {
for (const ExtrusionPath& path : loop.paths) {
path.visit(*this);
if(found) return;
}
}
void HasRoleVisitor::use(const ExtrusionEntityCollection& collection) {
for (const ExtrusionEntity* entity : collection.entities()) {
entity->visit(*this);
if(found) return;
}
}
bool HasRoleVisitor::search(const ExtrusionEntity &entity, HasRoleVisitor&& visitor) {
entity.visit(visitor);
return visitor.found;
}
bool HasRoleVisitor::search(const ExtrusionEntitiesPtr &entities, HasRoleVisitor&& visitor) {
for (ExtrusionEntity *ptr : entities) {
ptr->visit(visitor);
if (visitor.found) return true;
}
return visitor.found;
}

//class ExtrusionTreeVisitor : ExtrusionVisitor {
//public:
// //virtual void use(ExtrusionEntity &entity) { assert(false); };
Expand Down
34 changes: 31 additions & 3 deletions src/libslic3r/ExtrusionEntity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,17 @@ class ExtrusionMultiEntity : public ExtrusionEntity {
ExtrusionMultiEntity& operator=(ExtrusionMultiEntity &&rhs) { this->paths = std::move(rhs.paths); return *this; }

bool is_loop() const override { return false; }
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); }
ExtrusionRole role() const override
{
if (this->paths.empty())
return erNone;
ExtrusionRole role = this->paths.front().role();
for (const ExtrusionPath &path : this->paths)
if (role != path.role()) {
return erMixed;
}
return role;
}
virtual const Point& first_point() const override { return this->paths.front().polyline.as_polyline().front(); }
virtual const Point& last_point() const override { return this->paths.back().polyline.as_polyline().back(); }

Expand Down Expand Up @@ -480,7 +490,7 @@ class ExtrusionLoop : public ExtrusionEntity
// Test, whether the point is extruded by a bridging flow.
// This used to be used to avoid placing seams on overhangs, but now the EdgeGrid is used instead.
bool has_overhang_point(const Point &point) const;
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); }
ExtrusionRole role() const override;
ExtrusionLoopRole loop_role() const { return m_loop_role; }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
Expand Down Expand Up @@ -674,6 +684,23 @@ class ExtrusionVisitorRecursive : public ExtrusionVisitor {
virtual void use(ExtrusionEntityCollection& collection) override;
};

class HasRoleVisitor : public ExtrusionVisitorConst{
public:
bool found = false;
void use(const ExtrusionMultiPath& multipath) override;
void use(const ExtrusionMultiPath3D& multipath3D) override;
void use(const ExtrusionLoop& loop) override;
void use(const ExtrusionEntityCollection& collection) override;
static bool search(const ExtrusionEntity &entity, HasRoleVisitor&& visitor);
static bool search(const ExtrusionEntitiesPtr &entities, HasRoleVisitor&& visitor);
};
struct HasInfillVisitor : public HasRoleVisitor{
void default_use(const ExtrusionEntity &entity) override { found = is_infill(entity.role()); };
};
struct HasSolidInfillVisitor : public HasRoleVisitor{
void default_use(const ExtrusionEntity &entity) override { found = is_solid_infill(entity.role()); };
};


//call simplify for all paths.
class SimplifyVisitor : public ExtrusionVisitorRecursive {
Expand Down Expand Up @@ -726,7 +753,8 @@ class ExtrusionModifyFlow : public ExtrusionVisitorRecursive {
#if _DEBUG
struct LoopAssertVisitor : public ExtrusionVisitorRecursiveConst {
virtual void default_use(const ExtrusionEntity& entity) override {};
virtual void use(const ExtrusionLoop& loop) override {
virtual void use(const ExtrusionPath &path) override { assert(path.length() > SCALED_EPSILON); }
virtual void use(const ExtrusionLoop &loop) override {
for (auto it = std::next(loop.paths.begin()); it != loop.paths.end(); ++it) {
assert(it->polyline.size() >= 2);
assert(std::prev(it)->polyline.back() == it->polyline.front());
Expand Down
37 changes: 4 additions & 33 deletions src/libslic3r/ExtrusionEntityCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,40 +81,11 @@ void ExtrusionEntityCollection::remove(size_t i)
this->m_entities.erase(this->m_entities.begin() + i);
}

ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const ExtrusionEntitiesPtr& extrusion_entities, const Point &start_near, ExtrusionRole role)
//ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const Point &start_near, ExtrusionRole role)
void ExtrusionEntityCollection::chained_path_from(const Point &start_near)
{
//ExtrusionEntityCollection out;
//if (this->no_sort) {
// out = *this;
//} else {
// if (role == erMixed)
// out = *this;
// else {
// for (const ExtrusionEntity *ee : this->entities()) {
// if (role != erMixed) {
// // The caller wants only paths with a specific extrusion role.
// auto role2 = ee->role();
// if (role != role2) {
// // This extrusion entity does not match the role asked.
// assert(role2 != erMixed);
// continue;
// }
// }
// out.entities().emplace_back(ee->clone());
// }
// }
// chain_and_reorder_extrusion_entities(out.entities(), &start_near);
//}
//return out;
// Return a filtered copy of the collection.
ExtrusionEntityCollection out;
out.m_entities = filter_by_extrusion_role(extrusion_entities, role);
// Clone the extrusion entities.
for (ExtrusionEntity* &ptr : out.m_entities)
ptr = ptr->clone();
chain_and_reorder_extrusion_entities(out.m_entities, &start_near);
return out;
if (this->m_no_sort)
return;
chain_and_reorder_extrusion_entities(this->m_entities, &start_near);
}

void ExtrusionEntityCollection::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
Expand Down
9 changes: 1 addition & 8 deletions src/libslic3r/ExtrusionEntityCollection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,7 @@ class ExtrusionEntityCollection : public ExtrusionEntity
}
void replace(size_t i, const ExtrusionEntity &entity);
void remove(size_t i);
static ExtrusionEntityCollection chained_path_from(const ExtrusionEntitiesPtr &extrusion_entities, const Point &start_near, ExtrusionRole role = erMixed);
ExtrusionEntityCollection chained_path_from(const Point &start_near, ExtrusionRole role = erNone) const {
if (role == erNone) role = this->role();
if( this->m_no_sort || (role == erMixed) )
return *this;
else
return chained_path_from(this->m_entities, start_near, role);
}
void chained_path_from(const Point &start_near);
void reverse() override;
const Point& first_point() const override { return this->entities().front()->first_point(); }
const Point& last_point() const override { return this->entities().back()->last_point(); }
Expand Down
5 changes: 3 additions & 2 deletions src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,8 +696,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
double real_surface = 0;
for(auto &t : temp) real_surface += t.area();
assert(compute_volume.volume < unscaled(unscaled(surface_fill.surface.area())) * surface_fill.params.layer_height + EPSILON);
assert(compute_volume.volume < unscaled(unscaled(real_surface)) * surface_fill.params.layer_height * 1.001);
assert(compute_volume.volume > unscaled(unscaled(real_surface)) * surface_fill.params.layer_height * 0.999);
double area = unscaled(unscaled(real_surface));
assert(compute_volume.volume < area * surface_fill.params.layer_height * 1.001);
assert(compute_volume.volume > area * surface_fill.params.layer_height * 0.999 || area < std::max(1.,surface_fill.params.config->solid_infill_below_area.value));
}
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/Fill/FillBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ Fill::do_gap_fill(const ExPolygons& gapfill_areas, const FillParams& params, Ext
for (ThickPolyline poly : polylines_gapfill) {
for (coord_t width : poly.points_width) {
if (width > params.flow.scaled_width() * 2.2) {
std::cerr << "ERRROR!!!! gapfill width = " << unscaled(width) << " > max_width = " << (params.flow.width() * 2) << "\n";
BOOST_LOG_TRIVIAL(error) << "ERRROR!!!! gapfill width = " << unscaled(width) << " > max_width = " << (params.flow.width() * 2) << "\n";
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/libslic3r/Flow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,14 @@ Flow Flow::new_from_config(FlowRole role, const DynamicConfig& print_config, flo
if (role == frExternalPerimeter) {
config_width = print_config.opt<ConfigOptionFloatOrPercent>("external_perimeter_extrusion_width");
config_spacing = print_config.opt<ConfigOptionFloatOrPercent>("external_perimeter_extrusion_spacing");
// external peri spacing is only half spacing -> transform it into a full spacing
if (!config_spacing.is_phony() && !config_spacing.value == 0) {
double raw_spacing = config_spacing.get_abs_value(nozzle_diameter);
config_spacing.percent = false;
config_spacing.value = rounded_rectangle_extrusion_spacing(
rounded_rectangle_extrusion_width_from_spacing(raw_spacing, layer_height, 0.5f),
layer_height, 1.f);
}
overlap = (float)print_config.get_abs_value("external_perimeter_overlap", 1.0);
} else if (role == frPerimeter) {
config_width = print_config.opt<ConfigOptionFloatOrPercent>("perimeter_extrusion_width");
Expand Down
14 changes: 11 additions & 3 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3423,9 +3423,16 @@ LayerResult GCode::process_layer(
gcode += m_writer.set_temperature(m_config.first_layer_temperature.get_at(m_writer.tool()->id()), false, m_writer.tool()->id());
else if (m_config.temperature.get_at(m_writer.tool()->id()) > 0) // don't set it if disabled
gcode += m_writer.set_temperature(m_config.temperature.get_at(m_writer.tool()->id()), false, m_writer.tool()->id());
gcode += this->extrude_support(
//create support-only collection (by copy)
ExtrusionEntityCollection only_support;
// support_extrusion_role is erSupportMaterial, erSupportMaterialInterface or erMixed for all extrusion paths.
instance_to_print.object_by_extruder.support->chained_path_from(m_last_pos, instance_to_print.object_by_extruder.support_extrusion_role));
only_support.set_can_sort_reverse(instance_to_print.object_by_extruder.support->can_sort(), instance_to_print.object_by_extruder.support->can_reverse());
only_support.append(
filter_by_extrusion_role(instance_to_print.object_by_extruder.support->entities(),
instance_to_print.object_by_extruder.support_extrusion_role));
only_support.chained_path_from(m_last_pos);
//it's reaordered, now extrude.
gcode += this->extrude_support(only_support);
m_layer = layer_to_print.layer();
m_object_layer_over_raft = object_layer_over_raft;
}
Expand Down Expand Up @@ -4887,7 +4894,8 @@ void GCode::use(const ExtrusionEntityCollection &collection) {
next_entity->visit(*this);
}
} else {
ExtrusionEntityCollection chained = collection.chained_path_from(m_last_pos);
ExtrusionEntityCollection chained = collection; // TODO: 2.7 maybe we can visit a modifiable colelction, so we don't copy it at every step?
chained.chained_path_from(m_last_pos);
for (const ExtrusionEntity* next_entity : chained.entities()) {
next_entity->visit(*this);
}
Expand Down
66 changes: 42 additions & 24 deletions src/libslic3r/GCode/SeamPlacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,28 +432,40 @@ Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition confi
SeamPosition configured_seam_preference;
public:
bool also_overhangs = false;
bool also_thin_walls = false;
PerimeterCopy(std::vector<const LayerRegion*>* regions_out, Polygons* polys, SeamPosition configured_seam)
: corresponding_regions_out(regions_out), configured_seam_preference(configured_seam), polygons(polys) {
}
virtual void default_use(const ExtrusionEntity& entity) { };
virtual void default_use(const ExtrusionEntity& entity) {};
virtual void use(const ExtrusionLoop& loop) override {
ExtrusionRole role = loop.role();
for (const ExtrusionPath& path : loop.paths) {
if (path.role() == ExtrusionRole::erExternalPerimeter) {
role = ExtrusionRole::erExternalPerimeter;
}
if (path.role() == ExtrusionRole::erOverhangPerimeter &&
also_overhangs) { // TODO find a way to search for external overhangs only
role = ExtrusionRole::erOverhangPerimeter;
}
}

if (role == ExtrusionRole::erExternalPerimeter || (role == ExtrusionRole::erOverhangPerimeter && also_overhangs)
|| (is_perimeter(role) && configured_seam_preference == spAllRandom)) { //for random seam alignment, extract all perimeters
if ((configured_seam_preference == spAllRandom && !loop.paths.empty() &&
is_perimeter(loop.paths.front().role()))
|| (also_thin_walls && loop.role() == erThinWall)) {
Points p;
loop.collect_points(p);
polygons->emplace_back(std::move(p));
corresponding_regions_out->push_back(current_layer_region);
return;
}else {
Points p;
for (const ExtrusionPath &path : loop.paths) {
if (path.role() == ExtrusionRole::erExternalPerimeter) {
path.collect_points(p);
}
if (path.role() == ExtrusionRole::erOverhangPerimeter &&
also_overhangs) { // TODO find a way to search for external overhangs only
path.collect_points(p);
}
//if (path.role() == ExtrusionRole::erThinWall && also_thin_walls) {
// path.collect_points(p); // TODO: 2.7: reactivate when it's possible to distinguish between thinwalltravel & thinextrusions
// // currently, only looking for thinwall-only loop
//}
}

if (!p.empty()) { // for random seam alignment, extract all perimeters
polygons->emplace_back(std::move(p));
corresponding_regions_out->push_back(current_layer_region);
}
}
}
virtual void use(const ExtrusionEntityCollection& collection) override {
Expand All @@ -469,20 +481,26 @@ Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition confi
visitor.set_current_layer_region(layer_region);
ex_entity->visit(visitor);
if (polygons.empty()) {
//can happen if the external is fully an overhang
visitor.also_overhangs = true;
// maybe only thin walls?
visitor.also_thin_walls = true;
ex_entity->visit(visitor);
visitor.also_overhangs = false;
if (polygons.empty()) {
//shouldn't happen
// can happen if the external is fully an overhang
visitor.also_overhangs = true;
ex_entity->visit(visitor);
assert(false);
// what to do in this case?
Points p;
ex_entity->collect_points(p);
polygons.emplace_back(std::move(p));
corresponding_regions_out.push_back(layer_region);
visitor.also_overhangs = false;
if (polygons.empty()) {
// shouldn't happen
ex_entity->visit(visitor);
assert(ex_entity->role() == erThinWall); // no loops
// what to do in this case?
Points p;
ex_entity->collect_points(p);
polygons.emplace_back(std::move(p));
corresponding_regions_out.push_back(layer_region);
}
}
visitor.also_thin_walls = false;
}
}
}
Expand Down
21 changes: 12 additions & 9 deletions src/libslic3r/GCode/ToolOrdering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,15 @@ uint16_t LayerTools::extruder(const ExtrusionEntityCollection &extrusions, const
assert(region.config().infill_extruder.value > 0);
assert(region.config().solid_infill_extruder.value > 0);
// 1 based extruder ID.
uint16_t extruder = ((this->extruder_override == 0) ?
(is_infill(extrusions.role()) ?
(is_solid_infill(extrusions.entities().front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) :
region.config().perimeter_extruder.value) :
this->extruder_override);
uint16_t extruder = this->extruder_override;
if (this->extruder_override == 0)
if (HasRoleVisitor::search(extrusions, HasInfillVisitor{}))
if (HasRoleVisitor::search(extrusions, HasSolidInfillVisitor{}))
extruder = region.config().solid_infill_extruder;
else
extruder = region.config().infill_extruder;
else
extruder = region.config().perimeter_extruder.value;
return (extruder == 0) ? 0 : extruder - 1;
}

Expand Down Expand Up @@ -248,11 +252,10 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (const ExtrusionEntity *ee : layerm->fills.entities()) {
// fill represents infill extrusions of a single island.
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
//FIXME: if first role is gapfill, please search deeper for another role
ExtrusionRole role = fill->entities().empty() ? erNone : fill->entities().front()->role();
if (is_solid_infill(role))
// we search as deep as available, in case there is some gapfill role
if (HasRoleVisitor::search(fill->entities(), HasSolidInfillVisitor{}))
has_solid_infill = true;
else if (role != erNone)
else if (HasRoleVisitor::search(fill->entities(), HasInfillVisitor{}))
has_infill = true;

if (m_print_config_ptr) {
Expand Down
Loading

0 comments on commit 8b5bbe0

Please sign in to comment.