From f851526c67aa6d6315c08af217dc100f224b3c2e Mon Sep 17 00:00:00 2001
From: jean-pierre charras <jp.charras@wanadoo.fr>
Date: Tue, 20 Sep 2022 18:29:29 +0200
Subject: [PATCH] Plotters: make virtual void PLOTTER::Arc() using arc angles
 protected. Using arc angles to plot an arc is really error prone due to
 different options between plotters, and angles defined in Kicad, using this
 version of arc plotting from Kicad is no longer allowed in Kicad code.

---
 common/plotters/SVG_plotter.cpp    |  7 -------
 common/plotters/plotter.cpp        |  6 +++---
 eeschema/sch_shape.cpp             | 18 ++++++++---------
 include/plotters/plotter.h         | 22 ++++++++++----------
 include/plotters/plotter_dxf.h     |  8 +++++---
 include/plotters/plotter_gerber.h  | 15 +++++++-------
 include/plotters/plotter_hpgl.h    | 32 +++++++++++++++---------------
 include/plotters/plotters_pslike.h | 16 ++++++++-------
 8 files changed, 60 insertions(+), 64 deletions(-)

diff --git a/common/plotters/SVG_plotter.cpp b/common/plotters/SVG_plotter.cpp
index 6ded555136..110c46036d 100644
--- a/common/plotters/SVG_plotter.cpp
+++ b/common/plotters/SVG_plotter.cpp
@@ -469,13 +469,6 @@ void SVG_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
     VECTOR2D  centre_device  = userToDeviceCoordinates( aCenter );
     double  radius_device  = userToDeviceSize( aRadius );
 
-    if( !m_yaxisReversed )   // Should be never the case
-    {
-        std::swap( startAngle, endAngle );
-        startAngle = -startAngle;
-        endAngle = -endAngle;
-    }
-
     if( m_plotMirror )
     {
         if( m_mirrorIsHorizontal )
diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp
index 11a5f3a231..312a35af41 100644
--- a/common/plotters/plotter.cpp
+++ b/common/plotters/plotter.cpp
@@ -161,9 +161,9 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR
             startAngle = startAngle.Normalize() - ANGLE_360;
     }
 
-    // In Kicad code, call to Arc() using angles call this function after
-    // sawpping angles and negate them (to compensate the inverted Y axis).
-    // So to mimic the other calls in Kicad, do the same thing
+    // In old Kicad code, calls to Arc() using angles calls this function after
+    // swapping angles and negate them (to compensate the inverted Y axis).
+    // So to be compatible with Arc() calls with angles, do the same thing
     std::swap( startAngle, endAngle );
     startAngle = -startAngle;
     endAngle = -endAngle;
diff --git a/eeschema/sch_shape.cpp b/eeschema/sch_shape.cpp
index f20db1cc42..9ef6c0bac8 100644
--- a/eeschema/sch_shape.cpp
+++ b/eeschema/sch_shape.cpp
@@ -138,11 +138,10 @@ void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground ) const
             {
             case SHAPE_T::ARC:
             {
-                EDA_ANGLE start;
-                EDA_ANGLE end;
-                CalcArcAngles( start, end );
-
-                aPlotter->Arc( getCenter(), -end, -start, GetRadius(), m_fill, 0 );
+                // In some plotters (not all) the arc is approximated by segments, and
+                // a error max is needed. We try to approximate by 360/5 segments by 360 deg
+                int arc2segment_error = CircleToEndSegmentDeltaRadius( GetRadius(), 360/5 );
+                aPlotter->Arc( getCenter(), GetStart(), GetEnd(), m_fill, 0, arc2segment_error );
             }
 
                 break;
@@ -182,11 +181,10 @@ void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground ) const
         {
         case SHAPE_T::ARC:
         {
-            EDA_ANGLE start;
-            EDA_ANGLE end;
-            CalcArcAngles( start, end );
-
-            aPlotter->Arc( getCenter(), -end, -start, GetRadius(), FILL_T::NO_FILL, pen_size );
+            // In some plotters (not all) the arc is approximated by segments, and
+            // a error max is needed. We try to approximate by 360/5 segments by 360 deg
+            int arc2segment_error = CircleToEndSegmentDeltaRadius( GetRadius(), 360/5 );
+            aPlotter->Arc( getCenter(), GetStart(), GetEnd(), FILL_T::NO_FILL, pen_size, arc2segment_error );
         }
 
             break;
diff --git a/include/plotters/plotter.h b/include/plotters/plotter.h
index cc9094e02d..e74e994a4b 100644
--- a/include/plotters/plotter.h
+++ b/include/plotters/plotter.h
@@ -223,13 +223,6 @@ public:
     virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
                       FILL_T aFill, int aWidth, int aMaxError );
 
-    /**
-     * Generic fallback: arc rendered as a polyline.
-     */
-    virtual void Arc( const VECTOR2I& aCentre, const EDA_ANGLE& aStartAngle,
-                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
-                      int aWidth = USE_DEFAULT_LINE_WIDTH );
-
     /**
      * Generic fallback: Cubic Bezier curve rendered as a polyline
      * In KiCad the bezier curves have 4 control points:
@@ -310,10 +303,6 @@ public:
     virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width,
                                OUTLINE_MODE tracemode, void* aData );
 
-    virtual void ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& StAngle,
-                           const EDA_ANGLE& EndAngle, int aRadius, int aWidth,
-                           OUTLINE_MODE aTraceMode, void* aData );
-
     virtual void ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart,
                            const VECTOR2I& aEnd, int aWidth,
                            OUTLINE_MODE aTraceMode, void* aData );
@@ -526,6 +515,17 @@ public:
 
 
 protected:
+    /**
+     * Generic fallback: arc rendered as a polyline.
+     */
+    virtual void Arc( const VECTOR2I& aCentre, const EDA_ANGLE& aStartAngle,
+                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
+                      int aWidth = USE_DEFAULT_LINE_WIDTH );
+
+    virtual void ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& StAngle,
+                           const EDA_ANGLE& EndAngle, int aRadius, int aWidth,
+                           OUTLINE_MODE aTraceMode, void* aData );
+
     // These are marker subcomponents
     /**
      * Plot a circle centered on the position. Building block for markers
diff --git a/include/plotters/plotter_dxf.h b/include/plotters/plotter_dxf.h
index 49fcfaa46b..90aa09585a 100644
--- a/include/plotters/plotter_dxf.h
+++ b/include/plotters/plotter_dxf.h
@@ -112,9 +112,7 @@ public:
                            int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
     virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width,
                                OUTLINE_MODE tracemode, void* aData ) override;
-    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
-                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
-                      int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
+
     virtual void PenTo( const VECTOR2I& pos, char plume ) override;
 
     /**
@@ -208,6 +206,10 @@ public:
     }
 
 protected:
+    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
+                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
+                      int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
+
     bool           m_textAsLines;
     COLOR4D        m_currentColor;
     PLOT_DASH_TYPE m_currentLineType;
diff --git a/include/plotters/plotter_gerber.h b/include/plotters/plotter_gerber.h
index 232939f474..75c42bd43e 100644
--- a/include/plotters/plotter_gerber.h
+++ b/include/plotters/plotter_gerber.h
@@ -69,18 +69,11 @@ public:
                        int width = USE_DEFAULT_LINE_WIDTH ) override;
     virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
                          int width = USE_DEFAULT_LINE_WIDTH ) override;
-    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
-                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
-                      int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
 
     // These functions plot an item and manage X2 gerber attributes
     virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width,
                                OUTLINE_MODE tracemode, void* aData ) override;
 
-    virtual void ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& aStartAngle,
-                           const EDA_ANGLE& aEndAngle, int aRadius, int aWidth,
-                           OUTLINE_MODE aTraceMode, void* aData ) override;
-
     virtual void ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart,
                            const VECTOR2I& aEnd, int aWidth,
                            OUTLINE_MODE aTraceMode, void* aData ) override;
@@ -263,6 +256,14 @@ public:
                              APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
 
 protected:
+    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
+                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
+                      int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
+
+    virtual void ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& aStartAngle,
+                           const EDA_ANGLE& aEndAngle, int aRadius, int aWidth,
+                           OUTLINE_MODE aTraceMode, void* aData ) override;
+
     /**
      * Plot a round rect (a round rect shape in fact) as a Gerber region using lines and arcs
      * for corners.
diff --git a/include/plotters/plotter_hpgl.h b/include/plotters/plotter_hpgl.h
index 603f6f07ce..4e53f6f7a4 100644
--- a/include/plotters/plotter_hpgl.h
+++ b/include/plotters/plotter_hpgl.h
@@ -106,22 +106,6 @@ public:
     virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width,
                                OUTLINE_MODE tracemode, void* aData ) override;
 
-    /**
-     * Plot an arc.
-     *
-     * Command
-     * PU PY x, y; PD start_arc_X AA, start_arc_Y, angle, NbSegm; PU;
-     * Or PU PY x, y; PD start_arc_X AA, start_arc_Y, angle, PU;
-     *
-     * center is the center of the arc.
-     * StAngled is the start angle of the arc.
-     * aEndAngle is end angle the arc.
-     * Radius is the radius of the arc.
-     */
-    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
-                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
-                      int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
-
     virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
                       FILL_T aFill, int aWidth, int aMaxError ) override;
 
@@ -149,6 +133,22 @@ public:
                                       void* aData ) override;
 
 protected:
+    /**
+     * Plot an arc.
+     *
+     * Command
+     * PU PY x, y; PD start_arc_X AA, start_arc_Y, angle, NbSegm; PU;
+     * Or PU PY x, y; PD start_arc_X AA, start_arc_Y, angle, PU;
+     *
+     * center is the center of the arc.
+     * StAngled is the start angle of the arc.
+     * aEndAngle is end angle the arc.
+     * Radius is the radius of the arc.
+     */
+    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
+                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
+                      int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
+
     /**
      * Start a new HPGL_ITEM if necessary, keeping the current one if it exists.
      *
diff --git a/include/plotters/plotters_pslike.h b/include/plotters/plotters_pslike.h
index 1df8d839ef..fbcbb36d42 100644
--- a/include/plotters/plotters_pslike.h
+++ b/include/plotters/plotters_pslike.h
@@ -326,10 +326,6 @@ public:
     virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
                       FILL_T aFill, int aWidth, int aMaxError ) override;
 
-    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
-                      const EDA_ANGLE& aEndAngle, int aRadius,
-                      FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
-
     /**
      * Polygon plotting for PDF. Everything is supported
      */
@@ -363,6 +359,11 @@ public:
 
 
 protected:
+
+    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
+                      const EDA_ANGLE& aEndAngle, int aRadius,
+                      FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
+
     /// convert a wxString unicode string to a char string compatible with the accepted
     /// string PDF format (convert special chars and non ascii7 chars)
     std::string encodeStringForPlotter( const wxString& aUnicode ) override;
@@ -470,9 +471,6 @@ public:
                        int width = USE_DEFAULT_LINE_WIDTH ) override;
     virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
                          int width = USE_DEFAULT_LINE_WIDTH ) override;
-    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
-                      const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill,
-                      int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
 
     virtual void BezierCurve( const VECTOR2I& aStart, const VECTOR2I& aControl1,
                               const VECTOR2I& aControl2, const VECTOR2I& aEnd,
@@ -531,6 +529,10 @@ public:
                        void*                       aData = nullptr ) override;
 
 protected:
+    virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
+                      const EDA_ANGLE& aEndAngle, int aRadius,
+                      FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
+
     /**
      * Initialize m_pen_rgb_color from reduced values r, g ,b
      * ( reduced values are 0.0 to 1.0 )