mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-02-01 16:38:43 +03:00
Prusa 2.7.2
This commit is contained in:
@@ -24,8 +24,9 @@
|
||||
#include "GCode/WipeTowerIntegration.hpp"
|
||||
#include "GCode/SeamPlacer.hpp"
|
||||
#include "GCode/GCodeProcessor.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
#include "GCode/ThumbnailData.hpp"
|
||||
#include "GCode/Travels.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
#include "tcbspan/span.hpp"
|
||||
|
||||
#include <memory>
|
||||
@@ -38,6 +39,7 @@ namespace Slic3r {
|
||||
|
||||
// Forward declarations.
|
||||
class GCodeGenerator;
|
||||
struct WipeTowerData;
|
||||
|
||||
namespace { struct Item; }
|
||||
struct PrintInstance;
|
||||
@@ -75,136 +77,33 @@ struct LayerResult {
|
||||
static LayerResult make_nop_layer_result() { return {"", std::numeric_limits<coord_t>::max(), false, false, true}; }
|
||||
};
|
||||
|
||||
namespace GCode::Impl {
|
||||
struct DistancedPoint {
|
||||
Point point;
|
||||
double distance_from_start;
|
||||
namespace GCode {
|
||||
// Object and support extrusions of the same PrintObject at the same print_z.
|
||||
// public, so that it could be accessed by free helper functions from GCode.cpp
|
||||
struct ObjectLayerToPrint
|
||||
{
|
||||
ObjectLayerToPrint() : object_layer(nullptr), support_layer(nullptr) {}
|
||||
const Layer* object_layer;
|
||||
const SupportLayer* support_layer;
|
||||
const Layer* layer() const { return (object_layer != nullptr) ? object_layer : support_layer; }
|
||||
const PrintObject* object() const { return (this->layer() != nullptr) ? this->layer()->object() : nullptr; }
|
||||
coordf_t print_z() const { return (object_layer != nullptr && support_layer != nullptr) ? 0.5 * (object_layer->print_z + support_layer->print_z) : this->layer()->print_z; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Takes a path described as a list of points and adds points to it.
|
||||
*
|
||||
* @param xy_path A list of points describing a path in xy.
|
||||
* @param sorted_distances A sorted list of distances along the path.
|
||||
* @return Sliced path.
|
||||
*
|
||||
* The algorithm travels along the path segments and adds points to
|
||||
* the segments in such a way that the points have specified distances
|
||||
* from the xy_path start. **Any distances over the xy_path end will
|
||||
* be simply ignored.**
|
||||
*
|
||||
* Example usage - simplified for clarity:
|
||||
* @code
|
||||
* std::vector<double> distances{0.5, 1.5};
|
||||
* std::vector<Points> xy_path{{0, 0}, {1, 0}};
|
||||
* // produces
|
||||
* {{0, 0}, {0, 0.5}, {1, 0}}
|
||||
* // notice that 1.5 is omitted
|
||||
* @endcode
|
||||
*/
|
||||
std::vector<DistancedPoint> slice_xy_path(tcb::span<const Point> xy_path, tcb::span<const double> sorted_distances);
|
||||
struct PrintObjectInstance
|
||||
{
|
||||
const PrintObject *print_object = nullptr;
|
||||
int instance_idx = -1;
|
||||
|
||||
/**
|
||||
* @brief Take xy_path and genrate a travel acording to elevation.
|
||||
*
|
||||
* @param xy_path A list of points describing a path in xy.
|
||||
* @param ensure_points_at_distances See slice_xy_path sorted_distances.
|
||||
* @param elevation A function taking current distance in mm as input and returning elevation in mm as output.
|
||||
*
|
||||
* **Be aweare** that the elevation function operates in mm, while xy_path and returned travel are in
|
||||
* scaled coordinates.
|
||||
*/
|
||||
Points3 generate_elevated_travel(
|
||||
const tcb::span<const Point> xy_path,
|
||||
const std::vector<double>& ensure_points_at_distances,
|
||||
const double initial_elevation,
|
||||
const std::function<double(double)>& elevation
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Takes a list o polygons and builds a AABBTree over all unscaled lines.
|
||||
*
|
||||
* @param polygons A list of polygons.
|
||||
* @return AABB Tree over all lines of the polygons.
|
||||
*
|
||||
* Unscales the lines in the process!
|
||||
*/
|
||||
AABBTreeLines::LinesDistancer<Linef> get_expolygons_distancer(const ExPolygons& polygons);
|
||||
|
||||
/**
|
||||
* @brief Given a AABB tree over lines find intersection with xy_path closest to the xy_path start.
|
||||
*
|
||||
* @param xy_path A path in 2D.
|
||||
* @param distancer AABB Tree over lines.
|
||||
* @return Distance to the first intersection if there is one.
|
||||
*
|
||||
* **Ignores intersection with xy_path starting point.**
|
||||
*/
|
||||
std::optional<double> get_first_crossed_line_distance(
|
||||
tcb::span<const Line> xy_path,
|
||||
const AABBTreeLines::LinesDistancer<Linef>& distancer
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Generates a regular polygon - all angles are the same (e.g. typical hexagon).
|
||||
*
|
||||
* @param centroid Central point.
|
||||
* @param start_point The polygon point are ordered. This is the first point.
|
||||
* @param points_count Amount of nodes of the polygon (e.g. 6 for haxagon).
|
||||
*
|
||||
* Distance between centroid and start point sets the scale of the polygon.
|
||||
*/
|
||||
Polygon generate_regular_polygon(
|
||||
const Point& centroid,
|
||||
const Point& start_point,
|
||||
const unsigned points_count
|
||||
);
|
||||
|
||||
class Bed {
|
||||
private:
|
||||
Polygon inner_offset;
|
||||
static Polygon get_inner_offset(const std::vector<Vec2d>& shape, const double padding);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Bed shape with inner padding.
|
||||
*/
|
||||
Bed(const std::vector<Vec2d>& shape, const double padding);
|
||||
|
||||
Vec2d centroid;
|
||||
|
||||
/**
|
||||
* Returns true if the point is within the bed shape including inner padding.
|
||||
*/
|
||||
bool contains_within_padding(const Vec2d& point) const;
|
||||
bool operator==(const PrintObjectInstance &other) const {return print_object == other.print_object && instance_idx == other.instance_idx; }
|
||||
bool operator!=(const PrintObjectInstance &other) const { return *this == other; }
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace GCode
|
||||
|
||||
class GCodeGenerator {
|
||||
public:
|
||||
GCodeGenerator() :
|
||||
m_origin(Vec2d::Zero()),
|
||||
m_enable_loop_clipping(true),
|
||||
m_enable_cooling_markers(false),
|
||||
m_enable_extrusion_role_markers(false),
|
||||
m_last_processor_extrusion_role(GCodeExtrusionRole::None),
|
||||
m_layer_count(0),
|
||||
m_layer_index(-1),
|
||||
m_layer(nullptr),
|
||||
m_object_layer_over_raft(false),
|
||||
m_volumetric_speed(0),
|
||||
m_last_pos_defined(false),
|
||||
m_last_extrusion_role(GCodeExtrusionRole::None),
|
||||
m_last_width(0.0f),
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_last_mm3_per_mm(0.0),
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_brim_done(false),
|
||||
m_second_layer_things_done(false),
|
||||
m_silent_time_estimator_enabled(false),
|
||||
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
|
||||
{}
|
||||
GCodeGenerator(const Print* print = nullptr); // The default value is only used in unit tests.
|
||||
~GCodeGenerator() = default;
|
||||
|
||||
// throws std::runtime_exception on error,
|
||||
@@ -215,13 +114,25 @@ public:
|
||||
const Vec2d& origin() const { return m_origin; }
|
||||
void set_origin(const Vec2d &pointf);
|
||||
void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); }
|
||||
const Point& last_pos() const { return m_last_pos; }
|
||||
// Convert coordinates of the active object to G-code coordinates, possibly adjusted for extruder offset.
|
||||
template<typename Derived>
|
||||
Vec2d point_to_gcode(const Eigen::MatrixBase<Derived> &point) const {
|
||||
static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "GCodeGenerator::point_to_gcode(): first parameter is not a 2D vector");
|
||||
Eigen::Matrix<double, Derived::SizeAtCompileTime, 1, Eigen::DontAlign> point_to_gcode(const Eigen::MatrixBase<Derived> &point) const {
|
||||
static_assert(
|
||||
Derived::IsVectorAtCompileTime,
|
||||
"GCodeGenerator::point_to_gcode(): first parameter is not a vector"
|
||||
);
|
||||
static_assert(
|
||||
int(Derived::SizeAtCompileTime) == 2 || int(Derived::SizeAtCompileTime) == 3,
|
||||
"GCodeGenerator::point_to_gcode(): first parameter is not a 2D or 3D vector"
|
||||
);
|
||||
|
||||
if constexpr (Derived::SizeAtCompileTime == 2) {
|
||||
return Vec2d(unscaled<double>(point.x()), unscaled<double>(point.y())) + m_origin
|
||||
- m_config.extruder_offset.get_at(m_writer.extruder()->id());
|
||||
} else {
|
||||
const Vec2d gcode_point_xy{this->point_to_gcode(point.template head<2>())};
|
||||
return to_3d(gcode_point_xy, unscaled(point.z()));
|
||||
}
|
||||
}
|
||||
// Convert coordinates of the active object to G-code coordinates, possibly adjusted for extruder offset and quantized to G-code resolution.
|
||||
template<typename Derived>
|
||||
@@ -242,8 +153,6 @@ public:
|
||||
std::string placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr);
|
||||
bool enable_cooling_markers() const { return m_enable_cooling_markers; }
|
||||
|
||||
// For Perl bindings, to be used exclusively by unit tests.
|
||||
unsigned int layer_count() const { return m_layer_count; }
|
||||
void set_layer_count(unsigned int value) { m_layer_count = value; }
|
||||
void apply_print_config(const PrintConfig &print_config);
|
||||
|
||||
@@ -252,18 +161,10 @@ public:
|
||||
// translate full config into a list of <key, value> items
|
||||
static void encode_full_config(const Print& print, std::vector<std::pair<std::string, std::string>>& config);
|
||||
|
||||
// Object and support extrusions of the same PrintObject at the same print_z.
|
||||
// public, so that it could be accessed by free helper functions from GCode.cpp
|
||||
struct ObjectLayerToPrint
|
||||
{
|
||||
ObjectLayerToPrint() : object_layer(nullptr), support_layer(nullptr) {}
|
||||
const Layer* object_layer;
|
||||
const SupportLayer* support_layer;
|
||||
const Layer* layer() const { return (object_layer != nullptr) ? object_layer : support_layer; }
|
||||
const PrintObject* object() const { return (this->layer() != nullptr) ? this->layer()->object() : nullptr; }
|
||||
coordf_t print_z() const { return (object_layer != nullptr && support_layer != nullptr) ? 0.5 * (object_layer->print_z + support_layer->print_z) : this->layer()->print_z; }
|
||||
};
|
||||
using ObjectsLayerToPrint = std::vector<ObjectLayerToPrint>;
|
||||
using ObjectLayerToPrint = GCode::ObjectLayerToPrint;
|
||||
using ObjectsLayerToPrint = std::vector<GCode::ObjectLayerToPrint>;
|
||||
|
||||
std::optional<Point> last_position;
|
||||
|
||||
private:
|
||||
class GCodeOutputStream {
|
||||
@@ -309,6 +210,8 @@ private:
|
||||
static ObjectsLayerToPrint collect_layers_to_print(const PrintObject &object);
|
||||
static std::vector<std::pair<coordf_t, ObjectsLayerToPrint>> collect_layers_to_print(const Print &print);
|
||||
|
||||
/** @brief Generates ramping travel gcode for layer change. */
|
||||
std::string get_layer_change_gcode(const Vec3d& from, const Vec3d& to, const unsigned extruder_id);
|
||||
LayerResult process_layer(
|
||||
const Print &print,
|
||||
// Set of object & print layers of the same PrintObject and with the same print_z.
|
||||
@@ -342,19 +245,12 @@ private:
|
||||
const GCode::SmoothPathCache &smooth_path_cache_global,
|
||||
GCodeOutputStream &output_stream);
|
||||
|
||||
void set_last_pos(const Point &pos) { m_last_pos = pos; m_last_pos_defined = true; }
|
||||
bool last_pos_defined() const { return m_last_pos_defined; }
|
||||
void set_extruders(const std::vector<unsigned int> &extruder_ids);
|
||||
std::string preamble();
|
||||
std::optional<std::string> get_helical_layer_change_gcode(
|
||||
const coordf_t previous_layer_z,
|
||||
const coordf_t print_z,
|
||||
const std::string& comment
|
||||
);
|
||||
std::string change_layer(
|
||||
coordf_t previous_layer_z,
|
||||
coordf_t print_z,
|
||||
const bool spiral_vase_enabled
|
||||
bool vase_mode
|
||||
);
|
||||
std::string extrude_entity(const ExtrusionEntityReference &entity, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
|
||||
std::string extrude_loop(const ExtrusionLoop &loop, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
|
||||
@@ -414,8 +310,14 @@ private:
|
||||
const bool needs_retraction,
|
||||
bool& could_be_wipe_disabled
|
||||
);
|
||||
std::string travel_to(
|
||||
const Point &start_point,
|
||||
const Point &end_point,
|
||||
ExtrusionRole role,
|
||||
const std::string &comment
|
||||
);
|
||||
|
||||
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
|
||||
std::string travel_to_first_position(const Vec3crd& point, const double from_z);
|
||||
bool needs_retraction(const Polyline &travel, ExtrusionRole role = ExtrusionRole::None);
|
||||
|
||||
//B41
|
||||
@@ -446,7 +348,7 @@ private:
|
||||
struct PlaceholderParserIntegration {
|
||||
void reset();
|
||||
void init(const GCodeWriter &config);
|
||||
void update_from_gcodewriter(const GCodeWriter &writer);
|
||||
void update_from_gcodewriter(const GCodeWriter &writer, const WipeTowerData& wipe_tower_data);
|
||||
void validate_output_vector_variables();
|
||||
|
||||
PlaceholderParser parser;
|
||||
@@ -479,6 +381,7 @@ private:
|
||||
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
|
||||
JPSPathFinder m_avoid_crossing_curled_overhangs;
|
||||
RetractWhenCrossingPerimeters m_retract_when_crossing_perimeters;
|
||||
GCode::TravelObstacleTracker m_travel_obstacle_tracker;
|
||||
bool m_enable_loop_clipping;
|
||||
// If enabled, the G-code generator will put following comments at the ends
|
||||
// of the G-code lines: _EXTRUDE_SET_SPEED, _WIPE, _BRIDGE_FAN_START, _BRIDGE_FAN_END
|
||||
@@ -498,7 +401,6 @@ private:
|
||||
// In non-sequential mode, all its copies will be printed.
|
||||
const Layer* m_layer;
|
||||
// m_layer is an object layer and it is being printed over raft surface.
|
||||
std::optional<AABBTreeLines::LinesDistancer<Linef>> m_previous_layer_distancer;
|
||||
bool m_object_layer_over_raft;
|
||||
double m_volumetric_speed;
|
||||
// Support for the extrusion role markers. Which marker is active?
|
||||
@@ -512,8 +414,12 @@ private:
|
||||
double m_last_mm3_per_mm;
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
Point m_last_pos;
|
||||
bool m_last_pos_defined;
|
||||
std::optional<Vec3d> m_previous_layer_last_position;
|
||||
std::optional<Vec3d> m_previous_layer_last_position_before_wipe;
|
||||
// This needs to be populated during the layer processing!
|
||||
std::optional<Vec3d> m_current_layer_first_position;
|
||||
std::optional<unsigned> m_layer_change_extruder_id;
|
||||
bool m_already_unretracted{false};
|
||||
|
||||
std::unique_ptr<CoolingBuffer> m_cooling_buffer;
|
||||
std::unique_ptr<SpiralVase> m_spiral_vase;
|
||||
@@ -527,19 +433,23 @@ private:
|
||||
bool m_brim_done;
|
||||
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
|
||||
bool m_second_layer_things_done;
|
||||
// Index of a last object copy extruded.
|
||||
std::pair<const PrintObject*, Point> m_last_obj_copy;
|
||||
// G-code that is due to be written before the next extrusion
|
||||
std::string m_pending_pre_extrusion_gcode;
|
||||
// Pointer to currently exporting PrintObject and instance index.
|
||||
GCode::PrintObjectInstance m_current_instance;
|
||||
|
||||
bool m_silent_time_estimator_enabled;
|
||||
|
||||
// Processor
|
||||
GCodeProcessor m_processor;
|
||||
|
||||
// Back-pointer to Print (const).
|
||||
const Print* m_print;
|
||||
std::string _extrude(
|
||||
const ExtrusionAttributes &attribs, const Geometry::ArcWelder::Path &path, const std::string_view description, double speed = -1);
|
||||
void print_machine_envelope(GCodeOutputStream &file, Print &print);
|
||||
void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||
void print_machine_envelope(GCodeOutputStream &file, const Print &print);
|
||||
void _print_first_layer_bed_temperature(GCodeOutputStream &file, const Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, const Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||
|
||||
// On the first printing layer. This flag triggers first layer speeds.
|
||||
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; }
|
||||
|
||||
Reference in New Issue
Block a user