OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::SpiralVase Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/GCode/SpiralVase.hpp>

Collaboration diagram for Slic3r::SpiralVase:

Classes

class  SpiralPoint

Public Member Functions

 SpiralVase (const PrintConfig &config)
void enable (bool en)
std::string process_layer (const std::string &gcode, bool last_layer)
void set_max_xy_smoothing (float max)

Private Attributes

const PrintConfig & m_config
GCodeReader m_reader
float m_max_xy_smoothing = 0.f
bool m_enabled = false
bool m_transition_layer = false
bool m_smooth_spiral = false
std::vector< SpiralPoint > * m_previous_layer

Detailed Description

Constructor & Destructor Documentation

◆ SpiralVase()

Slic3r::SpiralVase::SpiralVase ( const PrintConfig & config)
inline
24 : m_config(config)
25 {
26 m_reader.z() = (float)m_config.z_offset;
27 m_reader.apply_config(m_config);
28 m_previous_layer = NULL;
29 m_smooth_spiral = config.spiral_mode_smooth;
30 };
const PrintConfig & m_config
Definition SpiralVase.hpp:42
GCodeReader m_reader
Definition SpiralVase.hpp:43
std::vector< SpiralPoint > * m_previous_layer
Definition SpiralVase.hpp:51
bool m_smooth_spiral
Definition SpiralVase.hpp:50

References m_config, m_previous_layer, m_reader, and m_smooth_spiral.

Member Function Documentation

◆ enable()

void Slic3r::SpiralVase::enable ( bool en)
inline
32 {
34 m_enabled = en;
35 }
bool m_enabled
Definition SpiralVase.hpp:46
bool m_transition_layer
Definition SpiralVase.hpp:48

References m_enabled, and m_transition_layer.

◆ process_layer()

std::string Slic3r::SpiralVase::process_layer ( const std::string & gcode,
bool last_layer )
74{
75 /* This post-processor relies on several assumptions:
76 - all layers are processed through it, including those that are not supposed
77 to be transformed, in order to update the reader with the XY positions
78 - each call to this method includes a full layer, with a single Z move
79 at the beginning
80 - each layer is composed by suitable geometry (i.e. a single complete loop)
81 - loops were not clipped before calling this method */
82
83 // If we're not going to modify G-code, just feed it to the reader
84 // in order to update positions.
85 if (! m_enabled) {
86 m_reader.parse_buffer(gcode);
87 return gcode;
88 }
89
90 // Get total XY length for this layer by summing all extrusion moves.
91 float total_layer_length = 0;
92 float layer_height = 0;
93 float z = 0.f;
94
95 {
96 //FIXME Performance warning: This copies the GCodeConfig of the reader.
97 GCodeReader r = m_reader; // clone
98 bool set_z = false;
99 r.parse_buffer(gcode, [&total_layer_length, &layer_height, &z, &set_z]
100 (GCodeReader &reader, const GCodeReader::GCodeLine &line) {
101 if (line.cmd_is("G1")) {
102 if (line.extruding(reader)) {
103 total_layer_length += line.dist_XY(reader);
104 } else if (line.has(Z)) {
105 layer_height += line.dist_Z(reader);
106 if (!set_z) {
107 z = line.new_Z(reader);
108 set_z = true;
109 }
110 }
111 }
112 });
113 }
114
115 // Remove layer height from initial Z.
116 z -= layer_height;
117
118 std::vector<SpiralVase::SpiralPoint>* current_layer = new std::vector<SpiralVase::SpiralPoint>();
119 std::vector<SpiralVase::SpiralPoint>* previous_layer = m_previous_layer;
120
121 bool smooth_spiral = m_smooth_spiral;
122 std::string new_gcode;
123 std::string transition_gcode;
124 float max_xy_dist_for_smoothing = m_max_xy_smoothing;
125 //FIXME Tapering of the transition layer only works reliably with relative extruder distances.
126 // For absolute extruder distances it will be switched off.
127 // Tapering the absolute extruder distances requires to process every extrusion value after the first transition
128 // layer.
129 bool transition_in = m_transition_layer && m_config.use_relative_e_distances.value;
130 bool transition_out = last_layer && m_config.use_relative_e_distances.value;
131
132 float starting_flowrate = float(m_config.spiral_starting_flow_ratio.value);
133 float finishing_flowrate = float(m_config.spiral_finishing_flow_ratio.value);
134 const float min_segment_length = std::max(float(EPSILON), 2 * float(m_config.resolution.value));
135
136 const int xyz_digits = GCodeFormatter::xyz_digits(m_config.high_precision_gcode.value);
137 const int e_digits = GCodeFormatter::e_digits(m_config.high_precision_gcode.value);
138 float len = 0.f;
139 SpiralVase::SpiralPoint last_point = previous_layer != NULL && previous_layer->size() >0? previous_layer->at(previous_layer->size()-1): SpiralVase::SpiralPoint(0,0);
140 m_reader.parse_buffer(gcode, [&new_gcode, &z, total_layer_length, layer_height, transition_in, &len, &current_layer, &previous_layer, &transition_gcode, transition_out, smooth_spiral, &max_xy_dist_for_smoothing, &last_point, starting_flowrate, finishing_flowrate, min_segment_length, xyz_digits, e_digits]
141 (GCodeReader &reader, GCodeReader::GCodeLine line) {
142 if (line.cmd_is("G1")) {
143 // Orca: Filter out retractions at layer change
144 if (line.retracting(reader) || (line.extruding(reader) && line.dist_XY(reader) < min_segment_length)) return;
145 if (line.has_z() && !(line.has_x() || line.has_y())) {
146 // If this is the initial Z move of the layer, replace it with a
147 // (redundant) move to the last Z of previous layer.
148 line.set(Z, z, xyz_digits);
149 new_gcode += line.raw() + '\n';
150 return;
151 } else {
152 float dist_XY = line.dist_XY(reader);
153 if (line.has_x() || line.has_y()) { // Sometimes lines have X/Y but the move is to the last position
154 if (dist_XY > 0 && line.extruding(reader)) { // Exclude wipe and retract
155 len += dist_XY;
156 float factor = len / total_layer_length;
157 if (transition_in){
158 // Transition layer, interpolate the amount of extrusion starting from spiral_vase_starting_flow_rate to 100%.
159 float starting_e_factor = starting_flowrate + (factor * (1.f - starting_flowrate));
160 line.set(E, line.e() * starting_e_factor, e_digits);
161 } else if (transition_out) {
162 // We want the last layer to ramp down extrusion, but without changing z height!
163 // So clone the line before we mess with its Z and duplicate it into a new layer that ramps down E
164 // We add this new layer at the very end
165 // As with transition_in, the amount is ramped down from 100% to spiral_vase_finishing_flow_rate
166 GCodeReader::GCodeLine transitionLine(line);
167 float finishing_e_factor = finishing_flowrate + ((1.f -factor) * (1.f - finishing_flowrate));
168 transitionLine.set(E, line.e() * finishing_e_factor, e_digits);
169 transition_gcode += transitionLine.raw() + '\n';
170 }
171 // This line is the core of Spiral Vase mode, ramp up the Z smoothly
172 line.set(Z, z + factor * layer_height, xyz_digits);
173 if (smooth_spiral) {
174 // Now we also need to try to interpolate X and Y
175 SpiralVase::SpiralPoint p(line.x(), line.y()); // Get current x/y coordinates
176 current_layer->push_back(p); // Store that point for later use on the next layer
177 if (previous_layer != NULL) {
178 bool found = false;
179 float dist = 0;
180 SpiralVase::SpiralPoint nearestp = SpiralVaseHelpers::nearest_point_on_lines(p, previous_layer, found, dist);
181 if (found && dist < max_xy_dist_for_smoothing) {
182 // Interpolate between the point on this layer and the point on the previous layer
183 SpiralVase::SpiralPoint target = SpiralVaseHelpers::add(SpiralVaseHelpers::scale(nearestp, 1 - factor), SpiralVaseHelpers::scale(p, factor));
184
185 // Remove tiny movement
186 // We need to figure out the distance of this new line!
187 float modified_dist_XY = SpiralVaseHelpers::distance(last_point, target);
188 if (modified_dist_XY < min_segment_length)
189 line.clear();
190 else {
191 line.set(X, target.x, xyz_digits);
192 line.set(Y, target.y, xyz_digits);
193 // Scale the extrusion amount according to change in length
194 line.set(E, line.e() * modified_dist_XY / dist_XY, e_digits);
195 last_point = target;
196 }
197 } else {
198 last_point = p;
199 }
200 }
201 }
202 new_gcode += line.raw() + '\n';
203 }
204 return;
205 /* Skip travel moves: the move to first perimeter point will
206 cause a visible seam when loops are not aligned in XY; by skipping
207 it we blend the first loop move in the XY plane (although the smoothness
208 of such blend depend on how long the first segment is; maybe we should
209 enforce some minimum length?).
210 When smooth_spiral is enabled, we're gonna end up exactly where the next layer should
211 start anyway, so we don't need the travel move */
212 }
213 }
214 }
215 new_gcode += line.raw() + '\n';
216 if(transition_out) {
217 transition_gcode += line.raw() + '\n';
218 }
219 });
220
221 delete m_previous_layer;
222 m_previous_layer = current_layer;
223
224 return new_gcode + transition_gcode;
225}
#define EPSILON
Definition ColorUtils.cpp:64
static constexpr int e_digits(bool high_precision)
Definition GCodeWriter.hpp:335
static constexpr int xyz_digits(bool high_precision)
Definition GCodeWriter.hpp:334
float m_max_xy_smoothing
Definition SpiralVase.hpp:44
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:298
SpiralVase::SpiralPoint add(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:26
SpiralVase::SpiralPoint nearest_point_on_lines(SpiralVase::SpiralPoint p, std::vector< SpiralVase::SpiralPoint > *points, bool &found, float &dist)
Definition SpiralVase.cpp:48
SpiralVase::SpiralPoint scale(SpiralVase::SpiralPoint a, float factor)
Definition SpiralVase.cpp:28
float distance(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:19
@ gcode
Definition Time.hpp:14
layer_height((ConfigOptionInt, faded_layers))((ConfigOptionFloat
@ Y
Definition libslic3r.h:142
@ Z
Definition libslic3r.h:143
@ E
Definition libslic3r.h:144
@ X
Definition libslic3r.h:141

References Slic3r::SpiralVaseHelpers::add(), Slic3r::GCodeReader::GCodeLine::clear(), Slic3r::GCodeReader::GCodeLine::cmd_is(), Slic3r::Geometry::dist(), Slic3r::GCodeReader::GCodeLine::dist_XY(), Slic3r::GCodeReader::GCodeLine::dist_Z(), Slic3r::SpiralVaseHelpers::distance(), Slic3r::E, Slic3r::GCodeReader::GCodeLine::e(), Slic3r::GCodeFormatter::e_digits(), EPSILON, Slic3r::GCodeReader::GCodeLine::extruding(), Slic3r::GCodeReader::GCodeLine::has(), Slic3r::GCodeReader::GCodeLine::has_x(), Slic3r::GCodeReader::GCodeLine::has_y(), Slic3r::GCodeReader::GCodeLine::has_z(), Slic3r::layer_height(), m_config, m_enabled, m_max_xy_smoothing, m_previous_layer, m_reader, m_smooth_spiral, m_transition_layer, Slic3r::SpiralVaseHelpers::nearest_point_on_lines(), Slic3r::GCodeReader::GCodeLine::new_Z(), Slic3r::GCodeReader::parse_buffer(), Slic3r::GCodeReader::GCodeLine::raw(), Slic3r::GCodeReader::GCodeLine::retracting(), Slic3r::SpiralVaseHelpers::scale(), Slic3r::GCodeReader::GCodeLine::set(), Slic3r::X, Slic3r::GCodeReader::GCodeLine::x(), Slic3r::SpiralVase::SpiralPoint::x, Slic3r::GCodeFormatter::xyz_digits(), Slic3r::Y, Slic3r::GCodeReader::GCodeLine::y(), Slic3r::SpiralVase::SpiralPoint::y, and Slic3r::Z.

Here is the call graph for this function:

◆ set_max_xy_smoothing()

void Slic3r::SpiralVase::set_max_xy_smoothing ( float max)
inline
38 {
40 }

References m_max_xy_smoothing.

Member Data Documentation

◆ m_config

const PrintConfig& Slic3r::SpiralVase::m_config
private

Referenced by SpiralVase(), and process_layer().

◆ m_enabled

bool Slic3r::SpiralVase::m_enabled = false
private

Referenced by enable(), and process_layer().

◆ m_max_xy_smoothing

float Slic3r::SpiralVase::m_max_xy_smoothing = 0.f
private

◆ m_previous_layer

std::vector<SpiralPoint>* Slic3r::SpiralVase::m_previous_layer
private

Referenced by SpiralVase(), and process_layer().

◆ m_reader

GCodeReader Slic3r::SpiralVase::m_reader
private

Referenced by SpiralVase(), and process_layer().

◆ m_smooth_spiral

bool Slic3r::SpiralVase::m_smooth_spiral = false
private

Referenced by SpiralVase(), and process_layer().

◆ m_transition_layer

bool Slic3r::SpiralVase::m_transition_layer = false
private

Referenced by enable(), and process_layer().


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/GCode/SpiralVase.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/GCode/SpiralVase.cpp