diff options
author | FormerLurker <hochgebe@gmail.com> | 2021-07-02 22:24:47 +0300 |
---|---|---|
committer | FormerLurker <hochgebe@gmail.com> | 2021-07-02 22:24:47 +0300 |
commit | 18d1e992d3773485d2b7b05ffaec1ea00b16c777 (patch) | |
tree | 42983ee7c351d32d38afb437642ed9f9e861a024 | |
parent | 65768d59a9ed785ddb740fc6df67d2912d2a5bdf (diff) |
Add support for variable line widths.
28 files changed, 422 insertions, 195 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp index a1f4ca7..95fbcda 100644 --- a/ArcWelder/arc_welder.cpp +++ b/ArcWelder/arc_welder.cpp @@ -34,6 +34,7 @@ #include <fstream> #include <iomanip> #include <sstream> +#include <version.h> arc_welder::arc_welder( std::string source_path, @@ -53,7 +54,7 @@ arc_welder::arc_welder( int buffer_size, progress_callback callback) : current_arc_( DEFAULT_MIN_SEGMENTS, - buffer_size - 5, + buffer_size, resolution_mm, path_tolerance_percent, max_radius, @@ -92,6 +93,7 @@ arc_welder::arc_welder( last_gcode_line_written_ = 0; points_compressed_ = 0; arcs_created_ = 0; + arcs_aborted_by_flow_rate_ = 0; waiting_for_arc_ = false; previous_feedrate_ = -1; gcode_position_args_.set_num_extruders(8); @@ -114,6 +116,10 @@ gcode_position_args arc_welder::get_args_(bool g90_g91_influences_extruder, int gcode_position_args args; // Configure gcode_position_args args.g90_influences_extruder = g90_g91_influences_extruder; + if (buffer_size < 2) + { + buffer_size = 2; + } args.position_buffer_size = buffer_size; args.autodetect_position = true; args.home_x = 0; @@ -258,7 +264,8 @@ arc_welder_results results; p_logger_->log(logger_type_, DEBUG, "Sending initial progress update."); continue_processing = on_progress_(get_progress_(static_cast<long>(gcodeFile.tellg()), static_cast<double>(start_clock))); p_logger_->log(logger_type_, DEBUG, "Processing source file."); - + + bool arc_Welder_comment_added = false; while (std::getline(gcodeFile, line) && continue_processing) { lines_processed_++; @@ -267,17 +274,20 @@ arc_welder_results results; if (lines_processed_ == 1) { bool isUltiGCode = line == ";FLAVOR:UltiGCode"; - if (isUltiGCode) + bool isPrusaSlicer = line.rfind("; generated by PrusaSlicer", 0) == 0; + if (isUltiGCode || isPrusaSlicer) { write_gcode_to_file(line); } add_arcwelder_comment_to_target(); - if (isUltiGCode) + if (isUltiGCode || isPrusaSlicer) { lines_with_no_commands++; continue; } } + + cmd.clear(); if (verbose_logging_enabled_) { @@ -368,6 +378,7 @@ arc_welder_progress arc_welder::get_progress_(long source_file_position, double progress.lines_processed = lines_processed_; progress.points_compressed = points_compressed_; progress.arcs_created = arcs_created_; + progress.arcs_aborted_by_flow_rate = arcs_aborted_by_flow_rate_; progress.source_file_position = source_file_position; progress.target_file_size = static_cast<long>(output_file_.tellp()); progress.source_file_size = file_size_; @@ -432,6 +443,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess // calculate the extrusion rate (mm/mm) and see how much it changes double mm_extruded_per_mm_travel = 0; double extrusion_rate_change_percent = 0; + bool aborted_by_flow_rate = false; if (movement_length_mm > 0) { mm_extruded_per_mm_travel = extruder_current.e_relative / movement_length_mm; @@ -440,9 +452,10 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess extrusion_rate_change_percent = std::fabs(utilities::get_percent_change(previous_extrusion_rate_, mm_extruded_per_mm_travel)); } } - if (extrusion_rate_change_percent > extrusion_rate_variance_percent_) + if (previous_extrusion_rate_ != 0 && utilities::greater_than(extrusion_rate_change_percent, extrusion_rate_variance_percent_)) { - std::cout << "Extrusion Rate Change Percent: " << extrusion_rate_change_percent << "\n"; + arcs_aborted_by_flow_rate_++; + aborted_by_flow_rate = true; } // 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 @@ -483,6 +496,8 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess ( !waiting_for_arc_ || extruder_current.is_extruding || + // Test for travel conversion + //(previous_extruder.is_extruding && extruder_current.is_extruding) || // Test to see if // we can get more arcs. (previous_extruder.is_retracting && extruder_current.is_retracting) @@ -493,6 +508,8 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess ) ) { + // Record the extrusion rate + previous_extrusion_rate_ = mm_extruded_per_mm_travel; printer_point p(p_cur_pos->get_gcode_x(), p_cur_pos->get_gcode_y(), p_cur_pos->get_gcode_z(), extruder_current.e_relative, movement_length_mm); if (!waiting_for_arc_) { @@ -514,6 +531,11 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess arc_added = current_arc_.try_add_point(p); if (arc_added) { + // Make sure our position list is large enough to handle all the segments + if (current_arc_.get_num_segments()+2 > p_source_position_->get_max_positions()) + { + p_source_position_->grow_max_positions(p_source_position_->get_max_positions()*2); + } if (!waiting_for_arc_) { waiting_for_arc_ = true; @@ -533,7 +555,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess } } else { - previous_extrusion_rate_ = 0; + if (debug_logging_enabled_) { if (is_end) { @@ -606,9 +628,12 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess { p_logger_->log(logger_type_, DEBUG, "Feature type changed, cannot add point to current arc: " + cmd.gcode); } - else if (previous_extrusion_rate_ != 0 && !utilities::is_equal(previous_extrusion_rate_, mm_extruded_per_mm_travel)) + else if (aborted_by_flow_rate) { - p_logger_->log(logger_type_, DEBUG, "Previus extrusion rate changed: " + cmd.gcode); + std::stringstream stream; + stream << std::fixed << std::setprecision(5); + stream << "Arc Canceled - The extrusion rate variance of " << extrusion_rate_variance_percent_ << "% exceeded by " << extrusion_rate_change_percent - extrusion_rate_variance_percent_ <<"% on line " << lines_processed_ << ". Extruded " << extruder_current.e_relative << "mm over " << movement_length_mm << "mm of travel (" << mm_extruded_per_mm_travel << "mm/mm). Previous rate: " << previous_extrusion_rate_ << "mm/mm."; + p_logger_->log(logger_type_, DEBUG, stream.str()); } else { @@ -617,9 +642,12 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess } } } + + // Reset the previous extrusion rate + previous_extrusion_rate_ = 0; } - previous_extrusion_rate_ = mm_extruded_per_mm_travel; + if (!arc_added && !(cmd.is_empty && cmd.comment.length() == 0)) { @@ -844,6 +872,7 @@ void arc_welder::add_arcwelder_comment_to_target() stream << std::fixed; stream << "; Postprocessed by [ArcWelder](https://github.com/FormerLurker/ArcWelderLib)\n"; stream << "; Copyright(C) 2020 - Brad Hochgesang\n"; + stream << "; Version: " << GIT_TAGGED_VERSION << ", Branch: " << GIT_BRANCH << ", BuildDate: " << BUILD_DATE << "\n"; stream << "; resolution=" << std::setprecision(2) << resolution_mm_ << "mm\n"; stream << "; path_tolerance=" << std::setprecision(0) << (current_arc_.get_path_tolerance_percent() * 100.0) << "%\n"; stream << "; max_radius=" << std::setprecision(2) << (current_arc_.get_max_radius()) << "mm\n"; diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h index 2da8929..a4fdded 100644 --- a/ArcWelder/arc_welder.h +++ b/ArcWelder/arc_welder.h @@ -354,6 +354,7 @@ struct arc_welder_progress { lines_processed = 0; points_compressed = 0; arcs_created = 0; + arcs_aborted_by_flow_rate = 0; num_firmware_compensations = 0; source_file_size = 0; source_file_position = 0; @@ -368,6 +369,7 @@ struct arc_welder_progress { int lines_processed; int points_compressed; int arcs_created; + int arcs_aborted_by_flow_rate; int num_firmware_compensations; double compression_ratio; double compression_percent; @@ -385,6 +387,7 @@ struct arc_welder_progress { stream << ", current_file_line: " << lines_processed; stream << ", points_compressed: " << points_compressed; stream << ", arcs_created: " << arcs_created; + stream << ", arcs_aborted_by_flowrate: " << arcs_aborted_by_flow_rate; stream << ", num_firmware_compensations: " << num_firmware_compensations; stream << ", compression_ratio: " << compression_ratio; stream << ", size_reduction: " << compression_percent << "% "; @@ -412,11 +415,10 @@ struct arc_welder_results { std::string message; arc_welder_progress progress; }; -#define DEFAULT_GCODE_BUFFER_SIZE 1000 +#define DEFAULT_GCODE_BUFFER_SIZE 10 #define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false #define DEFAULT_ALLOW_DYNAMIC_PRECISION false -#define DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT 1 -//#define DEFAULT_EXTRUSION_RATE_VARIANCE 0.0001 +#define DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT 5 class arc_welder { public: @@ -469,6 +471,7 @@ private: int last_gcode_line_written_; int points_compressed_; int arcs_created_; + int arcs_aborted_by_flow_rate_; source_target_segment_statistics segment_statistics_; long get_file_size(const std::string& file_path); double get_time_elapsed(double start_clock, double end_clock); diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp index 4da8f8e..62593d7 100644 --- a/ArcWelder/segmented_arc.cpp +++ b/ArcWelder/segmented_arc.cpp @@ -127,11 +127,12 @@ bool segmented_arc::try_add_point(printer_point p) bool point_added = false; // if we don't have enough segnemts to check the shape, just add - if (points_.count() > get_max_segments() - 1) + + if (points_.count() == points_.get_max_size()) { // Too many points, we can't add more - return false; - } + points_.resize(points_.get_max_size()*2); + } if (points_.count() > 0) { printer_point p1 = points_[points_.count() - 1]; @@ -193,9 +194,6 @@ bool segmented_arc::try_add_point_internal_(printer_point p) if (points_.count() < get_min_segments() - 1) return false; - // Create a test circle - circle target_circle; - // the circle is new.. we have to test it now, which is expensive :( points_.push_back(p); double previous_shape_length = original_shape_length_; diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp index 42aadcb..ec0611e 100644 --- a/ArcWelder/segmented_shape.cpp +++ b/ArcWelder/segmented_shape.cpp @@ -86,6 +86,11 @@ bool point::is_near_collinear(const point& p1, const point& p2, const point& p3, return fabs((p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x)) <= 1e-9; } +double point::cartesian_distance(const point& p1, const point& p2) +{ + return utilities::get_cartesian_distance(p1.x, p1.y, p2.x, p2.y); +} + #pragma endregion Point Functions #pragma region Segment Functions @@ -148,15 +153,12 @@ double vector::cross_product_magnitude(vector v1, vector v2) #pragma region Circle Functions - bool circle::try_create_circle(const point& p1, const point& p2, const point& p3, const double max_radius, circle& new_circle) { if (point::is_near_collinear(p1,p2,p3, 0.001)) { return false; } - - double x1 = p1.x; double y1 = p1.y; double x2 = p2.x; @@ -196,22 +198,40 @@ bool circle::try_create_circle(const point& p1, const point& p2, const point& p3 bool circle::try_create_circle(const array_list<printer_point>& points, const double max_radius, const double resolution_mm, const double xyz_tolerance, bool allow_3d_arcs, circle& new_circle) { int count = points.count(); - int middle_index = count / 2; + int end_index = count - 1; + - // The middle point will almost always produce the best arcs. - if (circle::try_create_circle(points[0], points[middle_index], points[count - 1], max_radius, new_circle) && !new_circle.is_over_deviation(points, resolution_mm, xyz_tolerance, allow_3d_arcs)) + + if (circle::try_create_circle(points[0], points[middle_index], points[end_index], max_radius, new_circle) && !new_circle.is_over_deviation(points, resolution_mm, xyz_tolerance, allow_3d_arcs)) { return true; } - + + /* + // This could be a near complete circle. In that case, the endpoints might be too close together to generate an accurate circle with the + // precision we have to work with. Let's adjust our circle into thirds and test those points as a last ditch effort. + if (count > 5) + { + middle_index = count / 3; + end_index = middle_index + middle_index; + if (circle::try_create_circle(points[0], points[middle_index], points[end_index], max_radius, test_circle) && !test_circle.is_over_deviation(points, resolution_mm, xyz_tolerance, allow_3d_arcs)) + { + new_circle = test_circle; + return true; + } + } + return false; + */ + // Find the circle with the least deviation, if one exists. // Note, this could possibly take a LONG time in the worst case, but it's a pretty unlikely. // However, if the midpoint check doesn't pass, it's worth it to spend a bit more time // finding the best fit for the circle (least squares deviation) - circle test_circle; + double least_deviation; bool found_circle=false; + for (int index = 1; index < count - 1; index++) { @@ -220,7 +240,7 @@ bool circle::try_create_circle(const array_list<printer_point>& points, const do // We already checked this one, and it failed, continue. continue; } - + circle test_circle; double current_deviation; if (circle::try_create_circle(points[0], points[index], points[count - 1], max_radius, test_circle) && test_circle.get_deviation_sum_squared(points, resolution_mm, xyz_tolerance, allow_3d_arcs, current_deviation)) { @@ -234,6 +254,7 @@ bool circle::try_create_circle(const array_list<printer_point>& points, const do } } return found_circle; + } double circle::get_polar_radians(const point& p1) const @@ -332,6 +353,7 @@ bool circle::is_over_deviation(const array_list<printer_point>& points, const do } // Check the point perpendicular from the segment to the circle's center, if any such point exists + if (segment::get_closest_perpendicular_point(current_point, points[index + 1], center, point_to_test)) { double distance = utilities::get_cartesian_distance(point_to_test.x, point_to_test.y, center.x, center.y); diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h index 8b014bc..ec4bde9 100644 --- a/ArcWelder/segmented_shape.h +++ b/ArcWelder/segmented_shape.h @@ -47,6 +47,7 @@ public: double z; static point get_midpoint(point p1, point p2); static bool is_near_collinear(const point& p1, const point& p2, const point& p3, double percent_tolerance); + static double cartesian_distance(const point& p1, const point& p2); }; struct printer_point : point @@ -99,7 +100,7 @@ struct vector : point }; -#define DEFAULT_MAX_RADIUS_MM 1000000.0 // 1km +#define DEFAULT_MAX_RADIUS_MM 10000.0 // 10m struct circle { circle() { center.x = 0; diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp index ea333b3..ca64ff3 100644 --- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp +++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp @@ -26,7 +26,7 @@ #define _CRT_SECURE_NO_DEPRECATE #endif -#include "inverse_processor.h" +#include "marlin_2_arc.h" #include "ArcWelderInverseProcessor.h" #include <cstring> #include <iostream> @@ -233,7 +233,7 @@ int main(int argc, char* argv[]) target_file_path = temp_file_path; } - inverse_processor processor(source_file_path, target_file_path, g90_g91_influences_extruder, 50, cs); + marlin_2_arc processor(source_file_path, target_file_path, g90_g91_influences_extruder, 50, cs); processor.process(); // Todo: get some results! if (true) diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj index 37ec7d0..f67571c 100644 --- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj +++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj @@ -202,11 +202,15 @@ </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="ArcWelderInverseProcessor.h" /> - <ClInclude Include="inverse_processor.h" /> + <ClInclude Include="firmware_types.h" /> + <ClInclude Include="marlin_2_arc.h" /> + <ClInclude Include="repiter_arc.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="ArcWelderInverseProcessor.cpp" /> - <ClCompile Include="inverse_processor.cpp" /> + <ClCompile Include="firmware_types.cpp" /> + <ClCompile Include="marlin_2_arc.cpp" /> + <ClCompile Include="repiter_arc.cpp" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\ArcWelder\ArcWelder.vcxproj"> diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters index fe669d6..bc338f9 100644 --- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters +++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters @@ -18,7 +18,13 @@ <ClInclude Include="ArcWelderInverseProcessor.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="inverse_processor.h"> + <ClInclude Include="repiter_arc.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="marlin_2_arc.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="firmware_types.h"> <Filter>Header Files</Filter> </ClInclude> </ItemGroup> @@ -26,7 +32,13 @@ <ClCompile Include="ArcWelderInverseProcessor.cpp"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="inverse_processor.cpp"> + <ClCompile Include="repiter_arc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="marlin_2_arc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="firmware_types.cpp"> <Filter>Source Files</Filter> </ClCompile> </ItemGroup> diff --git a/ArcWelderInverseProcessor/firmware_types.cpp b/ArcWelderInverseProcessor/firmware_types.cpp new file mode 100644 index 0000000..61820cf --- /dev/null +++ b/ArcWelderInverseProcessor/firmware_types.cpp @@ -0,0 +1 @@ +#include "firmware_types.h" diff --git a/ArcWelderInverseProcessor/firmware_types.h b/ArcWelderInverseProcessor/firmware_types.h new file mode 100644 index 0000000..b3507ad --- /dev/null +++ b/ArcWelderInverseProcessor/firmware_types.h @@ -0,0 +1,4 @@ +#pragma once +enum firmware_types { Marlin2, Repiter }; + + diff --git a/ArcWelderInverseProcessor/inverse_processor.cpp b/ArcWelderInverseProcessor/marlin_2_arc.cpp index c6edb6f..b7b3246 100644 --- a/ArcWelderInverseProcessor/inverse_processor.cpp +++ b/ArcWelderInverseProcessor/marlin_2_arc.cpp @@ -47,14 +47,14 @@ along with Grbl. If not, see <http://www.gnu.org/licenses/>. */ -#include "inverse_processor.h" +#include "marlin_2_arc.h" #include <cmath> //#include "Marlin.h" //#include "stepper.h" //#include "planner.h" -inverse_processor::inverse_processor(std::string source_path, std::string target_path, bool g90_g91_influences_extruder, int buffer_size, ConfigurationStore cs) +marlin_2_arc::marlin_2_arc(std::string source_path, std::string target_path, bool g90_g91_influences_extruder, int buffer_size, ConfigurationStore cs) { source_path_ = source_path; target_path_ = target_path; @@ -79,7 +79,7 @@ inverse_processor::inverse_processor(std::string source_path, std::string target */ } -gcode_position_args inverse_processor::get_args_(bool g90_g91_influences_extruder, int buffer_size) +gcode_position_args marlin_2_arc::get_args_(bool g90_g91_influences_extruder, int buffer_size) { gcode_position_args args; // Configure gcode_position_args @@ -112,12 +112,12 @@ gcode_position_args inverse_processor::get_args_(bool g90_g91_influences_extrude return args; } -inverse_processor::~inverse_processor() +marlin_2_arc::~marlin_2_arc() { delete p_source_position_; } -void inverse_processor::process() +void marlin_2_arc::process() { // Create a stringstream we can use for messaging. std::stringstream stream; @@ -239,7 +239,7 @@ void inverse_processor::process() // The arc is approximated by generating a huge number of tiny, linear segments. The length of each // segment is configured in settings.mm_per_arc_segment. -void inverse_processor::mc_arc(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder) +void marlin_2_arc::mc_arc(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder) { // Extract the position to reduce indexing at the cost of a few bytes of mem float p_x = position[X_AXIS]; @@ -363,7 +363,7 @@ void inverse_processor::mc_arc(float* position, float* target, float* offset, fl int8_t count = 0; for (i = 1; i < segments; i++) { // Increment (segments-1) - if (count < cs_.n_arc_correction) { + if (count < cs_.n_arc_correction /*&& theta_per_segment > 0.001 */) { // Apply vector rotation matrix r_axisi = r_axis_x * sin_T + r_axis_y * cos_T; r_axis_x = r_axis_x * cos_T - r_axis_y * sin_T; @@ -404,13 +404,13 @@ void inverse_processor::mc_arc(float* position, float* target, float* offset, fl position[E_AXIS] = t_e; } -void inverse_processor::clamp_to_software_endstops(float* target) +void marlin_2_arc::clamp_to_software_endstops(float* target) { // Do nothing, just added to keep mc_arc identical to the firmware version return; } -void inverse_processor::plan_buffer_line(float x, float y, bool has_z, float z, const float& e, float feed_rate, uint8_t extruder, const float* gcode_target) +void marlin_2_arc::plan_buffer_line(float x, float y, bool has_z, float z, const float& e, float feed_rate, uint8_t extruder, const float* gcode_target) { std::stringstream stream; stream << std::fixed; diff --git a/ArcWelderInverseProcessor/inverse_processor.h b/ArcWelderInverseProcessor/marlin_2_arc.h index ab33133..a7a2ac3 100644 --- a/ArcWelderInverseProcessor/inverse_processor.h +++ b/ArcWelderInverseProcessor/marlin_2_arc.h @@ -62,10 +62,10 @@ struct ConfigurationStore { int n_arc_correction; }; -class inverse_processor { +class marlin_2_arc { public: - inverse_processor(std::string source_path, std::string target_path, bool g90_g91_influences_extruder, int buffer_size, ConfigurationStore cs = ConfigurationStore()); - virtual ~inverse_processor(); + marlin_2_arc(std::string source_path, std::string target_path, bool g90_g91_influences_extruder, int buffer_size, ConfigurationStore cs = ConfigurationStore()); + virtual ~marlin_2_arc(); void process(); void mc_arc(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder); diff --git a/ArcWelderInverseProcessor/repiter_arc.cpp b/ArcWelderInverseProcessor/repiter_arc.cpp new file mode 100644 index 0000000..83818a0 --- /dev/null +++ b/ArcWelderInverseProcessor/repiter_arc.cpp @@ -0,0 +1,97 @@ +#include "repiter_arc.h" + + +/* +// Arc function taken from grbl +// The arc is approximated by generating a huge number of tiny, linear segments. The length of each +// segment is configured in settings.mm_per_arc_segment. +void repiter_arc::arc(float* position, float* target, float* offset, float radius, uint8_t isclockwise) { + // int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled(); + // plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc + float center_axis0 = position[X_AXIS] + offset[X_AXIS]; + float center_axis1 = position[Y_AXIS] + offset[Y_AXIS]; + //float linear_travel = 0; //target[axis_linear] - position[axis_linear]; + float extruder_travel = (Printer::destinationSteps[E_AXIS] - Printer::currentPositionSteps[E_AXIS]) * Printer::invAxisStepsPerMM[E_AXIS]; + float r_axis0 = -offset[0]; // Radius vector from center to current location + float r_axis1 = -offset[1]; + float rt_axis0 = target[0] - center_axis0; + float rt_axis1 = target[1] - center_axis1; + // CCW angle between position and target from circle center. Only one atan2() trig computation required. + float angular_travel = atan2(r_axis0 * rt_axis1 - r_axis1 * rt_axis0, r_axis0 * rt_axis0 + r_axis1 * rt_axis1); + if ((!isclockwise && angular_travel <= 0.00001) || (isclockwise && angular_travel < -0.000001)) { + angular_travel += 2.0f * M_PI; + } + if (isclockwise) { + angular_travel -= 2.0f * M_PI; + } + + float millimeters_of_travel = fabs(angular_travel) * radius; //hypot(angular_travel*radius, fabs(linear_travel)); + if (millimeters_of_travel < 0.001f) { + return; // treat as succes because there is nothing to do; + } + //uint16_t segments = (radius>=BIG_ARC_RADIUS ? floor(millimeters_of_travel/MM_PER_ARC_SEGMENT_BIG) : floor(millimeters_of_travel/MM_PER_ARC_SEGMENT)); + // Increase segment size if printing faster then computation speed allows + uint16_t segments = (Printer::feedrate > 60.0f ? floor(millimeters_of_travel / RMath::min(static_cast<float>(MM_PER_ARC_SEGMENT_BIG), Printer::feedrate * 0.01666f * static_cast<float>(MM_PER_ARC_SEGMENT))) : floor(millimeters_of_travel / static_cast<float>(MM_PER_ARC_SEGMENT))); + if (segments == 0) + segments = 1; + + float theta_per_segment = angular_travel / segments; + //float linear_per_segment = linear_travel/segments; + float extruder_per_segment = extruder_travel / segments; + + + // Vector rotation matrix values + float cos_T = 1 - 0.5 * theta_per_segment * theta_per_segment; // Small angle approximation + float sin_T = theta_per_segment; + + float arc_target[4]; + float sin_Ti; + float cos_Ti; + float r_axisi; + uint16_t i; + int8_t count = 0; + + // Initialize the linear axis + //arc_target[axis_linear] = position[axis_linear]; + + // Initialize the extruder axis + arc_target[E_AXIS] = Printer::currentPositionSteps[E_AXIS] * Printer::invAxisStepsPerMM[E_AXIS]; + + for (i = 1; i < segments; i++) { + // Increment (segments-1) + + if ((count & 3) == 0) { + //GCode::readFromSerial(); + Commands::checkForPeriodicalActions(false); + UI_MEDIUM; // do check encoder + } + + if (count < N_ARC_CORRECTION) { //25 pieces + // Apply vector rotation matrix + r_axisi = r_axis0 * sin_T + r_axis1 * cos_T; + r_axis0 = r_axis0 * cos_T - r_axis1 * sin_T; + r_axis1 = r_axisi; + count++; + } + else { + // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. + // Compute exact location by applying transformation matrix from initial radius vector(=-offset). + cos_Ti = cos(i * theta_per_segment); + sin_Ti = sin(i * theta_per_segment); + r_axis0 = -offset[0] * cos_Ti + offset[1] * sin_Ti; + r_axis1 = -offset[0] * sin_Ti - offset[1] * cos_Ti; + count = 0; + } + + // Update arc_target location + arc_target[X_AXIS] = center_axis0 + r_axis0; + arc_target[Y_AXIS] = center_axis1 + r_axis1; + //arc_target[axis_linear] += linear_per_segment; + arc_target[E_AXIS] += extruder_per_segment; + Printer::moveToReal(arc_target[X_AXIS], arc_target[Y_AXIS], IGNORE_COORDINATE, arc_target[E_AXIS], IGNORE_COORDINATE); + } + // Ensure last segment arrives at target location. + Printer::moveToReal(target[X_AXIS], target[Y_AXIS], IGNORE_COORDINATE, target[E_AXIS], IGNORE_COORDINATE); +} + +*/
\ No newline at end of file diff --git a/ArcWelderInverseProcessor/repiter_arc.h b/ArcWelderInverseProcessor/repiter_arc.h new file mode 100644 index 0000000..353c040 --- /dev/null +++ b/ArcWelderInverseProcessor/repiter_arc.h @@ -0,0 +1,7 @@ +#pragma once +#include <cstdint> +class repiter_arc +{ + void arc(float* position, float* target, float* offset, float radius, uint8_t isclockwise); +}; + diff --git a/ArcWelderTest/ArcWelderTest.cpp b/ArcWelderTest/ArcWelderTest.cpp index 3cb916c..9f3aa2f 100644 --- a/ArcWelderTest/ArcWelderTest.cpp +++ b/ArcWelderTest/ArcWelderTest.cpp @@ -269,6 +269,7 @@ static void TestAntiStutter(std::string filePath) //double max_resolution = DEFAULT_RESOLUTION_MM; double max_resolution = 0.05; double max_radius_mm = 100000; + //double max_radius_mm = 10000; //int min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS; int min_arc_segments = 0; double mm_per_arc_segment = 0; @@ -288,19 +289,20 @@ static void TestAntiStutter(std::string filePath) logger_levels.push_back(log_levels::CRITICAL); logger* p_logger = new logger(logger_names, logger_levels); p_logger->set_log_level(INFO); + //p_logger->set_log_level(DEBUG); //p_logger->set_log_level_by_value(5); //arc_welder arc_welder_obj(BENCHY_0_5_MM_NO_WIPE, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, false, 50, static_cast<progress_callback>(on_progress)); //arc_welder arc_welder_obj(SIX_SPEED_TEST, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, false, 50, on_progress); arc_welder arc_welder_obj( - BENCHY_L1_DIFFICULT, + METALTEST, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, path_tolerance_percent, - max_radius_mm, + DEFAULT_MAX_RADIUS_MM, min_arc_segments, mm_per_arc_segment, - false, + true, true, DEFAULT_ALLOW_DYNAMIC_PRECISION, DEFAULT_XYZ_PRECISION, diff --git a/ArcWelderTest/ArcWelderTest.h b/ArcWelderTest/ArcWelderTest.h index 249d70b..13f4940 100644 --- a/ArcWelderTest/ArcWelderTest.h +++ b/ArcWelderTest/ArcWelderTest.h @@ -94,6 +94,8 @@ static std::string BENCHY_MIN_RADIUS_TEST = "C:\\Users\\Brad\\Documents\\3DPrint static std::string ISSUE_93 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\93\\FailingGCode.gcode"; static std::string ISSUE_99 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\99\\FailingGCode.gcode"; static std::string ISSUE_134 = "C:\\Users\\Brad\\Documents\\AntiStutter\\Issues\\134\\BirdHouse [PETG] [brim]+Infill [20%,cubic]+Noz [0.6]+LH [0.2]+LW-[0.6]+Temps [240+70]+50.0mms+Support [normal (56)]+Coast-[False].gcode" ; +static std::string ISSUE_170 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\170\\lampenring.gcode"; +static std::string ISSUE_184 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\184\\Dome_60_1.2mm_max_test15_0.2mm_PETG_MK3S_2h1m.gcode"; static std::string CONE_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\ConeTest.gcode"; static std::string CONE_TEST_VASE = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\ConeTestVase.gcode"; @@ -107,7 +109,8 @@ static std::string ISSUE_34 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutte static std::string DIFFICULT_ARCS_ISSUE_34 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\DifficultArcs\\issue_34.gcode"; static std::string TORTURE_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\performance\\torture_test.gcode"; - +static std::string CURA_PLUGIN_ISSUE_18 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\CuraPlugin\\18\\Unwelded.gcode"; +static std::string METALTEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\MetalAltered.gcode"; diff --git a/GcodeProcessorLib/GcodeProcessorLib.vcxproj b/GcodeProcessorLib/GcodeProcessorLib.vcxproj index 956df18..778d3f3 100644 --- a/GcodeProcessorLib/GcodeProcessorLib.vcxproj +++ b/GcodeProcessorLib/GcodeProcessorLib.vcxproj @@ -210,8 +210,6 @@ <ClInclude Include="version.h" /> </ItemGroup> <ItemGroup> - <ClCompile Include="array_list.cpp" /> - <ClCompile Include="circular_buffer.cpp" /> <ClCompile Include="extruder.cpp" /> <ClCompile Include="fpconv.cpp" /> <ClCompile Include="gcode_comment_processor.cpp" /> diff --git a/GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters b/GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters index 60b8ca9..3aed5ba 100644 --- a/GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters +++ b/GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters @@ -18,9 +18,6 @@ <ClInclude Include="array_list.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="circular_buffer.h"> - <Filter>Header Files</Filter> - </ClInclude> <ClInclude Include="extruder.h"> <Filter>Header Files</Filter> </ClInclude> @@ -54,14 +51,11 @@ <ClInclude Include="fpconv.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="circular_buffer.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> - <ClCompile Include="array_list.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="circular_buffer.cpp"> - <Filter>Source Files</Filter> - </ClCompile> <ClCompile Include="extruder.cpp"> <Filter>Source Files</Filter> </ClCompile> diff --git a/GcodeProcessorLib/array_list.cpp b/GcodeProcessorLib/array_list.cpp deleted file mode 100644 index b2e46ea..0000000 --- a/GcodeProcessorLib/array_list.cpp +++ /dev/null @@ -1,22 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Gcode Processor Library -// -// Tools for parsing gcode and calculating printer state from parsed gcode commands. -// -// Copyright(C) 2020 - Brad Hochgesang -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// This program is free software : you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the -// GNU Affero General Public License for more details. -// -// -// You can contact the author at the following email address: -// FormerLurker@pm.me -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "array_list.h"
\ No newline at end of file diff --git a/GcodeProcessorLib/circular_buffer.cpp b/GcodeProcessorLib/circular_buffer.cpp deleted file mode 100644 index c17c240..0000000 --- a/GcodeProcessorLib/circular_buffer.cpp +++ /dev/null @@ -1,22 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Gcode Processor Library -// -// Tools for parsing gcode and calculating printer state from parsed gcode commands. -// -// Copyright(C) 2020 - Brad Hochgesang -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// This program is free software : you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the -// GNU Affero General Public License for more details. -// -// -// You can contact the author at the following email address: -// FormerLurker@pm.me -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "circular_buffer.h"
\ No newline at end of file diff --git a/GcodeProcessorLib/circular_buffer.h b/GcodeProcessorLib/circular_buffer.h index 0312a29..97f25ab 100644 --- a/GcodeProcessorLib/circular_buffer.h +++ b/GcodeProcessorLib/circular_buffer.h @@ -1,7 +1,9 @@ +#pragma once //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Gcode Processor Library // // Tools for parsing gcode and calculating printer state from parsed gcode commands. + // // Copyright(C) 2020 - Brad Hochgesang //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -19,6 +21,7 @@ // You can contact the author at the following email address: // FormerLurker@pm.me //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + #pragma once #include <exception> template <typename T> @@ -32,6 +35,7 @@ public: count_ = 0; items_ = new T[max_size_]; } + circular_buffer(int max_size) { max_size_ = max_size; @@ -39,13 +43,24 @@ public: count_ = 0; items_ = new T[max_size]; } + virtual ~circular_buffer() { delete[] items_; } + + void initialize(T object) + { + for (int index = 0; index < max_size_; index++) + { + push_back(object); + } + count_ = 0; + front_index_ = 0; + } + void resize(int max_size) { T* new_items = new T[max_size]; - int count = count_; for (int index = 0; index < count_; index++) { new_items[index] = items_[(front_index_ + index + max_size_) % max_size_]; @@ -55,12 +70,61 @@ public: items_ = new_items; max_size_ = max_size; } + + void resize(int max_size, T object) + { + T* new_items = new T[max_size]; + for (int index = 0; index < count_; index++) + { + new_items[index] = items_[(front_index_ + index + max_size_) % max_size_]; + } + // Initialize the rest of the entries + for (int index = count_; index < max_size; index++) + { + new_items[index] = object; + } + front_index_ = 0; + delete[] items_; + items_ = new_items; + max_size_ = max_size; + } + + inline int get_index_position(int index) const + { + int index_position = index + front_index_ + max_size_; + while (index_position >= max_size_) + { + index_position = index_position - max_size_; + } + return index_position; + } + void push_front(T object) { - front_index_ = (front_index_ - 1 + max_size_) % max_size_; - count_++; + //front_index_ = (front_index_ - 1 + max_size_) % max_size_; + front_index_ -= 1; + if (front_index_ < 0) + { + front_index_ = max_size_ - 1; + } + if (count_ != max_size_) + { + count_++; + } items_[front_index_] = object; } + + void push_back(T object) + { + int pos = get_index_position(count_); + items_[pos] = object; + count_++; + if (count_ != max_size_) + { + count_++; + } + } + T& pop_front() { if (count_ == 0) @@ -69,30 +133,55 @@ public: } int prev_start = front_index_; - front_index_ = (front_index_ + 1 + max_size_) % max_size_; + + front_index_ += 1; + if (front_index_ >= max_size_) + { + front_index_ = 0; + } count_--; return items_[prev_start]; } - T& get(int index) + T& pop_back() { - return items_[(front_index_ + index + max_size_) % max_size_]; + if (count_ == 0) + { + throw std::exception(); + } + int pos = get_index_position(count_ - 1); + count_--; + return items_[pos]; } - int count() + T& operator[] (int index) const { - return count_; + //int opos = get_index_position(index); + return items_[get_index_position(index)]; + } + + T& get(int index) const + { + int opos = get_index_position(index); + return items_[opos]; + } + int count() const + { + return count_; } - int get_max_size() + + int get_max_size() const { return max_size_; } + void clear() { count_ = 0; front_index_ = 0; } + void copy(const circular_buffer<T>& source) { if (max_size_ < source.max_size_) @@ -106,7 +195,6 @@ public: } front_index_ = source.front_index_; count_ = source.count_; - } protected: diff --git a/GcodeProcessorLib/gcode_position.cpp b/GcodeProcessorLib/gcode_position.cpp index fc469cd..444a879 100644 --- a/GcodeProcessorLib/gcode_position.cpp +++ b/GcodeProcessorLib/gcode_position.cpp @@ -206,10 +206,9 @@ void gcode_position_args::delete_y_firmware_offsets() } } -gcode_position::gcode_position() +gcode_position::gcode_position() : positions_(50), initial_position_(1) { position_buffer_size_ = 50; - positions_ = new position[position_buffer_size_]; autodetect_position_ = false; home_x_ = 0; home_y_ = 0; @@ -247,23 +246,19 @@ gcode_position::gcode_position() z_max_ = 0; is_circular_bed_ = false; - cur_pos_ = -1; - num_pos_ = 0; - for(int index = 0; index < position_buffer_size_; index ++) - { - position initial_pos(num_extruders_); - initial_pos.set_xyz_axis_mode(xyz_axis_default_mode_); - initial_pos.set_e_axis_mode(e_axis_default_mode_); - initial_pos.set_units_default(units_default_); - add_position(initial_pos); - } - num_pos_ = 0; + + position initial_pos(num_extruders_); + initial_pos.set_xyz_axis_mode(xyz_axis_default_mode_); + initial_pos.set_e_axis_mode(e_axis_default_mode_); + initial_pos.set_units_default(units_default_); + + positions_.initialize(initial_pos); + initial_position_ = initial_pos; } -gcode_position::gcode_position(gcode_position_args args) +gcode_position::gcode_position(gcode_position_args args) : positions_(args.position_buffer_size) { position_buffer_size_ = args.position_buffer_size; - positions_ = new position[args.position_buffer_size] ; autodetect_position_ = args.autodetect_position; home_x_ = args.home_x; home_y_ = args.home_y; @@ -330,9 +325,6 @@ gcode_position::gcode_position(gcode_position_args args) z_max_ = args.z_max; is_circular_bed_ = args.is_circular_bed; - - cur_pos_ = -1; - num_pos_ = 0; num_extruders_ = args.num_extruders; // Configure the initial position @@ -346,15 +338,11 @@ gcode_position::gcode_position(gcode_position_args args) initial_pos.p_extruders[index].x_firmware_offset = args.x_firmware_offsets[index]; initial_pos.p_extruders[index].y_firmware_offset = args.y_firmware_offsets[index]; } - - for (int index = 0; index < position_buffer_size_; index++) - { - - add_position(initial_pos); - } - num_pos_ = 0; + positions_.initialize(initial_pos); + initial_position_ = initial_pos; } + gcode_position::gcode_position(const gcode_position &source) { // Private copy constructor - you can't copy this class @@ -362,11 +350,7 @@ gcode_position::gcode_position(const gcode_position &source) gcode_position::~gcode_position() { - if (positions_ != NULL) - { - delete [] positions_; - positions_ = NULL; - } + delete_retraction_lengths_(); delete_z_lift_heights_(); } @@ -376,7 +360,6 @@ bool gcode_position::get_g90_91_influences_extruder() return g90_influences_extruder_; } - void gcode_position::set_num_extruders(int num_extruders) { delete_retraction_lengths_(); @@ -413,32 +396,44 @@ void gcode_position::delete_z_lift_heights_() int gcode_position::get_num_positions() { - return num_pos_; + return positions_.count(); +} + +int gcode_position::get_max_positions() +{ + return positions_.get_max_size(); +} + +void gcode_position::grow_max_positions(int size) +{ + int current_size = positions_.get_max_size(); + if (size < current_size) + { + return; + } + positions_.resize(size, initial_position_); + } void gcode_position::add_position(position& pos) { - cur_pos_ = (cur_pos_+1) % position_buffer_size_; - positions_[cur_pos_] = pos; - if (num_pos_ < position_buffer_size_) - num_pos_++; + positions_.push_front(pos); } void gcode_position::add_position(parsed_command& cmd) { - const int prev_pos = cur_pos_; - cur_pos_ = (cur_pos_+1) % position_buffer_size_; - positions_[cur_pos_] = positions_[prev_pos]; - positions_[cur_pos_].reset_state(); - positions_[cur_pos_].command = cmd; - positions_[cur_pos_].is_empty = false; - if (num_pos_ < position_buffer_size_) - num_pos_++; + + position current_position = positions_[0]; + current_position.reset_state(); + current_position.command = cmd; + current_position.is_empty = false; + positions_.push_front(current_position); + } position gcode_position::get_position(int index) { - return positions_[(cur_pos_ - index + position_buffer_size_) % position_buffer_size_]; + return positions_[index]; } position gcode_position::get_current_position() @@ -453,7 +448,7 @@ position gcode_position::get_previous_position() position * gcode_position::get_position_ptr(int index) { - return &positions_[(cur_pos_ - index + position_buffer_size_) % position_buffer_size_]; + return &positions_[index]; } position * gcode_position::get_current_position_ptr() @@ -697,11 +692,7 @@ void gcode_position::update(parsed_command& command, const long file_line_number void gcode_position::undo_update() { - if (num_pos_ != 0) - { - cur_pos_ = (cur_pos_ - 1 + position_buffer_size_) % position_buffer_size_; - num_pos_--; - } + positions_.pop_front(); } position* gcode_position::undo_update(int num_updates) @@ -715,21 +706,9 @@ position* gcode_position::undo_update(int num_updates) // add the positions we will undo to the array for (int index = 0; index < num_updates; index++) { - p_undo_positions[index] = get_position(index); - } - - if (num_pos_ < num_updates) - { - num_pos_ = 0; - cur_pos_ = 0; - } - else - { - cur_pos_ = (cur_pos_ - num_updates + position_buffer_size_) % position_buffer_size_; - num_pos_ -= num_updates; + p_undo_positions[index] = positions_.pop_front(); } return p_undo_positions; - } // Private Members diff --git a/GcodeProcessorLib/gcode_position.h b/GcodeProcessorLib/gcode_position.h index 521f0d3..5930cf6 100644 --- a/GcodeProcessorLib/gcode_position.h +++ b/GcodeProcessorLib/gcode_position.h @@ -25,6 +25,7 @@ #include <string> #include <vector> #include <map> +#include "circular_buffer.h" #include "gcode_parser.h" #include "position.h" #include "gcode_comment_processor.h" @@ -139,6 +140,8 @@ public: void undo_update(); position * undo_update(int num_updates); int get_num_positions(); + int get_max_positions(); + void grow_max_positions(int size); position get_position(int index); position get_current_position(); position get_previous_position(); @@ -149,10 +152,9 @@ public: bool get_g90_91_influences_extruder(); private: gcode_position(const gcode_position &source); + position initial_position_; int position_buffer_size_; - position* positions_; - int cur_pos_; - int num_pos_; + circular_buffer<position> positions_; void add_position(parsed_command &); void add_position(position &); bool autodetect_position_; diff --git a/GcodeProcessorLib/position.cpp b/GcodeProcessorLib/position.cpp index 6a85801..8fcd8cd 100644 --- a/GcodeProcessorLib/position.cpp +++ b/GcodeProcessorLib/position.cpp @@ -356,6 +356,10 @@ position& position::operator=(const position& pos) { return *this; } +bool position::is_travel() +{ + return is_xyz_travel || is_xy_travel; +} void position::set_num_extruders(int num_extruders_) { if (num_extruders_ == num_extruders) diff --git a/GcodeProcessorLib/position.h b/GcodeProcessorLib/position.h index 0958cd5..5059d5f 100644 --- a/GcodeProcessorLib/position.h +++ b/GcodeProcessorLib/position.h @@ -102,5 +102,6 @@ struct position void set_e_axis_mode(const std::string& e_axis_default_mode); void set_units_default(const std::string& units_default); bool can_take_snapshot(); + bool is_travel() }; #endif
\ No newline at end of file diff --git a/GcodeProcessorLib/utilities.cpp b/GcodeProcessorLib/utilities.cpp index 041f91f..b5a09a6 100644 --- a/GcodeProcessorLib/utilities.cpp +++ b/GcodeProcessorLib/utilities.cpp @@ -24,6 +24,7 @@ #include <sstream> #include <iostream> #include <iomanip> +#include <algorithm> #include "fpconv.h" const std::string utilities::WHITESPACE_ = " \n\r\t\f\v"; @@ -320,4 +321,20 @@ std::string utilities::dtos(double x, unsigned char precision) } */ return buffer; -}
\ No newline at end of file +} + +bool utilities::case_insensitive_compare_char(char& c1, char& c2) +{ + if (c1 == c2) + return true; + else if (std::toupper(c1) == std::toupper(c2)) + return true; + return false; +} +/* + * Case Insensitive String Comparision + */ +bool utilities::case_insensitive_compare(std::string& str1, std::string& str2) +{ + return ((str1.size() == str2.size()) && std::equal(str1.begin(), str1.end(), str2.begin(), &utilities::case_insensitive_compare_char)); +} diff --git a/GcodeProcessorLib/utilities.h b/GcodeProcessorLib/utilities.h index b41d6f6..33afd51 100644 --- a/GcodeProcessorLib/utilities.h +++ b/GcodeProcessorLib/utilities.h @@ -41,6 +41,9 @@ public: static double get_cartesian_distance(double x1, double y1, double x2, double y2); static double get_cartesian_distance(double x1, double y1, double z1, double x2, double y2, double z2); + + static bool case_insensitive_compare_char(char& c1, char& c2); + static bool case_insensitive_compare(std::string& str1, std::string& str2); static std::string to_string(double value); static std::string to_string(int value); static std::string ltrim(const std::string& s); diff --git a/PyArcWelder/py_arc_welder.cpp b/PyArcWelder/py_arc_welder.cpp index 36588f2..f811e6d 100644 --- a/PyArcWelder/py_arc_welder.cpp +++ b/PyArcWelder/py_arc_welder.cpp @@ -47,28 +47,30 @@ PyObject* py_arc_welder::build_py_progress(const arc_welder_progress& progress, progress.points_compressed, //6 "arcs_created", progress.arcs_created, //7 + "arcs_aborted_by_flowrate", + progress.arcs_aborted_by_flow_rate, //8 "num_firmware_compensations", - progress.num_firmware_compensations, //8 + progress.num_firmware_compensations, //9 "source_file_position", - progress.source_file_position, //9 + progress.source_file_position, //10 "source_file_size", - progress.source_file_size, //10 + progress.source_file_size, //11 "target_file_size", - progress.target_file_size, //11 + progress.target_file_size, //12 "compression_ratio", - progress.compression_ratio, //12 + progress.compression_ratio, //13 "compression_percent", - progress.compression_percent, //13 + progress.compression_percent, //14 "source_file_total_length", - progress.segment_statistics.total_length_source, //14 + progress.segment_statistics.total_length_source, //15 "target_file_total_length", - progress.segment_statistics.total_length_target, //15 + progress.segment_statistics.total_length_target, //16 "source_file_total_count", - progress.segment_statistics.total_count_source, //16 + progress.segment_statistics.total_count_source, //17 "target_file_total_count", - progress.segment_statistics.total_count_target, //17 + progress.segment_statistics.total_count_target, //18 "total_count_reduction_percent", - total_count_reduction_percent //18 + total_count_reduction_percent //19 ); |