PrusaSlicer-NonPlainar/xs/src/libslic3r/GCode/Analyzer.hpp
2018-01-08 16:05:01 +01:00

545 lines
18 KiB
C++

#ifndef slic3r_GCode_Analyzer_hpp_
#define slic3r_GCode_Analyzer_hpp_
#include "../libslic3r.h"
#include "../PrintConfig.hpp"
#include "../ExtrusionEntity.hpp"
//############################################################################################################
#if ENRICO_GCODE_PREVIEW
#include "Point.hpp"
#include "GCodeReader.hpp"
#endif // ENRICO_GCODE_PREVIEW
//############################################################################################################
namespace Slic3r {
//############################################################################################################
#if ENRICO_GCODE_PREVIEW
class Print;
#endif // ENRICO_GCODE_PREVIEW
//############################################################################################################
//############################################################################################################
#if !ENRICO_GCODE_PREVIEW
//############################################################################################################
enum GCodeMoveType
{
GCODE_MOVE_TYPE_NOOP,
GCODE_MOVE_TYPE_RETRACT,
GCODE_MOVE_TYPE_UNRETRACT,
GCODE_MOVE_TYPE_TOOL_CHANGE,
GCODE_MOVE_TYPE_MOVE,
GCODE_MOVE_TYPE_EXTRUDE,
};
// For visualization purposes, for the purposes of the G-code analysis and timing.
// The size of this structure is 56B.
// Keep the size of this structure as small as possible, because all moves of a complete print
// may be held in RAM.
struct GCodeMove
{
bool moving_xy(const float* pos_start) const { return fabs(pos_end[0] - pos_start[0]) > 0.f || fabs(pos_end[1] - pos_start[1]) > 0.f; }
bool moving_xy() const { return moving_xy(get_pos_start()); }
bool moving_z (const float* pos_start) const { return fabs(pos_end[2] - pos_start[2]) > 0.f; }
bool moving_z () const { return moving_z(get_pos_start()); }
bool extruding(const float* pos_start) const { return moving_xy() && pos_end[3] > pos_start[3]; }
bool extruding() const { return extruding(get_pos_start()); }
bool retracting(const float* pos_start) const { return pos_end[3] < pos_start[3]; }
bool retracting() const { return retracting(get_pos_start()); }
bool deretracting(const float* pos_start) const { return ! moving_xy() && pos_end[3] > pos_start[3]; }
bool deretracting() const { return deretracting(get_pos_start()); }
float dist_xy2(const float* pos_start) const { return (pos_end[0] - pos_start[0]) * (pos_end[0] - pos_start[0]) + (pos_end[1] - pos_start[1]) * (pos_end[1] - pos_start[1]); }
float dist_xy2() const { return dist_xy2(get_pos_start()); }
float dist_xyz2(const float* pos_start) const { return (pos_end[0] - pos_start[0]) * (pos_end[0] - pos_start[0]) + (pos_end[1] - pos_start[1]) * (pos_end[1] - pos_start[1]) + (pos_end[2] - pos_start[2]) * (pos_end[2] - pos_start[2]); }
float dist_xyz2() const { return dist_xyz2(get_pos_start()); }
float dist_xy(const float* pos_start) const { return sqrt(dist_xy2(pos_start)); }
float dist_xy() const { return dist_xy(get_pos_start()); }
float dist_xyz(const float* pos_start) const { return sqrt(dist_xyz2(pos_start)); }
float dist_xyz() const { return dist_xyz(get_pos_start()); }
float dist_e(const float* pos_start) const { return fabs(pos_end[3] - pos_start[3]); }
float dist_e() const { return dist_e(get_pos_start()); }
float feedrate() const { return pos_end[4]; }
float time(const float* pos_start) const { return dist_xyz(pos_start) / feedrate(); }
float time() const { return time(get_pos_start()); }
float time_inv(const float* pos_start) const { return feedrate() / dist_xyz(pos_start); }
float time_inv() const { return time_inv(get_pos_start()); }
const float* get_pos_start() const { assert(type != GCODE_MOVE_TYPE_NOOP); return this[-1].pos_end; }
// Pack the enums to conserve space. With C++x11 the allocation size could be declared for enums, but for old C++ this is the only portable way.
// GCodeLineType
uint8_t type;
// Index of the active extruder.
uint8_t extruder_id;
// ExtrusionRole
uint8_t extrusion_role;
// For example, is it a bridge flow? Is the fan on?
uint8_t flags;
// X,Y,Z,E,F. Storing the state of the currently active extruder only.
float pos_end[5];
// Extrusion width, height for this segment in um.
uint16_t extrusion_width;
uint16_t extrusion_height;
};
typedef std::vector<GCodeMove> GCodeMoves;
struct GCodeLayer
{
// Index of an object printed.
size_t object_idx;
// Index of an object instance printed.
size_t object_instance_idx;
// Index of the layer printed.
size_t layer_idx;
// Top z coordinate of the layer printed.
float layer_z_top;
// Moves over this layer. The 0th move is always of type GCODELINETYPE_NOOP and
// it sets the initial position and tool for the layer.
GCodeMoves moves;
// Indices into m_moves, where the tool changes happen.
// This is useful, if one wants to display just only a piece of the path quickly.
std::vector<size_t> tool_changes;
};
typedef std::vector<GCodeLayer*> GCodeLayerPtrs;
class GCodeMovesDB
{
public:
GCodeMovesDB() {};
~GCodeMovesDB() { reset(); }
void reset();
GCodeLayerPtrs m_layers;
};
// Processes a G-code to extract moves and their types.
// This information is then used to render the print simulation colored by the extrusion type
// or various speeds.
// The GCodeAnalyzer is employed as a G-Code filter. It reads the G-code as it is generated,
// parses the comments generated by Slic3r just for the analyzer, and removes these comments.
class GCodeAnalyzer
{
public:
GCodeAnalyzer(const Slic3r::GCodeConfig *config);
~GCodeAnalyzer();
void reset();
// Process a next batch of G-code lines. Flush the internal buffers if asked for.
const char* process(const char *szGCode, bool flush);
// Length of the buffer returned by process().
size_t get_output_buffer_length() const { return output_buffer_length; }
private:
// Keeps the reference, does not own the config.
const Slic3r::GCodeConfig *m_config;
// Internal data.
// X,Y,Z,E,F
float m_current_pos[5];
size_t m_current_extruder;
ExtrusionRole m_current_extrusion_role;
uint16_t m_current_extrusion_width;
uint16_t m_current_extrusion_height;
bool m_retracted;
GCodeMovesDB *m_moves;
// Output buffer will only grow. It will not be reallocated over and over.
std::vector<char> output_buffer;
size_t output_buffer_length;
bool process_line(const char *line, const size_t len);
// Push the text to the end of the output_buffer.
void push_to_output(const char *text, const size_t len, bool add_eol = true);
};
//############################################################################################################
#endif // !ENRICO_GCODE_PREVIEW
//############################################################################################################
//############################################################################################################
#if ENRICO_GCODE_PREVIEW
class GCodeAnalyzer
{
public:
static const std::string Extrusion_Role_Tag;
static const std::string Mm3_Per_Mm_Tag;
static const std::string Width_Tag;
static const std::string Height_Tag;
static const double Default_mm3_per_mm;
static const float Default_Width;
static const float Default_Height;
enum EUnits : unsigned char
{
Millimeters,
Inches
};
enum EAxis : unsigned char
{
X,
Y,
Z,
E,
Num_Axis
};
enum EPositioningType : unsigned char
{
Absolute,
Relative
};
struct Metadata
{
ExtrusionRole extrusion_role;
unsigned int extruder_id;
double mm3_per_mm;
float width;
float height;
float feedrate;
Metadata();
Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate);
bool operator != (const Metadata& other) const;
};
struct GCodeMove
{
enum EType : unsigned char
{
Noop,
Retract,
Unretract,
Tool_change,
Move,
Extrude,
Num_Types
};
EType type;
Metadata data;
Pointf3 start_position;
Pointf3 end_position;
float delta_extruder;
GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder);
GCodeMove(EType type, const Metadata& data, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder);
};
typedef std::vector<GCodeMove> GCodeMovesList;
typedef std::map<GCodeMove::EType, GCodeMovesList> TypeToMovesMap;
private:
struct State
{
EUnits units;
EPositioningType positioning_xyz_type;
EPositioningType positioning_e_type;
Metadata data;
Pointf3 start_position;
float start_extrusion;
float position[Num_Axis];
};
public:
struct PreviewData
{
struct Color
{
float rgba[4];
Color();
Color(float r, float g, float b, float a);
static const Color Dummy;
};
struct Range
{
static const unsigned int Colors_Count = 10;
static const Color Default_Colors[Colors_Count];
Color colors[Colors_Count];
float min;
float max;
Range();
void reset();
bool empty() const;
void update_from(float value);
void set_from(const Range& other);
const Color& get_color_at(float value) const;
const Color& get_color_at_max() const;
private:
float _step() const;
};
struct Extrusion
{
enum EViewType : unsigned char
{
FeatureType,
Height,
Width,
Feedrate,
Num_View_Types
};
static const unsigned int Num_Extrusion_Roles = (unsigned int)erMixed + 1;
static const Color Default_Extrusion_Role_Colors[Num_Extrusion_Roles];
static const EViewType Default_View_Type;
struct Ranges
{
Range height;
Range width;
Range feedrate;
};
struct Layer
{
float z;
ExtrusionPaths paths;
Layer(float z, const ExtrusionPaths& paths);
};
typedef std::vector<Layer> LayersList;
EViewType view_type;
Color role_colors[Num_Extrusion_Roles];
Ranges ranges;
LayersList layers;
unsigned int role_flags;
void set_default();
bool is_role_flag_set(ExtrusionRole role) const;
};
struct Travel
{
enum EType : unsigned char
{
Move,
Extrude,
Retract,
Num_Types
};
static const float Default_Width;
static const float Default_Height;
static const Color Default_Type_Colors[Num_Types];
struct Polyline
{
enum EDirection
{
Vertical,
Generic,
Num_Directions
};
EType type;
EDirection direction;
Polyline3 polyline;
Polyline(EType type, EDirection direction, const Polyline3& polyline);
};
typedef std::vector<Polyline> PolylinesList;
PolylinesList polylines;
float width;
float height;
Color type_colors[Num_Types];
bool is_visible;
void set_default();
};
struct Retraction
{
static const Color Default_Color;
struct Position
{
Point3 position;
float width;
float height;
Position(const Point3& position, float width, float height);
};
typedef std::vector<Position> PositionsList;
PositionsList positions;
Color color;
bool is_visible;
void set_default();
};
Extrusion extrusion;
Travel travel;
Retraction retraction;
Retraction unretraction;
PreviewData();
void set_default();
void reset();
const Color& get_extrusion_role_color(ExtrusionRole role) const;
const Color& get_extrusion_height_color(float height) const;
const Color& get_extrusion_width_color(float width) const;
const Color& get_extrusion_feedrate_color(float feedrate) const;
};
private:
State m_state;
GCodeReader m_parser;
TypeToMovesMap m_moves_map;
// The output of process_layer()
std::string m_process_output;
public:
GCodeAnalyzer();
// Reinitialize the analyzer
void reset();
// Adds the gcode contained in the given string to the analysis and returns it after removing the workcodes
const std::string& process_gcode(const std::string& gcode);
// Calculates all data needed for gcode visualization
void calc_gcode_preview_data(Print& print);
private:
// Processes the given gcode line
void _process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line);
// Move
void _processG1(const GCodeReader::GCodeLine& line);
// Firmware controlled Retract
void _processG22(const GCodeReader::GCodeLine& line);
// Firmware controlled Unretract
void _processG23(const GCodeReader::GCodeLine& line);
// Set to Absolute Positioning
void _processG90(const GCodeReader::GCodeLine& line);
// Set to Relative Positioning
void _processG91(const GCodeReader::GCodeLine& line);
// Set Position
void _processG92(const GCodeReader::GCodeLine& line);
// Set extruder to absolute mode
void _processM82(const GCodeReader::GCodeLine& line);
// Set extruder to relative mode
void _processM83(const GCodeReader::GCodeLine& line);
// Processes T line (Select Tool)
void _processT(const GCodeReader::GCodeLine& line);
// Processes the tags
// Returns true if any tag has been processed
bool _process_tags(const GCodeReader::GCodeLine& line);
// Processes extrusion role tag
void _process_extrusion_role_tag(const std::string& comment, size_t pos);
// Processes mm3_per_mm tag
void _process_mm3_per_mm_tag(const std::string& comment, size_t pos);
// Processes width tag
void _process_width_tag(const std::string& comment, size_t pos);
// Processes height tag
void _process_height_tag(const std::string& comment, size_t pos);
void _set_units(EUnits units);
EUnits _get_units() const;
void _set_positioning_xyz_type(EPositioningType type);
EPositioningType _get_positioning_xyz_type() const;
void _set_positioning_e_type(EPositioningType type);
EPositioningType _get_positioning_e_type() const;
void _set_extrusion_role(ExtrusionRole extrusion_role);
ExtrusionRole _get_extrusion_role() const;
void _set_extruder_id(unsigned int id);
unsigned int _get_extruder_id() const;
void _set_mm3_per_mm(double value);
double _get_mm3_per_mm() const;
void _set_width(float width);
float _get_width() const;
void _set_height(float height);
float _get_height() const;
void _set_feedrate(float feedrate_mm_sec);
float _get_feedrate() const;
void _set_axis_position(EAxis axis, float position);
float _get_axis_position(EAxis axis) const;
// Sets axes position to zero
void _reset_axes_position();
void _set_start_position(const Pointf3& position);
const Pointf3& _get_start_position() const;
void _set_start_extrusion(float extrusion);
float _get_start_extrusion() const;
float _get_delta_extrusion() const;
// Returns current xyz position (from m_state.position[])
Pointf3 _get_end_position() const;
// Adds a new move with the given data
void _store_move(GCodeMove::EType type);
// Checks if the given int is a valid extrusion role (contained into enum ExtrusionRole)
bool _is_valid_extrusion_role(int value) const;
void _calc_gcode_preview_extrusion_layers(Print& print);
void _calc_gcode_preview_travel(Print& print);
void _calc_gcode_preview_retractions(Print& print);
void _calc_gcode_preview_unretractions(Print& print);
};
GCodeAnalyzer::PreviewData::Color operator + (const GCodeAnalyzer::PreviewData::Color& c1, const GCodeAnalyzer::PreviewData::Color& c2);
GCodeAnalyzer::PreviewData::Color operator * (float f, const GCodeAnalyzer::PreviewData::Color& color);
#endif // ENRICO_GCODE_PREVIEW
//############################################################################################################
} // namespace Slic3r
#endif /* slic3r_GCode_Analyzer_hpp_ */