Skip to content

Commit

Permalink
fix M204, solid fill overextrusion
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Jan 10, 2024
2 parents 05af3be + 85f90bc commit cf92bc2
Show file tree
Hide file tree
Showing 34 changed files with 1,174 additions and 555 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.13)
project(Slic3r-native)

add_subdirectory(build-utils)
add_subdirectory(test-utils)
add_subdirectory(admesh)
add_subdirectory(avrdude)
# boost/nowide
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2320,7 +2320,7 @@ class ConfigBase : public ConfigOptionResolver
// to resolve renamed and removed configuration keys.
bool set_deserialize_nothrow(const t_config_option_key &opt_key_src, const std::string &value_src, ConfigSubstitutionContext& substitutions, bool append = false);
// May throw BadOptionTypeException() if the operation fails.
void set_deserialize(const t_config_option_key &opt_key, const std::string &str, ConfigSubstitutionContext& config_substitutions, bool append = false);
void set_deserialize(const t_config_option_key &opt_key, const std::string &str, ConfigSubstitutionContext& config_substitutions = ConfigSubstitutionContext(ForwardCompatibilitySubstitutionRule::Disable), bool append = false);
void set_deserialize_strict(const t_config_option_key &opt_key, const std::string &str, bool append = false)
{ ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable }; this->set_deserialize(opt_key, str, ctxt, append); }
struct SetDeserializeItem {
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/Extruder.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef slic3r_Extruder_hpp_
#define slic3r_Extruder_hpp_

#include <optional>

#include "libslic3r.h"
#include "Point.hpp"

Expand Down
75 changes: 64 additions & 11 deletions src/libslic3r/ExtrusionEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,58 +378,111 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
else
return erNone;
}


std::string role_to_code(ExtrusionRole role)
{
switch (role) {
case erNone : return L("None");
case erPerimeter : return L("IPeri");
case erExternalPerimeter : return L("EPeri");
case erOverhangPerimeter : return L("OPeri");
case erInternalInfill : return L("IFill");
case erSolidInfill : return L("SFill");
case erTopSolidInfill : return L("TFill");
case erIroning : return L("Iron");
case erBridgeInfill : return L("EBridge");
case erInternalBridgeInfill : return L("IBridge");
case erThinWall : return L("ThinW");
case erGapFill : return L("GFill");
case erSkirt : return L("Skirt");
case erSupportMaterial : return L("Supp");
case erSupportMaterialInterface : return L("SuppI");
case erWipeTower : return L("WTower");
case erMilling : return L("Mill");
case erCustom : return L("Custom");
case erMixed : return L("Mixed");
case erTravel : return L("Travel");
default : assert(false);
}

return "";
}


std::string looprole_to_code(ExtrusionLoopRole looprole)
{
std::string code;
if(elrDefault == (looprole & elrDefault))
code += std::string("D");
if(elrInternal == (looprole & elrInternal))
code += std::string("Int");
if(elrSkirt == (looprole & elrSkirt))
code += std::string("Skirt");
if(elrHole == (looprole & elrHole))
code += std::string("Hole");
if(elrVase == (looprole & elrVase))
code += std::string("Vase");
if(elrFirstLoop == (looprole & elrFirstLoop))
code += std::string("First");

return code;
}

void ExtrusionPrinter::use(const ExtrusionPath &path) {
ss << "ExtrusionPath:" << (uint16_t)path.role() << "{";
ss << (json?"\"":"") << "ExtrusionPath" << (path.can_reverse()?"":"Oriented") << (json?"_":":") << role_to_code(path.role()) << (json?"\":":"") << "[";
for (int i = 0; i < path.polyline.size(); i++) {
if (i != 0) ss << ",";
double x = (mult * (path.polyline.get_points()[i].x()));
double y = (mult * (path.polyline.get_points()[i].y()));
ss << std::fixed << "{"<<(trunc?(int)x:x) << "," << (trunc ? (int)y : y) <<"}";
ss << std::fixed << "["<<(trunc>0?(int(x*trunc))/double(trunc):x) << "," << (trunc>0?(int(y*trunc))/double(trunc):y) <<"]";
}
ss << "}";
ss << "]";
}
void ExtrusionPrinter::use(const ExtrusionPath3D &path3D) {
ss << "ExtrusionPath3D:" << (uint16_t)path3D.role() << "{";
ss << (json?"\"":"") << "ExtrusionPath3D" << (path3D.can_reverse()?"":"Oriented") << (json?"_":":") << role_to_code(path3D.role()) << (json?"\":":"") << "[";
for (int i = 0; i < path3D.polyline.size();i++){
if (i != 0) ss << ",";
double x = (mult * (path3D.polyline.get_points()[i].x()));
double y = (mult * (path3D.polyline.get_points()[i].y()));
double z = (path3D.z_offsets.size() > i ? mult * (path3D.z_offsets[i]) : -1);
ss << std::fixed << "{" << (trunc ? (int)x : x) << "," << (trunc ? (int)y : y) << "," << (trunc ? (int)z : z) << "}";
ss << std::fixed << "[" << (trunc>0?(int(x*trunc))/double(trunc):x) << "," << (trunc>0?(int(y*trunc))/double(trunc):y) << "," << (trunc>0?(int(z*trunc))/double(trunc):z) << "]";
}
ss << "}";
ss << "]";
}
void ExtrusionPrinter::use(const ExtrusionMultiPath &multipath) {
ss << "ExtrusionMultiPath:" << (uint16_t)multipath.role() << "{";
ss << (json?"\"":"") << "ExtrusionMultiPath" << (multipath.can_reverse()?"":"Oriented") << (json?"_":":") << role_to_code(multipath.role()) << (json?"\":":"") << "{";
for (int i = 0; i < multipath.paths.size(); i++) {
if (i != 0) ss << ",";
multipath.paths[i].visit(*this);
}
ss << "}";
}
void ExtrusionPrinter::use(const ExtrusionMultiPath3D &multipath3D) {
ss << "multipath3D:" << (uint16_t)multipath3D.role() << "{";
ss << (json?"\"":"") << "multipath3D" << (multipath3D.can_reverse()?"":"Oriented") << (json?"_":":") << role_to_code(multipath3D.role()) << (json?"\":":"") << "{";
for (int i = 0; i < multipath3D.paths.size(); i++) {
if (i != 0) ss << ",";
multipath3D.paths[i].visit(*this);
}
ss << "}";
}
void ExtrusionPrinter::use(const ExtrusionLoop &loop) {
ss << "ExtrusionLoop:" << (uint16_t)loop.role()<<":" <<(uint16_t)loop.loop_role()<<"{";
ss << (json?"\"":"") << "ExtrusionLoop" << (json?"_":":") << role_to_code(loop.role())<<"_" << looprole_to_code(loop.loop_role()) << (json?"\":":"") << "{";
if(!loop.can_reverse()) ss << (json?"\"":"") << "oriented" << (json?"\":":"=") << "true,";
for (int i = 0; i < loop.paths.size(); i++) {
if (i != 0) ss << ",";
loop.paths[i].visit(*this);
}
ss << "}";
}
void ExtrusionPrinter::use(const ExtrusionEntityCollection &collection) {
ss << "ExtrusionEntityCollection:" << (uint16_t)collection.role() << "{";
ss << (json?"\"":"") << "ExtrusionEntityCollection" << (json?"_":":") << role_to_code(collection.role()) << (json?"\":":"") << "{";
if(!collection.can_sort()) ss << (json?"\"":"") << "no_sort" << (json?"\":":"=") << "true,";
if(!collection.can_reverse()) ss << (json?"\"":"") << "oriented" << (json?"\":":"=") << "true,";
for (int i = 0; i < collection.entities().size(); i++) {
if (i != 0) ss << ",";
collection.entities()[i]->visit(*this);
}
if(!collection.can_sort()) ss<<", no_sort=true";
ss << "}";
}

Expand Down
5 changes: 3 additions & 2 deletions src/libslic3r/ExtrusionEntity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,10 @@ inline void extrusion_entities_append_loops_and_paths(ExtrusionEntitiesPtr &dst,
class ExtrusionPrinter : public ExtrusionVisitorConst {
std::stringstream ss;
double mult;
bool trunc;
int trunc;
bool json;
public:
ExtrusionPrinter(double mult = 0.0001, bool trunc = false) : mult(mult), trunc(trunc) { }
ExtrusionPrinter(double mult = 0.000001, int trunc = 0, bool json = false) : mult(mult), trunc(trunc), json(json) { }
virtual void use(const ExtrusionPath& path) override;
virtual void use(const ExtrusionPath3D& path3D) override;
virtual void use(const ExtrusionMultiPath& multipath) override;
Expand Down
9 changes: 8 additions & 1 deletion src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,14 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:

//give the overlap size to let the infill do his overlap
//add overlap if at least one perimeter
const float perimeter_spacing = layerm->flow(frPerimeter).spacing();
float perimeter_spacing = 0;
if(layerm->region().config().perimeters == 1)
perimeter_spacing = layerm->flow(frExternalPerimeter).spacing();
else if(layerm->region().config().only_one_perimeter_top)
//note: use the min of the two to avoid overextrusion if only one perimeter top
perimeter_spacing = std::min(layerm->flow(frPerimeter).spacing(), layerm->flow(frExternalPerimeter).spacing());
else //if(layerm->region().config().perimeters > 1)
perimeter_spacing = layerm->flow(frPerimeter).spacing();

// Used by the concentric infill pattern to clip the loops to create extrusion paths.
f->loop_clipping = scale_t(layerm->region().config().get_computed_value("seam_gap", surface_fill.params.extruder - 1) * surface_fill.params.flow.nozzle_diameter());
Expand Down
12 changes: 1 addition & 11 deletions src/libslic3r/Fill/FillBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,7 @@ double Fill::compute_unscaled_volume_to_fill(const Surface* surface, const FillP
} else {
for (const ExPolygon& poly : intersection_ex(ExPolygons{ surface->expolygon }, this->no_overlap_expolygons)) {
polyline_volume += params.flow.height() * unscaled(unscaled(poly.area()));
double perimeter_gap_usage = params.config->perimeter_overlap.get_abs_value(1);
// add external "perimeter gap"
//TODO: use filament_max_overlap to reduce it
//double filament_max_overlap = params.config->get_computed_value("filament_max_overlap", params.extruder - 1);
double perimeter_round_gap = unscaled(poly.contour.length()) * params.flow.height() * (1 - 0.25 * PI) * 0.5;
// add holes "perimeter gaps"
double holes_gaps = 0;
for (auto hole = poly.holes.begin(); hole != poly.holes.end(); ++hole) {
holes_gaps += unscaled(hole->length()) * params.flow.height() * (1 - 0.25 * PI) * 0.5;
}
polyline_volume += (perimeter_round_gap + holes_gaps) * perimeter_gap_usage;
//note: the no_overlap_expolygons is already at spacing from the centerline of the perimeter.
}
}
return polyline_volume;
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/Fill/FillBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ class Fill
ExPolygon /* expolygon */,
Polylines & /* polylines_out */) const {
BOOST_LOG_TRIVIAL(error)<<"Error, the fill isn't implemented";
assert(false);
};

// Used for concentric infill to generate ThickPolylines using Arachne.
Expand All @@ -182,6 +183,7 @@ class Fill
ExPolygon expolygon,
ThickPolylines &thick_polylines_out) const {
BOOST_LOG_TRIVIAL(error) << "Error, the arachne fill isn't implemented";
assert(false);
};

virtual float _layer_angle(size_t idx) const { return can_angle_cross && (idx & 1) ? float(M_PI/2.) : 0; }
Expand Down
4 changes: 2 additions & 2 deletions src/libslic3r/Flow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,12 +526,12 @@ float Flow::rounded_rectangle_extrusion_spacing(float width, float height, float
#endif
}

float Flow::rounded_rectangle_extrusion_width_from_spacing(float spacing, float height, float m_spacing_ratio)
float Flow::rounded_rectangle_extrusion_width_from_spacing(float spacing, float height, float spacing_ratio)
{
#ifdef HAS_PERIMETER_LINE_OVERLAP
return (spacing + PERIMETER_LINE_OVERLAP_FACTOR * height * (1. - 0.25 * PI) * spacing_ratio);
#else
return float(spacing + height * (1. - 0.25 * PI) * m_spacing_ratio);
return float(spacing + height * (1. - 0.25 * PI) * spacing_ratio);
#endif
}

Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Format/STL.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Slic3r {

class TriangleMesh;
class ModelObject;
class Model;

// Load an STL file into a provided model.
extern bool load_stl(const char *path, Model *model, const char *object_name = nullptr);
Expand Down
4 changes: 2 additions & 2 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3277,7 +3277,7 @@ LayerResult GCode::process_layer(
if (this->m_layer != nullptr && this->m_layer->id() == 0) {
m_avoid_crossing_perimeters.use_external_mp(true);
for (const ExtrusionEntity* ee : print_object->brim().entities())
gcode += this->extrude_entity(*ee, "brim");
gcode += this->extrude_entity(*ee, "Brim");
m_avoid_crossing_perimeters.use_external_mp(false);
m_avoid_crossing_perimeters.disable_once();
m_last_too_small.polyline.clear();
Expand Down Expand Up @@ -3386,7 +3386,7 @@ LayerResult GCode::process_layer(
assert(instance_to_print.print_object.brim().entities()[instance_to_print.instance_id]->is_collection());
if (const ExtrusionEntityCollection* coll = dynamic_cast<const ExtrusionEntityCollection*>(instance_to_print.print_object.brim().entities()[instance_to_print.instance_id])) {
for (const ExtrusionEntity* ee : coll->entities())
gcode += this->extrude_entity(*ee, "brim");
gcode += this->extrude_entity(*ee, "Brim");
}
m_avoid_crossing_perimeters.use_external_mp(false);
m_avoid_crossing_perimeters.disable_once();
Expand Down
34 changes: 24 additions & 10 deletions src/libslic3r/GCodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,23 +311,34 @@ std::string GCodeWriter::write_acceleration(){
//try to set only printing acceleration, travel should be untouched if possible
if (FLAVOR_IS(gcfRepetier)) {
// M201: Set max printing acceleration
gcode << "M201 X" << m_current_acceleration << " Y" << m_current_acceleration;
if (m_current_acceleration > 0)
gcode << "M201 X" << m_current_acceleration << " Y" << m_current_acceleration;
} else if(FLAVOR_IS(gcfLerdge) || FLAVOR_IS(gcfSprinter)){
// M204: Set printing acceleration
// This is new MarlinFirmware with separated print/retraction/travel acceleration.
// Use M204 P, we don't want to override travel acc by M204 S (which is deprecated anyway).
gcode << "M204 P" << m_current_acceleration;
if (m_current_acceleration > 0)
gcode << "M204 P" << m_current_acceleration;
} else if (FLAVOR_IS(gcfMarlinFirmware) || FLAVOR_IS(gcfRepRap)) {
// M204: Set printing & travel acceleration
gcode << "M204 P" << m_current_acceleration << " T" << (m_current_travel_acceleration > 0 ? m_current_travel_acceleration : m_current_acceleration);
if (m_current_acceleration > 0)
gcode << "M204 P" << m_current_acceleration << " T" << (m_current_travel_acceleration > 0 ? m_current_travel_acceleration : m_current_acceleration);
else if(m_current_travel_acceleration > 0)
gcode << "M204 T" << m_current_travel_acceleration;
} else { // gcfMarlinLegacy
// M204: Set default acceleration
gcode << "M204 S" << m_current_acceleration;
if (m_current_acceleration > 0)
gcode << "M204 S" << m_current_acceleration;
}
if (this->config.gcode_comments) gcode << " ; adjust acceleration";
gcode << "\n";

return gcode.str();
//if at least something, add comment and line return
if (gcode.tellp() != std::streampos(0)) {
if (this->config.gcode_comments)
gcode << " ; adjust acceleration";
gcode << "\n";
return gcode.str();
}
assert(gcode.str().empty());
return "";
}

std::string GCodeWriter::reset_e(bool force)
Expand Down Expand Up @@ -433,7 +444,7 @@ std::string GCodeWriter::set_speed(const double speed, const std::string &commen
const double F = speed * 60;
m_current_speed = speed;
assert(F > 0.);
assert(F < 100000.);
assert(F < 10000000.);
// GCodeG1Formatter w;
// w.emit_f(F);
// w.emit_comment(this->config.gcode_comments, comment);
Expand Down Expand Up @@ -565,7 +576,7 @@ bool GCodeWriter::will_move_z(double z) const
we don't perform an actual Z move. */
if (m_lifted > 0) {
double nominal_z = m_pos.z() - m_lifted;
if (z >= nominal_z + EPSILON && z <= m_pos.z() - EPSILON)
if (z >= nominal_z - EPSILON && z <= m_pos.z() + EPSILON)
return false;
}
return true;
Expand Down Expand Up @@ -637,6 +648,9 @@ std::string GCodeWriter::retract(bool before_wipe)
{
double factor = before_wipe ? m_tool->retract_before_wipe() : 1.;
assert(factor >= 0. && factor <= 1. + EPSILON);
// if before_wipe but no retract_before_wipe, then no retract
if (factor == 0)
return "";
//check for override
if (config_region && config_region->print_retract_length >= 0) {
return this->_retract(
Expand Down
38 changes: 16 additions & 22 deletions src/libslic3r/GCodeWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ class GCodeWriter {
// override from region
const PrintRegionConfig* config_region = nullptr;

GCodeWriter() :
multiple_extruders(false), m_extrusion_axis("E"), m_tool(nullptr),
m_single_extruder_multi_material(false),
m_last_acceleration(0), m_current_acceleration(0), m_current_speed(0),
m_last_bed_temperature(0), m_last_bed_temperature_reached(true),
m_lifted(0)
{}
GCodeWriter() {}
Tool* tool() { return m_tool; }
const Tool* tool() const { return m_tool; }

Expand Down Expand Up @@ -96,25 +90,25 @@ class GCodeWriter {
// Extruders are sorted by their ID, so that binary search is possible.
std::vector<Extruder> m_extruders;
std::vector<Mill> m_millers;
std::string m_extrusion_axis;
bool m_single_extruder_multi_material;
Tool* m_tool;
uint32_t m_last_acceleration;
uint32_t m_last_travel_acceleration;
uint32_t m_current_acceleration;
uint32_t m_current_travel_acceleration;
double m_current_speed;
uint8_t m_last_fan_speed;
int16_t m_last_temperature;
int16_t m_last_temperature_with_offset;
int16_t m_last_bed_temperature;
bool m_last_bed_temperature_reached;
std::string m_extrusion_axis = "E";
bool m_single_extruder_multi_material = false;
Tool* m_tool = nullptr;
uint32_t m_last_acceleration = 0;
uint32_t m_last_travel_acceleration = 0;
uint32_t m_current_acceleration = 0;
uint32_t m_current_travel_acceleration = 0;
double m_current_speed = 0;
uint8_t m_last_fan_speed = 0;
int16_t m_last_temperature = 0;
int16_t m_last_temperature_with_offset = 0;
int16_t m_last_bed_temperature = 0;
bool m_last_bed_temperature_reached = true;
// if positive, it's set, and the next lift wil have this extra lift
double m_extra_lift = 0;
// current lift, to remove from m_pos to have the current height.
double m_lifted;
double m_lifted = 0;
Vec3d m_pos = Vec3d::Zero();

std::string _travel_to_z(double z, const std::string &comment);
std::string _retract(double length, std::optional<double> restart_extra, std::optional<double> restart_extra_toolchange, const std::string &comment);

Expand Down
Loading

0 comments on commit cf92bc2

Please sign in to comment.