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-05-17 01:17:15 +0300
committerFormerLurker <hochgebe@gmail.com>2020-05-17 01:17:15 +0300
commitd201085f565ed498d218ece1783a5c76bcfdb25d (patch)
treeaaa7304ecb0c89c0fdb5e4930e7db7a5897d907e
parentf98db3c33c4199eb966c45c9ab2e914b3a689ae1 (diff)
Add max_radius_mm and switch to polar coordinates for arc generation.
-rw-r--r--ArcWelder/arc_welder.cpp75
-rw-r--r--ArcWelder/arc_welder.h28
-rw-r--r--ArcWelder/segmented_arc.cpp83
-rw-r--r--ArcWelder/segmented_arc.h12
-rw-r--r--ArcWelder/segmented_shape.cpp162
-rw-r--r--ArcWelder/segmented_shape.h36
-rw-r--r--ArcWelderConsole/ArcWelderConsole.cpp21
-rw-r--r--ArcWelderInverseProcessor/inverse_processor.h6
-rw-r--r--ArcWelderTest/ArcWelderTest.cpp6
-rw-r--r--ArcWelderTest/ArcWelderTest.h5
-rw-r--r--GcodeProcessorLib/array_list.h2
-rw-r--r--GcodeProcessorLib/logger.cpp2
-rw-r--r--PyArcWelder/PyArcWelder.vcxproj24
-rw-r--r--PyArcWelder/py_arc_welder.cpp12
-rw-r--r--PyArcWelder/py_arc_welder.h4
-rw-r--r--PyArcWelder/py_arc_welder_extension.cpp20
-rw-r--r--PyArcWelder/py_arc_welder_extension.h10
17 files changed, 297 insertions, 211 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp
index 0d3c021..81cc467 100644
--- a/ArcWelder/arc_welder.cpp
+++ b/ArcWelder/arc_welder.cpp
@@ -32,7 +32,7 @@
#include <fstream>
#include <iomanip>
#include <sstream>
-arc_welder::arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, gcode_position_args args) : current_arc_(gcode_position_args_.position_buffer_size - 5, resolution_mm)
+arc_welder::arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, double max_radius, gcode_position_args args) : current_arc_(DEFAULT_MIN_SEGMENTS, gcode_position_args_.position_buffer_size - 5, resolution_mm, max_radius)
{
p_logger_ = log;
debug_logging_enabled_ = false;
@@ -70,14 +70,14 @@ arc_welder::arc_welder(std::string source_path, std::string target_path, logger
p_source_position_ = new gcode_position(gcode_position_args_);
}
-arc_welder::arc_welder(std::string source_path, std::string target_path, logger* log, double resolution_mm, bool g90_g91_influences_extruder, int buffer_size)
- : arc_welder(source_path, target_path, log, resolution_mm, arc_welder::get_args_(g90_g91_influences_extruder, buffer_size))
+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)
+ : arc_welder(source_path, target_path, log, resolution_mm, max_radius, arc_welder::get_args_(g90_g91_influences_extruder, buffer_size))
{
}
-arc_welder::arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, bool g90_g91_influences_extruder, int buffer_size, progress_callback callback)
- : arc_welder(source_path, target_path, log, resolution_mm, arc_welder::get_args_(g90_g91_influences_extruder, buffer_size))
+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)
+ : arc_welder(source_path, target_path, log, resolution_mm, max_radius, arc_welder::get_args_(g90_g91_influences_extruder, buffer_size))
{
progress_callback_ = callback;
}
@@ -248,7 +248,7 @@ arc_welder_results arc_welder::process()
process_gcode(cmd, false);
// Only continue to process if we've found a command and either a progress_callback_ is supplied, or debug loggin is enabled.
- if (has_gcode && (progress_callback_ != NULL || debug_logging_enabled_))
+ if (has_gcode && (progress_callback_ != NULL || info_logging_enabled_))
{
if ((lines_processed_ % read_lines_before_clock_check) == 0 && next_update_time < clock())
{
@@ -256,20 +256,7 @@ arc_welder_results arc_welder::process()
{
p_logger_->log(logger_type_, VERBOSE, "Sending progress update.");
}
- arc_welder_progress progress;
- progress.gcodes_processed = gcodes_processed_;
- progress.lines_processed = lines_processed_;
- progress.points_compressed = points_compressed_;
- progress.arcs_created = arcs_created_;
- progress.target_file_size = static_cast<long>(output_file_.tellp());
- progress.source_file_size = static_cast<long>(gcodeFile.tellg());
- // ToDo: tellg does not do what I think it does, but why?
- long bytesRemaining = file_size_ - progress.source_file_size;
- progress.percent_complete = static_cast<double>(progress.source_file_size) / static_cast<double>(file_size_) * 100.0;
- progress.seconds_elapsed = get_time_elapsed(start_clock, clock());
- double bytesPerSecond = static_cast<double>(progress.source_file_size) / progress.seconds_elapsed;
- progress.seconds_remaining = bytesRemaining / bytesPerSecond;
- continue_processing = on_progress_(progress);
+ continue_processing = on_progress_(get_progress_(static_cast<long>(gcodeFile.tellg()), static_cast<double>(start_clock)));
next_update_time = get_next_update_time();
}
}
@@ -284,36 +271,62 @@ arc_welder_results arc_welder::process()
write_unwritten_gcodes_to_file();
p_logger_->log(logger_type_, DEBUG, "Processing complete, closing source and target file.");
+ arc_welder_progress final_progress = get_progress_(static_cast<long>(file_size_), static_cast<double>(start_clock));
+ if (progress_callback_ != NULL || info_logging_enabled_)
+ {
+ // Sending final progress update message
+ on_progress_(final_progress);
+ }
+
output_file_.close();
gcodeFile.close();
const clock_t end_clock = clock();
- const double total_seconds = static_cast<double>(end_clock - start_clock) / CLOCKS_PER_SEC;
+
results.success = continue_processing;
results.cancelled = !continue_processing;
- results.progress.target_file_size = get_file_size(target_path_);
- results.progress.seconds_elapsed = total_seconds;
- results.progress.gcodes_processed = gcodes_processed_;
- results.progress.lines_processed = lines_processed_;
- results.progress.points_compressed = points_compressed_;
- results.progress.arcs_created = arcs_created_;
- results.progress.source_file_size = file_size_;
+ results.progress = final_progress;
return results;
}
-bool arc_welder::on_progress_(arc_welder_progress progress)
+bool arc_welder::on_progress_(const arc_welder_progress& progress)
{
if (progress_callback_ != NULL)
{
return progress_callback_(progress);
}
- else if (debug_logging_enabled_)
+ else if (info_logging_enabled_)
{
- p_logger_->log(logger_type_, DEBUG, progress.str());
+ p_logger_->log(logger_type_, INFO, progress.str());
}
return true;
}
+arc_welder_progress arc_welder::get_progress_(long source_file_position, double start_clock)
+{
+ arc_welder_progress progress;
+ progress.gcodes_processed = gcodes_processed_;
+ progress.lines_processed = lines_processed_;
+ progress.points_compressed = points_compressed_;
+ progress.arcs_created = arcs_created_;
+ progress.source_file_position = source_file_position;
+ progress.target_file_size = static_cast<long>(output_file_.tellp());
+ progress.source_file_size = file_size_;
+ long bytesRemaining = file_size_ - static_cast<long>(source_file_position);
+ progress.percent_complete = static_cast<double>(source_file_position) / static_cast<double>(file_size_) * 100.0;
+ progress.seconds_elapsed = get_time_elapsed(start_clock, clock());
+ double bytesPerSecond = static_cast<double>(source_file_position) / progress.seconds_elapsed;
+ progress.seconds_remaining = bytesRemaining / bytesPerSecond;
+
+ if (source_file_position > 0) {
+ progress.compression_ratio = (static_cast<float>(source_file_position) / static_cast<float>(progress.target_file_size));
+ progress.compression_percent = (1.0 - (static_cast<float>(progress.target_file_size) / static_cast<float>(source_file_position))) * 100.0f;
+ }
+
+ return progress;
+
+}
+
int arc_welder::process_gcode(parsed_command cmd, bool is_end)
{
// Update the position for the source gcode file
diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h
index 208abf3..3e501af 100644
--- a/ArcWelder/arc_welder.h
+++ b/ArcWelder/arc_welder.h
@@ -37,6 +37,8 @@
#include "unwritten_command.h"
#include "logger.h"
+#define DEFAULT_G90_G91_INFLUENCES_EXTREUDER false
+
struct arc_welder_progress {
arc_welder_progress() {
percent_complete = 0.0;
@@ -47,7 +49,10 @@ struct arc_welder_progress {
points_compressed = 0;
arcs_created = 0;
source_file_size = 0;
+ source_file_position = 0;
target_file_size = 0;
+ compression_ratio = 0;
+ compression_percent = 0;
}
double percent_complete;
double seconds_elapsed;
@@ -56,19 +61,15 @@ struct arc_welder_progress {
int lines_processed;
int points_compressed;
int arcs_created;
+ double compression_ratio;
+ double compression_percent;
+ long source_file_position;
long source_file_size;
long target_file_size;
- std::string str() {
+ std::string str() const {
std::stringstream stream;
stream << std::fixed << std::setprecision(2);
- double compression_ratio = 0;
- double target_compression_percent = 0;
-
- if (target_file_size > 0) {
- compression_ratio = (static_cast<float>(source_file_size) / static_cast<float>(target_file_size));
- target_compression_percent = (1.0 - (static_cast<float>(target_file_size) / static_cast<float>(source_file_size))) * 100.0f;
- }
stream << percent_complete << "% complete in " << seconds_elapsed << " seconds with " << seconds_remaining << " seconds remaining.";
stream << " Gcodes Processed: " << gcodes_processed;
@@ -76,7 +77,7 @@ struct arc_welder_progress {
stream << ", Points Compressed: " << points_compressed;
stream << ", ArcsCreated: " << arcs_created;
stream << ", Compression Ratio: " << compression_ratio;
- stream << ", Size Reduction: " << target_compression_percent << "% ";
+ stream << ", Size Reduction: " << compression_percent << "% ";
return stream.str();
}
};
@@ -100,16 +101,17 @@ struct arc_welder_results {
class arc_welder
{
public:
- arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, gcode_position_args args);
- arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, bool g90_g91_influences_extruder, int buffer_size);
- arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, bool g90_g91_influences_extruder, int buffer_size, progress_callback callback);
+ arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, double max_radius_mm, gcode_position_args args);
+ arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, double max_radius_mm, bool g90_g91_influences_extruder, int buffer_size);
+ arc_welder(std::string source_path, std::string target_path, logger * log, double resolution_mm, double max_radius_mm, bool g90_g91_influences_extruder, int buffer_size, progress_callback callback);
void set_logger_type(int logger_type);
virtual ~arc_welder();
arc_welder_results process();
double notification_period_seconds;
protected:
- virtual bool on_progress_(arc_welder_progress progress);
+ virtual bool on_progress_(const arc_welder_progress& progress);
private:
+ arc_welder_progress get_progress_(long source_file_position, double start_clock);
void add_arcwelder_comment_to_target();
void reset();
static gcode_position_args get_args_(bool g90_g91_influences_extruder, int buffer_size);
diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp
index 2af6bc4..28145fd 100644
--- a/ArcWelder/segmented_arc.cpp
+++ b/ArcWelder/segmented_arc.cpp
@@ -32,16 +32,16 @@
#include <stdio.h>
#include <cmath>
-segmented_arc::segmented_arc() : segmented_shape()
+segmented_arc::segmented_arc() : segmented_arc(DEFAULT_MIN_SEGMENTS, DEFAULT_MAX_SEGMENTS, DEFAULT_RESOLUTION_MM, DEFAULT_MAX_RADIUS_MM)
{
- min_segments_ = 3;
- s_stream_ << std::fixed;
}
-segmented_arc::segmented_arc(int max_segments, double resolution_mm) : segmented_shape(3, max_segments, resolution_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)
{
- min_segments_ = 3;
- s_stream_ << std::fixed;
+ gcode_buffer_[0] = '\0';
+
+ 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()
@@ -51,7 +51,7 @@ segmented_arc::~segmented_arc()
point segmented_arc::pop_front(double e_relative)
{
e_relative_ -= e_relative;
- if (points_.count() == min_segments_)
+ if (points_.count() == get_min_segments())
{
set_is_shape(false);
}
@@ -61,7 +61,7 @@ point segmented_arc::pop_back(double e_relative)
{
e_relative_ -= e_relative;
return points_.pop_back();
- if (points_.count() == min_segments_)
+ if (points_.count() == get_min_segments())
{
set_is_shape(false);
}
@@ -115,9 +115,11 @@ bool segmented_arc::try_add_point(point p, double e_relative)
return false;
}*/ // Test - see what happens without a max segment length.
}
- if (points_.count() < min_segments_ - 1)
+ if (points_.count() < get_min_segments() - 1)
{
point_added = true;
+ points_.push_back(p);
+ original_shape_length_ += distance;
}
else
{
@@ -126,8 +128,7 @@ bool segmented_arc::try_add_point(point p, double e_relative)
}
if (point_added)
{
- points_.push_back(p);
- original_shape_length_ += distance;
+
if (points_.count() > 1)
{
// Only add the relative distance to the second point on up.
@@ -135,7 +136,7 @@ bool segmented_arc::try_add_point(point p, double e_relative)
}
//std::cout << " success - " << points_.count() << " points.\n";
}
- else if (points_.count() < min_segments_ && points_.count() > 1)
+ else if (points_.count() < get_min_segments() && points_.count() > 1)
{
// If we haven't added a point, and we have exactly min_segments_,
// pull off the initial arc point and try again
@@ -155,7 +156,7 @@ bool segmented_arc::try_add_point(point p, double e_relative)
bool segmented_arc::try_add_point_internal_(point p, double pd)
{
// If we don't have enough points (at least min_segments) return false
- if (points_.count() < min_segments_ - 1)
+ if (points_.count() < get_min_segments() - 1)
return false;
// Create a test circle
@@ -163,7 +164,7 @@ bool segmented_arc::try_add_point_internal_(point p, double pd)
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, test_circle);
+ circle_created = circle::try_create_circle(points_[0], points_[mid_point_index], p, max_radius_mm_, test_circle);
if (circle_created)
{
@@ -172,11 +173,20 @@ bool segmented_arc::try_add_point_internal_(point p, double pd)
bool circle_fits_points;
// the circle is new.. we have to test it now, which is expensive :(
- circle_fits_points = does_circle_fit_points_(test_circle, p, pd);
+ 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())
@@ -190,7 +200,7 @@ bool segmented_arc::try_add_point_internal_(point p, double pd)
}
-bool segmented_arc::does_circle_fit_points_(circle c, point p, double pd)
+bool segmented_arc::does_circle_fit_points_(const circle& c)
{
// 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.
@@ -229,36 +239,25 @@ bool segmented_arc::does_circle_fit_points_(circle c, point p, double pd)
}
}
-
- // Check the midpoint of the new point and the final point
- point point_to_test;
- if (segment::get_closest_perpendicular_point(points_[points_.count() - 1], p, 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 = 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 try_get_arc_(c, p, pd, a );
+ return try_get_arc_(c, a);
}
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);
+ //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);
}
-bool segmented_arc::try_get_arc_(circle& c, point endpoint, double additional_distance, arc &target_arc)
+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);
+ //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);
}
std::string segmented_arc::get_shape_gcode_absolute(double e, double f)
@@ -290,12 +289,12 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f)
if (utilities::greater_than_or_equal(f, 1))
{
// Add F param
- snprintf(gcode_buffer_, sizeof(gcode_buffer_), "G2 X%.3f Y%.3f I%.3f J%.3f E%.5f F%.0f", c.end_point.x, c.end_point.y, i, j, e, f);
+ snprintf(gcode_buffer_, GCODE_CHAR_BUFFER_SIZE, "G2 X%.3f Y%.3f I%.3f J%.3f E%.5f F%.0f", c.end_point.x, c.end_point.y, i, j, e, f);
}
else
{
// No F param
- snprintf(gcode_buffer_, sizeof(gcode_buffer_), "G2 X%.3f Y%.3f I%.3f J%.3f E%.5f", c.end_point.x, c.end_point.y, i, j, e);
+ snprintf(gcode_buffer_, GCODE_CHAR_BUFFER_SIZE, "G2 X%.3f Y%.3f I%.3f J%.3f E%.5f", c.end_point.x, c.end_point.y, i, j, e);
}
}
else
@@ -305,12 +304,12 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f)
if (utilities::greater_than_or_equal(f, 1))
{
// Add F param
- snprintf(gcode_buffer_, sizeof(gcode_buffer_), "G2 X%.3f Y%.3f I%.3f J%.3f F%.0f", c.end_point.x, c.end_point.y, i, j, f);
+ snprintf(gcode_buffer_, GCODE_CHAR_BUFFER_SIZE, "G2 X%.3f Y%.3f I%.3f J%.3f F%.0f", c.end_point.x, c.end_point.y, i, j, f);
}
else
{
// No F param
- snprintf(gcode_buffer_, sizeof(gcode_buffer_), "G2 X%.3f Y%.3f I%.3f J%.3f", c.end_point.x, c.end_point.y, i, j);
+ snprintf(gcode_buffer_, GCODE_CHAR_BUFFER_SIZE, "G2 X%.3f Y%.3f I%.3f J%.3f", c.end_point.x, c.end_point.y, i, j);
}
}
}
@@ -323,12 +322,12 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f)
if (utilities::greater_than_or_equal(f, 1))
{
// Add F param
- snprintf(gcode_buffer_, sizeof(gcode_buffer_), "G3 X%.3f Y%.3f I%.3f J%.3f E%.5f F%.0f", c.end_point.x, c.end_point.y, i, j, e, f);
+ snprintf(gcode_buffer_, GCODE_CHAR_BUFFER_SIZE, "G3 X%.3f Y%.3f I%.3f J%.3f E%.5f F%.0f", c.end_point.x, c.end_point.y, i, j, e, f);
}
else
{
// No F param
- snprintf(gcode_buffer_, sizeof(gcode_buffer_), "G3 X%.3f Y%.3f I%.3f J%.3f E%.5f", c.end_point.x, c.end_point.y, i, j, e);
+ snprintf(gcode_buffer_, GCODE_CHAR_BUFFER_SIZE, "G3 X%.3f Y%.3f I%.3f J%.3f E%.5f", c.end_point.x, c.end_point.y, i, j, e);
}
}
else
@@ -338,7 +337,7 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f)
if (utilities::greater_than_or_equal(f, 1))
{
// Add F param
- snprintf(gcode_buffer_, sizeof(gcode_buffer_), "G3 X%.3f Y%.3f I%.3f J%.3f F%.0f", c.end_point.x, c.end_point.y, i, j, f);
+ snprintf(gcode_buffer_, GCODE_CHAR_BUFFER_SIZE, "G3 X%.3f Y%.3f I%.3f J%.3f F%.0f", c.end_point.x, c.end_point.y, i, j, f);
}
else
{
diff --git a/ArcWelder/segmented_arc.h b/ArcWelder/segmented_arc.h
index 416fd3e..4a19b5c 100644
--- a/ArcWelder/segmented_arc.h
+++ b/ArcWelder/segmented_arc.h
@@ -29,12 +29,13 @@
#include <sstream>
#define GCODE_CHAR_BUFFER_SIZE 100
+#define DEFAULT_MAX_RADIUS_MM 1000000.0 // 1km
class segmented_arc :
public segmented_shape
{
public:
segmented_arc();
- segmented_arc(int max_segments, double resolution_mm);
+ segmented_arc(int min_segments, int max_segments, double resolution_mm, double max_radius);
virtual ~segmented_arc();
virtual bool try_add_point(point p, double e_relative);
std::string get_shape_gcode_absolute(double e, double f);
@@ -47,14 +48,13 @@ public:
// static gcode buffer
private:
- char gcode_buffer_[GCODE_CHAR_BUFFER_SIZE];
+ char gcode_buffer_[GCODE_CHAR_BUFFER_SIZE + 1];
bool try_add_point_internal_(point p, double pd);
- bool does_circle_fit_points_(circle c, point p, double additional_distance);
- bool try_get_arc_(circle& c, point endpoint, double additional_distance, arc & target_arc);
+ bool does_circle_fit_points_(const circle& c);
+ bool try_get_arc_(const circle& c, arc& target_arc);
std::string get_shape_gcode_(bool has_e, double e, double f);
- int min_segments_;
circle arc_circle_;
int test_count_ = 0;
- std::ostringstream s_stream_;
+ double max_radius_mm_;
};
diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp
index 21ca2b1..9cf0830 100644
--- a/ArcWelder/segmented_shape.cpp
+++ b/ArcWelder/segmented_shape.cpp
@@ -54,6 +54,14 @@ vector operator -(point& lhs, point& rhs) {
);
}
+vector operator -(const point& lhs, const point& rhs) {
+ return vector(
+ lhs.x - rhs.x,
+ lhs.y - rhs.y,
+ lhs.z - rhs.z
+ );
+}
+
vector operator *(vector lhs, const double& rhs) {
return vector(
lhs.x*rhs,
@@ -88,7 +96,7 @@ 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_FLOATING_POINT_TOLERANCE) || utilities::greater_than_or_equal(t, 1, CIRCLE_FLOATING_POINT_TOLERANCE))
+ 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))
return false;
d.x = p1.x + t * (p2.x - p1.x);
@@ -151,10 +159,10 @@ 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_FLOATING_POINT_TOLERANCE);
+ return utilities::less_than(difference, resolution_mm, CIRCLE_GENERATION_A_ZERO_TOLERANCE);
}
-bool circle::try_create_circle(point p1, point p2, point p3, circle& new_circle)
+bool circle::try_create_circle(point p1, point p2, point p3, double max_radius, circle& new_circle)
{
double x1 = p1.x;
double y1 = p1.y;
@@ -165,12 +173,17 @@ bool circle::try_create_circle(point p1, point p2, point p3, circle& new_circle)
double a = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - x3 * y2;
- if (utilities::is_zero(a, CIRCLE_FLOATING_POINT_TOLERANCE))
+ if (utilities::is_zero(a, CIRCLE_GENERATION_A_ZERO_TOLERANCE))
{
+#if _DEBUG
+ if (!utilities::is_zero(a, 0.000001))
+ {
+ std::cout << "This is an interesting point. Colinear";
+ }
+#endif
return false;
}
-
double b = (x1 * x1 + y1 * y1) * (y3 - y2)
+ (x2 * x2 + y2 * y2) * (y1 - y3)
+ (x3 * x3 + y3 * y3) * (y2 - y1);
@@ -182,20 +195,31 @@ bool circle::try_create_circle(point p1, point p2, point p3, circle& new_circle)
double x = -b / (2.0 * a);
double y = -c / (2.0 * a);
+ double radius = utilities::get_cartesian_distance(x, y, x1, y1);
+ if (radius > max_radius)
+ return false;
new_circle.center.x = x;
new_circle.center.y = y;
new_circle.center.z = p1.z;
- new_circle.radius = utilities::get_cartesian_distance(x, y, x1, y1);
+ new_circle.radius = radius;
return true;
}
-double circle::get_radians(point p1, point p2)
+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);
double two_r_sq = 2.0 * radius * radius;
return acos((two_r_sq - distance_sq) / two_r_sq);
}
-point circle::get_closest_point(point p)
+double circle::get_polar_radians(const point& p1) const
+{
+ double polar_radians = atan2(p1.y - center.y, p1.x - center.x);
+ if (polar_radians < 0)
+ polar_radians = (2.0 * PI_DOUBLE) + polar_radians;
+ return polar_radians;
+}
+
+point circle::get_closest_point(const point& p) const
{
vector v = p - center;
double mag = v.get_magnitude();
@@ -207,112 +231,102 @@ point circle::get_closest_point(point p)
#pragma endregion Circle Functions
#pragma region Arc Functions
-bool arc::try_create_arc(circle c, point start_point, point mid_point, 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, double resolution, arc& target_arc)
{
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)
+ /*// 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);
+ */
- bool found_angle = false;
+ double polar_start_theta = c.get_polar_radians(p1);
+ double polar_mid_theta = c.get_polar_radians(p2);
+ double polar_end_theta = c.get_polar_radians(p3);
+
+ // variable to hold radians
double angle_radians = 0;
- double angle_1, angle_2;
- if (utilities::is_equal(p1_p2_rad + p2_p3_rad + p3_p1_rad, 2 * PI_DOUBLE, CIRCLE_FLOATING_POINT_TOLERANCE))
+ int direction = 0; // 1 = counter clockwise, 2 = clockwise, 3 = unknown.
+ // Determine the direction of the arc
+ if (polar_end_theta > polar_start_theta)
{
- found_angle = true;
- angle_1 = p1_p2_rad;
- angle_2 = p2_p3_rad;
- }
- else if (utilities::is_equal(p1_p2_rad + p2_p3_rad + (2 * PI_DOUBLE - p3_p1_rad), 2 * PI_DOUBLE, CIRCLE_FLOATING_POINT_TOLERANCE))
- {
- found_angle = true;
- angle_1 = p2_p3_rad;
- angle_2 = p1_p2_rad;
+ if (polar_start_theta < polar_mid_theta && polar_mid_theta < polar_end_theta) {
+ direction = 1;
+ angle_radians = polar_end_theta - polar_start_theta;
+ }
+ else if (
+ (0.0 <= polar_mid_theta && polar_mid_theta < polar_start_theta) ||
+ (polar_end_theta < polar_mid_theta && polar_mid_theta < (2.0 * PI_DOUBLE))
+ )
+ {
+ direction = 2;
+ angle_radians = polar_start_theta + ((2.0 * PI_DOUBLE) - polar_end_theta);
+ }
}
- else
+ else if (polar_start_theta > polar_end_theta)
{
- double p1_p2_rad_lg = (2 * PI_DOUBLE - p1_p2_rad);
- if (utilities::is_equal(p1_p2_rad_lg + p2_p3_rad + p3_p1_rad, 2 * PI_DOUBLE, CIRCLE_FLOATING_POINT_TOLERANCE))
+ if (
+ (polar_start_theta < polar_mid_theta && polar_mid_theta < (2.0 * PI_DOUBLE)) ||
+ (0.0 < polar_mid_theta && polar_mid_theta < polar_end_theta)
+ )
{
- found_angle = true;
- angle_1 = p1_p2_rad_lg;
- angle_2 = p2_p3_rad;
+ direction = 1;
+ angle_radians = polar_end_theta + ((2.0 * PI_DOUBLE) - polar_start_theta);
}
- else
+ else if (polar_end_theta < polar_mid_theta && polar_mid_theta < polar_start_theta)
{
- double p2_p3_rad_lg = (2 * PI_DOUBLE - p2_p3_rad);
- if (utilities::is_equal(p1_p2_rad + p2_p3_rad_lg + p3_p1_rad, 2 * PI_DOUBLE, CIRCLE_FLOATING_POINT_TOLERANCE))
- {
- found_angle = true;
- angle_1 = p1_p2_rad;
- angle_2 = p2_p3_rad_lg;
- }
+ direction = 2;
+ angle_radians = polar_start_theta - polar_end_theta;
}
}
- if (!found_angle)
- return false; // No angle could be found, exit.
- angle_radians = angle_1 + angle_2;
- double length = angle_radians * c.radius;
- if (!utilities::is_equal(length, approximate_length, resolution))
- return false;
-
- // Very small angles can't be relied upon to calculate the sign of the arc (clockwise vs anticlockwise)
- if (angle_radians < MIN_ALLOWED_ARC_THETA)
- {
- return false;
- }
- // Calculate the sign of the angle. This should be accurate now that we have filtered out small angles and exited due to lengh mismatches
- vector v1 = p1 - p2;
- vector v2 = p3 - p2;
- // Try to make a reasonable guess about the angle's direction. This works well unless the the angle is very small
- double magnitude1 = vector::cross_product_magnitude(v1, v2);
- // We can't use our utility compare (utility::greater_that) here, else we will lose
- // very important resolution information
- bool is_clockwise = false;
-
- if (magnitude1 > 0.0)
- {
- is_clockwise = true;
- }
- // If the calculated length isn't within the resolution, exit
- if (is_clockwise)
- angle_radians *= -1.0f;
+ if (direction == 0) return false;
+ double arc_length = c.radius * angle_radians;
+ if (!utilities::is_equal(arc_length, approximate_length, resolution))
+ return false;
+
+ if(direction == 2)
+ angle_radians *= -1.0;
+
target_arc.center.x = c.center.x;
target_arc.center.y = c.center.y;
target_arc.center.z = c.center.z;
target_arc.radius = c.radius;
target_arc.start_point = start_point;
target_arc.end_point = end_point;
- target_arc.length = length;
+ target_arc.length = arc_length;
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)
+{
+ 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);
+}
#pragma endregion
-segmented_shape::segmented_shape() : points_(50)
+segmented_shape::segmented_shape() : segmented_shape(DEFAULT_MIN_SEGMENTS, DEFAULT_MAX_SEGMENTS, DEFAULT_RESOLUTION_MM )
{
- max_segments_ = 50;
- resolution_mm_ = 0.0250;
- e_relative_ = 0;
- is_shape_ = false;
- min_segments_ = 3;
- original_shape_length_ = 0;
- is_extruding_ = true;
}
+
segmented_shape::segmented_shape(int min_segments, int max_segments, double resolution_mm) : points_(max_segments)
{
+
max_segments_ = max_segments;
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;
- min_segments_ = min_segments;
+ // min segments can never be lower than 3 (the default) else there could be no compression.
+ if (min_segments < DEFAULT_MIN_SEGMENTS) min_segments_ = DEFAULT_MIN_SEGMENTS;
+ else min_segments_ = min_segments;
+
original_shape_length_ = 0;
is_extruding_ = true;
}
diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h
index 5a9b64c..53a30ee 100644
--- a/ArcWelder/segmented_shape.h
+++ b/ArcWelder/segmented_shape.h
@@ -26,14 +26,23 @@
#include <string>
#include <limits>
#define PI_DOUBLE 3.14159265358979323846
-#define CIRCLE_FLOATING_POINT_TOLERANCE 0.0000000001
+//#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
+//#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
+//#define CIRCLE_GENERATION_A_ZERO_TOLERANCE 0.000000875 // fail
+
+
#include <list>
#include "utilities.h"
#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.0001f // Safe value for full theta
//#define MIN_ALLOWED_ARC_THETA 0.0000046875f // Lowest discovered value for full theta
struct point
@@ -117,11 +126,13 @@ struct circle {
double radius;
bool is_point_on_circle(point p, double resolution_mm);
- static bool try_create_circle(point p1, point p2, point p3, circle& new_circle);
+ static bool try_create_circle(point p1, point p2, point p3, double max_radius, circle& new_circle);
- double get_radians(point p1, point p2);
+ double get_radians(const point& p1, const point& p2) const;
- point get_closest_point(point p);
+ double get_polar_radians(const point& p1) const;
+
+ point get_closest_point(const point& p) const;
};
struct arc : circle
@@ -140,19 +151,27 @@ struct arc : circle
end_point.y = 0;
end_point.z = 0;
is_arc = false;
+ polar_start_theta = 0;
+ polar_end_theta = 0;
}
bool is_arc;
double length;
double angle_radians;
+ double polar_start_theta;
+ double polar_end_theta;
point start_point;
point end_point;
- static bool try_create_arc(circle c, point start_point, point mid_point, point end_point, double approximate_length, double resolution, arc& target_arc);
-
+ bool is_point_in_arc_slice(const point& p);
+ 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);
};
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:
@@ -179,14 +198,13 @@ public:
protected:
array_list<point> points_;
void set_is_shape(bool value);
- int min_segments_;
double original_shape_length_;
double e_relative_;
bool is_extruding_;
double resolution_mm_;
bool is_shape_;
private:
-
+ int min_segments_;
int max_segments_;
};
diff --git a/ArcWelderConsole/ArcWelderConsole.cpp b/ArcWelderConsole/ArcWelderConsole.cpp
index a3b96cd..ae31e10 100644
--- a/ArcWelderConsole/ArcWelderConsole.cpp
+++ b/ArcWelderConsole/ArcWelderConsole.cpp
@@ -35,9 +35,9 @@ int main(int argc, char* argv[])
std::string source_file_path;
std::string target_file_path;
double resolution_mm;
- double resolution_mm_default = 0.05;
+ double max_radius_mm;
bool g90_g91_influences_extruder;
- bool hide_progress;
+ bool hide_progress;
std::string log_level_string;
std::string log_level_string_default = "INFO";
int log_level_value;
@@ -59,8 +59,14 @@ int main(int argc, char* argv[])
TCLAP::UnlabeledValueArg<std::string> target_arg("target", "The target gcode file containing the converted code.", true, "", "path to target gcode file");
// -r --resolution-mm
- arg_description_stream << "The resolution in mm of the of the output. Determines the maximum tool path deviation allowed during conversion. Default Value: " << resolution_mm_default;
- TCLAP::ValueArg<double> resolution_arg("r", "resolution-mm", arg_description_stream.str(), false, resolution_mm_default, "float");
+ arg_description_stream << "The resolution in mm of the of the output. Determines the maximum tool path deviation allowed during conversion. Default Value: " << DEFAULT_RESOLUTION_MM;
+ TCLAP::ValueArg<double> resolution_arg("r", "resolution-mm", arg_description_stream.str(), false, DEFAULT_RESOLUTION_MM, "float");
+
+ // -m --max-radius-mm
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The maximum radius of any arc in mm. Default Value: " << DEFAULT_MAX_RADIUS_MM;
+ TCLAP::ValueArg<double> max_radius_arg("m", "max-radius-mm", arg_description_stream.str(), false, DEFAULT_MAX_RADIUS_MM, "float");
// -g --g90-influences-extruder
TCLAP::SwitchArg g90_arg("g", "g90-influences-extruder", "If supplied, G90/G91 influences the extruder axis.", false);
@@ -88,6 +94,7 @@ int main(int argc, char* argv[])
cmd.add(source_arg);
cmd.add(target_arg);
cmd.add(resolution_arg);
+ cmd.add(max_radius_arg);
cmd.add(g90_arg);
cmd.add(hide_progress_arg);
cmd.add(log_level_arg);
@@ -99,6 +106,7 @@ int main(int argc, char* argv[])
source_file_path = source_arg.getValue();
target_file_path = target_arg.getValue();
resolution_mm = resolution_arg.getValue();
+ max_radius_mm = max_radius_arg.getValue();
g90_g91_influences_extruder = g90_arg.getValue();
hide_progress = hide_progress_arg.getValue();
log_level_string = log_level_arg.getValue();
@@ -140,6 +148,7 @@ int main(int argc, char* argv[])
log_messages << "\tSource File Path : " << source_file_path << "\n";
log_messages << "\tTarget File File : " << target_file_path << "\n";
log_messages << "\tResolution in MM : " << resolution_mm << "\n";
+ log_messages << "\tMaximum Arc Radius in MM : " << max_radius_mm << "\n";
log_messages << "\tG90/G91 Influences Extruder : " << (g90_g91_influences_extruder ? "True" : "False") << "\n";
log_messages << "\tLog Level : " << log_level_string << "\n";
log_messages << "\tHide Progress Updates : " << (hide_progress ? "True" : "False") << "\n";
@@ -147,9 +156,9 @@ int main(int argc, char* argv[])
arc_welder* p_arc_welder = NULL;
if (!hide_progress)
- p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, g90_g91_influences_extruder, 50, on_progress);
+ p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, max_radius_mm, g90_g91_influences_extruder, 50, on_progress);
else
- p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, g90_g91_influences_extruder, 50);
+ p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, max_radius_mm, g90_g91_influences_extruder, 50);
p_arc_welder->process();
diff --git a/ArcWelderInverseProcessor/inverse_processor.h b/ArcWelderInverseProcessor/inverse_processor.h
index d17386e..ae4e19b 100644
--- a/ArcWelderInverseProcessor/inverse_processor.h
+++ b/ArcWelderInverseProcessor/inverse_processor.h
@@ -35,11 +35,11 @@
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef signed char int8_t;
-#define M_PI 3.14159265358979323846f // pi
+#define M_PI 3.14159265358979323846 // pi
enum AxisEnum { X_AXIS = 0, Y_AXIS= 1, Z_AXIS = 2, E_AXIS = 3, X_HEAD = 4, Y_HEAD = 5 };
// Arc interpretation settings:
-#define DEFAULT_MM_PER_ARC_SEGMENT 100.0f // REQUIRED - The enforced maximum length of an arc segment
-#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.2f /* OPTIONAL - the enforced minimum length of an interpolated segment. Must be smaller than
+#define DEFAULT_MM_PER_ARC_SEGMENT 100.0 // REQUIRED - The enforced maximum length of an arc segment
+#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.2 /* OPTIONAL - the enforced minimum length of an interpolated segment. Must be smaller than
MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0 or ARC_SEGMENTS_PER_SEC > 0 */
// If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum calculated segment length is used.
#define DEFAULT_MIN_ARC_SEGMENTS 10 // OPTIONAL - The enforced minimum segments in a full circle of the same radius.
diff --git a/ArcWelderTest/ArcWelderTest.cpp b/ArcWelderTest/ArcWelderTest.cpp
index 58585d0..97bd44d 100644
--- a/ArcWelderTest/ArcWelderTest.cpp
+++ b/ArcWelderTest/ArcWelderTest.cpp
@@ -230,7 +230,8 @@ static gcode_position_args get_5_extruder_position_args()
static void TestAntiStutter(std::string filePath)
{
- double max_resolution = 0.05;
+ double max_resolution = DEFAULT_RESOLUTION_MM;
+ double max_radius_mm = DEFAULT_MAX_RADIUS_MM;
std::vector<std::string> logger_names;
logger_names.push_back("arc_welder.gcode_conversion");
std::vector<int> logger_levels;
@@ -240,7 +241,7 @@ static void TestAntiStutter(std::string filePath)
p_logger->set_log_level(INFO);
//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_GYROID_ABSOLUTE_E_NOWIPE, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, false, 50, on_progress);
+ arc_welder arc_welder_obj(BENCHY_GYROID_RELATIVE_E_NOWIPE, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, max_radius_mm, false, 50, on_progress);
//BENCHY_LAYER_1GCODE
//SMALL_TEST
//FACE_SHIELD
@@ -257,6 +258,7 @@ static void TestAntiStutter(std::string filePath)
//ORCHID_POD
//DIFFICULT_CURVES
//ISSUE_PRICKLYPEAR_LAYER_0_114
+ //BARBARIAN
arc_welder_obj.process();
p_logger->log(0, INFO, "Processing Complete.");
delete p_logger;
diff --git a/ArcWelderTest/ArcWelderTest.h b/ArcWelderTest/ArcWelderTest.h
index 9b5c3ea..d14e993 100644
--- a/ArcWelderTest/ArcWelderTest.h
+++ b/ArcWelderTest/ArcWelderTest.h
@@ -69,5 +69,8 @@ static std::string ARC_GYROID_BENCHY_DIFFICULT = "C:\\Users\\Brad\\Documents\\3D
static std::string SIX_SPEED_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\6_speed_test.gcode";
// Issues
static std::string ISSUE_MIMUPREFERIDA = "C:\\Users\\Brad\\Documents\\AntiStutter\\Issues\\MIMUPREFERIDA\\TESTSTUTTER.gcode";
-static std::string ISSUE_PRICKLYPEAR = "C:\\Users\\Brad\\Documents\\AntiStutter\\Issues\\PricklyPear\\Barbarian.gcode";
+static std::string BARBARIAN = "C:\\Users\\Brad\\Documents\\AntiStutter\\Issues\\PricklyPear\\Barbarian.gcode";
static std::string ISSUE_PRICKLYPEAR_LAYER_0_114 = "C:\\Users\\Brad\\Documents\\AntiStutter\\Issues\\PricklyPear\\Layers0_114.gcode";
+// Sanity tests
+static std::string COLINEAR_TEST_1 = "C:\\Users\\Brad\\Documents\\AntiStutter\\Sanity Checks\\G2_colinear_test.gcode";
+
diff --git a/GcodeProcessorLib/array_list.h b/GcodeProcessorLib/array_list.h
index a5ce323..94862f3 100644
--- a/GcodeProcessorLib/array_list.h
+++ b/GcodeProcessorLib/array_list.h
@@ -125,7 +125,7 @@ public:
return items_[(front_index_ + index + max_size_) % max_size_];
}
- int count()
+ int count() const
{
return count_;
diff --git a/GcodeProcessorLib/logger.cpp b/GcodeProcessorLib/logger.cpp
index 4af28d6..0118e52 100644
--- a/GcodeProcessorLib/logger.cpp
+++ b/GcodeProcessorLib/logger.cpp
@@ -24,7 +24,7 @@
logger::logger(std::vector<std::string> names, std::vector<int> levels) {
// set to true by default, but can be changed by inheritance to support mandatory innitialization (for python or other integrations)
loggers_created_ = true;
- num_loggers_ = names.size();
+ num_loggers_ = static_cast<int>(names.size());
logger_names_ = new std::string[static_cast<int>(num_loggers_)];
logger_levels_ = new int[static_cast<int>(num_loggers_)];
// this is slow due to the vectors, but it is trivial. Could switch to an iterator
diff --git a/PyArcWelder/PyArcWelder.vcxproj b/PyArcWelder/PyArcWelder.vcxproj
index 3f6138f..3888cca 100644
--- a/PyArcWelder/PyArcWelder.vcxproj
+++ b/PyArcWelder/PyArcWelder.vcxproj
@@ -26,26 +26,26 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
@@ -71,19 +71,19 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
- <IncludePath>C:\Python27\include;$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
+ <IncludePath>C:\Python38\include;$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
- <IncludePath>C:\Python27\include;$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
+ <IncludePath>C:\Python38\include;$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
- <IncludePath>C:\Python27\include;$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
+ <IncludePath>C:\Python38\include;$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
- <IncludePath>C:\Python27\include;$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
+ <IncludePath>C:\Python38\include;$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -95,7 +95,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalLibraryDirectories>C:\Python27\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>C:\Python38\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>
@@ -112,7 +112,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalLibraryDirectories>C:\Python27\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>C:\Python38\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>
@@ -133,7 +133,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalLibraryDirectories>C:\Python27\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>C:\Python38\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>$(SolutionDir)\DeployCodeToPlugin.bat $(SolutionDir) C:\Users\Brad\source\repos\ArcWelderPlugin\</Command>
@@ -153,7 +153,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalLibraryDirectories>C:\Python27\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>C:\Python38\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>$(SolutionDir)\DeployCodeToPlugin.bat $(SolutionDir) C:\Users\Brad\source\repos\ArcWelderPlugin\</Command>
diff --git a/PyArcWelder/py_arc_welder.cpp b/PyArcWelder/py_arc_welder.cpp
index 7844cfe..302aa95 100644
--- a/PyArcWelder/py_arc_welder.cpp
+++ b/PyArcWelder/py_arc_welder.cpp
@@ -25,7 +25,7 @@
PyObject* py_arc_welder::build_py_progress(arc_welder_progress progress)
{
- PyObject* py_progress = Py_BuildValue("{s:d,s:d,s:d,s:i,s:i,s:i,s:i,s:i,s:i}",
+ PyObject* py_progress = Py_BuildValue("{s:d,s:d,s:d,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:f,s:f}",
u8"percent_complete",
progress.percent_complete,
u8"seconds_elapsed",
@@ -40,15 +40,21 @@ PyObject* py_arc_welder::build_py_progress(arc_welder_progress progress)
progress.points_compressed,
u8"arcs_created",
progress.arcs_created,
+ u8"source_file_position",
+ progress.source_file_position,
u8"source_file_size",
progress.source_file_size,
u8"target_file_size",
- progress.target_file_size
+ progress.target_file_size,
+ u8"compression_ratio",
+ progress.compression_ratio,
+ u8"compression_percent",
+ progress.compression_percent
);
return py_progress;
}
-bool py_arc_welder::on_progress_(arc_welder_progress progress)
+bool py_arc_welder::on_progress_(const arc_welder_progress& progress)
{
PyObject* py_dict = py_arc_welder::build_py_progress(progress);
if (py_dict == NULL)
diff --git a/PyArcWelder/py_arc_welder.h b/PyArcWelder/py_arc_welder.h
index b116791..ef56715 100644
--- a/PyArcWelder/py_arc_welder.h
+++ b/PyArcWelder/py_arc_welder.h
@@ -34,7 +34,7 @@
class py_arc_welder : public arc_welder
{
public:
- py_arc_welder(std::string source_path, std::string target_path, py_logger* logger, double resolution_mm, bool g90_g91_influences_extruder, int buffer_size, PyObject* py_progress_callback):arc_welder(source_path, target_path, logger, resolution_mm, g90_g91_influences_extruder, buffer_size)
+ py_arc_welder(std::string source_path, std::string target_path, py_logger* logger, double resolution_mm, double max_radius, bool g90_g91_influences_extruder, int buffer_size, PyObject* py_progress_callback):arc_welder(source_path, target_path, logger, resolution_mm, max_radius, g90_g91_influences_extruder, buffer_size)
{
py_progress_callback_ = py_progress_callback;
}
@@ -43,7 +43,7 @@ public:
}
static PyObject* build_py_progress(arc_welder_progress progress);
protected:
- virtual bool on_progress_(arc_welder_progress progress);
+ virtual bool on_progress_(const arc_welder_progress& progress);
private:
PyObject* py_progress_callback_;
};
diff --git a/PyArcWelder/py_arc_welder_extension.cpp b/PyArcWelder/py_arc_welder_extension.cpp
index ca60196..7879909 100644
--- a/PyArcWelder/py_arc_welder_extension.cpp
+++ b/PyArcWelder/py_arc_welder_extension.cpp
@@ -188,13 +188,14 @@ extern "C"
std::stringstream stream;
stream << "py_gcode_arc_converter.ConvertFile - Parameters received: source_file_path: '" <<
args.source_file_path << "', target_file_path:'" << args.target_file_path << "' resolution_mm:" <<
- args.resolution_mm << ", g90_91_influences_extruder: " << (args.g90_g91_influences_extruder ? "True" : "False") << "\n";
+ args.resolution_mm << "' max_radius_mm:" <<
+ args.max_radius_mm << ", g90_91_influences_extruder: " << (args.g90_g91_influences_extruder ? "True" : "False") << "\n";
p_py_logger->log(GCODE_CONVERSION, INFO, stream.str());
std::string message = "py_gcode_arc_converter.ConvertFile - Beginning Arc Conversion.";
p_py_logger->log(GCODE_CONVERSION, INFO, message);
- py_arc_welder arc_welder_obj(args.source_file_path, args.target_file_path, p_py_logger, args.resolution_mm, args.g90_g91_influences_extruder, 50, py_progress_callback);
+ py_arc_welder arc_welder_obj(args.source_file_path, args.target_file_path, p_py_logger, args.resolution_mm, args.max_radius_mm, args.g90_g91_influences_extruder, 50, py_progress_callback);
arc_welder_results results = arc_welder_obj.process();
message = "py_gcode_arc_converter.ConvertFile - Arc Conversion Complete.";
p_py_logger->log(GCODE_CONVERSION, INFO, message);
@@ -259,6 +260,21 @@ static bool ParseArgs(PyObject* py_args, py_gcode_arc_args& args, PyObject** py_
{
args.resolution_mm = 0.05; // Set to the default if no resolution is provided, or if it is less than 0.
}
+
+ // Extract the max_radius in mm
+ PyObject* py_max_radius_mm = PyDict_GetItemString(py_args, "max_radius_mm");
+ if (py_max_radius_mm == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the max_radius_mm parameter from the args.";
+ p_py_logger->log_exception(GCODE_CONVERSION, message);
+ return false;
+ }
+ args.max_radius_mm = gcode_arc_converter::PyFloatOrInt_AsDouble(py_max_radius_mm);
+ if (args.max_radius_mm > DEFAULT_MAX_RADIUS_MM)
+ {
+ args.max_radius_mm = DEFAULT_MAX_RADIUS_MM; // Set to the default if no resolution is provided, or if it is less than 0.
+ }
+
// Extract G90/G91 influences extruder
// g90_influences_extruder
PyObject* py_g90_g91_influences_extruder = PyDict_GetItemString(py_args, "g90_g91_influences_extruder");
diff --git a/PyArcWelder/py_arc_welder_extension.h b/PyArcWelder/py_arc_welder_extension.h
index 47b7215..068621b 100644
--- a/PyArcWelder/py_arc_welder_extension.h
+++ b/PyArcWelder/py_arc_welder_extension.h
@@ -30,6 +30,7 @@
#endif
#include <string>
#include "py_logger.h"
+#include "arc_welder.h"
extern "C"
{
#if PY_MAJOR_VERSION >= 3
@@ -44,14 +45,16 @@ struct py_gcode_arc_args {
py_gcode_arc_args() {
source_file_path = "";
target_file_path = "";
- resolution_mm = 0.05;
- g90_g91_influences_extruder = false;
+ resolution_mm = DEFAULT_RESOLUTION_MM;
+ max_radius_mm = DEFAULT_MAX_RADIUS_MM;
+ g90_g91_influences_extruder = DEFAULT_G90_G91_INFLUENCES_EXTREUDER;
log_level = 0;
}
- py_gcode_arc_args(std::string source_file_path_, std::string target_file_path_, double resolution_mm_, bool g90_g91_influences_extruder_, int log_level_) {
+ py_gcode_arc_args(std::string source_file_path_, std::string target_file_path_, double resolution_mm_, double max_radius_mm_, bool g90_g91_influences_extruder_, int log_level_) {
source_file_path = source_file_path_;
target_file_path = target_file_path_;
resolution_mm = resolution_mm_;
+ max_radius_mm = max_radius_mm_;
g90_g91_influences_extruder = g90_g91_influences_extruder_;
log_level = log_level_;
}
@@ -59,6 +62,7 @@ struct py_gcode_arc_args {
std::string target_file_path;
double resolution_mm;
bool g90_g91_influences_extruder;
+ double max_radius_mm;
int log_level;
};