Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FormerLurker/ArcWelderLib.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFormerLurker <hochgebe@gmail.com>2020-11-08 21:27:34 +0300
committerFormerLurker <hochgebe@gmail.com>2020-11-08 21:27:34 +0300
commit5eb4453aed430b3c5f336030c9a6eeb6e8ed18eb (patch)
treef23df828a2b018b66571d8404b933c5f2f940b12 /ArcWelder
parent8bc8b43506c2601823cad652a33da84389381c99 (diff)
Code cleanup. Rename exe files for console and inverse processor app. Implement #15 and #16.
Diffstat (limited to 'ArcWelder')
-rw-r--r--ArcWelder/Makefile6
-rw-r--r--ArcWelder/arc_welder.cpp15
-rw-r--r--ArcWelder/arc_welder.h69
-rw-r--r--ArcWelder/segmented_arc.cpp216
-rw-r--r--ArcWelder/segmented_arc.h11
-rw-r--r--ArcWelder/segmented_shape.cpp116
-rw-r--r--ArcWelder/segmented_shape.h20
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);