|
@@ -41,13 +41,12 @@
|
41
|
41
|
#endif
|
42
|
42
|
|
43
|
43
|
/**
|
44
|
|
- * Plan an arc in 2 dimensions
|
|
44
|
+ * Plan an arc in 2 dimensions, with optional linear motion in a 3rd dimension
|
45
|
45
|
*
|
46
|
|
- * The arc is approximated by generating many small linear segments.
|
47
|
|
- * The length of each segment is configured in MM_PER_ARC_SEGMENT (Default 1mm)
|
48
|
|
- * Arcs should only be made relatively large (over 5mm), as larger arcs with
|
49
|
|
- * larger segments will tend to be more efficient. Your slicer should have
|
50
|
|
- * options for G2/G3 arc generation. In future these options may be GCode tunable.
|
|
46
|
+ * The arc is traced by generating many small linear segments, as configured by
|
|
47
|
+ * MM_PER_ARC_SEGMENT (Default 1mm). In the future we hope more slicers will include
|
|
48
|
+ * an option to generate G2/G3 arcs for curved surfaces, as this will allow faster
|
|
49
|
+ * boards to produce much smoother curved surfaces.
|
51
|
50
|
*/
|
52
|
51
|
void plan_arc(
|
53
|
52
|
const xyze_pos_t &cart, // Destination position
|
|
@@ -77,26 +76,33 @@ void plan_arc(
|
77
|
76
|
rt_Y = cart[q_axis] - center_Q,
|
78
|
77
|
start_L = current_position[l_axis];
|
79
|
78
|
|
80
|
|
- // Angle of rotation between position and target from the circle center.
|
81
|
|
- float angular_travel = ATAN2(rvec.a * rt_Y - rvec.b * rt_X, rvec.a * rt_X + rvec.b * rt_Y);
|
82
|
|
-
|
83
|
79
|
#ifdef MIN_ARC_SEGMENTS
|
84
|
80
|
uint16_t min_segments = MIN_ARC_SEGMENTS;
|
85
|
81
|
#else
|
86
|
82
|
constexpr uint16_t min_segments = 1;
|
87
|
83
|
#endif
|
88
|
84
|
|
89
|
|
- // Do a full circle if angular rotation is near 0 and the target is current position
|
90
|
|
- if (!angular_travel || (NEAR_ZERO(angular_travel) && NEAR(current_position[p_axis], cart[p_axis]) && NEAR(current_position[q_axis], cart[q_axis]))) {
|
|
85
|
+ // Angle of rotation between position and target from the circle center.
|
|
86
|
+ float angular_travel;
|
|
87
|
+
|
|
88
|
+ // Do a full circle if starting and ending positions are "identical"
|
|
89
|
+ if (NEAR(current_position[p_axis], cart[p_axis]) && NEAR(current_position[q_axis], cart[q_axis])) {
|
91
|
90
|
// Preserve direction for circles
|
92
|
91
|
angular_travel = clockwise ? -RADIANS(360) : RADIANS(360);
|
93
|
92
|
}
|
94
|
93
|
else {
|
|
94
|
+ // Calculate the angle
|
|
95
|
+ angular_travel = ATAN2(rvec.a * rt_Y - rvec.b * rt_X, rvec.a * rt_X + rvec.b * rt_Y);
|
|
96
|
+
|
|
97
|
+ // Angular travel too small to detect? Just return.
|
|
98
|
+ if (!angular_travel) return;
|
|
99
|
+
|
95
|
100
|
// Make sure angular travel over 180 degrees goes the other way around.
|
96
|
101
|
switch (((angular_travel < 0) << 1) | clockwise) {
|
97
|
102
|
case 1: angular_travel -= RADIANS(360); break; // Positive but CW? Reverse direction.
|
98
|
103
|
case 2: angular_travel += RADIANS(360); break; // Negative but CCW? Reverse direction.
|
99
|
104
|
}
|
|
105
|
+
|
100
|
106
|
#ifdef MIN_ARC_SEGMENTS
|
101
|
107
|
min_segments = CEIL(min_segments * ABS(angular_travel) / RADIANS(360));
|
102
|
108
|
NOLESS(min_segments, 1U);
|