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-11-21 21:31:00 +0300
committerFormerLurker <hochgebe@gmail.com>2021-11-21 21:31:00 +0300
commit9b0afec63643275ecdc9005bfbbba20e359a7938 (patch)
treecc9153d01a15d3764dd99bd53e30b6a178c21835
parent4c193828056771381f7bfc6f04133bd1a45447ac (diff)
Make extrusion-rate-variance-percent optional (0 to disable). Add HTML box drawing for pretty statistics. Separate extrusion and retraction statistics for analyzation purposes, but keep combined statistics.
-rw-r--r--ArcWelder/arc_welder.cpp320
-rw-r--r--ArcWelder/arc_welder.h289
-rw-r--r--ArcWelder/segmented_shape.cpp1
-rw-r--r--ArcWelder/unwritten_command.h11
-rw-r--r--ArcWelderConsole/ArcWelderConsole.cpp43
-rw-r--r--ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp18
-rw-r--r--ArcWelderTest/ArcWelderTest.cpp26
-rw-r--r--ArcWelderTest/ArcWelderTest.h1
-rw-r--r--GcodeProcessorLib/logger.cpp26
-rw-r--r--GcodeProcessorLib/logger.h14
-rw-r--r--GcodeProcessorLib/utilities.cpp88
-rw-r--r--GcodeProcessorLib/utilities.h31
-rw-r--r--PyArcWelder/py_arc_welder.cpp6
-rw-r--r--PyArcWelder/py_arc_welder_extension.cpp8
-rw-r--r--PyArcWelder/py_logger.cpp16
15 files changed, 566 insertions, 332 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp
index ab2f6ef..883f66b 100644
--- a/ArcWelder/arc_welder.cpp
+++ b/ArcWelder/arc_welder.cpp
@@ -36,89 +36,79 @@
#include <sstream>
#include <version.h>
-arc_welder::arc_welder(
- std::string source_path,
- std::string target_path,
- logger* log,
- 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 max_gcode_length,
- int buffer_size,
- double notification_period_seconds,
- progress_callback callback) : current_arc_(
- DEFAULT_MIN_SEGMENTS,
- buffer_size,
- resolution_mm,
- path_tolerance_percent,
- max_radius,
- min_arc_segments,
- mm_per_arc_segment,
- allow_3d_arcs,
- default_xyz_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
- )
+
+
+
+arc_welder::arc_welder(arc_welder_args args) : current_arc_(
+ DEFAULT_MIN_SEGMENTS,
+ args.buffer_size,
+ args.resolution_mm,
+ args.path_tolerance_percent,
+ args.max_radius_mm,
+ args.min_arc_segments,
+ args.mm_per_arc_segment,
+ args.allow_3d_arcs,
+ args.default_xyz_precision,
+ args.default_e_precision,
+ args.max_gcode_length
+ ),
+ segment_statistics_(
+ segment_statistic_lengths,
+ segment_statistic_lengths_count,
+ args.log
+ ),
+ segment_retraction_statistics_(
+ segment_statistic_lengths,
+ segment_statistic_lengths_count,
+ args.log
+ ),
+ travel_statistics_(
+ segment_statistic_lengths,
+ segment_statistic_lengths_count,
+ args.log
+ )
{
- p_logger_ = log;
- debug_logging_enabled_ = false;
- info_logging_enabled_ = false;
- error_logging_enabled_ = false;
- verbose_logging_enabled_ = false;
-
- logger_type_ = 0;
- resolution_mm_ = resolution_mm;
- progress_callback_ = callback;
- verbose_output_ = false;
- source_path_ = source_path;
- target_path_ = target_path;
- gcode_position_args_ = get_args_(g90_g91_influences_extruder, buffer_size);
- allow_3d_arcs_ = allow_3d_arcs;
- allow_travel_arcs_ = allow_travel_arcs;
- allow_dynamic_precision_ = allow_dynamic_precision;
- extrusion_rate_variance_percent_ = extrusion_rate_variance_percent;
- lines_processed_ = 0;
- gcodes_processed_ = 0;
- file_size_ = 0;
- notification_period_seconds_ = notification_period_seconds;
- last_gcode_line_written_ = 0;
- points_compressed_ = 0;
- arcs_created_ = 0;
- arcs_aborted_by_flow_rate_ = 0;
- waiting_for_arc_ = false;
- previous_feedrate_ = -1;
- gcode_position_args_.set_num_extruders(8);
- previous_extrusion_rate_ = 0;
- for (int index = 0; index < 8; index++)
- {
- gcode_position_args_.retraction_lengths[0] = .0001;
- gcode_position_args_.z_lift_heights[0] = 0.001;
- gcode_position_args_.x_firmware_offsets[0] = 0.0;
- gcode_position_args_.y_firmware_offsets[0] = 0.0;
- }
+ p_logger_ = args.log;
+ debug_logging_enabled_ = false;
+ info_logging_enabled_ = false;
+ error_logging_enabled_ = false;
+ verbose_logging_enabled_ = false;
+
+ logger_type_ = 0;
+ resolution_mm_ = args.resolution_mm;
+ progress_callback_ = args.callback;
+ verbose_output_ = false;
+ source_path_ = args.source_path;
+ target_path_ = args.target_path;
+ gcode_position_args_ = get_args_(args.g90_g91_influences_extruder, args.buffer_size);
+ allow_3d_arcs_ = args.allow_3d_arcs;
+ allow_travel_arcs_ = args.allow_travel_arcs;
+ allow_dynamic_precision_ = args.allow_dynamic_precision;
+ extrusion_rate_variance_percent_ = args.extrusion_rate_variance_percent;
+ lines_processed_ = 0;
+ gcodes_processed_ = 0;
+ file_size_ = 0;
+ notification_period_seconds_ = args.notification_period_seconds;
+ last_gcode_line_written_ = 0;
+ points_compressed_ = 0;
+ arcs_created_ = 0;
+ arcs_aborted_by_flow_rate_ = 0;
+ waiting_for_arc_ = false;
+ previous_feedrate_ = -1;
+ gcode_position_args_.set_num_extruders(8);
+ previous_extrusion_rate_ = 0;
+ box_encoding_ = args.box_encoding;
+ for (int index = 0; index < 8; index++)
+ {
+ gcode_position_args_.retraction_lengths[0] = .0001;
+ gcode_position_args_.z_lift_heights[0] = 0.001;
+ gcode_position_args_.x_firmware_offsets[0] = 0.0;
+ gcode_position_args_.y_firmware_offsets[0] = 0.0;
+ }
- // We don't care about the printer settings, except for g91 influences extruder.
+ // We don't care about the printer settings, except for g91 influences extruder.
- p_source_position_ = new gcode_position(gcode_position_args_);
+ p_source_position_ = new gcode_position(gcode_position_args_);
}
gcode_position_args arc_welder::get_args_(bool g90_g91_influences_extruder, int buffer_size)
@@ -170,7 +160,7 @@ void arc_welder::set_logger_type(int logger_type)
void arc_welder::reset()
{
- p_logger_->log(logger_type_, DEBUG, "Resetting all tracking variables.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Resetting all tracking variables.");
lines_processed_ = 0;
gcodes_processed_ = 0;
last_gcode_line_written_ = 0;
@@ -204,11 +194,11 @@ double arc_welder::get_time_elapsed(double start_clock, double end_clock)
arc_welder_results arc_welder::process()
{
arc_welder_results results;
- p_logger_->log(logger_type_, DEBUG, "Configuring logging settings.");
- verbose_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, VERBOSE);
- debug_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, DEBUG);
- info_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, INFO);
- error_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, ERROR);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Configuring logging settings.");
+ verbose_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, log_levels::VERBOSE);
+ debug_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, log_levels::DEBUG);
+ info_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, log_levels::INFO);
+ error_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, log_levels::ERROR);
std::stringstream stream;
// reset tracking variables
@@ -216,16 +206,16 @@ arc_welder_results arc_welder::process()
// local variable to hold the progress update return. If it's false, we will exit.
bool continue_processing = true;
- p_logger_->log(logger_type_, DEBUG, "Configuring progress updates.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Configuring progress updates.");
int read_lines_before_clock_check = 1000;
double next_update_time = get_next_update_time();
const clock_t start_clock = clock();
- p_logger_->log(logger_type_, DEBUG, "Getting source file size.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Getting source file size.");
file_size_ = get_file_size(source_path_);
stream.clear();
stream.str("");
stream << "Source file size: " << file_size_;
- p_logger_->log(logger_type_, DEBUG, stream.str());
+ p_logger_->log(logger_type_, log_levels::DEBUG, stream.str());
// Determine if we need to overwrite the source file
bool overwrite_source_file = false;
@@ -244,13 +234,13 @@ arc_welder_results arc_welder::process()
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());
+ p_logger_->log(logger_type_, log_levels::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.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Opening the source file for reading.");
gcodeFile.open(source_path_.c_str(), std::ifstream::in);
if (!gcodeFile.is_open())
{
@@ -259,9 +249,9 @@ arc_welder_results arc_welder::process()
p_logger_->log_exception(logger_type_, results.message);
return results;
}
- p_logger_->log(logger_type_, DEBUG, "Source file opened successfully.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Source file opened successfully.");
- p_logger_->log(logger_type_, DEBUG, "Opening the target file for writing.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Opening the target file for writing.");
output_file_.open(target_path_.c_str(), std::ios_base::binary | std::ios_base::out);
if (!output_file_.is_open())
@@ -273,14 +263,14 @@ arc_welder_results arc_welder::process()
return results;
}
- p_logger_->log(logger_type_, DEBUG, "Target file opened successfully.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Target file opened successfully.");
std::string line;
int lines_with_no_commands = 0;
parsed_command cmd;
// Communicate every second
- p_logger_->log(logger_type_, DEBUG, "Sending initial progress update.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Sending initial progress update.");
continue_processing = on_progress_(get_progress_(static_cast<long>(gcodeFile.tellg()), static_cast<double>(start_clock)));
- p_logger_->log(logger_type_, DEBUG, "Processing source file.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Processing source file.");
bool arc_Welder_comment_added = false;
while (std::getline(gcodeFile, line) && continue_processing)
@@ -311,7 +301,7 @@ arc_welder_results arc_welder::process()
stream.clear();
stream.str("");
stream << "Parsing: " << line;
- p_logger_->log(logger_type_, VERBOSE, stream.str());
+ p_logger_->log(logger_type_, log_levels::VERBOSE, stream.str());
}
parser_.try_parse_gcode(line.c_str(), cmd, true);
bool has_gcode = false;
@@ -337,7 +327,7 @@ arc_welder_results arc_welder::process()
{
if (verbose_logging_enabled_)
{
- p_logger_->log(logger_type_, VERBOSE, "Sending progress update.");
+ p_logger_->log(logger_type_, log_levels::VERBOSE, "Sending progress update.");
}
continue_processing = on_progress_(get_progress_(static_cast<long>(gcodeFile.tellg()), static_cast<double>(start_clock)));
next_update_time = get_next_update_time();
@@ -347,22 +337,22 @@ arc_welder_results arc_welder::process()
if (current_arc_.is_shape() && waiting_for_arc_)
{
- p_logger_->log(logger_type_, DEBUG, "Processing the final line.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Processing the final line.");
process_gcode(cmd, true, false);
}
- p_logger_->log(logger_type_, DEBUG, "Writing all unwritten gcodes to the target file.");
+ p_logger_->log(logger_type_, log_levels::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.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Fetching the final progress struct.");
arc_welder_progress final_progress = get_progress_(static_cast<long>(file_size_), static_cast<double>(start_clock));
if (debug_logging_enabled_)
{
- p_logger_->log(logger_type_, DEBUG, "Sending final progress update message.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Sending final progress update message.");
}
on_progress_(final_progress);
- p_logger_->log(logger_type_, DEBUG, "Closing source and target files.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Closing source and target files.");
output_file_.close();
gcodeFile.close();
@@ -371,19 +361,19 @@ arc_welder_results arc_welder::process()
stream.clear();
stream.str("");
stream << "Deleting the original source file at '" << source_path_ << "'.";
- p_logger_->log(logger_type_, DEBUG, stream.str());
+ p_logger_->log(logger_type_, log_levels::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());
+ p_logger_->log(0, log_levels::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;
- p_logger_->log(logger_type_, DEBUG, "Returning processing results.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Returning processing results.");
return results;
}
@@ -396,7 +386,7 @@ bool arc_welder::on_progress_(const arc_welder_progress& progress)
}
else if (info_logging_enabled_)
{
- p_logger_->log(logger_type_, INFO, progress.str());
+ p_logger_->log(logger_type_, log_levels::INFO, progress.str());
}
return true;
@@ -430,19 +420,17 @@ arc_welder_progress arc_welder::get_progress_(long source_file_position, double
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.segment_retraction_statistics = segment_retraction_statistics_;
progress.travel_statistics = travel_statistics_;
+ progress.box_encoding = box_encoding_;
return progress;
}
int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess)
{
- /* use to catch gcode for debugging since I can't set conditions equal to strings
- if (cmd.gcode == "G1 X118.762 Y104.054 E0.0163")
- {
- std::cout << "Found it!";
- }
- */
+
+
// Update the position for the source gcode file
p_source_position_->update(cmd, lines_processed_, gcodes_processed_, -1);
position* p_cur_pos = p_source_position_->get_current_position_ptr();
@@ -462,7 +450,10 @@ 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.e_relative != 0;
+ bool is_extrusion = extruder_current.e_relative > 0;
+ bool is_retraction = extruder_current.e_relative < 0;
+ bool is_travel = !(is_extrusion || is_retraction) && (is_g0_g1 || is_g2_g3);
+
// Update the source file statistics
if (p_cur_pos->has_xy_position_changed)
{
@@ -512,11 +503,15 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
{
if (!is_reprocess)
{
- if (has_e_changed)
+ if (is_extrusion)
{
segment_statistics_.update(movement_length_mm, true);
}
- else if (allow_travel_arcs_)
+ else if (is_retraction)
+ {
+ segment_retraction_statistics_.update(movement_length_mm, true);
+ }
+ else if (allow_travel_arcs_ && is_travel)
{
travel_statistics_.update(movement_length_mm, true);
}
@@ -529,20 +524,24 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
double mm_extruded_per_mm_travel = 0;
double extrusion_rate_change_percent = 0;
bool aborted_by_flow_rate = false;
- // TODO: MAKE SURE THIS WORKS FOR TRANSITIONS FROM TRAVEL TO NON TRAVEL MOVES
- if (movement_length_mm > 0 && has_e_changed)
- {
- mm_extruded_per_mm_travel = extruder_current.e_relative / movement_length_mm;
- if (previous_extrusion_rate_ > 0)
- {
- extrusion_rate_change_percent = utilities::abs(utilities::get_percent_change(previous_extrusion_rate_, mm_extruded_per_mm_travel));
- }
- }
- if (previous_extrusion_rate_ != 0 && utilities::greater_than(extrusion_rate_change_percent, extrusion_rate_variance_percent_))
+ if (extrusion_rate_variance_percent_ != 0)
{
- arcs_aborted_by_flow_rate_++;
- aborted_by_flow_rate = true;
+ // TODO: MAKE SURE THIS WORKS FOR TRANSITIONS FROM TRAVEL TO NON TRAVEL MOVES
+ if (movement_length_mm > 0 && (is_extrusion || is_retraction))
+ {
+ mm_extruded_per_mm_travel = extruder_current.e_relative / movement_length_mm;
+ if (previous_extrusion_rate_ > 0)
+ {
+ extrusion_rate_change_percent = utilities::abs(utilities::get_percent_change(previous_extrusion_rate_, mm_extruded_per_mm_travel));
+ }
+ }
+ if (previous_extrusion_rate_ != 0 && utilities::greater_than(extrusion_rate_change_percent, extrusion_rate_variance_percent_))
+ {
+ arcs_aborted_by_flow_rate_++;
+ aborted_by_flow_rate = true;
+ }
}
+
// 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.
@@ -567,7 +566,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
bool z_axis_ok = allow_3d_arcs_ ||
utilities::is_equal(p_cur_pos->z, p_pre_pos->z);
-
+
if (
!is_end && cmd.is_known_command && !cmd.is_empty && (
is_g0_g1 && z_axis_ok &&
@@ -603,7 +602,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
{
if (debug_logging_enabled_)
{
- p_logger_->log(logger_type_, DEBUG, "Starting new arc from Gcode:" + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Starting new arc from Gcode:" + cmd.gcode);
}
write_unwritten_gcodes_to_file();
// add the previous point as the starting point for the current arc
@@ -635,7 +634,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
{
if (num_points + 1 == current_arc_.get_num_segments())
{
- p_logger_->log(logger_type_, DEBUG, "Adding point to arc from Gcode:" + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Adding point to arc from Gcode:" + cmd.gcode);
}
}
@@ -647,25 +646,25 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
if (debug_logging_enabled_) {
if (is_end)
{
- p_logger_->log(logger_type_, DEBUG, "Procesing final shape, if one exists.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Procesing final shape, if one exists.");
}
else if (!cmd.is_empty)
{
if (!cmd.is_known_command)
{
- p_logger_->log(logger_type_, DEBUG, "Command '" + cmd.command + "' is Unknown. Gcode:" + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Command '" + cmd.command + "' is Unknown. Gcode:" + cmd.gcode);
}
else if (cmd.command != "G0" && cmd.command != "G1")
{
- p_logger_->log(logger_type_, DEBUG, "Command '" + cmd.command + "' is not G0/G1, skipping. Gcode:" + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Command '" + cmd.command + "' is not G0/G1, skipping. Gcode:" + cmd.gcode);
}
else if (!allow_3d_arcs_ && !utilities::is_equal(p_cur_pos->z, p_pre_pos->z))
{
- p_logger_->log(logger_type_, DEBUG, "Z axis position changed, cannot convert:" + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Z axis position changed, cannot convert:" + cmd.gcode);
}
else if (p_cur_pos->is_relative)
{
- p_logger_->log(logger_type_, DEBUG, "XYZ Axis is in relative mode, cannot convert:" + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "XYZ Axis is in relative mode, cannot convert:" + cmd.gcode);
}
else if (
waiting_for_arc_ && !(
@@ -696,37 +695,37 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
", Retracting: " + (previous_extruder.is_retracting ? "True" : "False") +
", Extruding: " + (previous_extruder.is_extruding ? "True" : "False")
);
- p_logger_->log(logger_type_, VERBOSE, message);
+ p_logger_->log(logger_type_, log_levels::VERBOSE, message);
}
else
{
- p_logger_->log(logger_type_, DEBUG, message);
+ p_logger_->log(logger_type_, log_levels::DEBUG, message);
}
}
else if (p_cur_pos->is_extruder_relative != p_pre_pos->is_extruder_relative)
{
- p_logger_->log(logger_type_, DEBUG, "Extruder axis mode changed, cannot add point to current arc: " + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Extruder axis mode changed, cannot add point to current arc: " + cmd.gcode);
}
else if (waiting_for_arc_ && p_pre_pos->f != p_cur_pos->f)
{
- p_logger_->log(logger_type_, DEBUG, "Feedrate changed, cannot add point to current arc: " + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Feedrate changed, cannot add point to current arc: " + cmd.gcode);
}
else if (waiting_for_arc_ && p_pre_pos->feature_type_tag != p_cur_pos->feature_type_tag)
{
- p_logger_->log(logger_type_, DEBUG, "Feature type changed, cannot add point to current arc: " + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Feature type changed, cannot add point to current arc: " + cmd.gcode);
}
else if (aborted_by_flow_rate)
{
std::stringstream stream;
stream << std::fixed << std::setprecision(5);
stream << "Arc Canceled - The extrusion rate variance of " << extrusion_rate_variance_percent_ << "% exceeded by " << extrusion_rate_change_percent - extrusion_rate_variance_percent_ << "% on line " << lines_processed_ << ". Extruded " << extruder_current.e_relative << "mm over " << movement_length_mm << "mm of travel (" << mm_extruded_per_mm_travel << "mm/mm). Previous rate: " << previous_extrusion_rate_ << "mm/mm.";
- p_logger_->log(logger_type_, DEBUG, stream.str());
+ p_logger_->log(logger_type_, log_levels::DEBUG, stream.str());
}
else
{
// Todo: Add all the relevant values
- p_logger_->log(logger_type_, DEBUG, "There was an unknown issue preventing the current point from being added to the arc: " + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "There was an unknown issue preventing the current point from being added to the arc: " + cmd.gcode);
}
}
}
@@ -742,7 +741,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
{
if (current_arc_.get_num_segments() != 0)
{
- p_logger_->log(logger_type_, DEBUG, "Not enough segments, resetting. Gcode:" + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Not enough segments, resetting. Gcode:" + cmd.gcode);
}
}
@@ -773,7 +772,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
{
if (debug_logging_enabled_)
{
- p_logger_->log(logger_type_, DEBUG, "Final arc created, exiting.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Final arc created, exiting.");
}
return 0;
}
@@ -783,7 +782,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
{
if (debug_logging_enabled_)
{
- p_logger_->log(logger_type_, DEBUG, "The current arc is not a valid arc, resetting.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "The current arc is not a valid arc, resetting.");
}
current_arc_.clear();
waiting_for_arc_ = false;
@@ -791,7 +790,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
}
else if (debug_logging_enabled_)
{
- p_logger_->log(logger_type_, DEBUG, "Could not add point to arc from gcode:" + cmd.gcode);
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Could not add point to arc from gcode:" + cmd.gcode);
}
}
@@ -800,8 +799,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, !has_e_changed && (is_g0_g1 || is_g2_g3), movement_length_mm));
+ unwritten_commands_.push_back(unwritten_command(cmd, is_previous_extruder_relative, is_extrusion, is_retraction, is_travel, movement_length_mm));
}
else if (!waiting_for_arc_)
@@ -844,19 +842,26 @@ void arc_welder::write_arc_gcodes(double current_feedrate)
message += buffer;
message += " segments: ";
message += gcode;
- p_logger_->log(logger_type_, DEBUG, message);
+ p_logger_->log(logger_type_, log_levels::DEBUG, message);
}
// Write everything that hasn't yet been written
write_unwritten_gcodes_to_file();
// Update the current extrusion statistics for the current arc gcode
- if (current_arc_.get_shape_e_relative() != 0)
+ double shape_e_relative = current_arc_.get_shape_e_relative();
+ bool is_retraction = shape_e_relative < 0;
+ bool is_extrusion = shape_e_relative > 0;
+ if (is_extrusion)
{
segment_statistics_.update(current_arc_.get_shape_length(), false);
}
- else if (allow_travel_arcs_) {
+ else if (is_retraction)
+ {
+ segment_retraction_statistics_.update(current_arc_.get_shape_length(), false);
+ }
+ else if (allow_travel_arcs_ ) {
travel_statistics_.update(current_arc_.get_shape_length(), false);
}
// now write the current arc to the file
@@ -909,11 +914,16 @@ int arc_welder::write_unwritten_gcodes_to_file()
unwritten_command p = unwritten_commands_.pop_front();
if ((p.is_g0_g1 || p.is_g2_g3) && p.length > 0)
{
- if (!p.is_travel)
+
+ if (p.is_extrusion)
{
segment_statistics_.update(p.length, false);
}
- else if (allow_travel_arcs_) {
+ else if (p.is_retraction)
+ {
+ segment_retraction_statistics_.update(p.length, false);
+ }
+ else if (p.is_travel && allow_travel_arcs_) {
travel_statistics_.update(p.length, false);
}
}
@@ -941,7 +951,7 @@ std::string arc_welder::get_arc_gcode(const std::string comment)
void arc_welder::add_arcwelder_comment_to_target()
{
- p_logger_->log(logger_type_, DEBUG, "Adding ArcWelder comment to the target file.");
+ p_logger_->log(logger_type_, log_levels::DEBUG, "Adding ArcWelder comment to the target file.");
std::stringstream stream;
stream << std::fixed;
stream << "; Postprocessed by [ArcWelder](https://github.com/FormerLurker/ArcWelderLib)\n";
diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h
index 7bcff0c..c7d7465 100644
--- a/ArcWelder/arc_welder.h
+++ b/ArcWelder/arc_welder.h
@@ -61,7 +61,8 @@ struct segment_statistic {
};
struct source_target_segment_statistics {
- source_target_segment_statistics(const double segment_tracking_lengths[], const int num_lengths, logger* p_logger = NULL) {
+ source_target_segment_statistics(const double segment_tracking_lengths[], const int num_lengths, logger* p_logger = NULL)
+ {
total_length_source = 0;
total_length_target = 0;
total_count_source = 0;
@@ -73,6 +74,7 @@ struct source_target_segment_statistics {
for (int index = 0; index < num_lengths; index++)
{
double current_max = segment_tracking_lengths[index];
+ segment_statistic_lengths.push_back(segment_tracking_lengths[index]);
source_segments.push_back(segment_statistic(current_min, segment_tracking_lengths[index]));
target_segments.push_back(segment_statistic(current_min, segment_tracking_lengths[index]));
current_min = current_max;
@@ -83,7 +85,8 @@ struct source_target_segment_statistics {
p_logger_ = p_logger;
logger_type_ = 0;
}
-
+
+ std::vector<double> segment_statistic_lengths;
std::vector<segment_statistic> source_segments;
std::vector<segment_statistic> target_segments;
double total_length_source;
@@ -93,7 +96,7 @@ struct source_target_segment_statistics {
int total_count_source;
int total_count_target;
int num_segment_tracking_lengths;
-
+
double get_total_count_reduction_percent() const {
return utilities::get_percent_change(total_count_source, total_count_target);
}
@@ -127,10 +130,49 @@ struct source_target_segment_statistics {
}
}
+ static source_target_segment_statistics add(source_target_segment_statistics stats1, const source_target_segment_statistics stats2)
+ {
+
+ double * lengths = &stats1.segment_statistic_lengths[0];
+ std::copy(stats1.segment_statistic_lengths.begin(), stats1.segment_statistic_lengths.end(), lengths);
+ source_target_segment_statistics combined_stats(lengths, segment_statistic_lengths_count, stats1.p_logger_);
+ if (stats1.num_segment_tracking_lengths != stats2.num_segment_tracking_lengths)
+ {
+ // Todo: throw a reasonable exception
+ throw std::exception();
+ }
+
+ // Copy the segment statistics
+ for (int index = 0; index <= stats1.num_segment_tracking_lengths; index++)
+ {
+ // Verify the stats are the same
+ if (
+ stats1.source_segments[index].min_mm != stats2.source_segments[index].min_mm
+ || stats1.source_segments[index].max_mm != stats2.source_segments[index].max_mm
+ )
+ {
+ // Todo: throw a reasonable exception
+ throw std::exception();
+ }
+ combined_stats.source_segments[index].count = stats1.source_segments[index].count + stats2.source_segments[index].count;
+ combined_stats.target_segments[index].count = stats1.target_segments[index].count + stats2.target_segments[index].count;
+ }
+
+ combined_stats.total_length_source = stats1.total_length_source + stats2.total_length_source;
+ combined_stats.total_length_target = stats1.total_length_target + stats2.total_length_target;
+ combined_stats.total_count_source = stats1.total_count_source + stats2.total_count_source;
+ combined_stats.total_count_target = stats1.total_count_target + stats2.total_count_target;
+
+ return combined_stats;
+ }
std::string str() const {
+ return str("", utilities::box_drawing::BoxEncodingEnum::ASCII);
+ }
+
+ std::string str(std::string title, utilities::box_drawing::BoxEncodingEnum box_encoding) const {
//if (p_logger_ != NULL) p_logger_->log(logger_type_, VERBOSE, "Building Segment Statistics.");
-
+
std::stringstream output_stream;
std::stringstream format_stream;
const int min_column_size = 8;
@@ -207,21 +249,51 @@ struct source_target_segment_statistics {
}
// Get the table width
int table_width = mm_col_size + min_max_label_col_size + mm_col_size + source_col_size + target_col_size + percent_col_size;
- // Add a separator for the statistics
- //output_stream << std::setw(table_width) << std::setfill('-') << "-" << "\n" << std::setfill(' ') ;
- // Output the column headers
- // Center the min and max column.
- output_stream << utilities::center("Min", mm_col_size);
+ int table_left_padding = 0;
+ int table_right_padding = 0;
+ if (table_width < (int)title.length())
+ {
+ table_left_padding = ((int)title.length() - table_width) / 2;
+ table_right_padding = ((int)title.length() - table_width - table_left_padding);
+ table_width = (int)title.length();
+
+ }
+ utilities::box_drawing box(box_encoding, table_width);
+ // Draw the top border
+ box.top(output_stream);
+
+ if (title != "")
+ {
+ // Draw the title
+ box.row(output_stream, utilities::center(title, table_width));
+ // Draw the title separator
+ box.middle(output_stream);
+ }
+
+ // Output the centered column headers
+ // start the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL);
+ // add the left padding for the table
+ output_stream << std::string(table_left_padding, ' ');
+ output_stream << std::setfill(' ') << utilities::center("Min", mm_col_size);
output_stream << std::setw(min_max_label_col_size) << "";
output_stream << utilities::center("Max", mm_col_size);
// right align the source, target and change columns
output_stream << std::setw(source_col_size) << std::right << "Source";
output_stream << std::setw(target_col_size) << std::right << "Target";
output_stream << std::setw(percent_col_size) << std::right << "Change";
- output_stream << "\n";
- output_stream << std::setw(table_width) << std::setfill('-') << "" << std::setfill(' ') << "\n";
+ // Add the right padding for the table
+ output_stream << std::string(table_right_padding, ' ');
+ // end the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL) << "\n";
output_stream << std::fixed << std::setprecision(max_precision);
+ // Add the separator
+ box.middle(output_stream);
for (int index = 0; index < source_segments.size(); index++) {
+ // start the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL);
+ // add the left padding for the table
+ output_stream << std::string(table_left_padding, ' ');
//extract the necessary variables from the source and target segments
double min_mm = source_segments[index].min_mm;
double max_mm = source_segments[index].max_mm;
@@ -284,24 +356,34 @@ struct source_target_segment_statistics {
output_stream << std::setw(target_col_size) << target_count_string;
// Add the percent change string
output_stream << std::setw(percent_col_size) << percent_change_string;
- // End the line
- output_stream << "\n";
+ // Add the right padding for the table
+ output_stream << std::string(table_right_padding, ' ');
+ // end the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL) << "\n";
}
- // Add the total rows separator
- output_stream << std::setw(table_width) << std::setfill('-') << "" << std::setfill(' ') << "\n";
+
+
// Add the total rows;
+ // Draw the totals separator
+ box.middle(output_stream);
if (utilities::is_equal(total_length_source, total_length_target, 0.001))
{
+ // start the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL);
std::string total_distance_string;
format_stream.str(std::string());
format_stream << std::fixed << std::setprecision(max_precision) << total_length_source << "mm";
total_distance_string = format_stream.str();
output_stream << std::setw(totals_row_label_size) << std::right << "Total distance:";
- output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_distance_string << "\n" << std::setfill(' ');
+ output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_distance_string << std::setfill(' ');
+ // end the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL) << "\n";
}
else
{
- // We need to output two different distances (this probably should never happen)
+ // We need to output two different distances
+ // start the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL);
// Format the total source distance string
std::string total_source_distance_string;
format_stream.str(std::string());
@@ -309,8 +391,12 @@ struct source_target_segment_statistics {
total_source_distance_string = format_stream.str();
// Add the total source distance row
output_stream << std::setw(totals_row_label_size) << std::right << "Total distance source:";
- output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_source_distance_string << "\n" << std::setfill(' ');
+ output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_source_distance_string << std::setfill(' ');
+ // end the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL) << "\n";
+ // start the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL);
// Format the total target distance string
std::string total_target_distance_string;
format_stream.str(std::string());
@@ -318,32 +404,55 @@ struct source_target_segment_statistics {
total_target_distance_string = format_stream.str();
// Add the total target distance row
output_stream << std::setw(totals_row_label_size) << std::right << "Total distance target:";
- output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_target_distance_string << "\n" << std::setfill(' ');
+ output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_target_distance_string << std::setfill(' ');
+ // end the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL) << "\n";
}
// Add the total count rows
+
+ // start the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL);
// Add the source count
output_stream << std::setprecision(0) << std::setw(totals_row_label_size) << std::right << "Total count source:";
- output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_count_source << "\n" << std::setfill(' ');
+ output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_count_source << std::setfill(' ');
+ // end the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL) << "\n";
+
+ // start the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL);
// Add the target count
output_stream << std::setw(totals_row_label_size) << std::right << "Total count target:";
- output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_count_target << "\n" << std::setfill(' ');
+ output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_count_target << std::setfill(' ');
+ // end the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL) << "\n";
+
+ // start the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL);
// Add the total percent change row
std::string total_percent_change_string = utilities::get_percent_change_string(total_count_source, total_count_target, 1);
output_stream << std::setw(totals_row_label_size) << std::right << "Total percent change:";
output_stream << std::setw(table_width - totals_row_label_size) << std::setfill('.') << std::right << total_percent_change_string << std::setfill(' ');
+ // end the row
+ output_stream << box.get_box_replacement_element(utilities::box_drawing::BoxElementEnum::VERTICAL) << "\n";
+
+ // Add the final separator
+ box.bottom(output_stream);
+
std::string output_string = output_stream.str();
+ box.make_replacements(output_string);
return output_string;
}
private:
+
logger* p_logger_;
int logger_type_;
};
// 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), travel_statistics(segment_statistic_lengths, segment_statistic_lengths_count, NULL) {
+ arc_welder_progress() : segment_statistics(segment_statistic_lengths, segment_statistic_lengths_count, NULL), segment_retraction_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;
@@ -359,6 +468,8 @@ struct arc_welder_progress {
target_file_size = 0;
compression_ratio = 0;
compression_percent = 0;
+ combine_extrusion_and_retraction = true;
+ box_encoding = utilities::box_drawing::BoxEncodingEnum::ASCII;
}
double percent_complete;
double seconds_elapsed;
@@ -375,7 +486,11 @@ struct arc_welder_progress {
long source_file_position;
long source_file_size;
long target_file_size;
+ bool combine_extrusion_and_retraction;
+ utilities::box_drawing::BoxEncodingEnum box_encoding;
+
source_target_segment_statistics segment_statistics;
+ source_target_segment_statistics segment_retraction_statistics;
source_target_segment_statistics travel_statistics;
std::string simple_progress_str() const {
@@ -395,6 +510,7 @@ struct arc_welder_progress {
}
std::string str() const {
+
std::stringstream stream;
stream << std::fixed << std::setprecision(2);
@@ -407,20 +523,36 @@ struct arc_welder_progress {
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 << "% ";
+ stream << ", size_reduction: " << compression_percent << "% " ;
return stream.str();
}
std::string detail_str() const {
- std::stringstream stream;
+ std::stringstream wstream;
+ wstream << "\n";
+
if (travel_statistics.total_count_source > 0)
{
- stream << "Target File Travel Statistics:" << "\n" << travel_statistics.str() << "\n";
+ wstream << travel_statistics.str("Target File Travel Statistics", box_encoding) << "\n";
}
-
- stream << "\n" << "Target File Extrusion Statistics:" << "\n" << segment_statistics.str() << "\n";
-
- return stream.str();
+
+ if (combine_extrusion_and_retraction)
+ {
+ source_target_segment_statistics combined_stats = source_target_segment_statistics::add(segment_statistics, segment_retraction_statistics);
+ wstream << combined_stats.str("Target File Extrusion/Retraction Statistics", box_encoding) << "\n";
+ }
+ else
+ {
+
+ if (segment_retraction_statistics.total_count_source > 0)
+ {
+ wstream << segment_retraction_statistics.str("Target File Retraction Statistics", box_encoding) << "\n";
+ }
+
+ wstream << segment_statistics.str("Target File Extrusion Statistics", box_encoding) << "\n";
+ }
+ return wstream.str();
}
+
};
// define the progress callback type
typedef bool(*progress_callback)(arc_welder_progress, logger* p_logger, int logger_type);
@@ -437,30 +569,14 @@ typedef bool(*progress_callback)(arc_welder_progress, logger* p_logger, int logg
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),
- notification_period_seconds(DEFAULT_NOTIFICATION_PERIOD_SECONDS),
- callback(NULL){};
+ arc_welder_args() {
+ set_defaults();
+ };
- arc_welder_args(std::string source, std::string target, logger* ptr_log) : arc_welder_args()
+ arc_welder_args(std::string source, std::string target, logger* ptr_log)
{
+ set_defaults();
source_path = source;
target_path = target;
log = ptr_log;
@@ -483,6 +599,7 @@ struct arc_welder_args
int buffer_size;
int max_gcode_length;
double notification_period_seconds;
+ utilities::box_drawing::BoxEncodingEnum box_encoding;
progress_callback callback;
@@ -529,6 +646,31 @@ struct arc_welder_args
return stream.str();
};
+private:
+ void set_defaults()
+ {
+ 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,
+ notification_period_seconds = DEFAULT_NOTIFICATION_PERIOD_SECONDS,
+ callback = NULL;
+ box_encoding = utilities::box_drawing::BoxEncodingEnum::ASCII;
+ }
+
};
struct arc_welder_results {
@@ -547,48 +689,8 @@ struct arc_welder_results {
class arc_welder
{
public:
- arc_welder(
- std::string source_path,
- std::string target_path,
- logger* log,
- 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 max_gcode_length,
- int buffer_size,
- double notification_period_seconds,
- 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.notification_period_seconds,
- args.callback
- ){};
+
+ arc_welder(arc_welder_args args);
void set_logger_type(int logger_type);
@@ -627,6 +729,7 @@ private:
int arcs_aborted_by_flow_rate_;
double notification_period_seconds_;
source_target_segment_statistics segment_statistics_;
+ source_target_segment_statistics segment_retraction_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);
@@ -649,5 +752,5 @@ private:
bool info_logging_enabled_;
bool verbose_logging_enabled_;
bool error_logging_enabled_;
-
+ utilities::box_drawing::BoxEncodingEnum box_encoding_;
};
diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp
index dd422a4..d50e5b5 100644
--- a/ArcWelder/segmented_shape.cpp
+++ b/ArcWelder/segmented_shape.cpp
@@ -521,7 +521,6 @@ bool arc::try_create_arc(
{
circle test_circle = (circle)target_arc;
-
if (!circle::try_create_circle(points, max_radius_mm, resolution_mm, xyz_tolerance, allow_3d_arcs, test_circle))
{
return false;
diff --git a/ArcWelder/unwritten_command.h b/ArcWelder/unwritten_command.h
index 5acf999..bfca84f 100644
--- a/ArcWelder/unwritten_command.h
+++ b/ArcWelder/unwritten_command.h
@@ -32,9 +32,14 @@ struct unwritten_command
length = 0;
is_g0_g1 = false;
is_g2_g3 = false;
+ is_travel = false;
+ is_extrusion = false;
+ is_retraction = false;
+ gcode = "";
+ comment = "";
}
- 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"), is_g2_g3(cmd.command == "G2" || cmd.command == "G3"), gcode(cmd.gcode), comment(cmd.comment), length(command_length)
+ unwritten_command(parsed_command &cmd, bool is_relative, bool is_extrusion, bool is_retraction, bool is_travel, double command_length)
+ : is_extruder_relative(is_relative), is_extrusion(is_extrusion), is_retraction(is_retraction), is_travel(is_travel), is_g0_g1(cmd.command == "G0" || cmd.command == "G1"), is_g2_g3(cmd.command == "G2" || cmd.command == "G3"), gcode(cmd.gcode), comment(cmd.comment), length(command_length)
{
}
@@ -42,6 +47,8 @@ struct unwritten_command
bool is_g2_g3;
bool is_extruder_relative;
bool is_travel;
+ bool is_extrusion;
+ bool is_retraction;
double length;
std::string gcode;
std::string comment;
diff --git a/ArcWelderConsole/ArcWelderConsole.cpp b/ArcWelderConsole/ArcWelderConsole.cpp
index e64d9d4..ad63b37 100644
--- a/ArcWelderConsole/ArcWelderConsole.cpp
+++ b/ArcWelderConsole/ArcWelderConsole.cpp
@@ -81,8 +81,8 @@ int main(int argc, char* argv[])
// -t --path-tolerance-percent
arg_description_stream.clear();
arg_description_stream.str("");
- arg_description_stream << "This is the maximum allowable difference between the arc path and the original toolpath. Since most slicers use interpolation when generating arc moves, this value can be relatively high without impacting print quality.";
- arg_description_stream << " Expressed as a decimal percent, where 0.05 = 5.0%. Default Value: " << ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT;
+ arg_description_stream << "This is the maximum allowable difference between the arc path and the original toolpath.";
+ arg_description_stream << " Expressed as a decimal percent, where 0.05 = 5.0%. The lower this value is, the more arcs will be aborted, but values over 0.25 (25%) are not recommended, as they could negatively impact print quality. Default Value: " << ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT << " (" << ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT * 100 << "%)";
TCLAP::ValueArg<double> path_tolerance_percent_arg("t", "path-tolerance-percent", arg_description_stream.str(), false, DEFAULT_RESOLUTION_MM, "float");
// -m --max-radius-mm
@@ -142,7 +142,7 @@ int main(int argc, char* argv[])
// -v --extrusion-rate-variance
arg_description_stream.clear();
arg_description_stream.str("");
- arg_description_stream << "(experimental) - The allowed variance in extrusion rate by percent. Default Value: " << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT;
+ arg_description_stream << "(experimental) - The allowed variance in extrusion rate by percent, where 0.05 = 5.0%. A value of 0 will disable this feature. Default Value: " << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT << " (" << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT * 100 << "%)";
TCLAP::ValueArg<double> extrusion_rate_variance_percent_arg("v", "extrusion-rate-variance-percent", arg_description_stream.str(), false, DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT, "double");
// -c --max-gcode-length
@@ -236,7 +236,7 @@ int main(int argc, char* argv[])
has_error = true;
}
- if (args.path_tolerance_percent <= 0)
+ if (args.path_tolerance_percent < 0)
{
std::cerr << "error: The provided path tolerance percentage of " << args.path_tolerance_percent << " is negative, which is not allowed." << std::endl;
has_error = true;
@@ -262,15 +262,15 @@ int main(int argc, char* argv[])
args.mm_per_arc_segment = 0;
}
- if (args.path_tolerance_percent > 0.05)
+ if (args.path_tolerance_percent > 0.25)
{
// warning
- 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;
+ std::cout << "warning: The provided path tolerance percent of " << args.path_tolerance_percent << " is greater than 0.25 (25%), which is not recommended." << std::endl;
}
- else if (args.path_tolerance_percent < 0.0001 && args.path_tolerance_percent > 0)
+ else if (args.path_tolerance_percent < 0.001 && args.path_tolerance_percent > 0)
{
// warning
- 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;
+ std::cout << "warning: The provided path tolerance percent of " << args.path_tolerance_percent << " is less than 0.001 (0.1%), which is not recommended, and will result in very few arcs being generated." << std::endl;
}
if (xyz_precision < 3)
@@ -308,7 +308,7 @@ int main(int argc, char* argv[])
if (args.extrusion_rate_variance_percent < 0)
{
// warning
- std::cout << "warning: The provided extrusion_rate_variance_percent " << args.extrusion_rate_variance_percent << " is less than 0. Setting to the default." << std::endl;
+ std::cout << "warning: The provided extrusion_rate_variance_percent " << args.extrusion_rate_variance_percent << " is less than 0. Applying the default setting of " << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT*100 << "%." << std::endl;
args.extrusion_rate_variance_percent = DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT;
}
@@ -351,7 +351,7 @@ int main(int argc, char* argv[])
std::vector<std::string> log_names;
log_names.push_back(ARC_WELDER_LOGGER_NAME);
std::vector<int> log_levels;
- log_levels.push_back(log_levels::DEBUG);
+ log_levels.push_back((int)log_levels::DEBUG);
logger* p_logger = new logger(log_names, log_levels);
p_logger->set_log_level_by_value(log_level_value);
args.log = p_logger;
@@ -360,12 +360,12 @@ int main(int argc, char* argv[])
if (progress_type == PROGRESS_TYPE_NONE)
{
- p_logger->log(0, INFO, "Suppressing progress messages.");
+ p_logger->log(0, log_levels::INFO, "Suppressing progress messages.");
args.callback = on_progress_suppress;
}
else if (progress_type == PROGRESS_TYPE_FULL)
{
- p_logger->log(0, INFO, "Displaying full progress messages.");
+ p_logger->log(0, log_levels::INFO, "Displaying full progress messages.");
args.callback = on_progress_full;
}
else {
@@ -374,11 +374,14 @@ int main(int argc, char* argv[])
// Log the arguments
std::stringstream log_messages;
log_messages << "Processing GCode.";
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
log_messages.clear();
log_messages.str("");
log_messages << args.str();
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
+
+ // Set the box encoding
+ args.box_encoding = args.box_encoding = utilities::box_drawing::ASCII;
p_arc_welder = new arc_welder(args);
@@ -395,15 +398,17 @@ int main(int argc, char* argv[])
}
else
{
- log_messages << "Target File Travel Statistics:" << std::endl << results.progress.travel_statistics.str();
+ log_messages << "\n" << results.progress.travel_statistics.str("Target File Travel Statistics", utilities::box_drawing::ASCII);
}
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
}
log_messages.clear();
log_messages.str("");
- log_messages << "Target File Extrusion Statistics:" << std::endl << results.progress.segment_statistics.str();
+ // Extrusion Statistics
+ source_target_segment_statistics combined_stats = source_target_segment_statistics::add(results.progress.segment_statistics, results.progress.segment_retraction_statistics);
+ log_messages << "\n" << combined_stats.str("Target File Extrusion Statistics", utilities::box_drawing::ASCII);
p_logger->log(0, INFO, log_messages.str() );
@@ -411,14 +416,14 @@ int main(int argc, char* argv[])
log_messages.clear();
log_messages.str("");
log_messages << "Arc Welder process completed successfully.";
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
}
else
{
log_messages.clear();
log_messages.str("");
log_messages << "File processing failed.";
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
}
delete p_arc_welder;
diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
index a3147eb..d43aec7 100644
--- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
+++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
@@ -436,7 +436,7 @@ int run_arc_straightener(int argc, char* argv[])
std::vector<std::string> log_names;
log_names.push_back("arc_welder.gcode_conversion");
std::vector<int> log_levels;
- log_levels.push_back(log_levels::DEBUG);
+ log_levels.push_back((int)log_levels::DEBUG);
logger* p_logger = new logger(log_names, log_levels);
p_logger->set_log_level_by_value(log_level_value);
@@ -449,7 +449,7 @@ int run_arc_straightener(int argc, char* argv[])
if (!utilities::get_temp_file_path_for_file(args.source_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());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
log_messages.clear();
log_messages.str("");
}
@@ -457,7 +457,7 @@ int run_arc_straightener(int argc, char* argv[])
// 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());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
log_messages.clear();
log_messages.str("");
}
@@ -483,11 +483,11 @@ int run_arc_straightener(int argc, char* argv[])
arc_interpolation interpolator(args);
log_messages << interpolator.get_firmware_argument_description();
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
- p_logger->log(0, INFO, "Running interpolation...");
+ p_logger->log(0, log_levels::INFO, "Running interpolation...");
interpolator.process();
- p_logger->log(0, INFO, "Interpolation Complete.");
+ p_logger->log(0, log_levels::INFO, "Interpolation Complete.");
log_messages.clear();
log_messages.str("");
@@ -498,19 +498,19 @@ int run_arc_straightener(int argc, char* argv[])
log_messages.clear();
log_messages.str("");
log_messages << "Deleting the original source file at '" << args.source_path << "'.";
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
log_messages.clear();
log_messages.str("");
std::remove(args.source_path.c_str());
log_messages << "Renaming temporary file at '" << args.target_path << "' to '" << args.source_path << "'.";
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
std::rename(args.target_path.c_str(), args.source_path.c_str());
}
log_messages.clear();
log_messages.str("");
log_messages << "Process completed successfully.";
- p_logger->log(0, INFO, log_messages.str());
+ p_logger->log(0, log_levels::INFO, log_messages.str());
return 0;
diff --git a/ArcWelderTest/ArcWelderTest.cpp b/ArcWelderTest/ArcWelderTest.cpp
index 2aaa8e4..bd173d5 100644
--- a/ArcWelderTest/ArcWelderTest.cpp
+++ b/ArcWelderTest/ArcWelderTest.cpp
@@ -25,7 +25,6 @@
#include "logger.h"
#include <iostream>
-
int main(int argc, char* argv[])
{
run_tests(argc, argv);
@@ -273,15 +272,15 @@ static void TestAntiStutter(std::string filePath)
std::vector<std::string> logger_names;
logger_names.push_back("arc_welder.gcode_conversion");
std::vector<int> logger_levels;
- logger_levels.push_back(log_levels::NOSET);
- logger_levels.push_back(log_levels::VERBOSE);
- logger_levels.push_back(log_levels::DEBUG);
- logger_levels.push_back(log_levels::INFO);
- logger_levels.push_back(log_levels::WARNING);
- logger_levels.push_back(log_levels::ERROR);
- logger_levels.push_back(log_levels::CRITICAL);
+ logger_levels.push_back((int)log_levels::NOSET);
+ logger_levels.push_back((int)log_levels::VERBOSE);
+ logger_levels.push_back((int)log_levels::DEBUG);
+ logger_levels.push_back((int)log_levels::INFO);
+ logger_levels.push_back((int)log_levels::WARNING);
+ //logger_levels.push_back((int)(log_levels::ERROR));
+ logger_levels.push_back((int)log_levels::CRITICAL);
logger* p_logger = new logger(logger_names, logger_levels);
- p_logger->set_log_level(INFO);
+ p_logger->set_log_level(log_levels::INFO);
//FIRMWARE_COMPENSATION_TEST_1
//BENCHY_MIN_RADIUS_TEST
@@ -306,9 +305,10 @@ static void TestAntiStutter(std::string filePath)
// BENCHY_L1_DIFFICULT
// SPIRAL_TEST
// SPIRAL_VASE_TEST_FUNNEL
- std::string source_path = BENCHY_DIFFICULT;
+ std::string source_path = SPIRAL_VASE_TEST_SINGLE_LAYER_CYLINDER;
std::string target_path = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode";
arc_welder_args args(source_path, target_path, p_logger);
+ args.box_encoding = args.box_encoding = utilities::box_drawing::HTML;
args.callback = on_progress;
// override any arguments here;
args.allow_travel_arcs = true;
@@ -319,14 +319,14 @@ static void TestAntiStutter(std::string filePath)
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.");
+ p_logger->log(0, log_levels::INFO, results.progress.detail_str());
+ p_logger->log(0, log_levels::INFO, "Processing Complete.");
delete p_logger;
}
bool on_progress(arc_welder_progress progress, logger * p_logger, int logger_type)
{
- p_logger->log(logger_type, INFO, progress.str());
+ p_logger->log(logger_type, log_levels::INFO, progress.str());
return true;
}
diff --git a/ArcWelderTest/ArcWelderTest.h b/ArcWelderTest/ArcWelderTest.h
index e854c4b..4c8f217 100644
--- a/ArcWelderTest/ArcWelderTest.h
+++ b/ArcWelderTest/ArcWelderTest.h
@@ -112,6 +112,7 @@ static std::string DIFFICULT_ARCS_ISSUE_34 = "C:\\Users\\Brad\\Documents\\3DPrin
static std::string TORTURE_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\performance\\torture_test.gcode";
static std::string CURA_PLUGIN_ISSUE_18 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\CuraPlugin\\18\\Unwelded.gcode";
static std::string METALTEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\MetalAltered.gcode";
+static std::string TEMP_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\temp.gcode";
diff --git a/GcodeProcessorLib/logger.cpp b/GcodeProcessorLib/logger.cpp
index 3bde18e..6aa591a 100644
--- a/GcodeProcessorLib/logger.cpp
+++ b/GcodeProcessorLib/logger.cpp
@@ -36,7 +36,7 @@ logger::logger(std::vector<std::string> names, std::vector<int> levels) {
logger_names_[index] = names[index];
logger_levels_[index] = levels[index];
}
- set_log_level_by_value(NOSET);
+ set_log_level_by_value((int)log_levels::NOSET);
}
@@ -58,9 +58,9 @@ void logger::set_log_level_by_value(const int level_value)
}
}
-void logger::set_log_level(const int logger_type, const int log_level)
+void logger::set_log_level(const int logger_type, log_levels log_level)
{
- logger_levels_[logger_type] = log_level;
+ logger_levels_[logger_type] = (int)log_level;
}
std::string logger::get_log_level_name(std::string logger_name)
{
@@ -76,17 +76,17 @@ std::string logger::get_log_level_name(std::string logger_name)
return log_level_name;
}
-void logger::set_log_level(const int log_level)
+void logger::set_log_level(log_levels log_level)
{
for (int type_index = 0; type_index < num_loggers_; type_index++)
{
- logger_levels_[type_index] = log_level;
+ logger_levels_[type_index] = (int)log_level;
}
}
-int logger::get_log_level_value(const int log_level)
+int logger::get_log_level_value(log_levels log_level)
{
- return log_level_values[log_level];
+ return log_level_values[(int)log_level];
}
int logger::get_log_level_for_value(int log_level_value)
{
@@ -97,12 +97,12 @@ int logger::get_log_level_for_value(int log_level_value)
}
return 0;
}
-bool logger::is_log_level_enabled(const int logger_type, const int log_level)
+bool logger::is_log_level_enabled(const int logger_type, log_levels log_level)
{
- return logger_levels_[logger_type] <= log_level;
+ return logger_levels_[logger_type] <= (int)log_level;
}
-void logger::create_log_message(const int logger_type, const int log_level, const std::string& message, std::string& output)
+void logger::create_log_message(const int logger_type, log_levels log_level, const std::string& message, std::string& output)
{
// example message
// 2020-04-20 21:36:59,414 - arc_welder.__init__ - INFO - MESSAGE_GOES_HERE
@@ -116,7 +116,7 @@ void logger::create_log_message(const int logger_type, const int log_level, cons
// add a spacer
output.append(" - ");
// add the log level name
- output.append(log_level_names[log_level]);
+ output.append(log_level_names[(int)log_level]);
// add a spacer
output.append(" - ");
// add the message
@@ -128,12 +128,12 @@ void logger::log_exception(const int logger_type, const std::string& message)
log(logger_type, log_levels::ERROR, message, true);
}
-void logger::log(const int logger_type, const int log_level, const std::string& message)
+void logger::log(const int logger_type, log_levels log_level, const std::string& message)
{
log(logger_type, log_level, message, false);
}
-void logger::log(const int logger_type, const int log_level, const std::string& message, bool is_exception)
+void logger::log(const int logger_type, log_levels log_level, const std::string& message, bool is_exception)
{
// Make sure the loggers have been initialized
if (!loggers_created_)
diff --git a/GcodeProcessorLib/logger.h b/GcodeProcessorLib/logger.h
index f345097..8cbd5e3 100644
--- a/GcodeProcessorLib/logger.h
+++ b/GcodeProcessorLib/logger.h
@@ -46,18 +46,18 @@ public:
void set_log_level_by_value(const int logger_type, const int log_level_value);
void set_log_level_by_value(const int log_level_value);
- void set_log_level(const int logger_type, const int log_level);
- void set_log_level(const int log_level);
+ void set_log_level(const int logger_type, log_levels log_level);
+ void set_log_level(log_levels 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(const int logger_type, log_levels log_level, const std::string& message);
+ virtual void log(const int logger_type, log_levels log_level, const std::string& message, bool is_exception);
virtual void log_exception(const int logger_type, const std::string& message);
- static int get_log_level_value(const int log_level);
+ static int get_log_level_value(log_levels log_level);
static int get_log_level_for_value(int log_level_value);
- virtual bool is_log_level_enabled(const int logger_type, const int log_level);
+ virtual bool is_log_level_enabled(const int logger_type, log_levels log_level);
protected:
- virtual void create_log_message(const int logger_type, const int log_level, const std::string& message, std::string& output);
+ virtual void create_log_message(const int logger_type, log_levels log_level, const std::string& message, std::string& output);
bool loggers_created_;
private:
diff --git a/GcodeProcessorLib/utilities.cpp b/GcodeProcessorLib/utilities.cpp
index c53ddf8..74fef46 100644
--- a/GcodeProcessorLib/utilities.cpp
+++ b/GcodeProcessorLib/utilities.cpp
@@ -23,6 +23,89 @@
#include "utilities.h"
namespace utilities {
+ // Box Drawing Consts
+ // String Consts
+ // Note: these ascii replacement characters must NOT appear in the text unless they will be replaced with box characters.
+ const char box_drawing::table_elements_replacement[8] = {char(128),char(129),char(130),char(131),char(132),char(133),char(134),char(135) };
+ //enum BoxElementEnum { HORIZONTAL = 0, VERTICAL = 1, UPPER_LEFT = 2, UPPER_RIGHT = 3, MIDDLE_LEFT = 4, MIDDLE_RIGHT = 5, LOWER_LEFT = 6, LOWER_RIGHT = 7 };
+ const std::string box_drawing::table_elements_ascii[8] = {"-","|","+" ,"+" ,"+" ,"+" ,"+" ,"+" };
+ const std::string box_drawing::table_elements_utf8[8] = { "\u2500","\u2502","\u250C" ,"\u2510" ,"\u251C" ,"\u2524" ,"\u2514" ,"\u2518" };
+ const std::string box_drawing::table_elements_html[8] = { "&#9472","&#9474", "&#9484","&#9488","&#9500","&#9508","&#9492","&#9496" };
+
+ box_drawing::box_drawing()
+ {
+ set_box_type(BoxEncodingEnum::ASCII);
+
+ width_ = 100;
+ }
+ box_drawing::box_drawing(BoxEncodingEnum encoding, int width)
+ {
+ set_box_type(encoding);
+ width_ = width;
+ }
+
+ void box_drawing::set_box_type(BoxEncodingEnum encoding)
+ {
+ box_encoding_ = encoding;
+ for (int index = 0; index < 8; index++)
+ {
+ switch (box_encoding_)
+ {
+ case BoxEncodingEnum::ASCII:
+ table_elements_[index] = table_elements_ascii[index];
+ break;
+ case BoxEncodingEnum::UTF8:
+ table_elements_[index] = table_elements_utf8[index];
+ break;
+ case BoxEncodingEnum::HTML:
+ table_elements_[index] = table_elements_html[index];
+ break;
+ default:
+ table_elements_[index] = table_elements_ascii[index];
+ }
+
+ }
+ }
+
+ void box_drawing::top(std::stringstream& stream)
+ {
+ stream << get_box_replacement_element(BoxElementEnum::UPPER_LEFT) << std::setw(width_) << std::setfill(get_box_replacement_element(BoxElementEnum::HORIZONTAL)) << "" << get_box_replacement_element(BoxElementEnum::UPPER_RIGHT) << "\n" << std::setfill(' ');
+ }
+
+ void box_drawing::row(std::stringstream& stream, std::string line)
+ {
+ stream << get_box_replacement_element(BoxElementEnum::VERTICAL) << line << get_box_replacement_element(BoxElementEnum::VERTICAL) << "\n" << std::setfill(' ');
+ }
+
+ void box_drawing::middle(std::stringstream& stream)
+ {
+ stream << get_box_replacement_element(BoxElementEnum::MIDDLE_LEFT) << std::setw(width_) << std::setfill(get_box_replacement_element(BoxElementEnum::HORIZONTAL)) << "" << get_box_replacement_element(BoxElementEnum::MIDDLE_RIGHT) << "\n" << std::setfill(' ');
+ }
+ void box_drawing::bottom(std::stringstream& stream)
+ {
+ stream << get_box_replacement_element(BoxElementEnum::LOWER_LEFT) << std::setw(width_) << std::setfill(get_box_replacement_element(BoxElementEnum::HORIZONTAL)) << "" << get_box_replacement_element(BoxElementEnum::LOWER_RIGHT) << "\n" << std::setfill(' ');
+ }
+
+ char box_drawing::get_box_replacement_element(BoxElementEnum element)
+ {
+ return table_elements_replacement[(int)element];
+ }
+
+ void box_drawing::make_replacements(std::string &box)
+ {
+ for (int index = 0; index < 8; index++)
+ {
+ char c = table_elements_replacement[index];
+ std::string search;
+ search += c;
+ box = utilities::replace(box, search, table_elements_[index]);
+ }
+
+ }
+
+
+
+
const std::string WHITESPACE_ = " \n\r\t\f\v";
const char GUID_RANGE[] = "0123456789abcdef";
const bool GUID_DASHES[] = { 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 };
@@ -504,11 +587,6 @@ double utilities::pow(int e, double x)
return std::pow(e, x);
}
-double utilities::pow(int e, int x)
-{
- return std::pow(e, x);
-}
-
double utilities::min(double x, double y)
{
return std::min(x, y);
diff --git a/GcodeProcessorLib/utilities.h b/GcodeProcessorLib/utilities.h
index 88e8c40..1b7923f 100644
--- a/GcodeProcessorLib/utilities.h
+++ b/GcodeProcessorLib/utilities.h
@@ -147,7 +147,6 @@ namespace utilities{
double pow(int e, double x);
- double pow(int e, int x);
double min(double x, double y);
@@ -187,7 +186,35 @@ namespace utilities{
unsigned char rand_range(unsigned char min, unsigned char max);
int rand_range(int min, int max);
-
+
+
+ class box_drawing {
+
+ public:
+ enum BoxElementEnum { HORIZONTAL = 0, VERTICAL = 1, UPPER_LEFT = 2, UPPER_RIGHT = 3, MIDDLE_LEFT = 4, MIDDLE_RIGHT = 5, LOWER_LEFT = 6, LOWER_RIGHT = 7 };
+ enum BoxEncodingEnum {ASCII=0, UTF8=1, HTML=2};
+ box_drawing();
+ box_drawing(BoxEncodingEnum encoding, int width);
+ static const char table_elements_replacement[8];
+ static const std::string table_elements_ascii[8];
+ static const std::string table_elements_utf8[8];
+ static const std::string table_elements_html[8];
+ char get_box_replacement_element(BoxElementEnum element);
+ void top(std::stringstream& stream);
+ void row(std::stringstream& stream, std::string line);
+ void middle(std::stringstream& stream);
+ void bottom(std::stringstream& stream);
+ void set_box_type(BoxEncodingEnum encoding);
+ void make_replacements(std::string &box);
+
+ private:
+ std::string table_elements_[8];
+ BoxEncodingEnum box_encoding_;
+ std::string output_;
+ std::stringstream output_stream_;
+ int width_;
+
+ };
}
#endif \ No newline at end of file
diff --git a/PyArcWelder/py_arc_welder.cpp b/PyArcWelder/py_arc_welder.cpp
index fcb4b71..635ad9d 100644
--- a/PyArcWelder/py_arc_welder.cpp
+++ b/PyArcWelder/py_arc_welder.cpp
@@ -28,13 +28,15 @@ PyObject* py_arc_welder::build_py_progress(const arc_welder_progress& progress,
if (pyGuid == NULL)
return NULL;
// Extrusion Statistics
- std::string segment_statistics = progress.segment_statistics.str();
+ source_target_segment_statistics combined_stats = source_target_segment_statistics::add(progress.segment_statistics, progress.segment_retraction_statistics);
+
+ std::string segment_statistics = combined_stats.str("", utilities::box_drawing::HTML);
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();
+ std::string segment_travel_statistics = progress.travel_statistics.str("", utilities::box_drawing::HTML);
PyObject* pyTravelMessage = gcode_arc_converter::PyUnicode_SafeFromString(segment_travel_statistics);
if (pyMessage == NULL)
return NULL;
diff --git a/PyArcWelder/py_arc_welder_extension.cpp b/PyArcWelder/py_arc_welder_extension.cpp
index 1e440f9..c08e3d7 100644
--- a/PyArcWelder/py_arc_welder_extension.cpp
+++ b/PyArcWelder/py_arc_welder_extension.cpp
@@ -190,19 +190,21 @@ extern "C"
{
return NULL;
}
- p_py_logger->set_log_level(args.log_level);
+ p_py_logger->set_log_level((log_levels)args.log_level);
std::string message = "py_gcode_arc_converter.ConvertFile - Beginning Arc Conversion.";
- p_py_logger->log(GCODE_CONVERSION, INFO, message);
+ p_py_logger->log(GCODE_CONVERSION, log_levels::INFO, message);
args.py_progress_callback = py_progress_callback;
args.log = p_py_logger;
+ // Set the encoding to html for the progress output
+ args.box_encoding = utilities::box_drawing::HTML;
py_arc_welder arc_welder_obj(args);
arc_welder_results results;
results = arc_welder_obj.process();
message = "py_gcode_arc_converter.ConvertFile - Arc Conversion Complete.";
- p_py_logger->log(GCODE_CONVERSION, INFO, message);
+ p_py_logger->log(GCODE_CONVERSION, log_levels::INFO, message);
Py_XDECREF(py_progress_callback);
// return the arguments
PyObject* p_progress = py_arc_welder::build_py_progress(results.progress, args.guid);
diff --git a/PyArcWelder/py_logger.cpp b/PyArcWelder/py_logger.cpp
index 0ae6548..3269c42 100644
--- a/PyArcWelder/py_logger.cpp
+++ b/PyArcWelder/py_logger.cpp
@@ -119,7 +119,7 @@ void py_logger::set_internal_log_levels(bool check_real_time)
void py_logger::log_exception(const int logger_type, const std::string& message)
{
- log(logger_type, ERROR, message, true);
+ log(logger_type, log_levels::ERROR, message, true);
}
void py_logger::log(const int logger_type, const int log_level, const std::string& message)
@@ -176,24 +176,24 @@ void py_logger::log(const int logger_type, const int log_level, const std::strin
}
else
{
- switch (log_level)
+ switch ((log_levels)log_level)
{
- case INFO:
+ case log_levels::INFO:
pyFunctionName = py_info_function_name;
break;
- case WARNING:
+ case log_levels::WARNING:
pyFunctionName = py_warn_function_name;
break;
- case ERROR:
+ case log_levels::ERROR:
pyFunctionName = py_error_function_name;
break;
- case DEBUG:
+ case log_levels::DEBUG:
pyFunctionName = py_debug_function_name;
break;
- case VERBOSE:
+ case log_levels::VERBOSE:
pyFunctionName = py_verbose_function_name;
break;
- case CRITICAL:
+ case log_levels::CRITICAL:
pyFunctionName = py_critical_function_name;
break;
default: