diff options
author | FormerLurker <hochgebe@gmail.com> | 2020-11-08 21:27:34 +0300 |
---|---|---|
committer | FormerLurker <hochgebe@gmail.com> | 2020-11-08 21:27:34 +0300 |
commit | 5eb4453aed430b3c5f336030c9a6eeb6e8ed18eb (patch) | |
tree | f23df828a2b018b66571d8404b933c5f2f940b12 /ArcWelder | |
parent | 8bc8b43506c2601823cad652a33da84389381c99 (diff) |
Code cleanup. Rename exe files for console and inverse processor app. Implement #15 and #16.
Diffstat (limited to 'ArcWelder')
-rw-r--r-- | ArcWelder/Makefile | 6 | ||||
-rw-r--r-- | ArcWelder/arc_welder.cpp | 15 | ||||
-rw-r--r-- | ArcWelder/arc_welder.h | 69 | ||||
-rw-r--r-- | ArcWelder/segmented_arc.cpp | 216 | ||||
-rw-r--r-- | ArcWelder/segmented_arc.h | 11 | ||||
-rw-r--r-- | ArcWelder/segmented_shape.cpp | 116 | ||||
-rw-r--r-- | ArcWelder/segmented_shape.h | 20 |
7 files changed, 210 insertions, 243 deletions
diff --git a/ArcWelder/Makefile b/ArcWelder/Makefile deleted file mode 100644 index a1f4894..0000000 --- a/ArcWelder/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -all: - g++ -c -I../GCodeProcessorLib *.cpp - - -clean: - rm -f *.o diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp index 417d09d..374196d 100644 --- a/ArcWelder/arc_welder.cpp +++ b/ArcWelder/arc_welder.cpp @@ -41,7 +41,7 @@ arc_welder::arc_welder( logger * log, double resolution_mm, double path_tolerance_percent, - double max_radius, + double max_radius, bool g90_g91_influences_extruder, int buffer_size, progress_callback callback) : current_arc_( @@ -184,8 +184,8 @@ arc_welder_results results; 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), 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"); + << ", max_radius_mm:" << current_arc_.get_max_radius() + << ", g90_91_influences_extruder: " << (p_source_position_->get_g90_91_influences_extruder() ? "True" : "False"); p_logger_->log(logger_type_, INFO, stream.str()); @@ -422,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) && // might need to skip the waiting for arc check... + (!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) ) ) { @@ -450,6 +450,7 @@ 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 { @@ -726,8 +727,7 @@ int arc_welder::write_gcode_to_file(std::string gcode) int arc_welder::write_unwritten_gcodes_to_file() { int size = unwritten_commands_.count(); - std::string gcode_to_write; - + std::string lines_to_write; for (int index = 0; index < size; index++) { @@ -737,9 +737,10 @@ int arc_welder::write_unwritten_gcodes_to_file() { segment_statistics_.update(p.extrusion_length, false); } - write_gcode_to_file(p.command.to_string()); + lines_to_write.append(p.command.to_string()).append("\n"); } + output_file_ << lines_to_write; return size; } diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h index c81a8e1..e26a1b5 100644 --- a/ArcWelder/arc_welder.h +++ b/ArcWelder/arc_welder.h @@ -132,34 +132,63 @@ struct source_target_segment_statistics { std::stringstream format_stream; const int min_column_size = 8; int mm_col_size = max_width + max_precision + 2; // Adding 2 for the mm + int percent_precision = 1; + int min_percent_col_size = 7; int min_max_label_col_size = 4; - int percent_col_size = 9; + int percent_col_size = min_percent_col_size; int totals_row_label_size = 22; - int count_col_size; - - // Calculate the count column size - int max_count = 0; + int source_col_size= 0; + int target_col_size = 0; + + // Calculate the count columns and percent column sizes + int max_source = 0; + int max_target = 0; + int max_percent = 0; // We only need to hold the integer part + //if (p_logger_ != NULL) p_logger_->log(logger_type_, VERBOSE, "Calculating Column Size."); for (int index = 0; index < source_segments.size(); index++) { int source_count = source_segments[index].count; int target_count = target_segments[index].count; - if (max_count < source_count) + int percent = 0; + if (source_count > 0) + { + percent = (((double)target_count - (double)source_count) / (double)source_count) * 100.0; + if (percent > max_percent) + { + max_percent = percent; + } + } + if (max_source < source_count) { - max_count = source_count; + max_source = source_count; } - if (max_count < target_count) + if (max_target < target_count) { - max_count = target_count; + max_target = target_count; } } // Get the number of digits in the max count - count_col_size = utilities::get_num_digits(max_count); + source_col_size = utilities::get_num_digits(max_source); + // enforce the minimum of 6 + if (source_col_size < min_column_size) + { + source_col_size = min_column_size; + } + // Get the number of digits in the max count + target_col_size = utilities::get_num_digits(max_target); // enforce the minimum of 6 - if (count_col_size < min_column_size) + if (target_col_size < min_column_size) { - count_col_size = min_column_size; + target_col_size = min_column_size; + } + // Get the percent column size, including one point of precision, the decimal point, a precent, and a space. + percent_col_size = utilities::get_num_digits(max_percent) + percent_precision + 3; // add two for . and % + // enforce the minumum percent col size + if (percent_col_size < min_percent_col_size) + { + percent_col_size = min_percent_col_size; } if (max_precision > 0) @@ -174,7 +203,7 @@ struct source_target_segment_statistics { mm_col_size = min_column_size; } // Get the table width - int table_width = mm_col_size + min_max_label_col_size + mm_col_size + count_col_size + count_col_size + percent_col_size; + int table_width = mm_col_size + min_max_label_col_size + mm_col_size + source_col_size + target_col_size + percent_col_size; // Add a separator for the statistics //output_stream << std::setw(table_width) << std::setfill('-') << "-" << "\n" << std::setfill(' ') ; // Output the column headers @@ -183,8 +212,8 @@ struct source_target_segment_statistics { output_stream << std::setw(min_max_label_col_size) << ""; output_stream << utilities::center("Max", mm_col_size); // right align the source, target and change columns - output_stream << std::setw(count_col_size) << std::right << "Source"; - output_stream << std::setw(count_col_size) << std::right << "Target"; + output_stream << std::setw(source_col_size) << std::right << "Source"; + output_stream << std::setw(target_col_size) << std::right << "Target"; output_stream << std::setw(percent_col_size) << std::right << "Change"; output_stream << "\n"; output_stream << std::setw(table_width) << std::setfill('-') << "" << std::setfill(' ') << "\n"; @@ -197,7 +226,7 @@ struct source_target_segment_statistics { int target_count = target_segments[index].count; // Calculate the percent change and create the string // Construct the percent_change_string - std::string percent_change_string = utilities::get_percent_change_string(source_count, target_count, 1); + std::string percent_change_string = utilities::get_percent_change_string(source_count, target_count, percent_precision); // Create the strings to hold the column values std::string min_mm_string; @@ -247,9 +276,9 @@ struct source_target_segment_statistics { output_stream << std::setw(mm_col_size) << std::internal << max_mm_string; } // Add the source count - output_stream << std::setw(count_col_size) << source_count_string; + output_stream << std::setw(source_col_size) << source_count_string; // Add the target count - output_stream << std::setw(count_col_size) << target_count_string; + output_stream << std::setw(target_col_size) << target_count_string; // Add the percent change string output_stream << std::setw(percent_col_size) << percent_change_string; // End the line @@ -376,7 +405,7 @@ struct arc_welder_results { arc_welder_progress progress; }; #define DEFAULT_GCODE_BUFFER_SIZE 100 - +#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false class arc_welder { public: @@ -387,7 +416,7 @@ public: double resolution_mm, double path_tolerance_percent, double max_radius, - bool g90_g91_influences_extruder, + bool g90_g91_influences_extruder = DEFAULT_G90_G91_INFLUENCES_EXTRUDER, int buffer_size = DEFAULT_GCODE_BUFFER_SIZE, progress_callback callback = NULL); void set_logger_type(int logger_type); diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp index abc50a4..f438761 100644 --- a/ArcWelder/segmented_arc.cpp +++ b/ArcWelder/segmented_arc.cpp @@ -41,10 +41,12 @@ segmented_arc::segmented_arc( 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) + 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; + } segmented_arc::~segmented_arc() @@ -73,14 +75,11 @@ double segmented_arc::get_max_radius() const { return max_radius_mm_; } + + + bool segmented_arc::is_shape() const { -/* - if (is_shape_) - { - arc a; - return arc::try_create_arc(arc_circle_, points_, original_shape_length_, resolution_mm_, a);; - } */ return is_shape_; } @@ -124,16 +123,13 @@ bool segmented_arc::try_add_point(point p, double e_relative) original_shape_length_ += distance; if (points_.count() == get_min_segments()) { - arc a; - if (!arc::try_create_arc(arc_circle_, points_, original_shape_length_, a, resolution_mm_, path_tolerance_percent_)) + if (!arc::try_create_arc(points_, current_arc_, original_shape_length_, max_radius_mm_, resolution_mm_, path_tolerance_percent_)) { point_added = false; points_.pop_back(); original_shape_length_ -= distance; } } - - } else { @@ -174,176 +170,25 @@ bool segmented_arc::try_add_point_internal_(point p, double pd) return false; // Create a test circle - circle test_circle; - bool circle_created; - // Find a point in the middle of our list for p2 - int mid_point_index = ((points_.count() - 2) / 2)+1; - circle_created = circle::try_create_circle(points_[0], points_[mid_point_index], p, max_radius_mm_, test_circle); - - if (circle_created) - { - - // If we got a circle, make sure all of the points fit within the tolerance. - bool circle_fits_points; + 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_; - original_shape_length_ += pd; - - circle_fits_points = does_circle_fit_points_(test_circle); - - if (circle_fits_points) - { - arc_circle_ = test_circle; - } - else - { - points_.pop_back(); - original_shape_length_ = previous_shape_length; - } - - // Only set is_shape if it goes from false to true - if (!is_shape()) - set_is_shape(circle_fits_points); - - return circle_fits_points; - } - - //std::cout << " failed - could not create a circle from the points.\n"; - return false; - -} + // the circle is new.. we have to test it now, which is expensive :( + points_.push_back(p); + double previous_shape_length = original_shape_length_; + original_shape_length_ += 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++) + if (arc::try_create_arc(points_, current_arc_, original_shape_length_, max_radius_mm_, resolution_mm_, path_tolerance_percent_)) { - // 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; + if (!is_shape()) + { + set_is_shape(true); } - - - } */ - // 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 - // Note: We have not added the current point, but that's fine since it is guaranteed to fit too. - // If this works, it will be added. - - double distance_from_center; - double difference_from_radius; - - // Check the endpoints to make sure they fit the current circle - for (int index = 1; index < points_.count(); 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, c.center.x, c.center.y); - double difference_from_radius = std::abs(distance_from_center - c.radius); - if (utilities::greater_than(difference_from_radius, resolution_mm_)) - { - //std::cout << " failed - end points do not lie on circle.\n"; - return false; - } - } - - // Check the point perpendicular from the segment to the circle's center, if any such point exists - for (int index = 0; index < points_.count() - 1; index++) - { - point point_to_test; - if (segment::get_closest_perpendicular_point(points_[index], points_[index + 1], c.center, point_to_test)) - { - distance_from_center = utilities::get_cartesian_distance(point_to_test.x, point_to_test.y, c.center.x, c.center.y); - difference_from_radius = std::abs(distance_from_center - c.radius); - // Test allowing more play for the midpoints. - if (utilities::greater_than(difference_from_radius, resolution_mm_)) - { - return false; - } - } - - } - - // 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)) - - return does_arc_fit_points(c); - -} - -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_, 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_, target_arc, resolution_mm_, path_tolerance_percent_); + // Can't create the arc. Remove the point and remove the previous segment length. + points_.pop_back(); + original_shape_length_ = previous_shape_length; + return false; } std::string segmented_arc::get_shape_gcode_absolute(double e, double f) @@ -351,6 +196,7 @@ std::string segmented_arc::get_shape_gcode_absolute(double e, double f) bool has_e = e_relative_ != 0; return get_shape_gcode_(has_e, e, f); } + std::string segmented_arc::get_shape_gcode_relative(double f) { bool has_e = e_relative_ != 0; @@ -362,16 +208,14 @@ 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_, c, resolution_mm_, path_tolerance_percent_); - double i = c.center.x - c.start_point.x; - double j = c.center.y - c.start_point.y; + + double i = current_arc_.center.x - current_arc_.start_point.x; + double j = current_arc_.center.y - current_arc_.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 (c.angle_radians < 0) + if (current_arc_.angle_radians < 0) { gcode = "G2"; } @@ -382,10 +226,10 @@ 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, xyz_precision_, buf, false); + gcode += utilities::to_string(current_arc_.end_point.x, xyz_precision_, buf, false); gcode += " Y"; - gcode += utilities::to_string(c.end_point.y, xyz_precision_, buf, false); + gcode += utilities::to_string(current_arc_.end_point.y, xyz_precision_, buf, false); gcode += " I"; gcode += utilities::to_string(i, xyz_precision_, buf, false); @@ -401,7 +245,11 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons } // Add F if it appears - // Never add F, it should NEVER change! + if (utilities::greater_than_or_equal(f, 1)) + { + gcode += " F"; + gcode += utilities::to_string(f, 0, buf, true); + } return gcode; diff --git a/ArcWelder/segmented_arc.h b/ArcWelder/segmented_arc.h index 179d7af..59e92d0 100644 --- a/ArcWelder/segmented_arc.h +++ b/ArcWelder/segmented_arc.h @@ -29,8 +29,6 @@ #include <sstream> #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 { @@ -51,18 +49,13 @@ public: virtual bool is_shape() const; point pop_front(double e_relative); point pop_back(double e_relative); - bool try_get_arc(arc & target_arc); double get_max_radius() const; - // static gcode buffer 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_; + //circle arc_circle_; + arc current_arc_; double max_radius_mm_; }; diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp index c1114c2..4a489da 100644 --- a/ArcWelder/segmented_shape.cpp +++ b/ArcWelder/segmented_shape.cpp @@ -24,6 +24,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "segmented_shape.h" +#include <stdio.h> #include <cmath> #include <iostream> #pragma region Operators for Vector and Point @@ -88,11 +89,11 @@ bool segment::get_closest_perpendicular_point(point c, point &d) return segment::get_closest_perpendicular_point(p1, p2, c, d); } -bool segment::get_closest_perpendicular_point(point p1, point p2, point c, point& d) +bool segment::get_closest_perpendicular_point(const point &p1, const point &p2, const point &c, point& d) { // [(Cx - Ax)(Bx - Ax) + (Cy - Ay)(By - Ay)] / [(Bx - Ax) ^ 2 + (By - Ay) ^ 2] double num = (c.x - p1.x)*(p2.x - p1.x) + (c.y - p1.y)*(p2.y - p1.y); - double denom = (pow((p2.x - p1.x), 2) + pow((p2.y - p1.y), 2)); + double denom = (std::pow((p2.x - p1.x), 2) + std::pow((p2.y - p1.y), 2)); 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. @@ -157,7 +158,7 @@ double distance_from_segment(segment s, point p) #pragma region Circle Functions -bool circle::try_create_circle(point p1, point p2, point p3, double max_radius, circle& new_circle) +bool circle::try_create_circle(const point& p1, const point& p2, const point& p3, const double max_radius, circle& new_circle) { double x1 = p1.x; double y1 = p1.y; @@ -193,13 +194,55 @@ bool circle::try_create_circle(point p1, point p2, point p3, double max_radius, new_circle.center.z = p1.z; new_circle.radius = radius; - /*if (utilities::is_zero(a, CIRCLE_GENERATION_A_ZERO_TOLERANCE)) - { - return false; - } */ - return true; } + +bool circle::try_create_circle(const array_list<point>& points, const double max_radius, const double resolution_mm, circle& new_circle, bool check_middle_only) +{ + int middle_index = points.count() / 2; + int check_index; + int step = 0; + bool is_right = true; + while (true) { + + check_index = middle_index + (is_right ? step : -1*step); + // Check the index + if (circle::try_create_circle(points[0], points[check_index], points[points.count() - 1], max_radius, new_circle)) + { + if (!new_circle.is_over_deviation(points, resolution_mm)) + { + return true; + } + } + if (is_right) + { + if (check_index == points.count() - 1) + { + return false; + } + if (check_index == middle_index) + { + if (check_middle_only) + { + return false; + } + step++; + continue; + } + } + else + { + if (check_index == 0) + { + return false; + } + step++; + } + is_right = !is_right; + } + return false; +} + double circle::get_radians(const point& p1, const point& p2) const { double distance_sq = pow(utilities::get_cartesian_distance(p1.x, p1.y, p2.x, p2.y), 2.0); @@ -224,16 +267,48 @@ point circle::get_closest_point(const point& p) const double pz = center.z + v.z / mag * radius; return point(px, py, pz, 0); } + +bool circle::is_over_deviation(const array_list<point>& points, const double resolution_mm) +{ + // Skip the first and last points since they will fit perfectly. + for (int index = 1; 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. + double distance = utilities::get_cartesian_distance(points[index].x, points[index].y, center.x, center.y); + if (std::abs(distance - radius) > resolution_mm) + { + return true; + } + } + + // Check the point perpendicular from the segment to the circle's center, if any such point exists + for (int index = 0; index < points.count() - 1; index++) + { + point point_to_test; + if (segment::get_closest_perpendicular_point(points[index], 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); + if (std::abs(distance - radius) > resolution_mm) + { + return true; + } + } + + } + return false; +} #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, arc& target_arc, + double approximate_length, double resolution, double path_tolerance_percent) { @@ -329,13 +404,29 @@ bool arc::try_create_arc( bool arc::try_create_arc( const circle& c, const array_list<point>& points, - double approximate_length, arc& target_arc, + double approximate_length, 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, target_arc, resolution, path_tolerance_percent); + return arc::try_create_arc(c, points[0], points[mid_point_index], points[points.count() - 1], target_arc, approximate_length, resolution, path_tolerance_percent); +} +bool arc::try_create_arc( + const array_list<point>& points, + arc& target_arc, + double approximate_length, + double max_radius_mm, + double resolution_mm, + double path_tolerance_percent) +{ + circle test_circle; + if (circle::try_create_circle(points, max_radius_mm, resolution_mm, test_circle, false)) + { + int mid_point_index = ((points.count() - 2) / 2) + 1; + return arc::try_create_arc(test_circle, points[0], points[mid_point_index], points[points.count()-1], target_arc, approximate_length, resolution_mm, path_tolerance_percent); + } + return false; } #pragma endregion @@ -367,6 +458,7 @@ 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) @@ -374,6 +466,7 @@ void segmented_shape::update_xyz_precision(double precision) xyz_precision_ = precision; } } + void segmented_shape::update_e_precision(double precision) { if (e_precision_ < precision) @@ -387,6 +480,7 @@ bool segmented_shape::is_extruding() { return is_extruding_; } + segmented_shape& segmented_shape::operator=(const segmented_shape& obj) { points_.clear(); diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h index c4d622e..505b465 100644 --- a/ArcWelder/segmented_shape.h +++ b/ArcWelder/segmented_shape.h @@ -47,7 +47,7 @@ // created. This prevents sign calculation issues for very small values of theta #define DEFAULT_XYZ_PRECISION 3 #define DEFAULT_E_PRECISION 5 -#define ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT 0.01 // one percent +#define ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT 0.05 // one percent struct point { public: @@ -81,7 +81,7 @@ struct segment point p2; bool get_closest_perpendicular_point(point c, point& d); - static bool get_closest_perpendicular_point(point p1, point p2, point c, point& d); + static bool get_closest_perpendicular_point(const point& p1, const point& p2, const point& c, point& d); }; struct vector : point @@ -102,6 +102,7 @@ struct vector : point }; +#define DEFAULT_MAX_RADIUS_MM 1000000.0 // 1km struct circle { circle() { center.x = 0; @@ -119,13 +120,17 @@ struct circle { point center; double radius; - static bool try_create_circle(point p1, point p2, point p3, double max_radius, circle& new_circle); + static bool try_create_circle(const point &p1, const point &p2, const point &p3, const double max_radius, circle& new_circle); + static bool try_create_circle(const array_list<point>& points, const double max_radius, const double resolutino_mm, circle& new_circle, bool check_middle_only=false); + double get_radians(const point& p1, const point& p2) const; double get_polar_radians(const point& p1) const; point get_closest_point(const point& p) const; + + bool is_over_deviation(const array_list<point>& points, const double resolution_mm); }; #define DEFAULT_RESOLUTION_MM 0.05 @@ -147,7 +152,7 @@ struct arc : circle is_arc = false; polar_start_theta = 0; polar_end_theta = 0; - + max_deviation = 0; } bool is_arc; @@ -155,10 +160,13 @@ struct arc : circle double angle_radians; double polar_start_theta; double polar_end_theta; + double max_deviation; 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, 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); + // Statis functions + static bool try_create_arc(const circle& c, const point& start_point, const point& mid_point, const point& end_point, arc& target_arc, double approximate_length, 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, arc& target_arc, double approximate_length, double resolution = DEFAULT_RESOLUTION_MM, double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT); + static bool try_create_arc(const array_list<point>& points, arc& target_arc, double approximate_length, double max_radius = DEFAULT_MAX_RADIUS_MM, double resolution = DEFAULT_RESOLUTION_MM, double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT); }; double distance_from_segment(segment s, point p); |