diff options
author | FormerLurker <hochgebe@gmail.com> | 2020-12-13 00:49:33 +0300 |
---|---|---|
committer | FormerLurker <hochgebe@gmail.com> | 2020-12-13 00:49:33 +0300 |
commit | 893b8eea5e182457e90db9ddbaac8a7fb435a0c7 (patch) | |
tree | 421dd5296fcdf57f807c86a2a78ceb5143201fbe /ArcWelder | |
parent | 8cbd08c6c27bb792d28345d24ffc7a7765c35079 (diff) |
Prevent arc generation if I and J are both 0 within the current precision. Add default xyz and e precision settings, and enable/disable dynamic gcode precision.
Diffstat (limited to 'ArcWelder')
-rw-r--r-- | ArcWelder/arc_welder.cpp | 15 | ||||
-rw-r--r-- | ArcWelder/arc_welder.h | 7 | ||||
-rw-r--r-- | ArcWelder/segmented_arc.cpp | 58 | ||||
-rw-r--r-- | ArcWelder/segmented_arc.h | 4 | ||||
-rw-r--r-- | ArcWelder/segmented_shape.cpp | 50 | ||||
-rw-r--r-- | ArcWelder/segmented_shape.h | 27 |
6 files changed, 121 insertions, 40 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp index 9fe02d0..d7b6120 100644 --- a/ArcWelder/arc_welder.cpp +++ b/ArcWelder/arc_welder.cpp @@ -46,6 +46,9 @@ arc_welder::arc_welder( double mm_per_arc_segment, bool g90_g91_influences_extruder, bool allow_3d_arcs, + bool allow_dynamic_precision, + unsigned char default_xyz_precision, + unsigned char default_e_precision, int buffer_size, progress_callback callback) : current_arc_( DEFAULT_MIN_SEGMENTS, @@ -55,7 +58,9 @@ arc_welder::arc_welder( max_radius, min_arc_segments, mm_per_arc_segment, - allow_3d_arcs + allow_3d_arcs, + default_xyz_precision, + default_e_precision ), segment_statistics_( segment_statistic_lengths, @@ -77,6 +82,7 @@ arc_welder::arc_welder( target_path_ = target_path; gcode_position_args_ = get_args_(g90_g91_influences_extruder, buffer_size); allow_3d_arcs_ = allow_3d_arcs; + allow_dynamic_precision_ = allow_dynamic_precision; notification_period_seconds = 1; lines_processed_ = 0; gcodes_processed_ = 0; @@ -195,7 +201,10 @@ arc_welder_results results; << ", min_arc_segments:" << std::setprecision(0) <<current_arc_.get_min_arc_segments() << ", mm_per_arc_segment:" << std::setprecision(0) << current_arc_.get_mm_per_arc_segment() << ", g90_91_influences_extruder: " << (p_source_position_->get_g90_91_influences_extruder() ? "True" : "False") - << ", allow_3d_arcs: " << (allow_3d_arcs_ ? "True" : "False"); + << ", allow_3d_arcs: " << (allow_3d_arcs_ ? "True" : "False") + << ", allow_dynamic_precision: " << (allow_dynamic_precision_ ? "True" : "False") + << ", default_xyz_precision: " << std::setprecision(0) << (current_arc_.get_xyz_precision()) + << ", default_e_precision: " << std::setprecision(0) << (current_arc_.get_e_precision()); p_logger_->log(logger_type_, INFO, stream.str()); @@ -407,7 +416,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess // We need to make sure the printer is using absolute xyz, is extruding, and the extruder axis mode is the same as that of the previous position // TODO: Handle relative XYZ axis. This is possible, but maybe not so important. bool is_g1_g2 = cmd.command == "G0" || cmd.command == "G1"; - if (is_g1_g2) + if (allow_dynamic_precision_ && is_g1_g2) { for (std::vector<parsed_command_parameter>::iterator it = cmd.parameters.begin(); it != cmd.parameters.end(); ++it) { diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h index 0e6bb81..9e6d74a 100644 --- a/ArcWelder/arc_welder.h +++ b/ArcWelder/arc_welder.h @@ -412,6 +412,7 @@ struct arc_welder_results { }; #define DEFAULT_GCODE_BUFFER_SIZE 1000 #define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false +#define DEFAULT_ALLOW_DYNAMIC_PRECISION false class arc_welder { public: @@ -425,7 +426,10 @@ public: int min_arc_segments, double mm_per_arc_segment, bool g90_g91_influences_extruder = DEFAULT_G90_G91_INFLUENCES_EXTRUDER, - bool allow_3d_arcs = DEFAULT_allow_3d_arcs, + bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS, + bool allow_dynamic_precision = DEFAULT_ALLOW_DYNAMIC_PRECISION, + unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION, + unsigned char default_e_precision = DEFAULT_E_PRECISION, int buffer_size = DEFAULT_GCODE_BUFFER_SIZE, progress_callback callback = NULL); void set_logger_type(int logger_type); @@ -451,6 +455,7 @@ private: std::string target_path_; double resolution_mm_; gcode_position_args gcode_position_args_; + bool allow_dynamic_precision_; bool allow_3d_arcs_; long file_size_; int lines_processed_; diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp index c92809f..0618917 100644 --- a/ArcWelder/segmented_arc.cpp +++ b/ArcWelder/segmented_arc.cpp @@ -35,7 +35,8 @@ segmented_arc::segmented_arc() : segmented_shape(DEFAULT_MIN_SEGMENTS, DEFAULT_M { max_radius_mm_ = DEFAULT_MAX_RADIUS_MM; min_arc_segments_ = DEFAULT_MIN_ARC_SEGMENTS, - allow_3d_arcs_ = DEFAULT_allow_3d_arcs; + mm_per_arc_segment_ = DEFAULT_MM_PER_ARC_SEGMENT; + allow_3d_arcs_ = DEFAULT_ALLOW_3D_ARCS; num_firmware_compensations_ = 0; } @@ -47,8 +48,10 @@ segmented_arc::segmented_arc( double max_radius_mm, int min_arc_segments, double mm_per_arc_segment, - bool allow_3d_arcs -) : segmented_shape(min_segments, max_segments, resolution_mm, path_tolerance_percent) + bool allow_3d_arcs, + unsigned char default_xyz_precision, + unsigned char default_e_precision +) : segmented_shape(min_segments, max_segments, resolution_mm, path_tolerance_percent, default_xyz_precision, default_e_precision) { max_radius_mm_ = max_radius_mm; if (max_radius_mm > DEFAULT_MAX_RADIUS_MM) { @@ -210,10 +213,10 @@ bool segmented_arc::try_add_point_internal_(point p, double pd) double previous_shape_length = original_shape_length_; original_shape_length_ += pd; arc original_arc = current_arc_; - if (arc::try_create_arc(points_, current_arc_, original_shape_length_, max_radius_mm_, resolution_mm_, path_tolerance_percent_, min_arc_segments_, mm_per_arc_segment_, xyz_precision_, allow_3d_arcs_)) + if (arc::try_create_arc(points_, current_arc_, original_shape_length_, max_radius_mm_, resolution_mm_, path_tolerance_percent_, min_arc_segments_, mm_per_arc_segment_, get_xyz_precision(), allow_3d_arcs_)) { // See how many arcs will be interpolated - bool firmware_corrected = false; + bool abort_arc = false; if (min_arc_segments_ > 0 && mm_per_arc_segment_ > 0) { double circumference = 2.0 * PI_DOUBLE * current_arc_.radius; @@ -222,14 +225,24 @@ bool segmented_arc::try_add_point_internal_(point p, double pd) //num_segments = (int)std::ceil(circumference/approximate_length) * (int)std::ceil(approximate_length / mm_per_arc_segment); num_segments = (int)std::floor(circumference / original_shape_length_); if (num_segments < min_arc_segments_) { - firmware_corrected = true; - current_arc_ = original_arc; + abort_arc = true; num_firmware_compensations_++; } } } + // check for I=0 and J=0 + if (!abort_arc && utilities::is_zero(current_arc_.get_i(), get_xyz_tolerance()) && utilities::is_zero(current_arc_.get_j(), get_xyz_tolerance())) + { + abort_arc = true; + } - if (!firmware_corrected) + if (abort_arc) + { + // This arc has been cancelled either due to firmware correction, + // or because both I and J == 0 + current_arc_ = original_arc; + } + else if (!abort_arc) { if (!is_shape()) { @@ -262,8 +275,8 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons std::string gcode; - double i = current_arc_.center.x - current_arc_.start_point.x; - double j = current_arc_.center.y - current_arc_.start_point.y; + double i = current_arc_.get_i(); + double j = current_arc_.get_j(); // Here is where the performance part kicks in (these are expensive calls) that makes things a bit ugly. // there are a few cases we need to take into consideration before choosing our sprintf string // create the XYZ portion @@ -279,35 +292,40 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons } // Add X, Y, I and J gcode += " X"; - gcode += utilities::to_string(current_arc_.end_point.x, xyz_precision_, buf, false); + gcode += utilities::to_string(current_arc_.end_point.x, get_xyz_precision(), buf, false); gcode += " Y"; - gcode += utilities::to_string(current_arc_.end_point.y, xyz_precision_, buf, false); + gcode += utilities::to_string(current_arc_.end_point.y, get_xyz_precision(), buf, false); if (allow_3d_arcs_) { // We may need to add a z coordinate double z_initial = current_arc_.start_point.z; double z_final = current_arc_.end_point.z; - if (!utilities::is_equal(z_initial, z_final, std::pow(10.0, -1.0 * xyz_precision_))) + if (!utilities::is_equal(z_initial, z_final, get_xyz_tolerance())) { // The z axis has changed within the precision of the gcode coordinates gcode += " Z"; - gcode += utilities::to_string(current_arc_.end_point.z, xyz_precision_, buf, false); + gcode += utilities::to_string(current_arc_.end_point.z, get_xyz_precision(), buf, false); } } - gcode += " I"; - gcode += utilities::to_string(i, xyz_precision_, buf, false); - - gcode += " J"; - gcode += utilities::to_string(j, xyz_precision_, buf, false); + if (!utilities::is_zero(i, get_xyz_tolerance())) + { + gcode += " I"; + gcode += utilities::to_string(i, get_xyz_precision(), buf, false); + } + if (!utilities::is_zero(j, get_xyz_tolerance())) + { + gcode += " J"; + gcode += utilities::to_string(j, get_xyz_precision(), buf, false); + } // Add E if it appears if (has_e) { gcode += " E"; - gcode += utilities::to_string(e, e_precision_, buf, false); + gcode += utilities::to_string(e, get_e_precision(), buf, false); } // Add F if it appears diff --git a/ArcWelder/segmented_arc.h b/ArcWelder/segmented_arc.h index a51cbbd..36d20da 100644 --- a/ArcWelder/segmented_arc.h +++ b/ArcWelder/segmented_arc.h @@ -43,7 +43,9 @@ public: double max_radius_mm = DEFAULT_MAX_RADIUS_MM, int min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS, double mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT, - bool allow_3d_arcs = DEFAULT_allow_3d_arcs + bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS, + unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION, + unsigned char default_e_precision = DEFAULT_E_PRECISION ); virtual ~segmented_arc(); virtual bool try_add_point(point p, double e_relative); diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp index 65995b4..f505d59 100644 --- a/ArcWelder/segmented_shape.cpp +++ b/ArcWelder/segmented_shape.cpp @@ -323,6 +323,16 @@ bool circle::is_over_deviation(const array_list<point>& points, const double res #pragma region Arc Functions +double arc::get_i() const +{ + return center.x - start_point.x; +} + +double arc::get_j() const +{ + return center.y - start_point.y; +} + bool arc::try_create_arc( const circle& c, const point& start_point, @@ -477,11 +487,11 @@ bool arc::try_create_arc( #pragma endregion -segmented_shape::segmented_shape(int min_segments, int max_segments, double resolution_mm, double path_tolerance_percnet) : points_(max_segments) +segmented_shape::segmented_shape(int min_segments, int max_segments, double resolution_mm, double path_tolerance_percnet, unsigned char default_xyz_precision, unsigned char default_e_precision) : points_(max_segments) { - xyz_precision_ = DEFAULT_XYZ_PRECISION; - e_precision_ = DEFAULT_E_PRECISION; + set_xyz_precision(default_xyz_precision); + e_precision_ = default_e_precision; max_segments_ = max_segments; path_tolerance_percent_ = path_tolerance_percnet; resolution_mm_ = resolution_mm / 2.0; // divide by 2 because it is + or - 1/2 of the desired resolution. @@ -500,21 +510,47 @@ segmented_shape::~segmented_shape() } +unsigned char segmented_shape::get_xyz_precision() const +{ + return xyz_precision_; +} + +double segmented_shape::get_xyz_tolerance() const +{ + return xyz_tolerance_; +} + +unsigned char segmented_shape::get_e_precision() const +{ + return e_precision_; +} + +void segmented_shape::set_xyz_precision(unsigned char precision) +{ + xyz_precision_ = precision; + set_xyz_tolerance_from_precision(); +} + +void segmented_shape::set_xyz_tolerance_from_precision() +{ + xyz_tolerance_ = std::pow(10.0, -1.0 * static_cast<double>(xyz_precision_)); +} + void segmented_shape::reset_precision() { - xyz_precision_ = DEFAULT_XYZ_PRECISION; + set_xyz_precision(DEFAULT_XYZ_PRECISION); e_precision_ = DEFAULT_E_PRECISION; } -void segmented_shape::update_xyz_precision(int precision) +void segmented_shape::update_xyz_precision(unsigned char precision) { if (xyz_precision_ < precision) { - xyz_precision_ = precision; + set_xyz_precision(precision); } } -void segmented_shape::update_e_precision(int precision) +void segmented_shape::update_e_precision(unsigned char precision) { if (e_precision_ < precision) { diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h index eda6a7c..3b8e807 100644 --- a/ArcWelder/segmented_shape.h +++ b/ArcWelder/segmented_shape.h @@ -121,7 +121,7 @@ struct circle { }; #define DEFAULT_RESOLUTION_MM 0.05 -#define DEFAULT_allow_3d_arcs false +#define DEFAULT_ALLOW_3D_ARCS false #define DEFAULT_MIN_ARC_SEGMENTS 0 #define DEFAULT_MM_PER_ARC_SEGMENT 0 struct arc : circle @@ -153,6 +153,9 @@ struct arc : circle double max_deviation; point start_point; point end_point; + + double get_i() const; + double get_j() const; // Statis functions static bool try_create_arc( const circle& c, @@ -163,7 +166,7 @@ struct arc : circle double approximate_length, double resolution = DEFAULT_RESOLUTION_MM, double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT, - bool allow_3d_arcs = DEFAULT_allow_3d_arcs); + bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS); static bool try_create_arc( const array_list<point>& points, @@ -175,7 +178,7 @@ struct arc : circle int min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS, double mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT, int xyz_precision = DEFAULT_XYZ_PRECISION, - bool allow_3d_arcs = DEFAULT_allow_3d_arcs); + bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS); }; double distance_from_segment(segment s, point p); @@ -189,7 +192,9 @@ public: segmented_shape(int min_segments = DEFAULT_MIN_SEGMENTS, int max_segments = DEFAULT_MAX_SEGMENTS, double resolution_mm = DEFAULT_RESOLUTION_MM, - double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT + double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT, + unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION, + unsigned char default_e_precision = DEFAULT_E_PRECISION ); segmented_shape& operator=(const segmented_shape& pos); virtual ~segmented_shape(); @@ -202,8 +207,8 @@ public: double get_shape_e_relative(); void set_resolution_mm(double resolution_mm); void reset_precision(); - void update_xyz_precision(int precision); - void update_e_precision(int precision); + void update_xyz_precision(unsigned char precision); + void update_e_precision(unsigned char precision); virtual bool is_shape() const; // public virtual functions virtual void clear(); @@ -213,11 +218,12 @@ public: virtual std::string get_shape_gcode_absolute(double e_abs_start); virtual std::string get_shape_gcode_relative(); bool is_extruding(); + unsigned char get_xyz_precision() const; + unsigned char get_e_precision() const; + double get_xyz_tolerance() const; protected: array_list<point> points_; void set_is_shape(bool value); - unsigned char xyz_precision_; - unsigned char e_precision_; double original_shape_length_; double e_relative_; bool is_extruding_; @@ -227,5 +233,10 @@ protected: private: int min_segments_; int max_segments_; + unsigned char xyz_precision_; + double xyz_tolerance_; + unsigned char e_precision_; + void set_xyz_tolerance_from_precision(); + void set_xyz_precision(unsigned char precision); }; |