206 {
207 if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool)
208 throw Slic3r::InvalidArgument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
209
211
212
213
215
216 auto transform_wt_pt = [&alpha,
this](
const Vec2f& pt) ->
Vec2f {
219 return out;
220 };
221
222 Vec2f start_pos = tcr.start_pos;
223 Vec2f end_pos = tcr.end_pos;
224 if (! tcr.priming) {
225 start_pos = transform_wt_pt(start_pos);
226 end_pos = transform_wt_pt(end_pos);
227 }
228
230 float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
231
233
234 gcode += gcodegen.writer().unlift();
235
236 double current_z = gcodegen.writer().get_position().z();
237 if (z == -1.)
238 z = current_z;
239
240 const bool needs_toolchange = gcodegen.writer().need_toolchange(new_extruder_id);
241 const bool will_go_down = !
is_approx(z, current_z);
242 if (tcr.force_travel || ! needs_toolchange || (gcodegen.config().single_extruder_multi_material && ! tcr.priming)) {
243
244
245
246
247 gcode += gcodegen.retract();
248 gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
249 gcode += gcodegen.travel_to(
252 "Travel to a Wipe Tower");
253 gcode += gcodegen.unretract();
254 }
255
256 if (will_go_down) {
257 gcode += gcodegen.writer().retract();
258 gcode += gcodegen.writer().travel_to_z(z,
"Travel down to the last wipe tower layer.");
259 gcode += gcodegen.writer().unretract();
260 }
261
262 std::string toolchange_gcode_str;
263 std::string deretraction_str;
264 if (tcr.priming || (new_extruder_id >= 0 && needs_toolchange)) {
265 if (gcodegen.config().single_extruder_multi_material)
266 gcodegen.m_wipe.reset_path();
267 toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z);
268 if (gcodegen.config().wipe_tower)
269 deretraction_str = gcodegen.unretract();
270 }
271
272
273
274
275
276 DynamicConfig config;
277 config.set_key_value("toolchange_gcode", new ConfigOptionString(toolchange_gcode_str));
278 config.set_key_value("deretraction_from_wipe_tower_generator", new ConfigOptionString(deretraction_str));
279 std::string tcr_gcode, tcr_escaped_gcode = gcodegen.placeholder_parser_process("tcr_rotated_gcode", tcr_rotated_gcode, new_extruder_id, &config);
283
284
285 gcodegen.writer().travel_to_xy(end_pos.cast<double>());
288 gcode += gcodegen.writer().retract();
289 gcode += gcodegen.writer().travel_to_z(current_z,
"Travel back up to the topmost object layer.");
290 gcode += gcodegen.writer().unretract();
291 }
292
293 else {
294
295 gcodegen.m_wipe.reset_path();
296 for (
const Vec2f& wipe_pt : tcr.wipe_path)
298 }
299
300
301 gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
303 }
#define M_PI
Definition ExtrusionSimulator.cpp:20
std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult &tcr, const Vec2f &translation, float angle) const
Definition GCode.cpp:307
Rotation2D< float > Rotation2Df
Definition Rotation2D.h:165
static Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2f &wipe_tower_pt)
Definition GCode.cpp:200
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:271
Eigen::Matrix< float, 2, 1, Eigen::DontAlign > Vec2f
Definition Point.hpp:48
bool unescape_string_cstyle(const std::string &str, std::string &str_out)
Definition Config.cpp:107
static void check_add_eol(std::string &gcode)
Definition GCode.cpp:75
static constexpr const ExtrusionRoleModifiers Mixed
Definition ExtrusionRole.hpp:79