diff options
author | FormerLurker <hochgebe@gmail.com> | 2020-11-06 19:43:13 +0300 |
---|---|---|
committer | FormerLurker <hochgebe@gmail.com> | 2020-11-06 19:43:13 +0300 |
commit | 91633ba765214d1c6eece514e2dd2d0e898be8b4 (patch) | |
tree | 21ed3e43d72bc89efb0f363464ec26ee5e3ce536 /ArcWelder | |
parent | 395c472dfc6080b0b0b2fca9f1dba6eeb46c21cf (diff) |
Implementations for #8, #9, #10, #11.
Diffstat (limited to 'ArcWelder')
-rw-r--r-- | ArcWelder/arc_welder.cpp | 60 | ||||
-rw-r--r-- | ArcWelder/arc_welder.h | 27 | ||||
-rw-r--r-- | ArcWelder/segmented_arc.cpp | 115 | ||||
-rw-r--r-- | ArcWelder/segmented_arc.h | 13 | ||||
-rw-r--r-- | ArcWelder/segmented_shape.cpp | 117 | ||||
-rw-r--r-- | ArcWelder/segmented_shape.h | 50 |
6 files changed, 292 insertions, 90 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp index 01de169..417d09d 100644 --- a/ArcWelder/arc_welder.cpp +++ b/ArcWelder/arc_welder.cpp @@ -35,8 +35,27 @@ #include <iomanip> #include <sstream> - -arc_welder::arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, double max_radius, bool g90_g91_influences_extruder, int buffer_size, progress_callback callback) : current_arc_(DEFAULT_MIN_SEGMENTS, buffer_size - 5, resolution_mm, max_radius), segment_statistics_(segment_statistic_lengths, segment_statistic_lengths_count, log) +arc_welder::arc_welder( + std::string source_path, + std::string target_path, + logger * log, + double resolution_mm, + double path_tolerance_percent, + double max_radius, + bool g90_g91_influences_extruder, + int buffer_size, + progress_callback callback) : current_arc_( + DEFAULT_MIN_SEGMENTS, + buffer_size - 5, + resolution_mm, + path_tolerance_percent, + max_radius + ), + segment_statistics_( + segment_statistic_lengths, + segment_statistic_lengths_count, + log + ) { p_logger_ = log; debug_logging_enabled_ = false; @@ -45,11 +64,11 @@ arc_welder::arc_welder(std::string source_path, std::string target_path, logger verbose_logging_enabled_ = false; logger_type_ = 0; + resolution_mm_ = resolution_mm; progress_callback_ = callback; verbose_output_ = false; source_path_ = source_path; target_path_ = target_path; - resolution_mm_ = resolution_mm; gcode_position_args_ = get_args_(g90_g91_influences_extruder, buffer_size); notification_period_seconds = 1; lines_processed_ = 0; @@ -164,8 +183,9 @@ arc_welder_results results; stream << std::fixed << std::setprecision(5); stream << "arc_welder::process - Parameters received: source_file_path: '" << source_path_ << "', target_file_path:'" << target_path_ << "', resolution_mm:" << - resolution_mm_ << "mm (+-" << current_arc_.get_resolution_mm() << "mm), max_radius_mm:" << current_arc_.get_max_radius() - << "mm, g90_91_influences_extruder: " << (p_source_position_->get_g90_91_influences_extruder() ? "True" : "False"); + resolution_mm_ << "mm (+-" << current_arc_.get_resolution_mm() << "mm), path_tolerance_percent: " << current_arc_.get_path_tolerance_percent() + << ", max_radius_mm:" << current_arc_.get_max_radius() << + "mm, g90_91_influences_extruder: " << (p_source_position_->get_g90_91_influences_extruder() ? "True" : "False"); p_logger_->log(logger_type_, INFO, stream.str()); @@ -333,6 +353,12 @@ arc_welder_progress arc_welder::get_progress_(long source_file_position, double int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess) { + /* use to catch gcode for debugging since I can't set conditions equal to strings + if (cmd.gcode == "G1 X118.762 Y104.054 E0.0163") + { + std::cout << "Found it!"; + } + */ // Update the position for the source gcode file p_source_position_->update(cmd, lines_processed_, gcodes_processed_, -1); position* p_cur_pos = p_source_position_->get_current_position_ptr(); @@ -360,9 +386,28 @@ 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) + { + for (std::vector<parsed_command_parameter>::iterator it = cmd.parameters.begin(); it != cmd.parameters.end(); ++it) + { + switch ((*it).name[0]) + { + case 'X': + case 'Y': + case 'Z': + current_arc_.update_xyz_precision((*it).double_precision); + break; + case 'E': + current_arc_.update_e_precision((*it).double_precision); + break; + } + } + } + if ( !is_end && cmd.is_known_command && !cmd.is_empty && ( - (cmd.command == "G0" || cmd.command == "G1") && + is_g1_g2 && utilities::is_equal(p_cur_pos->z, p_pre_pos->z) && utilities::is_equal(p_cur_pos->x_offset, p_pre_pos->x_offset) && utilities::is_equal(p_cur_pos->y_offset, p_pre_pos->y_offset) && @@ -377,7 +422,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess (previous_extruder.is_retracting && extruder_current.is_retracting) ) && p_cur_pos->is_extruder_relative == p_pre_pos->is_extruder_relative && - (!waiting_for_arc_ || p_pre_pos->f == p_cur_pos->f) && + (/*!waiting_for_arc_ || */p_pre_pos->f == p_cur_pos->f) && // might need to skip the waiting for arc check... (!waiting_for_arc_ || p_pre_pos->feature_type_tag == p_cur_pos->feature_type_tag) ) ) { @@ -405,7 +450,6 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess if (!waiting_for_arc_) { waiting_for_arc_ = true; - previous_feedrate_ = p_pre_pos->f; } else { diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h index 50917be..c81a8e1 100644 --- a/ArcWelder/arc_welder.h +++ b/ArcWelder/arc_welder.h @@ -344,13 +344,13 @@ struct arc_welder_progress { std::stringstream stream; stream << std::fixed << std::setprecision(2); - stream << percent_complete << "% complete in " << seconds_elapsed << " seconds with " << seconds_remaining << " seconds remaining."; - stream << " Gcodes Processed: " << gcodes_processed; - stream << ", Current Line: " << lines_processed; - stream << ", Points Compressed: " << points_compressed; - stream << ", ArcsCreated: " << arcs_created; - stream << ", Compression Ratio: " << compression_ratio; - stream << ", Size Reduction: " << compression_percent << "% "; + stream << " percent_complete:" << percent_complete << ", seconds_elapsed:" << seconds_elapsed << ", seconds_remaining:" << seconds_remaining; + stream << ", gcodes_processed: " << gcodes_processed; + stream << ", current_file_line: " << lines_processed; + stream << ", points_compressed: " << points_compressed; + stream << ", arcs_created: " << arcs_created; + stream << ", compression_ratio: " << compression_ratio; + stream << ", size_reduction: " << compression_percent << "% "; return stream.str(); } std::string detail_str() const { @@ -375,11 +375,21 @@ struct arc_welder_results { std::string message; arc_welder_progress progress; }; +#define DEFAULT_GCODE_BUFFER_SIZE 100 class arc_welder { public: - arc_welder(std::string source_path, std::string target_path, logger* log, double resolution_mm, double max_radius, bool g90_g91_influences_extruder, int buffer_size, progress_callback callback = NULL); + arc_welder( + std::string source_path, + std::string target_path, + logger* log, + double resolution_mm, + double path_tolerance_percent, + double max_radius, + bool g90_g91_influences_extruder, + int buffer_size = DEFAULT_GCODE_BUFFER_SIZE, + progress_callback callback = NULL); void set_logger_type(int logger_type); virtual ~arc_welder(); arc_welder_results process(); @@ -402,7 +412,6 @@ private: std::string source_path_; std::string target_path_; double resolution_mm_; - double max_segments_; gcode_position_args gcode_position_args_; long file_size_; int lines_processed_; diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp index 591d616..abc50a4 100644 --- a/ArcWelder/segmented_arc.cpp +++ b/ArcWelder/segmented_arc.cpp @@ -31,12 +31,17 @@ #include <stdio.h> #include <cmath> -segmented_arc::segmented_arc() : segmented_shape(DEFAULT_MIN_SEGMENTS, DEFAULT_MAX_SEGMENTS, DEFAULT_RESOLUTION_MM) +segmented_arc::segmented_arc() : segmented_shape(DEFAULT_MIN_SEGMENTS, DEFAULT_MAX_SEGMENTS, DEFAULT_RESOLUTION_MM, ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT) { - max_radius_mm_ = DEFAULT_MAX_RADIUS_MM; + } -segmented_arc::segmented_arc(int min_segments, int max_segments, double resolution_mm, double max_radius_mm) : segmented_shape(min_segments, max_segments, resolution_mm) +segmented_arc::segmented_arc( + int min_segments, + int max_segments, + double resolution_mm, + double path_tolerance_percent, + double max_radius_mm) : segmented_shape(min_segments, max_segments, resolution_mm, path_tolerance_percent) { if (max_radius_mm > DEFAULT_MAX_RADIUS_MM) max_radius_mm_ = DEFAULT_MAX_RADIUS_MM; else max_radius_mm_ = max_radius_mm; @@ -120,7 +125,7 @@ bool segmented_arc::try_add_point(point p, double e_relative) if (points_.count() == get_min_segments()) { arc a; - if (!arc::try_create_arc(arc_circle_, points_, original_shape_length_, resolution_mm_, a)) + if (!arc::try_create_arc(arc_circle_, points_, original_shape_length_, a, resolution_mm_, path_tolerance_percent_)) { point_added = false; points_.pop_back(); @@ -187,6 +192,7 @@ bool segmented_arc::try_add_point_internal_(point p, double pd) original_shape_length_ += pd; circle_fits_points = does_circle_fit_points_(test_circle); + if (circle_fits_points) { arc_circle_ = test_circle; @@ -209,6 +215,75 @@ bool segmented_arc::try_add_point_internal_(point p, double pd) } +bool segmented_arc::does_arc_fit_points(circle& c) const +{ + arc a; + return arc::try_create_arc(c, points_, original_shape_length_, a, resolution_mm_, path_tolerance_percent_); + /*double distance_from_center; + double difference_from_radius; + for (int index = 0; index < points_.count() - 1; index++) + { + // Make sure the length from the center of our circle to the test point is + // at or below our max distance. + point cur_point(points_[index]); + double x_rel = cur_point.x - c.center.x; + double y_rel = cur_point.y - c.center.y; + bool clockwise = a.angle_radians < 0; + + bool not_in_sector = ( + ! (-a.start_point.x * y_rel + a.start_point.y * x_rel > 0) + && (-a.end_point.x * y_rel + a.end_point.y * x_rel > 0) + ) == clockwise; + if (not_in_sector) + { + return false; + } + + + } */ + // Radius compare + /* + double r_axis_x = -(a.center.x - a.start_point.x); + double r_axis_y = -(a.center.y - a.start_point.y); + float center_axis_x = a.start_point.x - r_axis_x; + float center_axis_y = a.start_point.y - r_axis_y; + float rt_x = a.end_point.x - center_axis_x; + float rt_y = a.end_point.y - center_axis_y; + float angular_travel_total = std::atan2(r_axis_x * rt_y - r_axis_y * rt_x, r_axis_x * rt_x + r_axis_y * rt_y); + if (a.angle_radians>0) { angular_travel_total -= 2 * PI_DOUBLE; } + double test_radius = std::abs(a.radius * angular_travel_total); + if (utilities::is_zero(test_radius - original_shape_length_, resolution_mm_)) + { + return true; + } + return false; + */ +} + +bool segmented_arc::is_point_on_arc(const arc& a, const point& p) const +{ + double distance_from_center; + double difference_from_radius; + + + for (int index = 0; index < points_.count() - 1; index++) + { + // Make sure the length from the center of our circle to the test point is + // at or below our max distance. + distance_from_center = utilities::get_cartesian_distance(points_[index].x, points_[index].y, a.center.x, a.center.y); + double difference_from_radius = std::abs(distance_from_center - a.radius); + if (utilities::greater_than(difference_from_radius, resolution_mm_)) + { + //std::cout << " failed - end points do not lie on circle.\n"; + return false; + } + // see if the point is within the cone + + } + return true; +} + + bool segmented_arc::does_circle_fit_points_(circle& c) const { // We know point 1 must fit (we used it to create the circle). Check the other points @@ -250,8 +325,10 @@ bool segmented_arc::does_circle_fit_points_(circle& c) const } // get the current arc and compare the total length to the original length - arc a; - return arc::try_create_arc(c, points_, original_shape_length_, resolution_mm_, a); + //arc a; + //return arc::try_create_arc(c, points_, original_shape_length_, resolution_mm_, a)) + + return does_arc_fit_points(c); } @@ -259,14 +336,14 @@ bool segmented_arc::try_get_arc(arc & target_arc) { //int mid_point_index = ((points_.count() - 2) / 2) + 1; //return arc::try_create_arc(arc_circle_, points_[0], points_[mid_point_index], points_[points_.count() - 1], original_shape_length_, resolution_mm_, target_arc); - return arc::try_create_arc(arc_circle_ ,points_, original_shape_length_, resolution_mm_, target_arc); + return arc::try_create_arc(arc_circle_ ,points_, original_shape_length_, target_arc, resolution_mm_, path_tolerance_percent_); } bool segmented_arc::try_get_arc_(const circle& c, arc &target_arc) { //int mid_point_index = ((points_.count() - 1) / 2) + 1; //return arc::try_create_arc(c, points_[0], points_[mid_point_index], endpoint, original_shape_length_ + additional_distance, resolution_mm_, target_arc); - return arc::try_create_arc(c, points_, original_shape_length_, resolution_mm_, target_arc); + return arc::try_create_arc(c, points_, original_shape_length_, target_arc, resolution_mm_, path_tolerance_percent_); } std::string segmented_arc::get_shape_gcode_absolute(double e, double f) @@ -286,15 +363,15 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons char buf[20]; std::string gcode; arc c; - arc::try_create_arc(arc_circle_, points_, original_shape_length_, resolution_mm_, c); - + + arc::try_create_arc(arc_circle_, points_, original_shape_length_, c, resolution_mm_, path_tolerance_percent_); double i = c.center.x - c.start_point.x; double j = c.center.y - c.start_point.y; // 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 - if (utilities::less_than(c.angle_radians, 0)) + if (c.angle_radians < 0) { gcode = "G2"; } @@ -305,30 +382,26 @@ 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(c.end_point.x, 3, buf); + gcode += utilities::to_string(c.end_point.x, xyz_precision_, buf, false); gcode += " Y"; - gcode += utilities::to_string(c.end_point.y, 3, buf); + gcode += utilities::to_string(c.end_point.y, xyz_precision_, buf, false); gcode += " I"; - gcode += utilities::to_string(i, 3, buf); + gcode += utilities::to_string(i, xyz_precision_, buf, false); gcode += " J"; - gcode += utilities::to_string(j, 3, buf); + gcode += utilities::to_string(j, xyz_precision_, buf, false); // Add E if it appears if (has_e) { gcode += " E"; - gcode += utilities::to_string(e, 5, buf); + gcode += utilities::to_string(e, e_precision_, buf, false); } // Add F if it appears - if (utilities::greater_than_or_equal(f, 1)) - { - gcode += " F"; - gcode += utilities::to_string(f, 0, buf); - } + // Never add F, it should NEVER change! return gcode; diff --git a/ArcWelder/segmented_arc.h b/ArcWelder/segmented_arc.h index 352deab..179d7af 100644 --- a/ArcWelder/segmented_arc.h +++ b/ArcWelder/segmented_arc.h @@ -30,12 +30,19 @@ #define GCODE_CHAR_BUFFER_SIZE 100 #define DEFAULT_MAX_RADIUS_MM 1000000.0 // 1km +//#define DEFAULT_MAX_RADIUS_MM 10000.0 // 10M class segmented_arc : public segmented_shape { public: segmented_arc(); - segmented_arc(int min_segments = DEFAULT_MIN_SEGMENTS, int max_segments = DEFAULT_MAX_SEGMENTS, double resolution_mm = DEFAULT_RESOLUTION_MM, double max_radius_mm = DEFAULT_MAX_RADIUS_MM); + segmented_arc( + int min_segments = DEFAULT_MIN_SEGMENTS, + int max_segments = DEFAULT_MAX_SEGMENTS, + double resolution_mm = DEFAULT_RESOLUTION_MM, + double path_tolerance_percnet = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT, + double max_radius_mm = DEFAULT_MAX_RADIUS_MM + ); virtual ~segmented_arc(); virtual bool try_add_point(point p, double e_relative); std::string get_shape_gcode_absolute(double e, double f); @@ -51,9 +58,11 @@ public: private: bool try_add_point_internal_(point p, double pd); bool does_circle_fit_points_(circle& c) const; + bool does_arc_fit_points(circle& c) const; bool try_get_arc_(const circle& c, arc& target_arc); + bool is_point_on_arc(const arc& a, const point & p) const; std::string get_shape_gcode_(bool has_e, double e, double f) const; circle arc_circle_; double max_radius_mm_; -}; +}; diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp index 6ec8d84..c1114c2 100644 --- a/ArcWelder/segmented_shape.cpp +++ b/ArcWelder/segmented_shape.cpp @@ -96,7 +96,8 @@ bool segment::get_closest_perpendicular_point(point p1, point p2, point c, point double t = num / denom; // We're considering this a failure if t == 0 or t==1 within our tolerance. In that case we hit the endpoint, which is OK. - if (utilities::less_than_or_equal(t, 0, CIRCLE_GENERATION_A_ZERO_TOLERANCE) || utilities::greater_than_or_equal(t, 1, CIRCLE_GENERATION_A_ZERO_TOLERANCE)) + // Why are we using the CIRCLE_GENERATION_A_ZERO_TOLERANCE tolerance here?? + if (utilities::less_than_or_equal(t, 0) || utilities::greater_than_or_equal(t, 1)) return false; d.x = p1.x + t * (p2.x - p1.x); @@ -155,12 +156,6 @@ double distance_from_segment(segment s, point p) #pragma region Circle Functions -bool circle::is_point_on_circle(point p, double resolution_mm) -{ - // get the difference between the point and the circle's center. - double difference = std::abs(utilities::get_cartesian_distance(p.x, p.y, center.x, center.y) - radius); - return utilities::less_than(difference, resolution_mm, CIRCLE_GENERATION_A_ZERO_TOLERANCE); -} bool circle::try_create_circle(point p1, point p2, point p3, double max_radius, circle& new_circle) { @@ -172,11 +167,12 @@ bool circle::try_create_circle(point p1, point p2, point p3, double max_radius, double y3 = p3.y; double a = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - x3 * y2; - - if (utilities::is_zero(a, CIRCLE_GENERATION_A_ZERO_TOLERANCE)) + // Take out to figure out how we handle very small values for a + if (utilities::is_zero(a,0.000000001)) { return false; } + double b = (x1 * x1 + y1 * y1) * (y3 - y2) + (x2 * x2 + y2 * y2) * (y1 - y3) @@ -196,6 +192,12 @@ bool circle::try_create_circle(point p1, point p2, point p3, double max_radius, new_circle.center.y = y; new_circle.center.z = p1.z; new_circle.radius = radius; + + /*if (utilities::is_zero(a, CIRCLE_GENERATION_A_ZERO_TOLERANCE)) + { + return false; + } */ + return true; } double circle::get_radians(const point& p1, const point& p2) const @@ -225,17 +227,16 @@ point circle::get_closest_point(const point& p) const #pragma endregion Circle Functions #pragma region Arc Functions -bool arc::try_create_arc(const circle& c, const point& start_point, const point& mid_point, const point& end_point, double approximate_length, double resolution, arc& target_arc) +bool arc::try_create_arc( + const circle& c, + const point& start_point, + const point& mid_point, + const point& end_point, + double approximate_length, + arc& target_arc, + double resolution, + double path_tolerance_percent) { - //point p1 = c.get_closest_point(start_point); - //point p2 = c.get_closest_point(mid_point); - //point p3 = c.get_closest_point(end_point); - /*// Get the radians between p1 and p2 (short angle) - double p1_p2_rad = c.get_radians(p1, p2); - double p2_p3_rad = c.get_radians(p2, p3); - double p3_p1_rad = c.get_radians(p3, p1); - */ - double polar_start_theta = c.get_polar_radians(start_point); double polar_mid_theta = c.get_polar_radians(mid_point); double polar_end_theta = c.get_polar_radians(end_point); @@ -276,12 +277,37 @@ bool arc::try_create_arc(const circle& c, const point& start_point, const point& } } - if (direction == 0) return false; - - double arc_length = c.radius * angle_radians; - if (!utilities::is_equal(arc_length, approximate_length, resolution)) - return false; + // this doesn't always work.. in rare situations, the angle may be backward + if (direction == 0 || utilities::is_zero(angle_radians)) return false; + // Let's check the length against the original length + // This can trigger simply due to the differing path lengths + // but also could indicate that our vector calculation above + // got the direction wrong + double arc_length = c.radius * angle_radians; + // Calculate the percent difference of the original path + double difference = (arc_length - approximate_length) / approximate_length; + if (!utilities::is_zero(difference, path_tolerance_percent)) + { + // So it's possible our vector calculation above got the direction wrong. + // This can happen if there is a crazy arrangement of points + // extremely close to eachother. They have to be close enough to + // break our other checks. However, we may be able to salvage this. + // see if an arc moving in the opposite direction had the correct length. + + // Find the rest of the angle across the circle + double test_radians = std::abs(angle_radians - 2 * PI_DOUBLE); + // Calculate the length of that arc + double test_arc_length = c.radius * test_radians; + difference = (test_arc_length - approximate_length) / approximate_length; + if (!utilities::is_zero(difference, path_tolerance_percent)) + { + return false; + } + // So, let's set the new length and flip the direction (but not the angle)! + arc_length = test_arc_length; + direction = direction == 1 ? 2 : 1; + } if(direction == 2) angle_radians *= -1.0; @@ -295,21 +321,31 @@ bool arc::try_create_arc(const circle& c, const point& start_point, const point& target_arc.angle_radians = angle_radians; target_arc.polar_start_theta = polar_start_theta; target_arc.polar_end_theta = polar_end_theta; + return true; } -bool arc::try_create_arc(const circle& c, const array_list<point>& points, double approximate_length, double resolution, arc& target_arc) +bool arc::try_create_arc( + const circle& c, + const array_list<point>& points, + double approximate_length, + arc& target_arc, + double resolution, + double path_tolerance_percent) { int mid_point_index = ((points.count() - 2) / 2) + 1; - return arc::try_create_arc(c, points[0], points[mid_point_index], points[points.count() - 1], approximate_length, resolution, target_arc); + return arc::try_create_arc(c, points[0], points[mid_point_index], points[points.count() - 1], approximate_length, target_arc, resolution, path_tolerance_percent); } #pragma endregion -segmented_shape::segmented_shape(int min_segments, int max_segments, double resolution_mm) : points_(max_segments) +segmented_shape::segmented_shape(int min_segments, int max_segments, double resolution_mm, double path_tolerance_percnet) : points_(max_segments) { + 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. e_relative_ = 0; is_shape_ = false; @@ -326,6 +362,27 @@ segmented_shape::~segmented_shape() } +void segmented_shape::reset_precision() +{ + xyz_precision_ = DEFAULT_XYZ_PRECISION; + e_precision_ = DEFAULT_E_PRECISION; +} +void segmented_shape::update_xyz_precision(double precision) +{ + if (xyz_precision_ < precision) + { + xyz_precision_ = precision; + } +} +void segmented_shape::update_e_precision(double precision) +{ + if (e_precision_ < precision) + { + e_precision_ = precision; + } + +} + bool segmented_shape::is_extruding() { return is_extruding_; @@ -394,6 +451,12 @@ double segmented_shape::get_resolution_mm() { return resolution_mm_; } + +double segmented_shape::get_path_tolerance_percent() +{ + return path_tolerance_percent_; +} + void segmented_shape::set_resolution_mm(double resolution_mm) { resolution_mm_ = resolution_mm; diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h index 09d3d86..c4d622e 100644 --- a/ArcWelder/segmented_shape.h +++ b/ArcWelder/segmented_shape.h @@ -29,8 +29,11 @@ //#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.0000000001 // fail //#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.001 // pass //#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.0001 // pass -#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.00001 // PASS -//#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.000001 // pass +// Todo: Figure out EXACTLY what this should be!!! 0.00001 is conservative +//#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.00001 // PASS , but fails to draw spiral test +//#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.000005 // Pass, but fails the spiral test +//#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.0000025 // Passes both... This is tricky... +//#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.000001 // fails on barbarian test!!! //#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.0000001 // fail //#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.0000005 // fail //#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.00000075 // fail @@ -42,24 +45,15 @@ #include "array_list.h" // The minimum theta value allowed between any two arc in order for an arc to be // created. This prevents sign calculation issues for very small values of theta - -//#define MIN_ALLOWED_ARC_THETA 0.0000046875f // Lowest discovered value for full theta - +#define DEFAULT_XYZ_PRECISION 3 +#define DEFAULT_E_PRECISION 5 +#define ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT 0.01 // one percent struct point { public: - point() { - x = 0; - y = 0; - z = 0; - e_relative = 0; - } - point(double p_x, double p_y, double p_z, double p_e_relative) { - x = p_x; - y = p_y; - z = p_z; - e_relative = p_e_relative; - } + point() :x(0), y(0), z(0), e_relative(0){} + point(double x, double y, double z, double e_relative) + : x(x), y(y), z(z), e_relative(e_relative){} double x; double y; double z; @@ -125,7 +119,6 @@ struct circle { point center; double radius; - bool is_point_on_circle(point p, double resolution_mm); static bool try_create_circle(point p1, point p2, point p3, double max_radius, circle& new_circle); double get_radians(const point& p1, const point& p2) const; @@ -135,6 +128,7 @@ struct circle { point get_closest_point(const point& p) const; }; +#define DEFAULT_RESOLUTION_MM 0.05 struct arc : circle { arc() { @@ -163,28 +157,35 @@ struct arc : circle double polar_end_theta; point start_point; point end_point; - static bool try_create_arc(const circle& c, const point& start_point, const point& mid_point, const point& end_point, double approximate_length, double resolution, arc& target_arc); - static bool try_create_arc(const circle& c, const array_list<point>& points, double approximate_length, double resolution, arc& target_arc); + static bool try_create_arc(const circle& c, const point& start_point, const point& mid_point, const point& end_point, double approximate_length, arc& target_arc, double resolution = DEFAULT_RESOLUTION_MM, double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT); + static bool try_create_arc(const circle& c, const array_list<point>& points, double approximate_length, arc& target_arc, double resolution = DEFAULT_RESOLUTION_MM, double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT); }; double distance_from_segment(segment s, point p); #define DEFAULT_MIN_SEGMENTS 3 #define DEFAULT_MAX_SEGMENTS 50 -#define DEFAULT_RESOLUTION_MM 0.05 class segmented_shape { public: - segmented_shape(int min_segments = DEFAULT_MIN_SEGMENTS, int max_segments = DEFAULT_MAX_SEGMENTS, double resolution_mm = DEFAULT_RESOLUTION_MM); + 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 + ); segmented_shape& operator=(const segmented_shape& pos); virtual ~segmented_shape(); int get_num_segments(); int get_min_segments(); int get_max_segments(); double get_resolution_mm(); + double get_path_tolerance_percent(); double get_shape_length(); double get_shape_e_relative(); void set_resolution_mm(double resolution_mm); + void reset_precision(); + void update_xyz_precision(double precision); + void update_e_precision(double precision); virtual bool is_shape() const; // public virtual functions virtual void clear(); @@ -197,11 +198,14 @@ public: protected: array_list<point> points_; void set_is_shape(bool value); - double original_shape_length_; + unsigned char xyz_precision_; + unsigned char e_precision_; + double original_shape_length_; double e_relative_; bool is_extruding_; double resolution_mm_; bool is_shape_; + double path_tolerance_percent_; private: int min_segments_; int max_segments_; |