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>2021-07-06 02:57:33 +0300
committerFormerLurker <hochgebe@gmail.com>2021-07-06 02:57:33 +0300
commit9d3361e145c806a2ea0d3c7f1f6fc7252e4d0ef1 (patch)
tree52de3bf32785619982801e542c4121908916d145
parentb2e44aa85c9da175c6e78fd909c9f92531f5f393 (diff)
Add alpha gcode length restrictions. Enhance output statistics. Create arc_welder_args. Add new progress type args to command line processor.
-rw-r--r--ArcWelder/arc_welder.cpp165
-rw-r--r--ArcWelder/arc_welder.h174
-rw-r--r--ArcWelder/segmented_arc.cpp83
-rw-r--r--ArcWelder/segmented_arc.h13
-rw-r--r--ArcWelder/segmented_shape.cpp8
-rw-r--r--ArcWelder/segmented_shape.h20
-rw-r--r--ArcWelder/unwritten_command.h34
-rw-r--r--ArcWelderConsole/ArcWelderConsole.cpp258
-rw-r--r--ArcWelderConsole/ArcWelderConsole.h6
-rw-r--r--ArcWelderTest/ArcWelderTest.cpp46
-rw-r--r--ArcWelderTest/ArcWelderTest.h2
-rw-r--r--GcodeProcessorLib/logger.cpp14
-rw-r--r--GcodeProcessorLib/logger.h5
-rw-r--r--GcodeProcessorLib/utilities.cpp2
-rw-r--r--GcodeProcessorLib/utilities.h1
-rw-r--r--PyArcWelder/py_arc_welder.cpp507
-rw-r--r--PyArcWelder/py_arc_welder.h63
-rw-r--r--PyArcWelder/py_arc_welder_extension.cpp257
-rw-r--r--PyArcWelder/py_arc_welder_extension.h71
19 files changed, 947 insertions, 782 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp
index b45f9e9..0531a67 100644
--- a/ArcWelder/arc_welder.cpp
+++ b/ArcWelder/arc_welder.cpp
@@ -52,6 +52,7 @@ arc_welder::arc_welder(
unsigned char default_xyz_precision,
unsigned char default_e_precision,
double extrusion_rate_variance_percent,
+ int max_gcode_length,
int buffer_size,
progress_callback callback) : current_arc_(
DEFAULT_MIN_SEGMENTS,
@@ -63,13 +64,19 @@ arc_welder::arc_welder(
mm_per_arc_segment,
allow_3d_arcs,
default_xyz_precision,
- default_e_precision
+ default_e_precision,
+ max_gcode_length
),
segment_statistics_(
segment_statistic_lengths,
segment_statistic_lengths_count,
log
- )
+ ),
+ travel_statistics_(
+ segment_statistic_lengths,
+ segment_statistic_lengths_count,
+ log
+ )
{
p_logger_ = log;
debug_logging_enabled_ = false;
@@ -203,24 +210,6 @@ arc_welder_results results;
error_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, ERROR);
std::stringstream stream;
- stream << std::fixed << std::setprecision(2);
- 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()
- << "%, extrusion_rate_variance_percent: " << extrusion_rate_variance_percent_
- << "%, max_radius_mm:" << current_arc_.get_max_radius()
- << ", min_arc_segments:" << std::setprecision(0) <<current_arc_.get_min_arc_segments()
- << ", mm_per_arc_segment:" << std::setprecision(0) << current_arc_.get_mm_per_arc_segment()
- << ", g90_91_influences_extruder: " << (p_source_position_->get_g90_91_influences_extruder() ? "True" : "False")
- << ", allow_3d_arcs: " << (allow_3d_arcs_ ? "True" : "False")
- << ", allow_travel_arcs: " << (allow_travel_arcs_ ? "True" : "False")
- << ", allow_dynamic_precision: " << (allow_dynamic_precision_ ? "True" : "False")
- << ", default_xyz_precision: " << std::setprecision(0) << static_cast<double>(current_arc_.get_xyz_precision())
- << ", default_e_precision: " << std::setprecision(0) << static_cast<double>(current_arc_.get_e_precision());
- p_logger_->log(logger_type_, INFO, stream.str());
-
-
// reset tracking variables
reset();
// local variable to hold the progress update return. If it's false, we will exit.
@@ -236,6 +225,28 @@ arc_welder_results results;
stream.str("");
stream << "Source file size: " << file_size_;
p_logger_->log(logger_type_, DEBUG, stream.str());
+
+ // Determine if we need to overwrite the source file
+ bool overwrite_source_file = false;
+ std::string temp_file_path;
+ if (source_path_ == target_path_)
+ {
+ overwrite_source_file = true;
+ if (!utilities::get_temp_file_path_for_file(source_path_, temp_file_path))
+ {
+ results.success = false;
+ results.message = "The source and target path are the same, but a temporary file path could not be created. Are the paths empty?";
+ p_logger_->log_exception(logger_type_, results.message);
+ return results;
+ }
+
+ stream.clear();
+ stream.str("");
+ stream << "Source and target path are the same. The source file will be overwritten. Temporary file path: " << temp_file_path;
+ p_logger_->log(logger_type_, DEBUG, stream.str());
+ target_path_ = temp_file_path;
+ }
+
// Create the source file read stream and target write stream
std::ifstream gcodeFile;
p_logger_->log(logger_type_, DEBUG, "Opening the source file for reading.");
@@ -340,6 +351,7 @@ arc_welder_results results;
}
p_logger_->log(logger_type_, DEBUG, "Writing all unwritten gcodes to the target file.");
write_unwritten_gcodes_to_file();
+
p_logger_->log(logger_type_, DEBUG, "Fetching the final progress struct.");
arc_welder_progress final_progress = get_progress_(static_cast<long>(file_size_), static_cast<double>(start_clock));
@@ -347,13 +359,26 @@ arc_welder_results results;
{
p_logger_->log(logger_type_, DEBUG, "Sending final progress update message.");
}
- on_progress_(arc_welder_progress(final_progress));
+ on_progress_(final_progress);
- p_logger_->log(logger_type_, DEBUG, "Processing complete, closing source and target file.");
+ p_logger_->log(logger_type_, DEBUG, "Closing source and target files.");
output_file_.close();
gcodeFile.close();
- const clock_t end_clock = clock();
-
+
+ if (overwrite_source_file)
+ {
+ stream.clear();
+ stream.str("");
+ stream << "Deleting the original source file at '" << source_path_ << "'.";
+ p_logger_->log(logger_type_, DEBUG, stream.str());
+ stream.clear();
+ stream.str("");
+ std::remove(source_path_.c_str());
+ stream << "Renaming temporary file at '" << target_path_ << "' to '" << source_path_ << "'.";
+ p_logger_->log(0, DEBUG, stream.str());
+ std::rename(target_path_.c_str(), source_path_.c_str());
+ }
+
results.success = continue_processing;
results.cancelled = !continue_processing;
results.progress = final_progress;
@@ -397,8 +422,14 @@ arc_welder_progress arc_welder::get_progress_(long source_file_position, double
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;
}
+ else {
+ progress.compression_ratio = 0;
+ progress.compression_percent = 0;
+ }
progress.num_firmware_compensations = current_arc_.get_num_firmware_compensations();
+ progress.num_gcode_length_exceptions = current_arc_.get_num_gcode_length_exceptions();
progress.segment_statistics = segment_statistics_;
+ progress.travel_statistics = travel_statistics_;
return progress;
}
@@ -427,7 +458,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
bool arc_added = false;
bool clear_shapes = false;
double movement_length_mm = 0;
- bool has_e_changed = extruder_current.is_extruding || extruder_current.is_retracting;
+ bool has_e_changed = extruder_current.e_relative != 0;
// Update the source file statistics
if (p_cur_pos->has_xy_position_changed)
{
@@ -441,7 +472,17 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
if (movement_length_mm > 0)
{
if (!is_reprocess)
- segment_statistics_.update(movement_length_mm, true);
+ {
+ if (has_e_changed)
+ {
+ segment_statistics_.update(movement_length_mm, true);
+ }
+ else if (allow_3d_arcs_)
+ {
+ travel_statistics_.update(movement_length_mm, true);
+ }
+
+ }
}
}
@@ -466,8 +507,8 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// We need to make sure the printer is using absolute xyz, is extruding, and the extruder axis mode is the same as that of the previous position
// TODO: Handle relative XYZ axis. This is possible, but maybe not so important.
- bool is_g1_g2 = cmd.command == "G0" || cmd.command == "G1";
- if (allow_dynamic_precision_ && is_g1_g2)
+ bool is_g0_g1 = cmd.command == "G0" || cmd.command == "G1";
+ if (allow_dynamic_precision_ && is_g0_g1)
{
for (std::vector<parsed_command_parameter>::iterator it = cmd.parameters.begin(); it != cmd.parameters.end(); ++it)
{
@@ -490,7 +531,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
if (
!is_end && cmd.is_known_command && !cmd.is_empty && (
- is_g1_g2 && z_axis_ok &&
+ is_g0_g1 && z_axis_ok &&
utilities::is_equal(p_cur_pos->x_offset, p_pre_pos->x_offset) &&
utilities::is_equal(p_cur_pos->y_offset, p_pre_pos->y_offset) &&
utilities::is_equal(p_cur_pos->z_offset, p_pre_pos->z_offset) &&
@@ -516,7 +557,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// Record the extrusion rate
previous_extrusion_rate_ = mm_extruded_per_mm_travel;
- printer_point p(p_cur_pos->get_gcode_x(), p_cur_pos->get_gcode_y(), p_cur_pos->get_gcode_z(), extruder_current.e_relative, movement_length_mm);
+ printer_point p(p_cur_pos->get_gcode_x(), p_cur_pos->get_gcode_y(), p_cur_pos->get_gcode_z(), extruder_current.get_offset_e() ,extruder_current.e_relative, p_cur_pos->f, movement_length_mm, p_pre_pos->is_extruder_relative);
if (!waiting_for_arc_)
{
if (debug_logging_enabled_)
@@ -525,7 +566,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
}
write_unwritten_gcodes_to_file();
// add the previous point as the starting point for the current arc
- printer_point previous_p(p_pre_pos->get_gcode_x(), p_pre_pos->get_gcode_y(), p_pre_pos->get_gcode_z(), previous_extruder.e_relative, 0);
+ printer_point previous_p(p_pre_pos->get_gcode_x(), p_pre_pos->get_gcode_y(), p_pre_pos->get_gcode_z(), previous_extruder.get_offset_e(),previous_extruder.e_relative, p_pre_pos->f, 0, p_pre_pos->is_extruder_relative);
// Don't add any extrusion, or you will over extrude!
//std::cout << "Trying to add first point (" << p.x << "," << p.y << "," << p.z << ")...";
@@ -652,8 +693,6 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// Reset the previous extrusion rate
previous_extrusion_rate_ = 0;
}
-
-
if (!arc_added && !(cmd.is_empty && cmd.comment.length() == 0))
{
@@ -677,7 +716,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// update our statistics
points_compressed_ += current_arc_.get_num_segments()-1;
arcs_created_++; // increment the number of generated arcs
- write_arc_gcodes(p_pre_pos->is_extruder_relative, p_pre_pos->f);
+ write_arc_gcodes(p_pre_pos->f);
// Now clear the arc and flag the processor as not waiting for an arc
waiting_for_arc_ = false;
current_arc_.clear();
@@ -721,7 +760,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// This might not work....
//position* cur_pos = p_source_position_->get_current_position_ptr();
- unwritten_commands_.push_back(unwritten_command(cmd, is_previous_extruder_relative, movement_length_mm));
+ unwritten_commands_.push_back(unwritten_command(cmd, is_previous_extruder_relative, !has_e_changed && is_g0_g1, movement_length_mm));
}
else if (!waiting_for_arc_)
@@ -732,7 +771,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
return lines_written;
}
-void arc_welder::write_arc_gcodes(bool is_extruder_relative, double current_feedrate)
+void arc_welder::write_arc_gcodes(double current_feedrate)
{
std::string comment = get_comment_for_arc();
@@ -742,7 +781,7 @@ void arc_welder::write_arc_gcodes(bool is_extruder_relative, double current_feed
int num_segments = current_arc_.get_num_segments() - 1;
for (int index = 0; index < num_segments; index++)
{
- while (!unwritten_commands_.pop_back().is_g1_g2);
+ while (!unwritten_commands_.pop_back().is_g0_g1);
}
// Undo the current command, since it isn't included in the arc
@@ -754,16 +793,8 @@ void arc_welder::write_arc_gcodes(bool is_extruder_relative, double current_feed
}
// Craete the arc gcode
- std::string gcode;
- if (is_extruder_relative) {
- gcode = get_arc_gcode_relative(current_feedrate, comment);
- }
-
- else {
- gcode = get_arc_gcode_absolute(p_source_position_->get_current_position_ptr()->get_current_extruder().get_offset_e(), current_feedrate, comment);
- }
-
-
+ std::string gcode = get_arc_gcode(comment);
+
if (debug_logging_enabled_)
{
char buffer[20];
@@ -779,11 +810,16 @@ void arc_welder::write_arc_gcodes(bool is_extruder_relative, double current_feed
write_unwritten_gcodes_to_file();
// Update the current extrusion statistics for the current arc gcode
- segment_statistics_.update(current_arc_.get_shape_length() , false);
+ if (current_arc_.get_shape_e_relative() != 0)
+ {
+ segment_statistics_.update(current_arc_.get_shape_length(), false);
+
+ }
+ else if (allow_3d_arcs_){
+ travel_statistics_.update(current_arc_.get_shape_length(), false);
+ }
// now write the current arc to the file
write_gcode_to_file(gcode);
-
-
}
std::string arc_welder::get_comment_for_arc()
@@ -830,9 +866,15 @@ int arc_welder::write_unwritten_gcodes_to_file()
{
// The the current unwritten position and remove it from the list
unwritten_command p = unwritten_commands_.pop_front();
- if (p.extrusion_length > 0)
+ if(p.is_g0_g1 && p.length > 0)
{
- segment_statistics_.update(p.extrusion_length, false);
+ if (!p.is_travel)
+ {
+ segment_statistics_.update(p.length, false);
+ }
+ else if (allow_3d_arcs_) {
+ travel_statistics_.update(p.length, false);
+ }
}
lines_to_write.append(p.to_string()).append("\n");
}
@@ -841,27 +883,12 @@ int arc_welder::write_unwritten_gcodes_to_file()
return size;
}
-std::string arc_welder::get_arc_gcode_relative(double f, const std::string comment)
-{
- // Write gcode to file
- std::string gcode;
-
- gcode = current_arc_.get_shape_gcode_relative(f);
-
- if (comment.length() > 0)
- {
- gcode += ";" + comment;
- }
- return gcode;
-
-}
-
-std::string arc_welder::get_arc_gcode_absolute(double e, double f, const std::string comment)
+std::string arc_welder::get_arc_gcode(const std::string comment)
{
// Write gcode to file
std::string gcode;
- gcode = current_arc_.get_shape_gcode_absolute(e, f);
+ gcode = current_arc_.get_shape_gcode();
if (comment.length() > 0)
{
diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h
index 98564ec..fc5bb84 100644
--- a/ArcWelder/arc_welder.h
+++ b/ArcWelder/arc_welder.h
@@ -44,9 +44,6 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
-
-#define DEFAULT_G90_G91_INFLUENCES_EXTREUDER false
-
static const int segment_statistic_lengths_count = 12;
const double segment_statistic_lengths[] = { 0.002f, 0.005f, 0.01f, 0.05f, 0.1f, 0.5f, 1.0f, 5.0f, 10.0f, 20.0f, 50.0f, 100.0f };
@@ -346,7 +343,7 @@ private:
// Struct to hold the progress, statistics, and return values
struct arc_welder_progress {
- arc_welder_progress() : segment_statistics(segment_statistic_lengths, segment_statistic_lengths_count, NULL) {
+ arc_welder_progress() : segment_statistics(segment_statistic_lengths, segment_statistic_lengths_count, NULL), travel_statistics(segment_statistic_lengths, segment_statistic_lengths_count, NULL) {
percent_complete = 0.0;
seconds_elapsed = 0.0;
seconds_remaining = 0.0;
@@ -356,6 +353,7 @@ struct arc_welder_progress {
arcs_created = 0;
arcs_aborted_by_flow_rate = 0;
num_firmware_compensations = 0;
+ num_gcode_length_exceptions = 0;
source_file_size = 0;
source_file_position = 0;
target_file_size = 0;
@@ -371,12 +369,30 @@ struct arc_welder_progress {
int arcs_created;
int arcs_aborted_by_flow_rate;
int num_firmware_compensations;
+ int num_gcode_length_exceptions;
double compression_ratio;
double compression_percent;
long source_file_position;
long source_file_size;
long target_file_size;
source_target_segment_statistics segment_statistics;
+ source_target_segment_statistics travel_statistics;
+
+ std::string simple_progress_str() const {
+ std::stringstream stream;
+ if (percent_complete == 0) {
+ stream << " 00.0% complete - Estimating remaining time.";
+ }
+ else if (percent_complete == 100)
+ {
+ stream << "100.0% complete - " << seconds_elapsed << " seconds total.";
+ }
+ else {
+ stream << " " << std::fixed << std::setprecision(1) << std::setfill('0') << std::setw(4) << percent_complete << "% complete - Estimated " << std::setprecision(0) << std::setw(-1) << seconds_remaining << " of " << seconds_elapsed + seconds_remaining << " seconds remaing.";
+ }
+
+ return stream.str();
+ }
std::string str() const {
std::stringstream stream;
@@ -389,19 +405,128 @@ struct arc_welder_progress {
stream << ", arcs_created: " << arcs_created;
stream << ", arcs_aborted_by_flowrate: " << arcs_aborted_by_flow_rate;
stream << ", num_firmware_compensations: " << num_firmware_compensations;
+ stream << ", num_gcode_length_exceptions: " << num_gcode_length_exceptions;
stream << ", compression_ratio: " << compression_ratio;
stream << ", size_reduction: " << compression_percent << "% ";
return stream.str();
}
std::string detail_str() const {
std::stringstream stream;
- stream << "\n" << "Extrusion/Retraction Counts" << "\n" << segment_statistics.str() << "\n";
+ if (travel_statistics.total_count_source > 0)
+ {
+ stream << "Target File Travel Statistics:" << "\n" << travel_statistics.str() << "\n";
+ }
+
+ stream << "\n" << "Target File Extrusion Statistics:" << "\n" << segment_statistics.str() << "\n";
+
return stream.str();
}
};
-
// define the progress callback type
typedef bool(*progress_callback)(arc_welder_progress, logger* p_logger, int logger_type);
+// LOGGER_NAME
+#define ARC_WELDER_LOGGER_NAME "arc_welder.gcode_conversion"
+// Default argument values
+#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false
+#define DEFAULT_GCODE_BUFFER_SIZE 10
+#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false
+#define DEFAULT_ALLOW_DYNAMIC_PRECISION false
+#define DEFAULT_ALLOW_TRAVEL_ARCS false
+#define DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT 0.05
+#define DEFAULT_CONVERT_TRAVEL_MOVES false
+
+
+struct arc_welder_args
+{
+ arc_welder_args() :
+ source_path(""),
+ target_path(""),
+ log(NULL),
+ resolution_mm(DEFAULT_RESOLUTION_MM),
+ path_tolerance_percent(ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT),
+ max_radius_mm(DEFAULT_MAX_RADIUS_MM),
+ min_arc_segments(DEFAULT_MIN_ARC_SEGMENTS),
+ mm_per_arc_segment(DEFAULT_MM_PER_ARC_SEGMENT),
+ g90_g91_influences_extruder(DEFAULT_G90_G91_INFLUENCES_EXTRUDER),
+ allow_3d_arcs(DEFAULT_ALLOW_3D_ARCS),
+ allow_travel_arcs(DEFAULT_ALLOW_TRAVEL_ARCS),
+ allow_dynamic_precision(DEFAULT_ALLOW_DYNAMIC_PRECISION),
+ default_xyz_precision(DEFAULT_XYZ_PRECISION),
+ default_e_precision(DEFAULT_E_PRECISION),
+ extrusion_rate_variance_percent(DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT),
+ max_gcode_length(DEFAULT_MAX_GCODE_LENGTH),
+ buffer_size(DEFAULT_GCODE_BUFFER_SIZE),
+ callback(NULL){};
+
+ arc_welder_args(std::string source, std::string target, logger* ptr_log) : arc_welder_args()
+ {
+ source_path = source;
+ target_path = target;
+ log = ptr_log;
+ }
+ std::string source_path;
+ std::string target_path;
+ logger* log;
+ double resolution_mm;
+ double path_tolerance_percent;
+ double max_radius_mm;
+ int min_arc_segments;
+ double mm_per_arc_segment;
+ bool g90_g91_influences_extruder;
+ bool allow_3d_arcs;
+ bool allow_travel_arcs;
+ bool allow_dynamic_precision;
+ unsigned char default_xyz_precision;
+ unsigned char default_e_precision;
+ double extrusion_rate_variance_percent;
+ int buffer_size;
+ int max_gcode_length;
+
+ progress_callback callback;
+
+ std::string str() const {
+ std::string log_level_name = "NO_LOGGING";
+ if (log != NULL)
+ {
+ log_level_name = log->get_log_level_name(ARC_WELDER_LOGGER_NAME);
+ }
+ std::stringstream stream;
+ stream << "Arc Welder Arguments\n";
+ stream << std::fixed << std::setprecision(2);
+ stream << "\tSource File Path : " << source_path << "\n";
+ if (source_path == target_path)
+ {
+ stream << "\tTarget File Path (overwrite) : " << target_path << "\n";
+ }
+ else
+ {
+ stream << "\tTarget File Path : " << target_path << "\n";
+ }
+ stream << "\tResolution : " << resolution_mm << "mm (+-" << std::setprecision(5) << resolution_mm / 2.0 << "mm)\n";
+ stream << "\tPath Tolerance : " << std::setprecision(3) << path_tolerance_percent * 100.0 << "%\n";
+ stream << "\tMaximum Arc Radius : " << std::setprecision(0) << max_radius_mm << "mm\n";
+ stream << "\tMin Arc Segments : " << std::setprecision(0) << min_arc_segments << "\n";
+ stream << "\tMM Per Arc Segment : " << std::setprecision(3) << mm_per_arc_segment << "\n";
+ stream << "\tAllow 3D Arcs : " << (allow_3d_arcs ? "True" : "False") << "\n";
+ stream << "\tAllow Travel Arcs : " << (allow_travel_arcs ? "True" : "False") << "\n";
+ stream << "\tAllow Dynamic Precision : " << (allow_dynamic_precision ? "True" : "False") << "\n";
+ stream << "\tDefault XYZ Precision : " << std::setprecision(0) << static_cast<int>(default_xyz_precision) << "\n";
+ stream << "\tDefault E Precision : " << std::setprecision(0) << static_cast<int>(default_e_precision) << "\n";
+ stream << "\tExtrusion Rate Variance % : " << std::setprecision(3) << extrusion_rate_variance_percent * 100.0 << "%\n";
+ stream << "\tG90/G91 Influences Extruder : " << (g90_g91_influences_extruder ? "True" : "False") << "\n";
+ if (max_gcode_length == 0)
+ {
+ stream << "\tMax Gcode Length : Unlimited\n";
+ }
+ else {
+ stream << "\tMax Gcode Length : " << std::setprecision(0) << max_gcode_length << " characters\n";
+ }
+ stream << "\tLog Level : " << log_level_name << "\n";
+ stream << "\tHide Progress Updates : " << (callback == NULL ? "True" : "False");
+ return stream.str();
+ };
+
+};
struct arc_welder_results {
arc_welder_results() : progress()
@@ -415,12 +540,7 @@ struct arc_welder_results {
std::string message;
arc_welder_progress progress;
};
-#define DEFAULT_GCODE_BUFFER_SIZE 10
-#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false
-#define DEFAULT_ALLOW_DYNAMIC_PRECISION false
-#define DEFAULT_ALLOW_TRAVEL_ARCS false
-#define DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT 0.05
-#define DEFAULT_CONVERT_TRAVEL_MOVES false
+
class arc_welder
{
public:
@@ -440,8 +560,32 @@ public:
unsigned char default_xyz_precision,
unsigned char default_e_precision,
double extrusion_rate_variance_percent,
+ int max_gcode_length,
int buffer_size,
progress_callback callback);
+
+ arc_welder(arc_welder_args args) : arc_welder(
+ args.source_path,
+ args.target_path,
+ args.log,
+ args.resolution_mm,
+ args.path_tolerance_percent,
+ args.max_radius_mm,
+ args.min_arc_segments,
+ args.mm_per_arc_segment,
+ args.g90_g91_influences_extruder,
+ args.allow_3d_arcs,
+ args.allow_travel_arcs,
+ args.allow_dynamic_precision,
+ args.default_xyz_precision,
+ args.default_e_precision,
+ args.extrusion_rate_variance_percent,
+ args.max_gcode_length,
+ args.buffer_size,
+ args.callback
+ ){};
+
+
void set_logger_type(int logger_type);
virtual ~arc_welder();
arc_welder_results process();
@@ -455,10 +599,9 @@ private:
static gcode_position_args get_args_(bool g90_g91_influences_extruder, int buffer_size);
progress_callback progress_callback_;
int process_gcode(parsed_command cmd, bool is_end, bool is_reprocess);
- void write_arc_gcodes(bool is_extruder_relative, double current_feedrate);
+ void write_arc_gcodes(double current_feedrate);
int write_gcode_to_file(std::string gcode);
- std::string get_arc_gcode_relative(double f, const std::string comment);
- std::string get_arc_gcode_absolute(double e, double f, const std::string comment);
+ std::string get_arc_gcode(const std::string comment);
std::string get_comment_for_arc();
int write_unwritten_gcodes_to_file();
std::string create_g92_e(double absolute_e);
@@ -477,6 +620,7 @@ private:
int arcs_created_;
int arcs_aborted_by_flow_rate_;
source_target_segment_statistics segment_statistics_;
+ source_target_segment_statistics travel_statistics_;
long get_file_size(const std::string& file_path);
double get_time_elapsed(double start_clock, double end_clock);
double get_next_update_time() const;
diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp
index 51ef57e..531c9e5 100644
--- a/ArcWelder/segmented_arc.cpp
+++ b/ArcWelder/segmented_arc.cpp
@@ -38,7 +38,10 @@ segmented_arc::segmented_arc() : segmented_shape(DEFAULT_MIN_SEGMENTS, DEFAULT_M
min_arc_segments_ = DEFAULT_MIN_ARC_SEGMENTS,
mm_per_arc_segment_ = DEFAULT_MM_PER_ARC_SEGMENT;
allow_3d_arcs_ = DEFAULT_ALLOW_3D_ARCS;
+ max_gcode_length_ = DEFAULT_MAX_GCODE_LENGTH;
+ num_gcode_length_exceptions_ = 0;
num_firmware_compensations_ = 0;
+
}
segmented_arc::segmented_arc(
@@ -51,7 +54,8 @@ segmented_arc::segmented_arc(
double mm_per_arc_segment,
bool allow_3d_arcs,
unsigned char default_xyz_precision,
- unsigned char default_e_precision
+ unsigned char default_e_precision,
+ int max_gcode_length
) : segmented_shape(min_segments, max_segments, resolution_mm, path_tolerance_percent, default_xyz_precision, default_e_precision)
{
max_radius_mm_ = max_radius_mm;
@@ -69,7 +73,15 @@ segmented_arc::segmented_arc(
min_arc_segments_ = 0;
}
allow_3d_arcs_ = allow_3d_arcs;
+ max_gcode_length_ = max_gcode_length;
+ if (max_gcode_length_ < 1)
+ {
+ max_gcode_length_ = 0;
+ }
num_firmware_compensations_ = 0;
+ num_gcode_length_exceptions_ = 0;
+
+
}
segmented_arc::~segmented_arc()
@@ -108,7 +120,10 @@ int segmented_arc::get_num_firmware_compensations() const
{
return num_firmware_compensations_;
}
-
+int segmented_arc::get_num_gcode_length_exceptions() const
+{
+ return num_gcode_length_exceptions_;
+}
double segmented_arc::get_mm_per_arc_segment() const
{
return mm_per_arc_segment_;
@@ -143,7 +158,7 @@ bool segmented_arc::try_add_point(printer_point p)
}
// Need to separate travel moves from moves with extrusion
- if (points_.count() > 2)
+ if (points_.count() > 1)
{
// We already have at least an initial point and a second point. Make cure the current point and the previous are either both
// travel moves, or both extrusion
@@ -217,6 +232,11 @@ bool segmented_arc::try_add_point_internal_(printer_point p)
if (arc::try_create_arc(points_, current_arc_, original_shape_length_, max_radius_mm_, resolution_mm_, path_tolerance_percent_, min_arc_segments_, mm_per_arc_segment_, get_xyz_tolerance(), allow_3d_arcs_))
{
bool abort_arc = false;
+ if (max_gcode_length_ > 0 && get_shape_gcode_length() > max_gcode_length_)
+ {
+ abort_arc = true;
+ num_gcode_length_exceptions_++;
+ }
if (min_arc_segments_ > 0 && mm_per_arc_segment_ > 0)
{
// Apply firmware compensation
@@ -252,7 +272,7 @@ bool segmented_arc::try_add_point_internal_(printer_point p)
// or because both I and J == 0
current_arc_ = original_arc;
}
- else if (!abort_arc)
+ else
{
if (!is_shape())
{
@@ -267,22 +287,12 @@ bool segmented_arc::try_add_point_internal_(printer_point p)
return false;
}
-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;
- return get_shape_gcode_(has_e, e_relative_, f);
-}
-
-std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) const
+std::string segmented_arc::get_shape_gcode() const
{
std::string gcode;
- // Calculate gcode size
+ double e = current_arc_.end_point.is_extruder_relative ? e_relative_ : current_arc_.end_point.e_offset;
+ double f = current_arc_.start_point.f == current_arc_.end_point.f ? 0 : current_arc_.end_point.f;
+ bool has_e = e_relative_ != 0;
bool has_f = utilities::greater_than_or_equal(f, 1);
bool has_z = allow_3d_arcs_ && !utilities::is_equal(
current_arc_.start_point.z, current_arc_.end_point.z, get_xyz_tolerance()
@@ -298,6 +308,9 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons
gcode += "G3";
}
+ // TODO: Limit Gcode Precision based on max_gcode_length
+
+
// Add X, Y, I and J
gcode += " X";
gcode += utilities::dtos(current_arc_.end_point.x, get_xyz_precision());
@@ -340,6 +353,40 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons
}
+int segmented_arc::get_shape_gcode_length()
+{
+ double e = current_arc_.end_point.is_extruder_relative ? e_relative_ : current_arc_.end_point.e_offset;
+ double f = current_arc_.start_point.f == current_arc_.end_point.f ? 0 : current_arc_.end_point.f;
+ bool has_e = e_relative_ != 0;
+ bool has_f = utilities::greater_than_or_equal(f, 1);
+ bool has_z = allow_3d_arcs_ && !utilities::is_equal(
+ current_arc_.start_point.z, current_arc_.end_point.z, get_xyz_tolerance()
+ );
+
+ int xyz_precision = get_xyz_precision();
+ int e_precision = get_e_precision();
+
+ double i = current_arc_.get_i();
+ double j = current_arc_.get_j();
+
+ int num_spaces = 3 + (has_z ? 1 : 0) + (has_e ? 1 : 0) + (has_f ? 1 : 0);
+ int num_decimal_points = 4 + (has_z ? 1 : 0) + (has_e ? 1 : 0); // note f has no decimal point
+ int num_decimals = xyz_precision * (4 + (has_z ? 1 : 0) + (has_e ? 1 : 0)); // Note f is an int
+ int num_digits = (
+ utilities::get_num_digits(current_arc_.end_point.x) +
+ utilities::get_num_digits(current_arc_.end_point.y) +
+ (has_z ? utilities::get_num_digits(current_arc_.end_point.z) : 0) +
+ utilities::get_num_digits(i) +
+ utilities::get_num_digits(j) +
+ (has_f ? utilities::get_num_digits(f) : 0)
+ );
+ // Return the length of the gcode.
+ return 3 + num_spaces + num_decimal_points + num_decimal_points + num_digits;
+
+
+
+}
+
/*
* This is an older implementation using ostringstream. It is substantially slower.
* Keep this around in case there are problems with the custom dtos function
diff --git a/ArcWelder/segmented_arc.h b/ArcWelder/segmented_arc.h
index c67c071..2c7b240 100644
--- a/ArcWelder/segmented_arc.h
+++ b/ArcWelder/segmented_arc.h
@@ -42,14 +42,14 @@ public:
double mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT,
bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS,
unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION,
- unsigned char default_e_precision = DEFAULT_E_PRECISION
+ unsigned char default_e_precision = DEFAULT_E_PRECISION,
+ int max_gcode_length = DEFAULT_MAX_GCODE_LENGTH
);
virtual ~segmented_arc();
virtual bool try_add_point(printer_point p);
virtual double get_shape_length();
- std::string get_shape_gcode_absolute(double e, double f);
- std::string get_shape_gcode_relative(double f);
-
+ std::string get_shape_gcode() const;
+ int get_shape_gcode_length();
virtual bool is_shape() const;
printer_point pop_front(double e_relative);
printer_point pop_back(double e_relative);
@@ -57,15 +57,16 @@ public:
int get_min_arc_segments() const;
double get_mm_per_arc_segment() const;
int get_num_firmware_compensations() const;
-
+ int get_num_gcode_length_exceptions() const;
private:
bool try_add_point_internal_(printer_point p);
- std::string get_shape_gcode_(bool has_e, double e, double f) const;
arc current_arc_;
double max_radius_mm_;
int min_arc_segments_;
double mm_per_arc_segment_;
int num_firmware_compensations_;
bool allow_3d_arcs_;
+ int max_gcode_length_;
+ int num_gcode_length_exceptions_;
};
diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp
index 4e17d3c..447cfbe 100644
--- a/ArcWelder/segmented_shape.cpp
+++ b/ArcWelder/segmented_shape.cpp
@@ -359,7 +359,7 @@ bool circle::is_over_deviation(const array_list<printer_point>& points, const do
double distance = utilities::get_cartesian_distance(point_to_test.x, point_to_test.y, center.x, center.y);
if (std::fabs(distance - radius) > resolution_mm)
{
- return true;
+ return true;
}
}
}
@@ -380,9 +380,9 @@ double arc::get_j() const
bool arc::try_create_arc(
const circle& c,
- const point& start_point,
- const point& mid_point,
- const point& end_point,
+ const printer_point& start_point,
+ const printer_point& mid_point,
+ const printer_point& end_point,
arc& target_arc,
double approximate_length,
double resolution,
diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h
index ec4bde9..d6e7218 100644
--- a/ArcWelder/segmented_shape.h
+++ b/ArcWelder/segmented_shape.h
@@ -36,7 +36,7 @@
#define DEFAULT_XYZ_TOLERANCE 0.001
#define DEFAULT_E_PRECISION 5
#define ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT 0.05 // one percent
-
+#define DEFAULT_MAX_GCODE_LENGTH 0 // the maximum gcode length ( < 1 = unlimited)
struct point
{
public:
@@ -53,9 +53,13 @@ public:
struct printer_point : point
{
public:
- printer_point() :point(0, 0, 0), e_relative(0), distance(0) {}
- printer_point(double x, double y, double z, double e_relative, double distance) :point(x,y,z), e_relative(e_relative), distance(distance) {}
+ printer_point() :point(0, 0, 0), e_relative(0), distance(0), is_extruder_relative(false), e_offset(0), f(0) {}
+ printer_point(double x, double y, double z, double e_offset, double e_relative, double f, double distance, bool is_extruder_relative)
+ : point(x,y,z), e_offset(e_offset), e_relative(e_relative), f(f), distance(distance), is_extruder_relative(is_extruder_relative) {}
+ bool is_extruder_relative;
+ double e_offset;
double e_relative;
+ double f;
double distance;
};
@@ -164,8 +168,8 @@ struct arc : circle
double polar_start_theta;
double polar_end_theta;
double max_deviation;
- point start_point;
- point end_point;
+ printer_point start_point;
+ printer_point end_point;
DirectionEnum direction;
double get_i() const;
double get_j() const;
@@ -185,9 +189,9 @@ struct arc : circle
private:
static bool try_create_arc(
const circle& c,
- const point& start_point,
- const point& mid_point,
- const point& end_point,
+ const printer_point& start_point,
+ const printer_point& mid_point,
+ const printer_point& end_point,
arc& target_arc,
double approximate_length,
double resolution = DEFAULT_RESOLUTION_MM,
diff --git a/ArcWelder/unwritten_command.h b/ArcWelder/unwritten_command.h
index 8f85a50..d1ed490 100644
--- a/ArcWelder/unwritten_command.h
+++ b/ArcWelder/unwritten_command.h
@@ -29,34 +29,18 @@ struct unwritten_command
{
unwritten_command() {
is_extruder_relative = false;
- e_relative = 0;
- offset_e = 0;
- extrusion_length = 0;
- is_g1_g2 = false;
+ length = 0;
+ is_g0_g1 = false;
}
- unwritten_command(parsed_command &cmd, bool is_relative, double command_length) {
- is_extruder_relative = is_relative;
- is_g1_g2 = cmd.command == "G0" || cmd.command == "G1";
- gcode = cmd.gcode;
- comment = cmd.comment;
- extrusion_length = command_length;
+ unwritten_command(parsed_command &cmd, bool is_relative, bool is_travel, double command_length)
+ : is_extruder_relative(is_relative), is_travel(is_travel), is_g0_g1(cmd.command == "G0" || cmd.command == "G1"), gcode(cmd.gcode), comment(cmd.comment), length(command_length)
+ {
+
}
- /*
- unwritten_command(position* p, double command_length) {
-
- e_relative = p->get_current_extruder().e_relative;
- offset_e = p->get_current_extruder().get_offset_e();
- is_extruder_relative = p->is_extruder_relative;
- is_g1_g2 = p->command.command == "G0" || p->command.command == "G1";
- gcode = p->command.gcode;
- comment = p->command.comment;
- extrusion_length = command_length;
- } */
- bool is_g1_g2;
+ bool is_g0_g1;
bool is_extruder_relative;
- double e_relative;
- double offset_e;
- double extrusion_length;
+ bool is_travel;
+ double length;
std::string gcode;
std::string comment;
diff --git a/ArcWelderConsole/ArcWelderConsole.cpp b/ArcWelderConsole/ArcWelderConsole.cpp
index 16a6923..e7a1ea9 100644
--- a/ArcWelderConsole/ArcWelderConsole.cpp
+++ b/ArcWelderConsole/ArcWelderConsole.cpp
@@ -34,27 +34,19 @@
#include <tclap/CmdLine.h>
#define DEFAULT_ARG_DOUBLE_PRECISION 4
+#define PROGRESS_TYPE_NONE "NONE"
+#define PROGRESS_TYPE_SIMPLE "SIMPLE"
+#define PROGRESS_TYPE_FULL "FULL"
int main(int argc, char* argv[])
{
- std::string source_file_path;
- std::string target_file_path;
- double resolution_mm;
- double max_radius_mm;
- int min_arc_segments;
- double mm_per_arc_segment;
- double path_tolerance_percent;
- bool g90_g91_influences_extruder;
- bool hide_progress;
- bool overwrite_source_file = false;
- bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS;
- bool allow_travel_arcs = DEFAULT_ALLOW_TRAVEL_ARCS;
- bool allow_dynamic_precision = DEFAULT_ALLOW_DYNAMIC_PRECISION;
- unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION;
- unsigned char default_e_precision = DEFAULT_E_PRECISION;
- double extrusion_rate_variance_percent = DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT;
+
+ arc_welder_args args;
std::string log_level_string;
std::string log_level_string_default = "INFO";
+ std::string progress_type;
+ std::string progress_type_default_string = PROGRESS_TYPE_SIMPLE;
int log_level_value;
+ bool hide_progress = false;
// Add info about the application
std::string info = "Arc Welder: Anti-Stutter - Reduces the number of gcodes per second sent to a 3D printer that supports arc commands (G2 G3).";
@@ -154,9 +146,24 @@ int main(int argc, char* argv[])
arg_description_stream << "(experimental) - The allowed variance in extrusion rate by percent. Default Value: " << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT;
TCLAP::ValueArg<double> extrusion_rate_variance_percent_arg("v", "extrusion-rate-variance-percent", arg_description_stream.str(), false, DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT, "double");
+ // -l --max-gcode-length
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The maximum length allowed for a generated G2/G3 command, not including any comments. 0 = no limit. Default Value: " << DEFAULT_MAX_GCODE_LENGTH;
+ TCLAP::ValueArg<int> max_gcode_length_arg("l", "max-gcode-length", arg_description_stream.str(), false, DEFAULT_MAX_GCODE_LENGTH, "int");
- // -g --hide-progress
- TCLAP::SwitchArg hide_progress_arg("p", "hide-progress", "If supplied, prevents progress updates from being displayed.", false);
+ // -p --progress-type
+ // -l --log-level
+ std::vector<std::string> progress_type_vector;
+ std::string progress_type_default_string = PROGRESS_TYPE_SIMPLE;
+ progress_type_vector.push_back(PROGRESS_TYPE_NONE);
+ progress_type_vector.push_back(PROGRESS_TYPE_SIMPLE);
+ progress_type_vector.push_back(PROGRESS_TYPE_FULL);
+ TCLAP::ValuesConstraint<std::string> progress_type_constraint(progress_type_vector);
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "Sets the progress type display. Default Value " << progress_type_default_string;
+ TCLAP::ValueArg<std::string> progress_type_arg("p", "progress-type", arg_description_stream.str(), false, progress_type_default_string, &progress_type_constraint);
// -l --log-level
std::vector<std::string> log_levels_vector;
@@ -188,117 +195,125 @@ int main(int argc, char* argv[])
cmd.add(default_xyz_precision_arg);
cmd.add(default_e_precision_arg);
cmd.add(extrusion_rate_variance_percent_arg);
+ cmd.add(max_gcode_length_arg);
cmd.add(g90_arg);
- cmd.add(hide_progress_arg);
+ cmd.add(progress_type_arg);
cmd.add(log_level_arg);
// Parse the argv array.
cmd.parse(argc, argv);
// Get the value parsed by each arg.
- source_file_path = source_arg.getValue();
- target_file_path = target_arg.getValue();
+ args.source_path = source_arg.getValue();
+ args.target_path = target_arg.getValue();
- if (target_file_path.size() == 0)
+ if (args.target_path.size() == 0)
{
- target_file_path = source_file_path;
+ args.target_path = args.source_path;
}
- resolution_mm = resolution_arg.getValue();
- max_radius_mm = max_radius_arg.getValue();
- min_arc_segments = min_arc_segments_arg.getValue();
- mm_per_arc_segment = mm_per_arc_segment_arg.getValue();
- path_tolerance_percent = path_tolerance_percent_arg.getValue();
- allow_3d_arcs = allow_3d_arcs_arg.getValue();
- allow_travel_arcs = allow_travel_arcs_arg.getValue();
- g90_g91_influences_extruder = g90_arg.getValue();
- allow_dynamic_precision = allow_dynamic_precision_arg.getValue();
- default_xyz_precision = default_xyz_precision_arg.getValue();
- default_e_precision = default_e_precision_arg.getValue();
- extrusion_rate_variance_percent = extrusion_rate_variance_percent_arg.getValue();
-
- hide_progress = hide_progress_arg.getValue();
+ args.resolution_mm = resolution_arg.getValue();
+ args.max_radius_mm = max_radius_arg.getValue();
+ args.min_arc_segments = min_arc_segments_arg.getValue();
+ args.mm_per_arc_segment = mm_per_arc_segment_arg.getValue();
+ args.path_tolerance_percent = path_tolerance_percent_arg.getValue();
+ args.allow_3d_arcs = allow_3d_arcs_arg.getValue();
+ args.allow_travel_arcs = allow_travel_arcs_arg.getValue();
+ args.g90_g91_influences_extruder = g90_arg.getValue();
+ args.allow_dynamic_precision = allow_dynamic_precision_arg.getValue();
+ args.default_xyz_precision = default_xyz_precision_arg.getValue();
+ args.default_e_precision = default_e_precision_arg.getValue();
+ args.extrusion_rate_variance_percent = extrusion_rate_variance_percent_arg.getValue();
+ args.max_gcode_length = max_gcode_length_arg.getValue();
+ progress_type = progress_type_arg.getValue();
log_level_string = log_level_arg.getValue();
log_level_value = -1;
// Check the entered values
bool has_error = false;
- if (resolution_mm <= 0)
+ if (args.resolution_mm <= 0)
{
- std::cerr << "error: The provided resolution of " << resolution_mm << " is negative, which is not allowed." <<std::endl;
+ std::cerr << "error: The provided resolution of " << args.resolution_mm << " is negative, which is not allowed." <<std::endl;
has_error = true;
}
- if (path_tolerance_percent <= 0)
+ if (args.path_tolerance_percent <= 0)
{
- std::cerr << "error: The provided path tolerance percentage of " << path_tolerance_percent << " is negative, which is not allowed." << std::endl;
+ std::cerr << "error: The provided path tolerance percentage of " << args.path_tolerance_percent << " is negative, which is not allowed." << std::endl;
has_error = true;
}
- if (max_radius_mm > 1000000)
+ if (args.max_radius_mm > 1000000)
{
// warning
- std::cout << "warning: The provided path max radius of " << max_radius_mm << "mm is greater than 1000000 (1km), which is not recommended." << std::endl;
+ std::cout << "warning: The provided path max radius of " << args.max_radius_mm << "mm is greater than 1000000 (1km), which is not recommended." << std::endl;
}
- if (min_arc_segments < 0)
+ if (args.min_arc_segments < 0)
{
// warning
- std::cout << "warning: The provided min_arc_segments " << min_arc_segments << " is less than zero. Setting to 0." << std::endl;
- min_arc_segments = 0;
+ std::cout << "warning: The provided min_arc_segments " << args.min_arc_segments << " is less than zero. Setting to 0." << std::endl;
+ args.min_arc_segments = 0;
}
- if (mm_per_arc_segment < 0)
+ if (args.mm_per_arc_segment < 0)
{
// warning
- std::cout << "warning: The provided mm_per_arc_segment " << mm_per_arc_segment << "mm is less than zero. Setting to 0." << std::endl;
- mm_per_arc_segment = 0;
+ std::cout << "warning: The provided mm_per_arc_segment " << args.mm_per_arc_segment << "mm is less than zero. Setting to 0." << std::endl;
+ args.mm_per_arc_segment = 0;
}
- if (path_tolerance_percent > 0.05)
+ if (args.path_tolerance_percent > 0.05)
{
// warning
- std::cout << "warning: The provided path tolerance percent of " << path_tolerance_percent << " is greater than 0.05 (5%), which is not recommended." << std::endl;
+ std::cout << "warning: The provided path tolerance percent of " << args.path_tolerance_percent << " is greater than 0.05 (5%), which is not recommended." << std::endl;
}
- else if (path_tolerance_percent < 0.0001 && path_tolerance_percent > 0)
+ else if (args.path_tolerance_percent < 0.0001 && args.path_tolerance_percent > 0)
{
// warning
- std::cout << "warning: The provided path tolerance percent of " << path_tolerance_percent << " is less than greater than 0.001 (0.1%), which is not recommended." << std::endl;
+ std::cout << "warning: The provided path tolerance percent of " << args.path_tolerance_percent << " is less than greater than 0.001 (0.1%), which is not recommended." << std::endl;
}
- if (default_xyz_precision < 3)
+ if (args.default_xyz_precision < 3)
{
// warning
- std::cout << "warning: The provided default_xyz_precision " << default_xyz_precision << "mm is less than 3, with will cause issues printing arcs. A value of 3 will be used instead." << std::endl;
- default_xyz_precision = 3;
+ std::cout << "warning: The provided default_xyz_precision " << args.default_xyz_precision << "mm is less than 3, with will cause issues printing arcs. A value of 3 will be used instead." << std::endl;
+ args.default_xyz_precision = 3;
}
- if (default_e_precision < DEFAULT_E_PRECISION)
+ if (args.default_e_precision < DEFAULT_E_PRECISION)
{
// warning
- std::cout << "warning: The provided default_e_precision " << default_e_precision << "mm is less than 3, with will cause extrusion issues. A value of 3 will be used instead." << std::endl;
- default_e_precision = 3;
+ std::cout << "warning: The provided default_e_precision " << args.default_e_precision << "mm is less than 3, with will cause extrusion issues. A value of 3 will be used instead." << std::endl;
+ args.default_e_precision = 3;
}
- if (default_xyz_precision > 6)
+ if (args.default_xyz_precision > 6)
{
// warning
- std::cout << "warning: The provided default_xyz_precision " << default_xyz_precision << "mm is greater than 6, which may cause gcode checksum errors while printing depending on your firmeware, so a value of 6 will be used instead." << std::endl;
- default_xyz_precision = 6;
+ std::cout << "warning: The provided default_xyz_precision " << args.default_xyz_precision << "mm is greater than 6, which may cause gcode checksum errors while printing depending on your firmeware, so a value of 6 will be used instead." << std::endl;
+ args.default_xyz_precision = 6;
}
- if (default_e_precision > 6)
+ if (args.default_e_precision > 6)
{
// warning
- std::cout << "warning: The provided default_e_precision " << default_e_precision << "mm is greater than 6, which may cause gcode checksum errors while printing depending on your firmeware, so value of 6 will be used instead." << std::endl;
- default_e_precision = 6;
+ std::cout << "warning: The provided default_e_precision " << args.default_e_precision << "mm is greater than 6, which may cause gcode checksum errors while printing depending on your firmeware, so value of 6 will be used instead." << std::endl;
+ args.default_e_precision = 6;
}
- if (extrusion_rate_variance_percent < 0)
+ if (args.extrusion_rate_variance_percent < 0)
{
// warning
- std::cout << "warning: The provided extrusion_rate_variance_percent " << extrusion_rate_variance_percent << " is less than 0. Setting to the default." << std::endl;
- extrusion_rate_variance_percent = DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT;
+ std::cout << "warning: The provided extrusion_rate_variance_percent " << args.extrusion_rate_variance_percent << " is less than 0. Setting to the default." << std::endl;
+ args.extrusion_rate_variance_percent = DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT;
+ }
+
+ if (args.max_gcode_length < 0)
+ {
+ // warning
+ std::cout << "warning: The provided max_gcode_length " << args.max_gcode_length << " is less than 0. Setting to the default." << std::endl;
+ args.max_gcode_length = DEFAULT_MAX_GCODE_LENGTH;
}
if (has_error)
@@ -331,95 +346,56 @@ int main(int argc, char* argv[])
// Ensure the log level name is valid
std::vector<std::string> log_names;
- log_names.push_back("arc_welder.gcode_conversion");
+ log_names.push_back(ARC_WELDER_LOGGER_NAME);
std::vector<int> log_levels;
log_levels.push_back(log_levels::DEBUG);
logger* p_logger = new logger(log_names, log_levels);
p_logger->set_log_level_by_value(log_level_value);
-
- std::stringstream log_messages;
- std::string temp_file_path = "";
- log_messages << std::fixed << std::setprecision(DEFAULT_ARG_DOUBLE_PRECISION);
- if (source_file_path == target_file_path)
+ args.log = p_logger;
+
+ arc_welder* p_arc_welder = NULL;
+
+ if (progress_type == PROGRESS_TYPE_NONE)
{
- overwrite_source_file = true;
- if (!utilities::get_temp_file_path_for_file(source_file_path, temp_file_path))
- {
- log_messages << "The source and target path are the same, but a temporary file path could not be created. Is the path empty?";
- p_logger->log(0, INFO, log_messages.str());
- log_messages.clear();
- log_messages.str("");
- }
-
- // create a uuid with a tmp extension for the temporary file
- log_messages << "Source and target path are the same. The source file will be overwritten. Temporary file path: " << temp_file_path;
- p_logger->log(0, INFO, log_messages.str());
- log_messages.clear();
- log_messages.str("");
- target_file_path = temp_file_path;
+ p_logger->log(0, INFO, "Suppressing progress messages.");
+ args.callback = on_progress_suppress;
}
- log_messages << "Processing Gcode\n";
- log_messages << "\tSource File Path : " << source_file_path << "\n";
- if (overwrite_source_file)
+ else if (progress_type == PROGRESS_TYPE_FULL)
{
- log_messages << "\tTarget File Path (overwrite) : " << target_file_path << "\n";
- log_messages << "\tTemporary File Path : " << temp_file_path << "\n";
+ p_logger->log(0, INFO, "Displaying full progress messages.");
+ args.callback = on_progress_full;
}
- else
- {
- log_messages << "\tTarget File File : " << target_file_path << "\n";
+ else {
+ args.callback = on_progress_simple;
}
-
- log_messages << "\tResolution : " << resolution_mm << "mm (+-" << std::setprecision(5) << resolution_mm/2.0 << "mm)\n";
- log_messages << "\tPath Tolerance : " << std::setprecision(3) << path_tolerance_percent*100.0 << "%\n";
- log_messages << "\tMaximum Arc Radius : " << std::setprecision(0) << max_radius_mm << "mm\n";
- log_messages << "\tMin Arc Segments : " << std::setprecision(0) << min_arc_segments << "\n";
- log_messages << "\tMM Per Arc Segment : " << std::setprecision(3) << mm_per_arc_segment << "\n";
- log_messages << "\tAllow 3D Arcs : " << (allow_3d_arcs ? "True" : "False") << "\n";
- log_messages << "\tAllow Travel Arcs : " << (allow_travel_arcs ? "True" : "False") << "\n";
- log_messages << "\tAllow Dynamic Precision : " << (allow_dynamic_precision ? "True" : "False") << "\n";
- log_messages << "\tDefault XYZ Precision : " << std::setprecision(0) << static_cast<int>(default_xyz_precision) << "\n";
- log_messages << "\tDefault E Precision : " << std::setprecision(0) << static_cast<int>(default_e_precision) << "\n";
- log_messages << "\tExtrusion Rate Variance % : " << std::setprecision(3) << extrusion_rate_variance_percent*100.0 << "%\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");
+ // Log the arguments
+ std::stringstream log_messages;
+ log_messages << "Processing GCode.";
+ p_logger->log(0, INFO, log_messages.str());
+ log_messages.clear();
+ log_messages.str("");
+ log_messages << args.str();
p_logger->log(0, INFO, log_messages.str());
- arc_welder* p_arc_welder = NULL;
-
- if (overwrite_source_file)
- {
- target_file_path = temp_file_path;
- }
- if (!hide_progress)
- p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, path_tolerance_percent, max_radius_mm, min_arc_segments, mm_per_arc_segment, g90_g91_influences_extruder, allow_3d_arcs, allow_travel_arcs, allow_dynamic_precision, default_xyz_precision, default_e_precision, extrusion_rate_variance_percent, DEFAULT_GCODE_BUFFER_SIZE, on_progress);
- else
- p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, path_tolerance_percent, max_radius_mm, min_arc_segments, mm_per_arc_segment, g90_g91_influences_extruder, allow_3d_arcs, allow_travel_arcs, allow_dynamic_precision, default_xyz_precision, default_e_precision, extrusion_rate_variance_percent, DEFAULT_GCODE_BUFFER_SIZE, suppress_progress);
+ p_arc_welder = new arc_welder(args);
+
arc_welder_results results = p_arc_welder->process();
if (results.success)
{
- log_messages.clear();
- log_messages.str("");
- log_messages << "Target file at '" << target_file_path << "' created.";
-
- if (overwrite_source_file)
+ if (args.allow_travel_arcs)
{
log_messages.clear();
log_messages.str("");
- log_messages << "Deleting the original source file at '" << source_file_path << "'.";
+ log_messages << "Target File Travel Statistics:" << std::endl << results.progress.travel_statistics.str();
p_logger->log(0, INFO, log_messages.str());
- log_messages.clear();
- log_messages.str("");
- std::remove(source_file_path.c_str());
- log_messages << "Renaming temporary file at '" << target_file_path << "' to '" << source_file_path <<"'.";
- p_logger->log(0, INFO, log_messages.str());
- std::rename(target_file_path.c_str(), source_file_path.c_str());
}
+
log_messages.clear();
log_messages.str("");
- log_messages << std::endl << results.progress.segment_statistics.str();
+ log_messages << "Target File Extrusion Statistics:" << std::endl << results.progress.segment_statistics.str();
p_logger->log(0, INFO, log_messages.str() );
+
+
log_messages.clear();
log_messages.str("");
@@ -438,13 +414,21 @@ int main(int argc, char* argv[])
return 0;
}
-bool on_progress(arc_welder_progress progress, logger* p_logger, int logger_type)
+bool on_progress_full(arc_welder_progress progress, logger* p_logger, int logger_type)
{
std::cout << "Progress: "<< progress.str() << std::endl;
std::cout.flush();
return true;
}
-bool suppress_progress(arc_welder_progress progress, logger* p_logger, int logger_type)
+
+bool on_progress_simple(arc_welder_progress progress, logger* p_logger, int logger_type)
+{
+ std::cout << "Progress: " << progress.simple_progress_str() << std::endl;
+ std::cout.flush();
+ return true;
+}
+
+bool on_progress_suppress(arc_welder_progress progress, logger* p_logger, int logger_type)
{
return true;
}
diff --git a/ArcWelderConsole/ArcWelderConsole.h b/ArcWelderConsole/ArcWelderConsole.h
index 64425c9..1e4762f 100644
--- a/ArcWelderConsole/ArcWelderConsole.h
+++ b/ArcWelderConsole/ArcWelderConsole.h
@@ -25,6 +25,8 @@
#pragma once
#include "arc_welder.h"
#include "version.h"
-static bool on_progress(arc_welder_progress progress, logger* p_logger, int logger_type);
-static bool suppress_progress(arc_welder_progress progress, logger* p_logger, int logger_type);
+static bool on_progress_full(arc_welder_progress progress, logger* p_logger, int logger_type);
+static bool on_progress_simple(arc_welder_progress progress, logger* p_logger, int logger_type);
+static bool on_progress_suppress(arc_welder_progress progress, logger* p_logger, int logger_type);
+
diff --git a/ArcWelderTest/ArcWelderTest.cpp b/ArcWelderTest/ArcWelderTest.cpp
index 95aebc5..2ac30b1 100644
--- a/ArcWelderTest/ArcWelderTest.cpp
+++ b/ArcWelderTest/ArcWelderTest.cpp
@@ -266,17 +266,6 @@ static gcode_position_args get_5_extruder_position_args()
static void TestAntiStutter(std::string filePath)
{
- //double max_resolution = DEFAULT_RESOLUTION_MM;
- double max_resolution = 0.05;
- double max_radius_mm = 100000;
- //double max_radius_mm = 10000;
- //int min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS;
- int min_arc_segments = 0;
- double mm_per_arc_segment = 0;
-
- //double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT; // 1 percent
- double path_tolerance_percent = 0.05;
- //double path_tolerance_percent = 0.05;
std::vector<std::string> logger_names;
logger_names.push_back("arc_welder.gcode_conversion");
std::vector<int> logger_levels;
@@ -289,29 +278,7 @@ static void TestAntiStutter(std::string filePath)
logger_levels.push_back(log_levels::CRITICAL);
logger* p_logger = new logger(logger_names, logger_levels);
p_logger->set_log_level(INFO);
- //p_logger->set_log_level(DEBUG);
- //p_logger->set_log_level_by_value(5);
- //arc_welder arc_welder_obj(BENCHY_0_5_MM_NO_WIPE, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, false, 50, static_cast<progress_callback>(on_progress));
- //arc_welder arc_welder_obj(SIX_SPEED_TEST, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, false, 50, on_progress);
- arc_welder arc_welder_obj(
- BENCHY_DIFFICULT,
- "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode",
- p_logger,
- max_resolution,
- path_tolerance_percent,
- DEFAULT_MAX_RADIUS_MM,
- min_arc_segments,
- mm_per_arc_segment,
- true,
- true,
- true, //DEFAULT_ALLOW_TRAVEL_ARCS,
- DEFAULT_ALLOW_DYNAMIC_PRECISION,
- DEFAULT_XYZ_PRECISION,
- DEFAULT_E_PRECISION,
- //DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT,
- 1000000,
- DEFAULT_GCODE_BUFFER_SIZE,
- on_progress);
+
//FIRMWARE_COMPENSATION_TEST_1
//BENCHY_MIN_RADIUS_TEST
//BENCHY_DIFFICULT
@@ -335,6 +302,17 @@ static void TestAntiStutter(std::string filePath)
// BENCHY_L1_DIFFICULT
// SPIRAL_TEST
// SPIRAL_VASE_TEST_FUNNEL
+ std::string source_path = TravelWipeTest;
+ std::string target_path = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode";
+ arc_welder_args args(source_path, target_path, p_logger);
+ args.callback = on_progress;
+ // override any arguments here;
+ args.allow_travel_arcs = true;
+ args.allow_3d_arcs = true;
+ args.max_radius_mm = 9999;
+ args.resolution_mm = 0.05;
+ arc_welder arc_welder_obj(args);
+
arc_welder_results results = arc_welder_obj.process();
p_logger->log(0, INFO, results.progress.detail_str());
p_logger->log(0, INFO, "Processing Complete.");
diff --git a/ArcWelderTest/ArcWelderTest.h b/ArcWelderTest/ArcWelderTest.h
index b4331e9..e854c4b 100644
--- a/ArcWelderTest/ArcWelderTest.h
+++ b/ArcWelderTest/ArcWelderTest.h
@@ -83,7 +83,7 @@ static std::string ISSUE_PRICKLYPEAR_LAYER_0_114 = "C:\\Users\\Brad\\Documents\\
static std::string COLINEAR_TEST_1 = "C:\\Users\\Brad\\Documents\\AntiStutter\\Sanity Checks\\G2_colinear_test.gcode";
static std::string SPIRAL_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\smoothietest\\SPIRAL_TEST.gcode";
static std::string SPIRAL_TRAVEL_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\smoothietest\\SPIRAL_TRAVEL_TEST.gcode";
-
+static std::string TravelWipeTest = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\smoothietest\\TravelWipeTest.gcode";
static std::string SPIRAL_TEST_PRECISION = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\smoothietest\\SPIRAL_TEST_precision.gcode";
static std::string SPIRAL_VASE_TEST_DOUBLE_SPIRAL = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\SpiralVaseTest\\SpiralVaseTest_DOUBLE_SPIRAL.gcode";
static std::string SPIRAL_VASE_TEST_CYLINDER = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\SpiralVaseTest\\SpiralVaseTest_Cylinder.gcode";
diff --git a/GcodeProcessorLib/logger.cpp b/GcodeProcessorLib/logger.cpp
index 5b1e4eb..3bde18e 100644
--- a/GcodeProcessorLib/logger.cpp
+++ b/GcodeProcessorLib/logger.cpp
@@ -57,10 +57,24 @@ void logger::set_log_level_by_value(const int level_value)
logger_levels_[type_index] = log_level;
}
}
+
void logger::set_log_level(const int logger_type, const int log_level)
{
logger_levels_[logger_type] = log_level;
}
+std::string logger::get_log_level_name(std::string logger_name)
+{
+ std::string log_level_name = "UNKNOWN";
+ for (int type_index = 0; type_index < num_loggers_; type_index++)
+ {
+ if (logger_names_[type_index] == logger_name)
+ {
+ log_level_name = log_level_names[logger_levels_[type_index]];
+ break;
+ }
+ }
+ return log_level_name;
+}
void logger::set_log_level(const int log_level)
{
diff --git a/GcodeProcessorLib/logger.h b/GcodeProcessorLib/logger.h
index 9db2df1..f345097 100644
--- a/GcodeProcessorLib/logger.h
+++ b/GcodeProcessorLib/logger.h
@@ -36,7 +36,7 @@ enum log_levels { NOSET, VERBOSE, DEBUG, INFO, WARNING , ERROR, CRITICAL};
static const int log_level_names_size = 7;
static const char* log_level_names[] = {"NOSET", "VERBOSE", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"};
const static int log_level_values[LOG_LEVEL_COUNT] = { 0, 5, 10, 20, 30, 40, 50};
-
+#define DEFAULT_LOG_LEVEL_VALUE 40
class logger
{
public:
@@ -48,7 +48,8 @@ public:
void set_log_level(const int logger_type, const int log_level);
void set_log_level(const int log_level);
-
+
+ std::string get_log_level_name(std::string logger_name);
virtual void log(const int logger_type, const int log_level, const std::string& message);
virtual void log(const int logger_type, const int log_level, const std::string& message, bool is_exception);
virtual void log_exception(const int logger_type, const std::string& message);
diff --git a/GcodeProcessorLib/utilities.cpp b/GcodeProcessorLib/utilities.cpp
index a723cdf..4db0f6a 100644
--- a/GcodeProcessorLib/utilities.cpp
+++ b/GcodeProcessorLib/utilities.cpp
@@ -217,7 +217,7 @@ int utilities::get_num_digits(int x)
(x < 10000000 ? 7 :
(x < 100000000 ? 8 :
(x < 1000000000 ? 9 :
- 10)))))))));
+ (x < 10000000000 ? 10 : -1))))))))));
}
int utilities::get_num_digits(double x)
diff --git a/GcodeProcessorLib/utilities.h b/GcodeProcessorLib/utilities.h
index acbea6c..3261f91 100644
--- a/GcodeProcessorLib/utilities.h
+++ b/GcodeProcessorLib/utilities.h
@@ -55,7 +55,6 @@ public:
static double get_percent_change(int v1, int v2);
static double get_percent_change(double v1, double v2);
static std::string get_percent_change_string(int v1, int v2, int precision);
-
static int get_num_digits(int x);
static int get_num_digits(double x);
diff --git a/PyArcWelder/py_arc_welder.cpp b/PyArcWelder/py_arc_welder.cpp
index 7fdf9bd..482c09b 100644
--- a/PyArcWelder/py_arc_welder.cpp
+++ b/PyArcWelder/py_arc_welder.cpp
@@ -24,105 +24,420 @@
PyObject* py_arc_welder::build_py_progress(const arc_welder_progress& progress, std::string guid)
{
- std::string segment_statistics = progress.segment_statistics.str();
- PyObject* pyGuid = gcode_arc_converter::PyUnicode_SafeFromString(guid);
- if (pyGuid == NULL)
- return NULL;
- PyObject* pyMessage = gcode_arc_converter::PyUnicode_SafeFromString(segment_statistics);
- if (pyMessage == NULL)
- return NULL;
- double total_count_reduction_percent = progress.segment_statistics.get_total_count_reduction_percent();
- 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:i,s:i,s:f,s:f,s:f,s:f,s:i,s:i,s:f}",
- "percent_complete",
- progress.percent_complete, //1
- "seconds_elapsed",
- progress.seconds_elapsed, //2
- "seconds_remaining",
- progress.seconds_remaining, //3
- "gcodes_processed",
- progress.gcodes_processed, //4
- "lines_processed",
- progress.lines_processed, //5
- "points_compressed",
- progress.points_compressed, //6
- "arcs_created",
- progress.arcs_created, //7
- "arcs_aborted_by_flowrate",
- progress.arcs_aborted_by_flow_rate, //8
- "num_firmware_compensations",
- progress.num_firmware_compensations, //9
- "source_file_position",
- progress.source_file_position, //10
- "source_file_size",
- progress.source_file_size, //11
- "target_file_size",
- progress.target_file_size, //12
- "compression_ratio",
- progress.compression_ratio, //13
- "compression_percent",
- progress.compression_percent, //14
- "source_file_total_length",
- progress.segment_statistics.total_length_source, //15
- "target_file_total_length",
- progress.segment_statistics.total_length_target, //16
- "source_file_total_count",
- progress.segment_statistics.total_count_source, //17
- "target_file_total_count",
- progress.segment_statistics.total_count_target, //18
- "total_count_reduction_percent",
- total_count_reduction_percent //19
-
- );
+ PyObject* pyGuid = gcode_arc_converter::PyUnicode_SafeFromString(guid);
+ if (pyGuid == NULL)
+ return NULL;
+ // Extrusion Statistics
+ std::string segment_statistics = progress.segment_statistics.str();
+ PyObject* pyMessage = gcode_arc_converter::PyUnicode_SafeFromString(segment_statistics);
+ if (pyMessage == NULL)
+ return NULL;
+ double total_count_reduction_percent = progress.segment_statistics.get_total_count_reduction_percent();
+ // Travel Statistics
+ std::string segment_travel_statistics = progress.travel_statistics.str();
+ PyObject* pyTravelMessage = gcode_arc_converter::PyUnicode_SafeFromString(segment_travel_statistics);
+ if (pyMessage == NULL)
+ return NULL;
+ double total_travel_count_reduction_percent = progress.travel_statistics.get_total_count_reduction_percent();
+ 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:i,s:i,s:i,s:f,s:f,s:f,s:f,s:i,s:i,s:f,s:f,s:f,s:i,s:i,s:f}",
+ "percent_complete",
+ progress.percent_complete, //1
+ "seconds_elapsed",
+ progress.seconds_elapsed, //2
+ "seconds_remaining",
+ progress.seconds_remaining, //3
+ "gcodes_processed",
+ progress.gcodes_processed, //4
+ "lines_processed",
+ progress.lines_processed, //5
+ "points_compressed",
+ progress.points_compressed, //6
+ "arcs_created",
+ progress.arcs_created, //7
+ "arcs_aborted_by_flowrate",
+ progress.arcs_aborted_by_flow_rate, //8
+ "num_firmware_compensations",
+ progress.num_firmware_compensations, //9
+ "num_gcode_length_exceptions",
+ progress.num_gcode_length_exceptions, //10
+ "source_file_position",
+ progress.source_file_position, //11
+ "source_file_size",
+ progress.source_file_size, //12
+ "target_file_size",
+ progress.target_file_size, //13
+ "compression_ratio",
+ progress.compression_ratio, //14
+ "compression_percent",
+ progress.compression_percent, //15
+ "source_file_total_length",
+ progress.segment_statistics.total_length_source, //16
+ "target_file_total_length",
+ progress.segment_statistics.total_length_target, //17
+ "source_file_total_count",
+ progress.segment_statistics.total_count_source, //18
+ "target_file_total_count",
+ progress.segment_statistics.total_count_target, //19
+ "total_count_reduction_percent",
+ total_count_reduction_percent, //20
+ "source_file_total_travel_length",
+ progress.travel_statistics.total_length_source, //21
+ "target_file_total_travel_length",
+ progress.travel_statistics.total_length_target, //22
+ "source_file_total_travel_count",
+ progress.travel_statistics.total_count_source, //23
+ "target_file_total_travel_count",
+ progress.travel_statistics.total_count_target, //24
+ "total_travel_count_reduction_percent",
+ total_travel_count_reduction_percent //25
- if (py_progress == NULL)
- {
- return NULL;
- }
- // Due to a CRAZY issue, I have to add this item after building the py_progress object,
- // else it crashes in python 2.7. Looking forward to retiring this backwards
- // compatible code...
- PyDict_SetItemString(py_progress, "segment_statistics_text", pyMessage);
- PyDict_SetItemString(py_progress, "guid", pyGuid);
- return py_progress;
+ );
+
+ if (py_progress == NULL)
+ {
+ return NULL;
+ }
+ // Due to a CRAZY issue, I have to add this item after building the py_progress object,
+ // else it crashes in python 2.7. Looking forward to retiring this backwards
+ // compatible code...
+ PyDict_SetItemString(py_progress, "segment_statistics_text", pyMessage);
+ PyDict_SetItemString(py_progress, "segment_travel_statistics_text", pyTravelMessage);
+ PyDict_SetItemString(py_progress, "guid", pyGuid);
+ return py_progress;
}
bool py_arc_welder::on_progress_(const arc_welder_progress& progress)
{
- PyObject* py_dict = py_arc_welder::build_py_progress(progress, guid_);
- if (py_dict == NULL)
- {
- return false;
- }
- PyObject* func_args = Py_BuildValue("(O)", py_dict);
- if (func_args == NULL)
- {
- Py_DECREF(py_dict);
- return false; // This was returning true, I think it was a typo. Making a note just in case.
- }
-
- PyGILState_STATE gstate = PyGILState_Ensure();
- PyObject* pContinueProcessing = PyObject_CallObject(py_progress_callback_, func_args);
- PyGILState_Release(gstate);
- Py_DECREF(func_args);
- Py_DECREF(py_dict);
- bool continue_processing;
- if (pContinueProcessing == NULL)
- {
- // no return value was supply, assume true, but without decrefing pContinueProcessing
- continue_processing = true;
- }
- else
- {
- if (pContinueProcessing == Py_None)
- {
- continue_processing = true;
- }
- else
- {
- continue_processing = PyLong_AsLong(pContinueProcessing) > 0;
- }
- Py_DECREF(pContinueProcessing);
- }
-
- return continue_processing;
+ PyObject* py_dict = py_arc_welder::build_py_progress(progress, guid_);
+ if (py_dict == NULL)
+ {
+ return false;
+ }
+ PyObject* func_args = Py_BuildValue("(O)", py_dict);
+ if (func_args == NULL)
+ {
+ Py_DECREF(py_dict);
+ return false; // This was returning true, I think it was a typo. Making a note just in case.
+ }
+
+ PyGILState_STATE gstate = PyGILState_Ensure();
+ PyObject* pContinueProcessing = PyObject_CallObject(py_progress_callback_, func_args);
+ PyGILState_Release(gstate);
+ Py_DECREF(func_args);
+ Py_DECREF(py_dict);
+ bool continue_processing;
+ if (pContinueProcessing == NULL)
+ {
+ // no return value was supply, assume true, but without decrefing pContinueProcessing
+ continue_processing = true;
+ }
+ else
+ {
+ if (pContinueProcessing == Py_None)
+ {
+ continue_processing = true;
+ }
+ else
+ {
+ continue_processing = PyLong_AsLong(pContinueProcessing) > 0;
+ }
+ Py_DECREF(pContinueProcessing);
+ }
+
+ return continue_processing;
}
+
+bool py_gcode_arc_args::parse_args(PyObject* py_args, py_logger* p_py_logger, py_gcode_arc_args& args, PyObject** py_progress_callback)
+{
+ p_py_logger->log(
+ GCODE_CONVERSION, INFO,
+ "Parsing GCode Conversion Args."
+ );
+
+#pragma region Required_Arguments
+#pragma region guid
+ // Extract the job guid
+ PyObject* py_guid = PyDict_GetItemString(py_args, "guid");
+ if (py_guid == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve required parameter 'guid' from the args.";
+ p_py_logger->log_exception(GCODE_CONVERSION, message);
+ return false;
+ }
+ args.guid = gcode_arc_converter::PyUnicode_SafeAsString(py_guid);
+#pragma endregion guid
+#pragma region source_path
+ // Extract the source file path
+ PyObject* py_source_path = PyDict_GetItemString(py_args, "source_path");
+ if (py_source_path == NULL)
+ {
+ std::string message = "ParseArgs -Unable to retrieve required parameter 'source_path' from the args.";
+ p_py_logger->log_exception(GCODE_CONVERSION, message);
+ return false;
+ }
+ args.source_path = gcode_arc_converter::PyUnicode_SafeAsString(py_source_path);
+#pragma endregion source_path
+#pragma region target_path
+ // Extract the target file path
+ PyObject* py_target_path = PyDict_GetItemString(py_args, "target_path");
+ if (py_target_path == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve required parameter 'target_path' from the args.";
+ p_py_logger->log_exception(GCODE_CONVERSION, message);
+ return false;
+ }
+ args.target_path = gcode_arc_converter::PyUnicode_SafeAsString(py_target_path);
+#pragma endregion target_path
+#pragma region on_progress_received
+ // on_progress_received
+ PyObject* py_on_progress_received = PyDict_GetItemString(py_args, "on_progress_received");
+ if (py_on_progress_received == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve required parameter 'on_progress_received' from the args.";
+ p_py_logger->log_exception(GCODE_CONVERSION, message);
+ return false;
+ }
+ // need to incref this so it doesn't vanish later (borrowed reference we are saving)
+ Py_XINCREF(py_on_progress_received);
+ *py_progress_callback = py_on_progress_received;
+#pragma endregion on_progress_received
+#pragma endregion Required_Arguments
+
+#pragma region Optional_Arguments
+#pragma region resolution_mm
+ // Extract the resolution in millimeters
+ PyObject* py_resolution_mm = PyDict_GetItemString(py_args, "resolution_mm");
+ if (py_resolution_mm == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the 'resolution_mm' parameter from the args.";
+ p_py_logger->log(GCODE_CONVERSION, WARNING, message);
+ }
+ else {
+ args.resolution_mm = gcode_arc_converter::PyFloatOrInt_AsDouble(py_resolution_mm);
+ if (args.resolution_mm <= 0)
+ {
+ args.resolution_mm = 0.05; // Set to the default if no resolution is provided, or if it is less than 0.
+ }
+ }
+#pragma endregion resolution_mm
+#pragma region allow_dynamic_precision
+ // extract allow_dynamic_precision
+ PyObject* py_allow_dynamic_precision = PyDict_GetItemString(py_args, "allow_dynamic_precision");
+ if (py_allow_dynamic_precision == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve 'allow_dynamic_precision' from the args.";
+ p_py_logger->log(GCODE_CONVERSION, WARNING, message);
+ }
+ else {
+ args.allow_dynamic_precision = PyLong_AsLong(py_allow_dynamic_precision) > 0;
+ }
+#pragma endregion allow_dynamic_precision
+#pragma region default_xyz_precision
+ // extract default_xyz_precision
+ PyObject* py_default_xyz_precision = PyDict_GetItemString(py_args, "default_xyz_precision");
+ if (py_default_xyz_precision == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the 'default_xyz_precision' parameter from the args.";
+ p_py_logger->log(GCODE_CONVERSION, WARNING, message);
+ }
+ else {
+ args.default_xyz_precision = gcode_arc_converter::PyFloatOrInt_AsDouble(py_default_xyz_precision);
+ if (args.default_xyz_precision < 3)
+ {
+ std::string message = "ParseArgs - The default XYZ precision received was less than 3, which could cause problems printing arcs. Setting to 3.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ args.default_xyz_precision = 3;
+ }
+ else if (args.default_xyz_precision > 6)
+ {
+ std::string message = "ParseArgs - The default XYZ precision received was greater than 6, which could can cause checksum errors depending on your firmware. Setting to 6.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ args.default_xyz_precision = 6;
+ }
+ }
+#pragma endregion default_xyz_precision
+#pragma region default_e_precision
+ // extract default_e_precision
+ PyObject* py_default_e_precision = PyDict_GetItemString(py_args, "default_e_precision");
+ if (py_default_e_precision == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the 'default_e_precision parameter' from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else {
+ args.default_e_precision = gcode_arc_converter::PyFloatOrInt_AsDouble(py_default_e_precision);
+ if (args.default_e_precision < 3)
+ {
+ std::string message = "ParseArgs - The default E precision received was less than 3, which could cause extrusion problems. Setting to 3.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ args.default_e_precision = 3;
+ }
+ else if (args.default_e_precision > 6)
+ {
+ std::string message = "ParseArgs - The default E precision received was greater than 6, which could can cause checksum errors depending on your firmware. Setting to 6.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ args.default_e_precision = 6;
+ }
+ }
+#pragma endregion default_e_precision
+#pragma region extrusion_rate_variance_percent
+ // Extract the extrusion_rate_variance
+ PyObject* py_extrusion_rate_variance_percent = PyDict_GetItemString(py_args, "extrusion_rate_variance_percent");
+ if (py_extrusion_rate_variance_percent == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the 'extrusion_rate_variance_percent' parameter from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ args.extrusion_rate_variance_percent = gcode_arc_converter::PyFloatOrInt_AsDouble(py_extrusion_rate_variance_percent);
+ if (args.extrusion_rate_variance_percent < 0)
+ {
+ args.extrusion_rate_variance_percent = DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT; // Set to the default if no resolution is provided, or if it is less than 0.
+ }
+ }
+#pragma endregion extrusion_rate_variance_percent
+#pragma region path_tolerance_percent
+ // Extract the path tolerance_percent
+ PyObject* py_path_tolerance_percent = PyDict_GetItemString(py_args, "path_tolerance_percent");
+ if (py_path_tolerance_percent == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the 'path_tolerance_percent' parameter from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ args.path_tolerance_percent = gcode_arc_converter::PyFloatOrInt_AsDouble(py_path_tolerance_percent);
+ if (args.path_tolerance_percent < 0)
+ {
+ args.path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT; // Set to the default if no resolution is provided, or if it is less than 0.
+ }
+ }
+#pragma endregion path_tolerance_percent
+#pragma region max_radius_mm
+ // 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(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ 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.
+ }
+ }
+#pragma endregion max_radius_mm
+#pragma region mm_per_arc_segment
+ // Extract the mm_per_arc_segment
+ PyObject* py_mm_per_arc_segment = PyDict_GetItemString(py_args, "mm_per_arc_segment");
+ if (py_mm_per_arc_segment == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the 'mm_per_arc_segment' parameter from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ args.mm_per_arc_segment = gcode_arc_converter::PyFloatOrInt_AsDouble(py_mm_per_arc_segment);
+ if (args.mm_per_arc_segment < 0)
+ {
+ args.mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT;
+ }
+ }
+#pragma endregion mm_per_arc_segment
+#pragma region min_arc_segments
+ // Extract min_arc_segments
+ PyObject* py_min_arc_segments = PyDict_GetItemString(py_args, "min_arc_segments");
+ if (py_min_arc_segments == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the 'min_arc_segments' parameter from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ args.min_arc_segments = (int)gcode_arc_converter::PyIntOrLong_AsLong(py_min_arc_segments);
+ if (args.min_arc_segments < 0)
+ {
+ args.min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS; // Set to the default if no resolution is provided, or if it is less than 0.
+ }
+ }
+#pragma endregion min_arc_segments
+#pragma region max_gcode_length
+ // Extract max_gcode_length
+ PyObject* py_max_gcode_length = PyDict_GetItemString(py_args, "max_gcode_length");
+ if (py_max_gcode_length == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve the 'max_gcode_length' parameter from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ args.max_gcode_length = (int)gcode_arc_converter::PyIntOrLong_AsLong(py_max_gcode_length);
+ if (args.max_gcode_length < 0)
+ {
+ args.max_gcode_length = DEFAULT_MAX_GCODE_LENGTH;
+ }
+ }
+#pragma endregion max_gcode_length
+#pragma region allow_3d_arcs
+ // extract allow_3d_arcs
+ PyObject* py_allow_3d_arcs = PyDict_GetItemString(py_args, "allow_3d_arcs");
+ if (py_allow_3d_arcs == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve 'allow_3d_arcs' from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ args.allow_3d_arcs = PyLong_AsLong(py_allow_3d_arcs) > 0;
+ }
+#pragma endregion allow_3d_arcs
+#pragma region allow_travel_arcs
+ // extract allow_travel_arcs
+ PyObject* py_allow_travel_arcs = PyDict_GetItemString(py_args, "allow_travel_arcs");
+ if (py_allow_travel_arcs == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve 'allow_travel_arcs' from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ args.allow_travel_arcs = PyLong_AsLong(py_allow_travel_arcs) > 0;
+ }
+#pragma endregion allow_travel_arcs
+#pragma region g90_g91_influences_extruder
+ // Extract G90/G91 influences extruder
+ // g90_influences_extruder
+ PyObject* py_g90_g91_influences_extruder = PyDict_GetItemString(py_args, "g90_g91_influences_extruder");
+ if (py_g90_g91_influences_extruder == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve 'g90_g91_influences_extruder' from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ args.g90_g91_influences_extruder = PyLong_AsLong(py_g90_g91_influences_extruder) > 0;
+ }
+#pragma endregion g90_g91_influences_extruder
+#pragma region log_level
+ // Extract log_level
+ PyObject* py_log_level = PyDict_GetItemString(py_args, "log_level");
+ if (py_log_level == NULL)
+ {
+ std::string message = "ParseArgs - Unable to retrieve 'log_level' from the args.";
+ p_py_logger->log(WARNING, GCODE_CONVERSION, message);
+ }
+ else
+ {
+ int log_level_value = static_cast<int>(PyLong_AsLong(py_log_level));
+ // determine the log level as an index rather than as a value
+ args.log_level = p_py_logger->get_log_level_for_value(log_level_value);
+ }
+#pragma endregion log_level
+#pragma endregion Optional_Arguments
+
+ return true;
+} \ No newline at end of file
diff --git a/PyArcWelder/py_arc_welder.h b/PyArcWelder/py_arc_welder.h
index 40a9cab..686a9cd 100644
--- a/PyArcWelder/py_arc_welder.h
+++ b/PyArcWelder/py_arc_welder.h
@@ -31,49 +31,32 @@
#else
#include <Python.h>
#endif
+
+struct py_gcode_arc_args : arc_welder_args {
+ py_gcode_arc_args() : arc_welder_args() {
+ log_level = INFO;
+ py_progress_callback = NULL;
+ guid = "";
+
+ };
+ py_gcode_arc_args(std::string source_path, std::string target_path, logger* log, std::string progress_guid, PyObject* progress_callback) : arc_welder_args(source_path, target_path, log) {
+ guid = progress_guid;
+ py_progress_callback = progress_callback;
+ };
+
+ static bool parse_args(PyObject* py_args, py_logger* p_py_logger, py_gcode_arc_args& args, PyObject** py_progress_callback);
+ int log_level;
+ std::string guid;
+ PyObject* py_progress_callback;
+};
+
class py_arc_welder : public arc_welder
{
public:
- py_arc_welder(
- std::string guid,
- std::string source_path,
- std::string target_path,
- py_logger* logger,
- double resolution_mm,
- double path_tolerance_percent,
- double max_radius,
- int min_arc_segments,
- double mm_per_arc_segment,
- bool g90_g91_influences_extruder,
- bool allow_3d_arcs,
- bool allow_travel_arcs,
- bool allow_dynamic_precision,
- unsigned char default_xyz_precision,
- unsigned char default_e_precision,
- double extrusion_rate_variance_percent,
- int buffer_size,
- PyObject* py_progress_callback
- ): arc_welder(
- source_path,
- target_path,
- logger,
- resolution_mm,
- path_tolerance_percent,
- max_radius,
- min_arc_segments,
- mm_per_arc_segment,
- g90_g91_influences_extruder,
- allow_3d_arcs,
- allow_travel_arcs,
- allow_dynamic_precision,
- default_xyz_precision,
- default_e_precision,
- extrusion_rate_variance_percent,
- buffer_size,
- NULL
- ){
- guid_ = guid;
- py_progress_callback_ = py_progress_callback;
+ py_arc_welder(py_gcode_arc_args args): arc_welder( (arc_welder_args)args)
+ {
+ guid_ = args.guid;
+ py_progress_callback_ = args.py_progress_callback;
}
virtual ~py_arc_welder() {
diff --git a/PyArcWelder/py_arc_welder_extension.cpp b/PyArcWelder/py_arc_welder_extension.cpp
index 19a2274..b386d9f 100644
--- a/PyArcWelder/py_arc_welder_extension.cpp
+++ b/PyArcWelder/py_arc_welder_extension.cpp
@@ -186,7 +186,7 @@ extern "C"
py_gcode_arc_args args;
PyObject* py_progress_callback = NULL;
- if (!ParseArgs(py_convert_file_args, args, &py_progress_callback))
+ if (!py_gcode_arc_args::parse_args(py_convert_file_args, p_py_logger, args, &py_progress_callback))
{
return NULL;
}
@@ -195,26 +195,9 @@ extern "C"
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.guid,
- args.source_path,
- args.target_path,
- p_py_logger,
- args.resolution_mm,
- args.path_tolerance_percent,
- args.max_radius_mm,
- args.min_arc_segments,
- args.mm_per_arc_segment,
- args.g90_g91_influences_extruder,
- args.allow_3d_arcs,
- args.allow_travel_arcs,
- args.allow_dynamic_precision,
- args.default_xyz_precision,
- args.default_e_precision,
- args.extrusion_rate_variance_percent,
- DEFAULT_GCODE_BUFFER_SIZE,
- py_progress_callback
- );
+ args.py_progress_callback = py_progress_callback;
+ args.log = p_py_logger;
+ py_arc_welder arc_welder_obj(args);
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);
@@ -239,237 +222,5 @@ extern "C"
}
}
-static bool ParseArgs(PyObject* py_args, py_gcode_arc_args& args, PyObject** py_progress_callback)
-{
- p_py_logger->log(
- GCODE_CONVERSION, INFO,
- "Parsing GCode Conversion Args."
- );
-
- // Extract the job guid
- PyObject* py_guid = PyDict_GetItemString(py_args, "guid");
- if (py_guid == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the guid parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.guid = gcode_arc_converter::PyUnicode_SafeAsString(py_guid);
-
- // Extract the source file path
- PyObject* py_source_path = PyDict_GetItemString(py_args, "source_path");
- if (py_source_path == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the source_path parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.source_path = gcode_arc_converter::PyUnicode_SafeAsString(py_source_path);
-
- // Extract the target file path
- PyObject* py_target_path = PyDict_GetItemString(py_args, "target_path");
- if (py_target_path == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the target_path parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.target_path = gcode_arc_converter::PyUnicode_SafeAsString(py_target_path);
-
- // Extract the resolution in millimeters
- PyObject* py_resolution_mm = PyDict_GetItemString(py_args, "resolution_mm");
- if (py_resolution_mm == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the resolution_mm parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.resolution_mm = gcode_arc_converter::PyFloatOrInt_AsDouble(py_resolution_mm);
- if (args.resolution_mm <= 0)
- {
- args.resolution_mm = 0.05; // Set to the default if no resolution is provided, or if it is less than 0.
- }
-
- // extract allow_dynamic_precision
- PyObject* py_allow_dynamic_precision = PyDict_GetItemString(py_args, "allow_dynamic_precision");
- if (py_allow_dynamic_precision == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve allow_dynamic_precision from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.allow_dynamic_precision = PyLong_AsLong(py_allow_dynamic_precision) > 0;
-
- // extract default_xyz_precision
- PyObject* py_default_xyz_precision = PyDict_GetItemString(py_args, "default_xyz_precision");
- if (py_default_xyz_precision == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the default_xyz_precision parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.default_xyz_precision = gcode_arc_converter::PyFloatOrInt_AsDouble(py_default_xyz_precision);
- if (args.default_xyz_precision < 3)
- {
- std::string message = "ParseArgs - The default XYZ precision received was less than 3, which could cause problems printing arcs. Setting to 3.";
- p_py_logger->log(WARNING, GCODE_CONVERSION, message);
- args.default_xyz_precision = 3;
- }
- else if (args.default_xyz_precision > 6)
- {
- std::string message = "ParseArgs - The default XYZ precision received was greater than 6, which could can cause checksum errors depending on your firmware. Setting to 6.";
- p_py_logger->log(WARNING, GCODE_CONVERSION, message);
- args.default_xyz_precision = 6;
- }
-
- // extract default_e_precision
- PyObject* py_default_e_precision = PyDict_GetItemString(py_args, "default_e_precision");
- if (py_default_e_precision == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the default_e_precision parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.default_e_precision = gcode_arc_converter::PyFloatOrInt_AsDouble(py_default_e_precision);
- if (args.default_e_precision < 3)
- {
- std::string message = "ParseArgs - The default E precision received was less than 3, which could cause extrusion problems. Setting to 3.";
- p_py_logger->log(WARNING, GCODE_CONVERSION, message);
- args.default_e_precision = 3;
- }
- else if (args.default_e_precision > 6)
- {
- std::string message = "ParseArgs - The default E precision received was greater than 6, which could can cause checksum errors depending on your firmware. Setting to 6.";
- p_py_logger->log(WARNING, GCODE_CONVERSION, message);
- args.default_e_precision = 6;
- }
-
- // Extract the extrusion_rate_variance
- PyObject* py_extrusion_rate_variance_percent = PyDict_GetItemString(py_args, "extrusion_rate_variance_percent");
- if (py_extrusion_rate_variance_percent == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the extrusion_rate_variance_percent parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.extrusion_rate_variance_percent = gcode_arc_converter::PyFloatOrInt_AsDouble(py_extrusion_rate_variance_percent);
- if (args.extrusion_rate_variance_percent < 0)
- {
- args.extrusion_rate_variance_percent = DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT; // Set to the default if no resolution is provided, or if it is less than 0.
- }
-
- // Extract the path tolerance_percent
- PyObject* py_path_tolerance_percent = PyDict_GetItemString(py_args, "path_tolerance_percent");
- if (py_path_tolerance_percent == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the path_tolerance_percent parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.path_tolerance_percent = gcode_arc_converter::PyFloatOrInt_AsDouble(py_path_tolerance_percent);
- if (args.path_tolerance_percent < 0)
- {
- args.path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT; // 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 the mm_per_arc_segment
- PyObject* py_mm_per_arc_segment = PyDict_GetItemString(py_args, "mm_per_arc_segment");
- if (py_mm_per_arc_segment == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the mm_per_arc_segment parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.mm_per_arc_segment = gcode_arc_converter::PyFloatOrInt_AsDouble(py_mm_per_arc_segment);
- if (args.mm_per_arc_segment < 0)
- {
- args.mm_per_arc_segment = 0;
- }
-
- // Extract min_arc_segments
- PyObject* py_min_arc_segments = PyDict_GetItemString(py_args, "min_arc_segments");
- if (py_min_arc_segments == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve the min_arc_segments parameter from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.min_arc_segments = (int) gcode_arc_converter::PyIntOrLong_AsLong(py_min_arc_segments);
- if (args.min_arc_segments < 0)
- {
- args.min_arc_segments = 0; // Set to the default if no resolution is provided, or if it is less than 0.
- }
-
- // extract allow_3d_arcs
- PyObject* py_allow_3d_arcs = PyDict_GetItemString(py_args, "allow_3d_arcs");
- if (py_allow_3d_arcs == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve allow_3d_arcs from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.allow_3d_arcs = PyLong_AsLong(py_allow_3d_arcs) > 0;
-
- // extract allow_travel_arcs
- PyObject* py_allow_travel_arcs = PyDict_GetItemString(py_args, "allow_travel_arcs");
- if (py_allow_travel_arcs == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve allow_travel_arcs from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.allow_travel_arcs = PyLong_AsLong(py_allow_travel_arcs) > 0;
-
- // Extract G90/G91 influences extruder
- // g90_influences_extruder
- PyObject* py_g90_g91_influences_extruder = PyDict_GetItemString(py_args, "g90_g91_influences_extruder");
- if (py_g90_g91_influences_extruder == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve g90_g91_influences_extruder from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- args.g90_g91_influences_extruder = PyLong_AsLong(py_g90_g91_influences_extruder) > 0;
-
- // on_progress_received
- PyObject* py_on_progress_received = PyDict_GetItemString(py_args, "on_progress_received");
- if (py_on_progress_received == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve on_progress_received from the stabilization args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
- // need to incref this so it doesn't vanish later (borrowed reference we are saving)
- Py_XINCREF(py_on_progress_received);
- *py_progress_callback = py_on_progress_received;
-
- // Extract log_level
- PyObject* py_log_level = PyDict_GetItemString(py_args, "log_level");
- if (py_log_level == NULL)
- {
- std::string message = "ParseArgs - Unable to retrieve log_level from the args.";
- p_py_logger->log_exception(GCODE_CONVERSION, message);
- return false;
- }
-
- int log_level_value = static_cast<int>(PyLong_AsLong(py_log_level));
- // determine the log level as an index rather than as a value
- args.log_level = p_py_logger->get_log_level_for_value(log_level_value);
-
- return true;
-}
diff --git a/PyArcWelder/py_arc_welder_extension.h b/PyArcWelder/py_arc_welder_extension.h
index 2212748..b71f680 100644
--- a/PyArcWelder/py_arc_welder_extension.h
+++ b/PyArcWelder/py_arc_welder_extension.h
@@ -29,6 +29,7 @@
#include <Python.h>
#endif
#include <string>
+#include "py_arc_welder.h"
#include "py_logger.h"
#include "arc_welder.h"
extern "C"
@@ -41,76 +42,6 @@ extern "C"
static PyObject* ConvertFile(PyObject* self, PyObject* args);
}
-struct py_gcode_arc_args {
- py_gcode_arc_args() {
- guid = "";
- source_path = "";
- target_path = "";
- resolution_mm = DEFAULT_RESOLUTION_MM;
- path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT;
- max_radius_mm = DEFAULT_MAX_RADIUS_MM;
- min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS;
- mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT;
- g90_g91_influences_extruder = DEFAULT_G90_G91_INFLUENCES_EXTREUDER;
- allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS;
- allow_travel_arcs = DEFAULT_ALLOW_TRAVEL_ARCS;
- log_level = 0;
- }
- py_gcode_arc_args(
- std::string guid_,
- std::string source_path_,
- std::string target_path_,
- double resolution_mm_,
- double path_tolerance_percent_,
- double max_radius_mm_,
- int min_arc_segments_,
- double mm_per_arc_segment_,
- bool g90_g91_influences_extruder_,
- bool allow_3d_arcs_,
- bool allow_travel_arcs_,
- bool allow_dynamic_precision_,
- unsigned char default_xyz_precision_,
- unsigned char default_e_precision_,
- double extrusion_rate_variance_percent_,
- int log_level_
- ) {
- guid = guid_;
- source_path = source_path_;
- target_path = target_path_;
- resolution_mm = resolution_mm_;
- path_tolerance_percent = path_tolerance_percent_;
- max_radius_mm = max_radius_mm_;
- min_arc_segments = min_arc_segments_;
- mm_per_arc_segment = mm_per_arc_segment_;
- allow_3d_arcs = allow_3d_arcs_;
- allow_travel_arcs = allow_travel_arcs_;
- allow_dynamic_precision = allow_dynamic_precision_;
- default_xyz_precision = default_xyz_precision_;
- default_e_precision = default_e_precision_;
- extrusion_rate_variance_percent = extrusion_rate_variance_percent_;
- g90_g91_influences_extruder = g90_g91_influences_extruder_;
- log_level = log_level_;
- }
- std::string guid;
- std::string source_path;
- std::string target_path;
- double resolution_mm;
- double path_tolerance_percent;
- bool allow_3d_arcs;
- bool allow_travel_arcs;
- bool allow_dynamic_precision;
- unsigned char default_xyz_precision;
- unsigned char default_e_precision;
- double extrusion_rate_variance_percent;
- bool g90_g91_influences_extruder;
- double max_radius_mm;
- int min_arc_segments;
- double mm_per_arc_segment;
- int log_level;
-};
-
-static bool ParseArgs(PyObject* py_args, py_gcode_arc_args& args, PyObject** p_py_progress_callback);
-
// global logger
py_logger* p_py_logger = NULL;
/*