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-02 22:24:47 +0300
committerFormerLurker <hochgebe@gmail.com>2021-07-02 22:24:47 +0300
commit18d1e992d3773485d2b7b05ffaec1ea00b16c777 (patch)
tree42983ee7c351d32d38afb437642ed9f9e861a024 /ArcWelder
parent65768d59a9ed785ddb740fc6df67d2912d2a5bdf (diff)
Add support for variable line widths.
Diffstat (limited to 'ArcWelder')
-rw-r--r--ArcWelder/arc_welder.cpp49
-rw-r--r--ArcWelder/arc_welder.h9
-rw-r--r--ArcWelder/segmented_arc.cpp10
-rw-r--r--ArcWelder/segmented_shape.cpp40
-rw-r--r--ArcWelder/segmented_shape.h3
5 files changed, 82 insertions, 29 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp
index a1f4ca7..95fbcda 100644
--- a/ArcWelder/arc_welder.cpp
+++ b/ArcWelder/arc_welder.cpp
@@ -34,6 +34,7 @@
#include <fstream>
#include <iomanip>
#include <sstream>
+#include <version.h>
arc_welder::arc_welder(
std::string source_path,
@@ -53,7 +54,7 @@ arc_welder::arc_welder(
int buffer_size,
progress_callback callback) : current_arc_(
DEFAULT_MIN_SEGMENTS,
- buffer_size - 5,
+ buffer_size,
resolution_mm,
path_tolerance_percent,
max_radius,
@@ -92,6 +93,7 @@ arc_welder::arc_welder(
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);
@@ -114,6 +116,10 @@ gcode_position_args arc_welder::get_args_(bool g90_g91_influences_extruder, int
gcode_position_args args;
// Configure gcode_position_args
args.g90_influences_extruder = g90_g91_influences_extruder;
+ if (buffer_size < 2)
+ {
+ buffer_size = 2;
+ }
args.position_buffer_size = buffer_size;
args.autodetect_position = true;
args.home_x = 0;
@@ -258,7 +264,8 @@ arc_welder_results results;
p_logger_->log(logger_type_, 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.");
-
+
+ bool arc_Welder_comment_added = false;
while (std::getline(gcodeFile, line) && continue_processing)
{
lines_processed_++;
@@ -267,17 +274,20 @@ arc_welder_results results;
if (lines_processed_ == 1)
{
bool isUltiGCode = line == ";FLAVOR:UltiGCode";
- if (isUltiGCode)
+ bool isPrusaSlicer = line.rfind("; generated by PrusaSlicer", 0) == 0;
+ if (isUltiGCode || isPrusaSlicer)
{
write_gcode_to_file(line);
}
add_arcwelder_comment_to_target();
- if (isUltiGCode)
+ if (isUltiGCode || isPrusaSlicer)
{
lines_with_no_commands++;
continue;
}
}
+
+
cmd.clear();
if (verbose_logging_enabled_)
{
@@ -368,6 +378,7 @@ arc_welder_progress arc_welder::get_progress_(long source_file_position, double
progress.lines_processed = lines_processed_;
progress.points_compressed = points_compressed_;
progress.arcs_created = arcs_created_;
+ progress.arcs_aborted_by_flow_rate = arcs_aborted_by_flow_rate_;
progress.source_file_position = source_file_position;
progress.target_file_size = static_cast<long>(output_file_.tellp());
progress.source_file_size = file_size_;
@@ -432,6 +443,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// calculate the extrusion rate (mm/mm) and see how much it changes
double mm_extruded_per_mm_travel = 0;
double extrusion_rate_change_percent = 0;
+ bool aborted_by_flow_rate = false;
if (movement_length_mm > 0)
{
mm_extruded_per_mm_travel = extruder_current.e_relative / movement_length_mm;
@@ -440,9 +452,10 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
extrusion_rate_change_percent = std::fabs(utilities::get_percent_change(previous_extrusion_rate_, mm_extruded_per_mm_travel));
}
}
- if (extrusion_rate_change_percent > extrusion_rate_variance_percent_)
+ if (previous_extrusion_rate_ != 0 && utilities::greater_than(extrusion_rate_change_percent, extrusion_rate_variance_percent_))
{
- std::cout << "Extrusion Rate Change Percent: " << extrusion_rate_change_percent << "\n";
+ 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
@@ -483,6 +496,8 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
(
!waiting_for_arc_ ||
extruder_current.is_extruding ||
+ // Test for travel conversion
+
//(previous_extruder.is_extruding && extruder_current.is_extruding) || // Test to see if
// we can get more arcs.
(previous_extruder.is_retracting && extruder_current.is_retracting)
@@ -493,6 +508,8 @@ 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);
if (!waiting_for_arc_)
{
@@ -514,6 +531,11 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
arc_added = current_arc_.try_add_point(p);
if (arc_added)
{
+ // Make sure our position list is large enough to handle all the segments
+ if (current_arc_.get_num_segments()+2 > p_source_position_->get_max_positions())
+ {
+ p_source_position_->grow_max_positions(p_source_position_->get_max_positions()*2);
+ }
if (!waiting_for_arc_)
{
waiting_for_arc_ = true;
@@ -533,7 +555,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
}
}
else {
- previous_extrusion_rate_ = 0;
+
if (debug_logging_enabled_) {
if (is_end)
{
@@ -606,9 +628,12 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
{
p_logger_->log(logger_type_, DEBUG, "Feature type changed, cannot add point to current arc: " + cmd.gcode);
}
- else if (previous_extrusion_rate_ != 0 && !utilities::is_equal(previous_extrusion_rate_, mm_extruded_per_mm_travel))
+ else if (aborted_by_flow_rate)
{
- p_logger_->log(logger_type_, DEBUG, "Previus extrusion rate changed: " + cmd.gcode);
+ 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());
}
else
{
@@ -617,9 +642,12 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
}
}
}
+
+ // Reset the previous extrusion rate
+ previous_extrusion_rate_ = 0;
}
- previous_extrusion_rate_ = mm_extruded_per_mm_travel;
+
if (!arc_added && !(cmd.is_empty && cmd.comment.length() == 0))
{
@@ -844,6 +872,7 @@ void arc_welder::add_arcwelder_comment_to_target()
stream << std::fixed;
stream << "; Postprocessed by [ArcWelder](https://github.com/FormerLurker/ArcWelderLib)\n";
stream << "; Copyright(C) 2020 - Brad Hochgesang\n";
+ stream << "; Version: " << GIT_TAGGED_VERSION << ", Branch: " << GIT_BRANCH << ", BuildDate: " << BUILD_DATE << "\n";
stream << "; resolution=" << std::setprecision(2) << resolution_mm_ << "mm\n";
stream << "; path_tolerance=" << std::setprecision(0) << (current_arc_.get_path_tolerance_percent() * 100.0) << "%\n";
stream << "; max_radius=" << std::setprecision(2) << (current_arc_.get_max_radius()) << "mm\n";
diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h
index 2da8929..a4fdded 100644
--- a/ArcWelder/arc_welder.h
+++ b/ArcWelder/arc_welder.h
@@ -354,6 +354,7 @@ struct arc_welder_progress {
lines_processed = 0;
points_compressed = 0;
arcs_created = 0;
+ arcs_aborted_by_flow_rate = 0;
num_firmware_compensations = 0;
source_file_size = 0;
source_file_position = 0;
@@ -368,6 +369,7 @@ struct arc_welder_progress {
int lines_processed;
int points_compressed;
int arcs_created;
+ int arcs_aborted_by_flow_rate;
int num_firmware_compensations;
double compression_ratio;
double compression_percent;
@@ -385,6 +387,7 @@ struct arc_welder_progress {
stream << ", current_file_line: " << lines_processed;
stream << ", points_compressed: " << points_compressed;
stream << ", arcs_created: " << arcs_created;
+ stream << ", arcs_aborted_by_flowrate: " << arcs_aborted_by_flow_rate;
stream << ", num_firmware_compensations: " << num_firmware_compensations;
stream << ", compression_ratio: " << compression_ratio;
stream << ", size_reduction: " << compression_percent << "% ";
@@ -412,11 +415,10 @@ struct arc_welder_results {
std::string message;
arc_welder_progress progress;
};
-#define DEFAULT_GCODE_BUFFER_SIZE 1000
+#define DEFAULT_GCODE_BUFFER_SIZE 10
#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false
#define DEFAULT_ALLOW_DYNAMIC_PRECISION false
-#define DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT 1
-//#define DEFAULT_EXTRUSION_RATE_VARIANCE 0.0001
+#define DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT 5
class arc_welder
{
public:
@@ -469,6 +471,7 @@ private:
int last_gcode_line_written_;
int points_compressed_;
int arcs_created_;
+ int arcs_aborted_by_flow_rate_;
source_target_segment_statistics segment_statistics_;
long get_file_size(const std::string& file_path);
double get_time_elapsed(double start_clock, double end_clock);
diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp
index 4da8f8e..62593d7 100644
--- a/ArcWelder/segmented_arc.cpp
+++ b/ArcWelder/segmented_arc.cpp
@@ -127,11 +127,12 @@ bool segmented_arc::try_add_point(printer_point p)
bool point_added = false;
// if we don't have enough segnemts to check the shape, just add
- if (points_.count() > get_max_segments() - 1)
+
+ if (points_.count() == points_.get_max_size())
{
// Too many points, we can't add more
- return false;
- }
+ points_.resize(points_.get_max_size()*2);
+ }
if (points_.count() > 0)
{
printer_point p1 = points_[points_.count() - 1];
@@ -193,9 +194,6 @@ bool segmented_arc::try_add_point_internal_(printer_point p)
if (points_.count() < get_min_segments() - 1)
return false;
- // Create a test circle
- circle target_circle;
-
// the circle is new.. we have to test it now, which is expensive :(
points_.push_back(p);
double previous_shape_length = original_shape_length_;
diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp
index 42aadcb..ec0611e 100644
--- a/ArcWelder/segmented_shape.cpp
+++ b/ArcWelder/segmented_shape.cpp
@@ -86,6 +86,11 @@ bool point::is_near_collinear(const point& p1, const point& p2, const point& p3,
return fabs((p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x)) <= 1e-9;
}
+double point::cartesian_distance(const point& p1, const point& p2)
+{
+ return utilities::get_cartesian_distance(p1.x, p1.y, p2.x, p2.y);
+}
+
#pragma endregion Point Functions
#pragma region Segment Functions
@@ -148,15 +153,12 @@ double vector::cross_product_magnitude(vector v1, vector v2)
#pragma region Circle Functions
-
bool circle::try_create_circle(const point& p1, const point& p2, const point& p3, const double max_radius, circle& new_circle)
{
if (point::is_near_collinear(p1,p2,p3, 0.001))
{
return false;
}
-
-
double x1 = p1.x;
double y1 = p1.y;
double x2 = p2.x;
@@ -196,22 +198,40 @@ bool circle::try_create_circle(const point& p1, const point& p2, const point& p3
bool circle::try_create_circle(const array_list<printer_point>& points, const double max_radius, const double resolution_mm, const double xyz_tolerance, bool allow_3d_arcs, circle& new_circle)
{
int count = points.count();
-
int middle_index = count / 2;
+ int end_index = count - 1;
+
- // The middle point will almost always produce the best arcs.
- if (circle::try_create_circle(points[0], points[middle_index], points[count - 1], max_radius, new_circle) && !new_circle.is_over_deviation(points, resolution_mm, xyz_tolerance, allow_3d_arcs))
+
+ if (circle::try_create_circle(points[0], points[middle_index], points[end_index], max_radius, new_circle) && !new_circle.is_over_deviation(points, resolution_mm, xyz_tolerance, allow_3d_arcs))
{
return true;
}
-
+
+ /*
+ // This could be a near complete circle. In that case, the endpoints might be too close together to generate an accurate circle with the
+ // precision we have to work with. Let's adjust our circle into thirds and test those points as a last ditch effort.
+ if (count > 5)
+ {
+ middle_index = count / 3;
+ end_index = middle_index + middle_index;
+ if (circle::try_create_circle(points[0], points[middle_index], points[end_index], max_radius, test_circle) && !test_circle.is_over_deviation(points, resolution_mm, xyz_tolerance, allow_3d_arcs))
+ {
+ new_circle = test_circle;
+ return true;
+ }
+ }
+ return false;
+ */
+
// Find the circle with the least deviation, if one exists.
// Note, this could possibly take a LONG time in the worst case, but it's a pretty unlikely.
// However, if the midpoint check doesn't pass, it's worth it to spend a bit more time
// finding the best fit for the circle (least squares deviation)
- circle test_circle;
+
double least_deviation;
bool found_circle=false;
+
for (int index = 1; index < count - 1; index++)
{
@@ -220,7 +240,7 @@ bool circle::try_create_circle(const array_list<printer_point>& points, const do
// We already checked this one, and it failed, continue.
continue;
}
-
+ circle test_circle;
double current_deviation;
if (circle::try_create_circle(points[0], points[index], points[count - 1], max_radius, test_circle) && test_circle.get_deviation_sum_squared(points, resolution_mm, xyz_tolerance, allow_3d_arcs, current_deviation))
{
@@ -234,6 +254,7 @@ bool circle::try_create_circle(const array_list<printer_point>& points, const do
}
}
return found_circle;
+
}
double circle::get_polar_radians(const point& p1) const
@@ -332,6 +353,7 @@ bool circle::is_over_deviation(const array_list<printer_point>& points, const do
}
// Check the point perpendicular from the segment to the circle's center, if any such point exists
+
if (segment::get_closest_perpendicular_point(current_point, points[index + 1], center, point_to_test))
{
double distance = utilities::get_cartesian_distance(point_to_test.x, point_to_test.y, center.x, center.y);
diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h
index 8b014bc..ec4bde9 100644
--- a/ArcWelder/segmented_shape.h
+++ b/ArcWelder/segmented_shape.h
@@ -47,6 +47,7 @@ public:
double z;
static point get_midpoint(point p1, point p2);
static bool is_near_collinear(const point& p1, const point& p2, const point& p3, double percent_tolerance);
+ static double cartesian_distance(const point& p1, const point& p2);
};
struct printer_point : point
@@ -99,7 +100,7 @@ struct vector : point
};
-#define DEFAULT_MAX_RADIUS_MM 1000000.0 // 1km
+#define DEFAULT_MAX_RADIUS_MM 10000.0 // 10m
struct circle {
circle() {
center.x = 0;