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
parent65768d59a9ed785ddb740fc6df67d2912d2a5bdf (diff)
Add support for variable line widths.
-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
-rw-r--r--ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp4
-rw-r--r--ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj8
-rw-r--r--ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters16
-rw-r--r--ArcWelderInverseProcessor/firmware_types.cpp1
-rw-r--r--ArcWelderInverseProcessor/firmware_types.h4
-rw-r--r--ArcWelderInverseProcessor/marlin_2_arc.cpp (renamed from ArcWelderInverseProcessor/inverse_processor.cpp)18
-rw-r--r--ArcWelderInverseProcessor/marlin_2_arc.h (renamed from ArcWelderInverseProcessor/inverse_processor.h)6
-rw-r--r--ArcWelderInverseProcessor/repiter_arc.cpp97
-rw-r--r--ArcWelderInverseProcessor/repiter_arc.h7
-rw-r--r--ArcWelderTest/ArcWelderTest.cpp8
-rw-r--r--ArcWelderTest/ArcWelderTest.h5
-rw-r--r--GcodeProcessorLib/GcodeProcessorLib.vcxproj2
-rw-r--r--GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters12
-rw-r--r--GcodeProcessorLib/array_list.cpp22
-rw-r--r--GcodeProcessorLib/circular_buffer.cpp22
-rw-r--r--GcodeProcessorLib/circular_buffer.h108
-rw-r--r--GcodeProcessorLib/gcode_position.cpp107
-rw-r--r--GcodeProcessorLib/gcode_position.h8
-rw-r--r--GcodeProcessorLib/position.cpp4
-rw-r--r--GcodeProcessorLib/position.h1
-rw-r--r--GcodeProcessorLib/utilities.cpp19
-rw-r--r--GcodeProcessorLib/utilities.h3
-rw-r--r--PyArcWelder/py_arc_welder.cpp24
28 files changed, 422 insertions, 195 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;
diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
index ea333b3..ca64ff3 100644
--- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
+++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
@@ -26,7 +26,7 @@
#define _CRT_SECURE_NO_DEPRECATE
#endif
-#include "inverse_processor.h"
+#include "marlin_2_arc.h"
#include "ArcWelderInverseProcessor.h"
#include <cstring>
#include <iostream>
@@ -233,7 +233,7 @@ int main(int argc, char* argv[])
target_file_path = temp_file_path;
}
- inverse_processor processor(source_file_path, target_file_path, g90_g91_influences_extruder, 50, cs);
+ marlin_2_arc processor(source_file_path, target_file_path, g90_g91_influences_extruder, 50, cs);
processor.process();
// Todo: get some results!
if (true)
diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj
index 37ec7d0..f67571c 100644
--- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj
+++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj
@@ -202,11 +202,15 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ArcWelderInverseProcessor.h" />
- <ClInclude Include="inverse_processor.h" />
+ <ClInclude Include="firmware_types.h" />
+ <ClInclude Include="marlin_2_arc.h" />
+ <ClInclude Include="repiter_arc.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ArcWelderInverseProcessor.cpp" />
- <ClCompile Include="inverse_processor.cpp" />
+ <ClCompile Include="firmware_types.cpp" />
+ <ClCompile Include="marlin_2_arc.cpp" />
+ <ClCompile Include="repiter_arc.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ArcWelder\ArcWelder.vcxproj">
diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters
index fe669d6..bc338f9 100644
--- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters
+++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj.filters
@@ -18,7 +18,13 @@
<ClInclude Include="ArcWelderInverseProcessor.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="inverse_processor.h">
+ <ClInclude Include="repiter_arc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="marlin_2_arc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="firmware_types.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
@@ -26,7 +32,13 @@
<ClCompile Include="ArcWelderInverseProcessor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="inverse_processor.cpp">
+ <ClCompile Include="repiter_arc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="marlin_2_arc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="firmware_types.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
diff --git a/ArcWelderInverseProcessor/firmware_types.cpp b/ArcWelderInverseProcessor/firmware_types.cpp
new file mode 100644
index 0000000..61820cf
--- /dev/null
+++ b/ArcWelderInverseProcessor/firmware_types.cpp
@@ -0,0 +1 @@
+#include "firmware_types.h"
diff --git a/ArcWelderInverseProcessor/firmware_types.h b/ArcWelderInverseProcessor/firmware_types.h
new file mode 100644
index 0000000..b3507ad
--- /dev/null
+++ b/ArcWelderInverseProcessor/firmware_types.h
@@ -0,0 +1,4 @@
+#pragma once
+enum firmware_types { Marlin2, Repiter };
+
+
diff --git a/ArcWelderInverseProcessor/inverse_processor.cpp b/ArcWelderInverseProcessor/marlin_2_arc.cpp
index c6edb6f..b7b3246 100644
--- a/ArcWelderInverseProcessor/inverse_processor.cpp
+++ b/ArcWelderInverseProcessor/marlin_2_arc.cpp
@@ -47,14 +47,14 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "inverse_processor.h"
+#include "marlin_2_arc.h"
#include <cmath>
//#include "Marlin.h"
//#include "stepper.h"
//#include "planner.h"
-inverse_processor::inverse_processor(std::string source_path, std::string target_path, bool g90_g91_influences_extruder, int buffer_size, ConfigurationStore cs)
+marlin_2_arc::marlin_2_arc(std::string source_path, std::string target_path, bool g90_g91_influences_extruder, int buffer_size, ConfigurationStore cs)
{
source_path_ = source_path;
target_path_ = target_path;
@@ -79,7 +79,7 @@ inverse_processor::inverse_processor(std::string source_path, std::string target
*/
}
-gcode_position_args inverse_processor::get_args_(bool g90_g91_influences_extruder, int buffer_size)
+gcode_position_args marlin_2_arc::get_args_(bool g90_g91_influences_extruder, int buffer_size)
{
gcode_position_args args;
// Configure gcode_position_args
@@ -112,12 +112,12 @@ gcode_position_args inverse_processor::get_args_(bool g90_g91_influences_extrude
return args;
}
-inverse_processor::~inverse_processor()
+marlin_2_arc::~marlin_2_arc()
{
delete p_source_position_;
}
-void inverse_processor::process()
+void marlin_2_arc::process()
{
// Create a stringstream we can use for messaging.
std::stringstream stream;
@@ -239,7 +239,7 @@ void inverse_processor::process()
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
// segment is configured in settings.mm_per_arc_segment.
-void inverse_processor::mc_arc(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder)
+void marlin_2_arc::mc_arc(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder)
{
// Extract the position to reduce indexing at the cost of a few bytes of mem
float p_x = position[X_AXIS];
@@ -363,7 +363,7 @@ void inverse_processor::mc_arc(float* position, float* target, float* offset, fl
int8_t count = 0;
for (i = 1; i < segments; i++) { // Increment (segments-1)
- if (count < cs_.n_arc_correction) {
+ if (count < cs_.n_arc_correction /*&& theta_per_segment > 0.001 */) {
// Apply vector rotation matrix
r_axisi = r_axis_x * sin_T + r_axis_y * cos_T;
r_axis_x = r_axis_x * cos_T - r_axis_y * sin_T;
@@ -404,13 +404,13 @@ void inverse_processor::mc_arc(float* position, float* target, float* offset, fl
position[E_AXIS] = t_e;
}
-void inverse_processor::clamp_to_software_endstops(float* target)
+void marlin_2_arc::clamp_to_software_endstops(float* target)
{
// Do nothing, just added to keep mc_arc identical to the firmware version
return;
}
-void inverse_processor::plan_buffer_line(float x, float y, bool has_z, float z, const float& e, float feed_rate, uint8_t extruder, const float* gcode_target)
+void marlin_2_arc::plan_buffer_line(float x, float y, bool has_z, float z, const float& e, float feed_rate, uint8_t extruder, const float* gcode_target)
{
std::stringstream stream;
stream << std::fixed;
diff --git a/ArcWelderInverseProcessor/inverse_processor.h b/ArcWelderInverseProcessor/marlin_2_arc.h
index ab33133..a7a2ac3 100644
--- a/ArcWelderInverseProcessor/inverse_processor.h
+++ b/ArcWelderInverseProcessor/marlin_2_arc.h
@@ -62,10 +62,10 @@ struct ConfigurationStore {
int n_arc_correction;
};
-class inverse_processor {
+class marlin_2_arc {
public:
- inverse_processor(std::string source_path, std::string target_path, bool g90_g91_influences_extruder, int buffer_size, ConfigurationStore cs = ConfigurationStore());
- virtual ~inverse_processor();
+ marlin_2_arc(std::string source_path, std::string target_path, bool g90_g91_influences_extruder, int buffer_size, ConfigurationStore cs = ConfigurationStore());
+ virtual ~marlin_2_arc();
void process();
void mc_arc(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder);
diff --git a/ArcWelderInverseProcessor/repiter_arc.cpp b/ArcWelderInverseProcessor/repiter_arc.cpp
new file mode 100644
index 0000000..83818a0
--- /dev/null
+++ b/ArcWelderInverseProcessor/repiter_arc.cpp
@@ -0,0 +1,97 @@
+#include "repiter_arc.h"
+
+
+/*
+// Arc function taken from grbl
+// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
+// segment is configured in settings.mm_per_arc_segment.
+void repiter_arc::arc(float* position, float* target, float* offset, float radius, uint8_t isclockwise) {
+ // int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled();
+ // plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc
+ float center_axis0 = position[X_AXIS] + offset[X_AXIS];
+ float center_axis1 = position[Y_AXIS] + offset[Y_AXIS];
+ //float linear_travel = 0; //target[axis_linear] - position[axis_linear];
+ float extruder_travel = (Printer::destinationSteps[E_AXIS] - Printer::currentPositionSteps[E_AXIS]) * Printer::invAxisStepsPerMM[E_AXIS];
+ float r_axis0 = -offset[0]; // Radius vector from center to current location
+ float r_axis1 = -offset[1];
+ float rt_axis0 = target[0] - center_axis0;
+ float rt_axis1 = target[1] - center_axis1;
+ // CCW angle between position and target from circle center. Only one atan2() trig computation required.
+ float angular_travel = atan2(r_axis0 * rt_axis1 - r_axis1 * rt_axis0, r_axis0 * rt_axis0 + r_axis1 * rt_axis1);
+ if ((!isclockwise && angular_travel <= 0.00001) || (isclockwise && angular_travel < -0.000001)) {
+ angular_travel += 2.0f * M_PI;
+ }
+ if (isclockwise) {
+ angular_travel -= 2.0f * M_PI;
+ }
+
+ float millimeters_of_travel = fabs(angular_travel) * radius; //hypot(angular_travel*radius, fabs(linear_travel));
+ if (millimeters_of_travel < 0.001f) {
+ return; // treat as succes because there is nothing to do;
+ }
+ //uint16_t segments = (radius>=BIG_ARC_RADIUS ? floor(millimeters_of_travel/MM_PER_ARC_SEGMENT_BIG) : floor(millimeters_of_travel/MM_PER_ARC_SEGMENT));
+ // Increase segment size if printing faster then computation speed allows
+ uint16_t segments = (Printer::feedrate > 60.0f ? floor(millimeters_of_travel / RMath::min(static_cast<float>(MM_PER_ARC_SEGMENT_BIG), Printer::feedrate * 0.01666f * static_cast<float>(MM_PER_ARC_SEGMENT))) : floor(millimeters_of_travel / static_cast<float>(MM_PER_ARC_SEGMENT)));
+ if (segments == 0)
+ segments = 1;
+
+ float theta_per_segment = angular_travel / segments;
+ //float linear_per_segment = linear_travel/segments;
+ float extruder_per_segment = extruder_travel / segments;
+
+
+ // Vector rotation matrix values
+ float cos_T = 1 - 0.5 * theta_per_segment * theta_per_segment; // Small angle approximation
+ float sin_T = theta_per_segment;
+
+ float arc_target[4];
+ float sin_Ti;
+ float cos_Ti;
+ float r_axisi;
+ uint16_t i;
+ int8_t count = 0;
+
+ // Initialize the linear axis
+ //arc_target[axis_linear] = position[axis_linear];
+
+ // Initialize the extruder axis
+ arc_target[E_AXIS] = Printer::currentPositionSteps[E_AXIS] * Printer::invAxisStepsPerMM[E_AXIS];
+
+ for (i = 1; i < segments; i++) {
+ // Increment (segments-1)
+
+ if ((count & 3) == 0) {
+ //GCode::readFromSerial();
+ Commands::checkForPeriodicalActions(false);
+ UI_MEDIUM; // do check encoder
+ }
+
+ if (count < N_ARC_CORRECTION) { //25 pieces
+ // Apply vector rotation matrix
+ r_axisi = r_axis0 * sin_T + r_axis1 * cos_T;
+ r_axis0 = r_axis0 * cos_T - r_axis1 * sin_T;
+ r_axis1 = r_axisi;
+ count++;
+ }
+ else {
+ // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
+ // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
+ cos_Ti = cos(i * theta_per_segment);
+ sin_Ti = sin(i * theta_per_segment);
+ r_axis0 = -offset[0] * cos_Ti + offset[1] * sin_Ti;
+ r_axis1 = -offset[0] * sin_Ti - offset[1] * cos_Ti;
+ count = 0;
+ }
+
+ // Update arc_target location
+ arc_target[X_AXIS] = center_axis0 + r_axis0;
+ arc_target[Y_AXIS] = center_axis1 + r_axis1;
+ //arc_target[axis_linear] += linear_per_segment;
+ arc_target[E_AXIS] += extruder_per_segment;
+ Printer::moveToReal(arc_target[X_AXIS], arc_target[Y_AXIS], IGNORE_COORDINATE, arc_target[E_AXIS], IGNORE_COORDINATE);
+ }
+ // Ensure last segment arrives at target location.
+ Printer::moveToReal(target[X_AXIS], target[Y_AXIS], IGNORE_COORDINATE, target[E_AXIS], IGNORE_COORDINATE);
+}
+
+*/ \ No newline at end of file
diff --git a/ArcWelderInverseProcessor/repiter_arc.h b/ArcWelderInverseProcessor/repiter_arc.h
new file mode 100644
index 0000000..353c040
--- /dev/null
+++ b/ArcWelderInverseProcessor/repiter_arc.h
@@ -0,0 +1,7 @@
+#pragma once
+#include <cstdint>
+class repiter_arc
+{
+ void arc(float* position, float* target, float* offset, float radius, uint8_t isclockwise);
+};
+
diff --git a/ArcWelderTest/ArcWelderTest.cpp b/ArcWelderTest/ArcWelderTest.cpp
index 3cb916c..9f3aa2f 100644
--- a/ArcWelderTest/ArcWelderTest.cpp
+++ b/ArcWelderTest/ArcWelderTest.cpp
@@ -269,6 +269,7 @@ 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;
@@ -288,19 +289,20 @@ 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_L1_DIFFICULT,
+ METALTEST,
"C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode",
p_logger,
max_resolution,
path_tolerance_percent,
- max_radius_mm,
+ DEFAULT_MAX_RADIUS_MM,
min_arc_segments,
mm_per_arc_segment,
- false,
+ true,
true,
DEFAULT_ALLOW_DYNAMIC_PRECISION,
DEFAULT_XYZ_PRECISION,
diff --git a/ArcWelderTest/ArcWelderTest.h b/ArcWelderTest/ArcWelderTest.h
index 249d70b..13f4940 100644
--- a/ArcWelderTest/ArcWelderTest.h
+++ b/ArcWelderTest/ArcWelderTest.h
@@ -94,6 +94,8 @@ static std::string BENCHY_MIN_RADIUS_TEST = "C:\\Users\\Brad\\Documents\\3DPrint
static std::string ISSUE_93 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\93\\FailingGCode.gcode";
static std::string ISSUE_99 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\99\\FailingGCode.gcode";
static std::string ISSUE_134 = "C:\\Users\\Brad\\Documents\\AntiStutter\\Issues\\134\\BirdHouse [PETG] [brim]+Infill [20%,cubic]+Noz [0.6]+LH [0.2]+LW-[0.6]+Temps [240+70]+50.0mms+Support [normal (56)]+Coast-[False].gcode" ;
+static std::string ISSUE_170 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\170\\lampenring.gcode";
+static std::string ISSUE_184 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\184\\Dome_60_1.2mm_max_test15_0.2mm_PETG_MK3S_2h1m.gcode";
static std::string CONE_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\ConeTest.gcode";
static std::string CONE_TEST_VASE = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\ConeTestVase.gcode";
@@ -107,7 +109,8 @@ static std::string ISSUE_34 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutte
static std::string DIFFICULT_ARCS_ISSUE_34 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\DifficultArcs\\issue_34.gcode";
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";
diff --git a/GcodeProcessorLib/GcodeProcessorLib.vcxproj b/GcodeProcessorLib/GcodeProcessorLib.vcxproj
index 956df18..778d3f3 100644
--- a/GcodeProcessorLib/GcodeProcessorLib.vcxproj
+++ b/GcodeProcessorLib/GcodeProcessorLib.vcxproj
@@ -210,8 +210,6 @@
<ClInclude Include="version.h" />
</ItemGroup>
<ItemGroup>
- <ClCompile Include="array_list.cpp" />
- <ClCompile Include="circular_buffer.cpp" />
<ClCompile Include="extruder.cpp" />
<ClCompile Include="fpconv.cpp" />
<ClCompile Include="gcode_comment_processor.cpp" />
diff --git a/GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters b/GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters
index 60b8ca9..3aed5ba 100644
--- a/GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters
+++ b/GcodeProcessorLib/GcodeProcessorLib.vcxproj.filters
@@ -18,9 +18,6 @@
<ClInclude Include="array_list.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="circular_buffer.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="extruder.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -54,14 +51,11 @@
<ClInclude Include="fpconv.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="circular_buffer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="array_list.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="circular_buffer.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="extruder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/GcodeProcessorLib/array_list.cpp b/GcodeProcessorLib/array_list.cpp
deleted file mode 100644
index b2e46ea..0000000
--- a/GcodeProcessorLib/array_list.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Gcode Processor Library
-//
-// Tools for parsing gcode and calculating printer state from parsed gcode commands.
-//
-// Copyright(C) 2020 - Brad Hochgesang
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// This program is free software : you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published
-// by the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
-// GNU Affero General Public License for more details.
-//
-//
-// You can contact the author at the following email address:
-// FormerLurker@pm.me
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#include "array_list.h" \ No newline at end of file
diff --git a/GcodeProcessorLib/circular_buffer.cpp b/GcodeProcessorLib/circular_buffer.cpp
deleted file mode 100644
index c17c240..0000000
--- a/GcodeProcessorLib/circular_buffer.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Gcode Processor Library
-//
-// Tools for parsing gcode and calculating printer state from parsed gcode commands.
-//
-// Copyright(C) 2020 - Brad Hochgesang
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// This program is free software : you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published
-// by the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
-// GNU Affero General Public License for more details.
-//
-//
-// You can contact the author at the following email address:
-// FormerLurker@pm.me
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#include "circular_buffer.h" \ No newline at end of file
diff --git a/GcodeProcessorLib/circular_buffer.h b/GcodeProcessorLib/circular_buffer.h
index 0312a29..97f25ab 100644
--- a/GcodeProcessorLib/circular_buffer.h
+++ b/GcodeProcessorLib/circular_buffer.h
@@ -1,7 +1,9 @@
+#pragma once
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Gcode Processor Library
//
// Tools for parsing gcode and calculating printer state from parsed gcode commands.
+
//
// Copyright(C) 2020 - Brad Hochgesang
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -19,6 +21,7 @@
// You can contact the author at the following email address:
// FormerLurker@pm.me
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
#pragma once
#include <exception>
template <typename T>
@@ -32,6 +35,7 @@ public:
count_ = 0;
items_ = new T[max_size_];
}
+
circular_buffer(int max_size)
{
max_size_ = max_size;
@@ -39,13 +43,24 @@ public:
count_ = 0;
items_ = new T[max_size];
}
+
virtual ~circular_buffer() {
delete[] items_;
}
+
+ void initialize(T object)
+ {
+ for (int index = 0; index < max_size_; index++)
+ {
+ push_back(object);
+ }
+ count_ = 0;
+ front_index_ = 0;
+ }
+
void resize(int max_size)
{
T* new_items = new T[max_size];
- int count = count_;
for (int index = 0; index < count_; index++)
{
new_items[index] = items_[(front_index_ + index + max_size_) % max_size_];
@@ -55,12 +70,61 @@ public:
items_ = new_items;
max_size_ = max_size;
}
+
+ void resize(int max_size, T object)
+ {
+ T* new_items = new T[max_size];
+ for (int index = 0; index < count_; index++)
+ {
+ new_items[index] = items_[(front_index_ + index + max_size_) % max_size_];
+ }
+ // Initialize the rest of the entries
+ for (int index = count_; index < max_size; index++)
+ {
+ new_items[index] = object;
+ }
+ front_index_ = 0;
+ delete[] items_;
+ items_ = new_items;
+ max_size_ = max_size;
+ }
+
+ inline int get_index_position(int index) const
+ {
+ int index_position = index + front_index_ + max_size_;
+ while (index_position >= max_size_)
+ {
+ index_position = index_position - max_size_;
+ }
+ return index_position;
+ }
+
void push_front(T object)
{
- front_index_ = (front_index_ - 1 + max_size_) % max_size_;
- count_++;
+ //front_index_ = (front_index_ - 1 + max_size_) % max_size_;
+ front_index_ -= 1;
+ if (front_index_ < 0)
+ {
+ front_index_ = max_size_ - 1;
+ }
+ if (count_ != max_size_)
+ {
+ count_++;
+ }
items_[front_index_] = object;
}
+
+ void push_back(T object)
+ {
+ int pos = get_index_position(count_);
+ items_[pos] = object;
+ count_++;
+ if (count_ != max_size_)
+ {
+ count_++;
+ }
+ }
+
T& pop_front()
{
if (count_ == 0)
@@ -69,30 +133,55 @@ public:
}
int prev_start = front_index_;
- front_index_ = (front_index_ + 1 + max_size_) % max_size_;
+
+ front_index_ += 1;
+ if (front_index_ >= max_size_)
+ {
+ front_index_ = 0;
+ }
count_--;
return items_[prev_start];
}
- T& get(int index)
+ T& pop_back()
{
- return items_[(front_index_ + index + max_size_) % max_size_];
+ if (count_ == 0)
+ {
+ throw std::exception();
+ }
+ int pos = get_index_position(count_ - 1);
+ count_--;
+ return items_[pos];
}
- int count()
+ T& operator[] (int index) const
{
- return count_;
+ //int opos = get_index_position(index);
+ return items_[get_index_position(index)];
+ }
+
+ T& get(int index) const
+ {
+ int opos = get_index_position(index);
+ return items_[opos];
+ }
+ int count() const
+ {
+ return count_;
}
- int get_max_size()
+
+ int get_max_size() const
{
return max_size_;
}
+
void clear()
{
count_ = 0;
front_index_ = 0;
}
+
void copy(const circular_buffer<T>& source)
{
if (max_size_ < source.max_size_)
@@ -106,7 +195,6 @@ public:
}
front_index_ = source.front_index_;
count_ = source.count_;
-
}
protected:
diff --git a/GcodeProcessorLib/gcode_position.cpp b/GcodeProcessorLib/gcode_position.cpp
index fc469cd..444a879 100644
--- a/GcodeProcessorLib/gcode_position.cpp
+++ b/GcodeProcessorLib/gcode_position.cpp
@@ -206,10 +206,9 @@ void gcode_position_args::delete_y_firmware_offsets()
}
}
-gcode_position::gcode_position()
+gcode_position::gcode_position() : positions_(50), initial_position_(1)
{
position_buffer_size_ = 50;
- positions_ = new position[position_buffer_size_];
autodetect_position_ = false;
home_x_ = 0;
home_y_ = 0;
@@ -247,23 +246,19 @@ gcode_position::gcode_position()
z_max_ = 0;
is_circular_bed_ = false;
- cur_pos_ = -1;
- num_pos_ = 0;
- for(int index = 0; index < position_buffer_size_; index ++)
- {
- position initial_pos(num_extruders_);
- initial_pos.set_xyz_axis_mode(xyz_axis_default_mode_);
- initial_pos.set_e_axis_mode(e_axis_default_mode_);
- initial_pos.set_units_default(units_default_);
- add_position(initial_pos);
- }
- num_pos_ = 0;
+
+ position initial_pos(num_extruders_);
+ initial_pos.set_xyz_axis_mode(xyz_axis_default_mode_);
+ initial_pos.set_e_axis_mode(e_axis_default_mode_);
+ initial_pos.set_units_default(units_default_);
+
+ positions_.initialize(initial_pos);
+ initial_position_ = initial_pos;
}
-gcode_position::gcode_position(gcode_position_args args)
+gcode_position::gcode_position(gcode_position_args args) : positions_(args.position_buffer_size)
{
position_buffer_size_ = args.position_buffer_size;
- positions_ = new position[args.position_buffer_size] ;
autodetect_position_ = args.autodetect_position;
home_x_ = args.home_x;
home_y_ = args.home_y;
@@ -330,9 +325,6 @@ gcode_position::gcode_position(gcode_position_args args)
z_max_ = args.z_max;
is_circular_bed_ = args.is_circular_bed;
-
- cur_pos_ = -1;
- num_pos_ = 0;
num_extruders_ = args.num_extruders;
// Configure the initial position
@@ -346,15 +338,11 @@ gcode_position::gcode_position(gcode_position_args args)
initial_pos.p_extruders[index].x_firmware_offset = args.x_firmware_offsets[index];
initial_pos.p_extruders[index].y_firmware_offset = args.y_firmware_offsets[index];
}
-
- for (int index = 0; index < position_buffer_size_; index++)
- {
-
- add_position(initial_pos);
- }
- num_pos_ = 0;
+ positions_.initialize(initial_pos);
+ initial_position_ = initial_pos;
}
+
gcode_position::gcode_position(const gcode_position &source)
{
// Private copy constructor - you can't copy this class
@@ -362,11 +350,7 @@ gcode_position::gcode_position(const gcode_position &source)
gcode_position::~gcode_position()
{
- if (positions_ != NULL)
- {
- delete [] positions_;
- positions_ = NULL;
- }
+
delete_retraction_lengths_();
delete_z_lift_heights_();
}
@@ -376,7 +360,6 @@ bool gcode_position::get_g90_91_influences_extruder()
return g90_influences_extruder_;
}
-
void gcode_position::set_num_extruders(int num_extruders)
{
delete_retraction_lengths_();
@@ -413,32 +396,44 @@ void gcode_position::delete_z_lift_heights_()
int gcode_position::get_num_positions()
{
- return num_pos_;
+ return positions_.count();
+}
+
+int gcode_position::get_max_positions()
+{
+ return positions_.get_max_size();
+}
+
+void gcode_position::grow_max_positions(int size)
+{
+ int current_size = positions_.get_max_size();
+ if (size < current_size)
+ {
+ return;
+ }
+ positions_.resize(size, initial_position_);
+
}
void gcode_position::add_position(position& pos)
{
- cur_pos_ = (cur_pos_+1) % position_buffer_size_;
- positions_[cur_pos_] = pos;
- if (num_pos_ < position_buffer_size_)
- num_pos_++;
+ positions_.push_front(pos);
}
void gcode_position::add_position(parsed_command& cmd)
{
- const int prev_pos = cur_pos_;
- cur_pos_ = (cur_pos_+1) % position_buffer_size_;
- positions_[cur_pos_] = positions_[prev_pos];
- positions_[cur_pos_].reset_state();
- positions_[cur_pos_].command = cmd;
- positions_[cur_pos_].is_empty = false;
- if (num_pos_ < position_buffer_size_)
- num_pos_++;
+
+ position current_position = positions_[0];
+ current_position.reset_state();
+ current_position.command = cmd;
+ current_position.is_empty = false;
+ positions_.push_front(current_position);
+
}
position gcode_position::get_position(int index)
{
- return positions_[(cur_pos_ - index + position_buffer_size_) % position_buffer_size_];
+ return positions_[index];
}
position gcode_position::get_current_position()
@@ -453,7 +448,7 @@ position gcode_position::get_previous_position()
position * gcode_position::get_position_ptr(int index)
{
- return &positions_[(cur_pos_ - index + position_buffer_size_) % position_buffer_size_];
+ return &positions_[index];
}
position * gcode_position::get_current_position_ptr()
@@ -697,11 +692,7 @@ void gcode_position::update(parsed_command& command, const long file_line_number
void gcode_position::undo_update()
{
- if (num_pos_ != 0)
- {
- cur_pos_ = (cur_pos_ - 1 + position_buffer_size_) % position_buffer_size_;
- num_pos_--;
- }
+ positions_.pop_front();
}
position* gcode_position::undo_update(int num_updates)
@@ -715,21 +706,9 @@ position* gcode_position::undo_update(int num_updates)
// add the positions we will undo to the array
for (int index = 0; index < num_updates; index++)
{
- p_undo_positions[index] = get_position(index);
- }
-
- if (num_pos_ < num_updates)
- {
- num_pos_ = 0;
- cur_pos_ = 0;
- }
- else
- {
- cur_pos_ = (cur_pos_ - num_updates + position_buffer_size_) % position_buffer_size_;
- num_pos_ -= num_updates;
+ p_undo_positions[index] = positions_.pop_front();
}
return p_undo_positions;
-
}
// Private Members
diff --git a/GcodeProcessorLib/gcode_position.h b/GcodeProcessorLib/gcode_position.h
index 521f0d3..5930cf6 100644
--- a/GcodeProcessorLib/gcode_position.h
+++ b/GcodeProcessorLib/gcode_position.h
@@ -25,6 +25,7 @@
#include <string>
#include <vector>
#include <map>
+#include "circular_buffer.h"
#include "gcode_parser.h"
#include "position.h"
#include "gcode_comment_processor.h"
@@ -139,6 +140,8 @@ public:
void undo_update();
position * undo_update(int num_updates);
int get_num_positions();
+ int get_max_positions();
+ void grow_max_positions(int size);
position get_position(int index);
position get_current_position();
position get_previous_position();
@@ -149,10 +152,9 @@ public:
bool get_g90_91_influences_extruder();
private:
gcode_position(const gcode_position &source);
+ position initial_position_;
int position_buffer_size_;
- position* positions_;
- int cur_pos_;
- int num_pos_;
+ circular_buffer<position> positions_;
void add_position(parsed_command &);
void add_position(position &);
bool autodetect_position_;
diff --git a/GcodeProcessorLib/position.cpp b/GcodeProcessorLib/position.cpp
index 6a85801..8fcd8cd 100644
--- a/GcodeProcessorLib/position.cpp
+++ b/GcodeProcessorLib/position.cpp
@@ -356,6 +356,10 @@ position& position::operator=(const position& pos) {
return *this;
}
+bool position::is_travel()
+{
+ return is_xyz_travel || is_xy_travel;
+}
void position::set_num_extruders(int num_extruders_)
{
if (num_extruders_ == num_extruders)
diff --git a/GcodeProcessorLib/position.h b/GcodeProcessorLib/position.h
index 0958cd5..5059d5f 100644
--- a/GcodeProcessorLib/position.h
+++ b/GcodeProcessorLib/position.h
@@ -102,5 +102,6 @@ struct position
void set_e_axis_mode(const std::string& e_axis_default_mode);
void set_units_default(const std::string& units_default);
bool can_take_snapshot();
+ bool is_travel()
};
#endif \ No newline at end of file
diff --git a/GcodeProcessorLib/utilities.cpp b/GcodeProcessorLib/utilities.cpp
index 041f91f..b5a09a6 100644
--- a/GcodeProcessorLib/utilities.cpp
+++ b/GcodeProcessorLib/utilities.cpp
@@ -24,6 +24,7 @@
#include <sstream>
#include <iostream>
#include <iomanip>
+#include <algorithm>
#include "fpconv.h"
const std::string utilities::WHITESPACE_ = " \n\r\t\f\v";
@@ -320,4 +321,20 @@ std::string utilities::dtos(double x, unsigned char precision)
}
*/
return buffer;
-} \ No newline at end of file
+}
+
+bool utilities::case_insensitive_compare_char(char& c1, char& c2)
+{
+ if (c1 == c2)
+ return true;
+ else if (std::toupper(c1) == std::toupper(c2))
+ return true;
+ return false;
+}
+/*
+ * Case Insensitive String Comparision
+ */
+bool utilities::case_insensitive_compare(std::string& str1, std::string& str2)
+{
+ return ((str1.size() == str2.size()) && std::equal(str1.begin(), str1.end(), str2.begin(), &utilities::case_insensitive_compare_char));
+}
diff --git a/GcodeProcessorLib/utilities.h b/GcodeProcessorLib/utilities.h
index b41d6f6..33afd51 100644
--- a/GcodeProcessorLib/utilities.h
+++ b/GcodeProcessorLib/utilities.h
@@ -41,6 +41,9 @@ public:
static double get_cartesian_distance(double x1, double y1, double x2, double y2);
static double get_cartesian_distance(double x1, double y1, double z1, double x2, double y2, double z2);
+
+ static bool case_insensitive_compare_char(char& c1, char& c2);
+ static bool case_insensitive_compare(std::string& str1, std::string& str2);
static std::string to_string(double value);
static std::string to_string(int value);
static std::string ltrim(const std::string& s);
diff --git a/PyArcWelder/py_arc_welder.cpp b/PyArcWelder/py_arc_welder.cpp
index 36588f2..f811e6d 100644
--- a/PyArcWelder/py_arc_welder.cpp
+++ b/PyArcWelder/py_arc_welder.cpp
@@ -47,28 +47,30 @@ PyObject* py_arc_welder::build_py_progress(const arc_welder_progress& progress,
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, //8
+ progress.num_firmware_compensations, //9
"source_file_position",
- progress.source_file_position, //9
+ progress.source_file_position, //10
"source_file_size",
- progress.source_file_size, //10
+ progress.source_file_size, //11
"target_file_size",
- progress.target_file_size, //11
+ progress.target_file_size, //12
"compression_ratio",
- progress.compression_ratio, //12
+ progress.compression_ratio, //13
"compression_percent",
- progress.compression_percent, //13
+ progress.compression_percent, //14
"source_file_total_length",
- progress.segment_statistics.total_length_source, //14
+ progress.segment_statistics.total_length_source, //15
"target_file_total_length",
- progress.segment_statistics.total_length_target, //15
+ progress.segment_statistics.total_length_target, //16
"source_file_total_count",
- progress.segment_statistics.total_count_source, //16
+ progress.segment_statistics.total_count_source, //17
"target_file_total_count",
- progress.segment_statistics.total_count_target, //17
+ progress.segment_statistics.total_count_target, //18
"total_count_reduction_percent",
- total_count_reduction_percent //18
+ total_count_reduction_percent //19
);