From 650ebf693ebb5eafcab5931e01f1388719d17b39 Mon Sep 17 00:00:00 2001 From: Billy Huddleston Date: Sun, 11 Jan 2026 21:41:12 -0500 Subject: [PATCH] CAM: Add threshold for treating large-radius arcs as linear in simulator Arc segments with extremely large radius compared to chord length can cause floating-point precision issues in simulation. This change introduces ARC_LINEARIZATION_THRESHOLD to treat such arcs as linear, improving numerical stability in the simulator. The following g-code was causing erractic behavior in the simulator due to large-radius arcs: ``` G2 I88775.835760 J-1936991.545892 K0.000000 X102.063107 Y100.102815 Z12.700001 ``` src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp: - Added ARC_LINEARIZATION_THRESHOLD constant - Updated arc motion detection to treat large-radius arcs as linear - Improved handling of arc vs. linear segment classification --- .../PathSimulator/AppGL/MillPathSegment.cpp | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp b/src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp index cfe4153fa0..793d69bdc7 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp @@ -39,6 +39,11 @@ constexpr auto pi = std::numbers::pi_v; #define PY 1 #define PZ 2 +// Maximum ratio of radius to chord length for treating arc as curved +// Ratios above this indicate the arc is essentially a straight line +// and should be treated as linear to avoid numerical precision issues +constexpr float ARC_LINEARIZATION_THRESHOLD = 100000.0f; + namespace MillSim { @@ -71,9 +76,21 @@ MillPathSegment::MillPathSegment(EndMill* _endmill, MillMotion* from, MillMotion mXYAngle = atan2f(mDiff[PY], mDiff[PX]); endmill = _endmill; mStartAngRad = mStepAngRad = 0; - if (IsArcMotion(to)) { - mMotionType = MTCurved; + + // Check if this is an arc motion and whether it should be treated as curved + bool isArc = IsArcMotion(to); + bool treatAsCurved = false; + + if (isArc) { mRadius = sqrtf(to->j * to->j + to->i * to->i); + + // Check if arc is essentially a straight line by comparing radius to chord length + // When radius >> chord length, floating-point precision issues occur in angle calculations + treatAsCurved = (mRadius <= mXYDistance * ARC_LINEARIZATION_THRESHOLD); + } + + if (treatAsCurved) { + mMotionType = MTCurved; mSmallRad = mRadius <= endmill->radius; if (mSmallRad) {