Browse Source

Improve plan_arc circle detection (#20440)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
yysh12 3 years ago
parent
commit
6ec4e744c0
No account linked to committer's email address
1 changed files with 17 additions and 11 deletions
  1. 17
    11
      Marlin/src/gcode/motion/G2_G3.cpp

+ 17
- 11
Marlin/src/gcode/motion/G2_G3.cpp View File

@@ -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);

Loading…
Cancel
Save