From 0a668ee55030f8f6b07a80cdc42232485ade9ede Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@ucdavis.edu>
Date: Thu, 16 May 2019 06:46:54 -0700
Subject: [PATCH] pcbnew: Remove segment count from board file

This removes the setting for number of segments per circle from the zone
definition.  All segment counts are handled by absolute error allowed.
---
 pcbnew/class_zone.cpp                    |  2 --
 pcbnew/class_zone.h                      |  7 -------
 pcbnew/exporters/export_vrml.cpp         |  7 ++++---
 pcbnew/kicad_plugin.cpp                  |  3 +--
 pcbnew/kicad_plugin.h                    |  3 ++-
 pcbnew/legacy_plugin.cpp                 |  9 +--------
 pcbnew/microwave/microwave_inductor.cpp  | 12 +++++-------
 pcbnew/pcb_parser.cpp                    |  2 +-
 pcbnew/pcbnew.h                          |  9 ---------
 pcbnew/plot_board_layers.cpp             |  1 -
 pcbnew/zone_settings.cpp                 |  6 ------
 pcbnew/zone_settings.h                   |  3 ---
 pcbnew/zones_functions_for_undo_redo.cpp |  3 ---
 pcbnew/zones_test_and_combine_areas.cpp  |  3 ---
 14 files changed, 14 insertions(+), 56 deletions(-)

diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp
index 44d5284b0d..694dadfca5 100644
--- a/pcbnew/class_zone.cpp
+++ b/pcbnew/class_zone.cpp
@@ -95,7 +95,6 @@ ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) :
     m_FillMode = aZone.m_FillMode;               // Filling mode (segments/polygons)
     m_hv45 = aZone.m_hv45;
     m_priority = aZone.m_priority;
-    m_ArcToSegmentsCount = aZone.m_ArcToSegmentsCount;
     m_PadConnection = aZone.m_PadConnection;
     m_ThermalReliefGap = aZone.m_ThermalReliefGap;
     m_ThermalReliefCopperBridge = aZone.m_ThermalReliefCopperBridge;
@@ -133,7 +132,6 @@ ZONE_CONTAINER& ZONE_CONTAINER::operator=( const ZONE_CONTAINER& aOther )
     m_ZoneClearance    = aOther.m_ZoneClearance;            // clearance value
     m_ZoneMinThickness = aOther.m_ZoneMinThickness;
     m_FillMode = aOther.m_FillMode;                         // filling mode (segments/polygons)
-    m_ArcToSegmentsCount = aOther.m_ArcToSegmentsCount;
     m_PadConnection = aOther.m_PadConnection;
     m_ThermalReliefGap = aOther.m_ThermalReliefGap;
     m_ThermalReliefCopperBridge = aOther.m_ThermalReliefCopperBridge;
diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h
index 0e0389c83e..5e93e50972 100644
--- a/pcbnew/class_zone.h
+++ b/pcbnew/class_zone.h
@@ -181,9 +181,6 @@ public:
     }
     int GetThermalReliefCopperBridge( D_PAD* aPad = NULL ) const;
 
-    void SetArcSegmentCount( int aArcSegCount ) { m_ArcToSegmentsCount = aArcSegCount; }
-    int GetArcSegmentCount() const { return m_ArcToSegmentsCount; }
-
     bool IsFilled() const { return m_IsFilled; }
     void SetIsFilled( bool isFilled ) { m_IsFilled = isFilled; }
 
@@ -752,10 +749,6 @@ private:
     int                   m_ZoneClearance;           ///< Clearance value in internal units.
     int                   m_ZoneMinThickness;        ///< Minimum thickness value in filled areas.
 
-    /** The number of segments to convert a circle to a polygon.  Valid values are
-        #ARC_APPROX_SEGMENTS_COUNT_LOW_DEF or #ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF. */
-    int                   m_ArcToSegmentsCount;
-
     /** True when a zone was filled, false after deleting the filled areas. */
     bool                  m_IsFilled;
 
diff --git a/pcbnew/exporters/export_vrml.cpp b/pcbnew/exporters/export_vrml.cpp
index 88de2ac358..5705924304 100644
--- a/pcbnew/exporters/export_vrml.cpp
+++ b/pcbnew/exporters/export_vrml.cpp
@@ -50,6 +50,7 @@
 #include "../../kicad/kicad.h"
 
 #include <convert_basic_shapes_to_polygon.h>
+#include <geometry/geometry_utils.h>
 
 #include <zone_filler.h>
 
@@ -679,8 +680,6 @@ static void export_vrml_arc( MODEL_VRML& aModel, LAYER_NUM layer,
 static void export_vrml_polygon( MODEL_VRML& aModel, LAYER_NUM layer,
         DRAWSEGMENT *aOutline, double aOrientation, wxPoint aPos )
 {
-    const int circleSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
-
     if( aOutline->IsPolyShapeValid() )
     {
         SHAPE_POLY_SET shape = aOutline->GetPolyShape();
@@ -691,7 +690,9 @@ static void export_vrml_polygon( MODEL_VRML& aModel, LAYER_NUM layer,
 
         if( aOutline->GetWidth() )
         {
-            shape.Inflate( aOutline->GetWidth()/2, circleSegmentsCount );
+            int numSegs = std::max(
+                    GetArcToSegmentCount( aOutline->GetWidth() / 2, ARC_HIGH_DEF, 360.0 ), 6 );
+            shape.Inflate( aOutline->GetWidth() / 2, numSegs );
             shape.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
         }
 
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index e97900d0a6..0f66befd4c 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -1727,8 +1727,7 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
     if( aZone->GetFillMode() == ZFM_HATCH_PATTERN )
         m_out->Print( 0, " (mode hatch)" );
 
-    m_out->Print( 0, " (arc_segments %d) (thermal_gap %s) (thermal_bridge_width %s)",
-                  aZone->GetArcSegmentCount(),
+    m_out->Print( 0, " (thermal_gap %s) (thermal_bridge_width %s)",
                   FormatInternalUnits( aZone->GetThermalReliefGap() ).c_str(),
                   FormatInternalUnits( aZone->GetThermalReliefCopperBridge() ).c_str() );
 
diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h
index 27855b3fd8..4eb39e8b45 100644
--- a/pcbnew/kicad_plugin.h
+++ b/pcbnew/kicad_plugin.h
@@ -49,7 +49,8 @@ class NETINFO_MAPPING;
 //#define SEXPR_BOARD_FILE_VERSION    20171125  // Locked/unlocked TEXTE_MODULE
 //#define SEXPR_BOARD_FILE_VERSION    20171130  // 3D model offset written using "offset" parameter
 //#define SEXPR_BOARD_FILE_VERSION    20190331  // hatched zones and chamfered round rect pads
-#define SEXPR_BOARD_FILE_VERSION      20190421  // curves in custom pads
+//#define SEXPR_BOARD_FILE_VERSION    20190421  // curves in custom pads
+#define SEXPR_BOARD_FILE_VERSION      20190516  // Remove segment count from zones
 
 #define CTL_STD_LAYER_NAMES         (1 << 0)    ///< Use English Standard layer names
 #define CTL_OMIT_NETS               (1 << 1)    ///< Omit pads net names (useless in library)
diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp
index 10cb3b70bf..988f1c2094 100644
--- a/pcbnew/legacy_plugin.cpp
+++ b/pcbnew/legacy_plugin.cpp
@@ -2624,7 +2624,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
         {
             // e.g. "ZOptions 0 32 F 200 200"
             int     fillmode    = intParse( line + SZ( "ZOptions" ), &data );
-            int     arcsegcount = intParse( data, &data );
+            static_cast<void>( intParse( data, &data ) ); // Ignored
             char    fillstate   = data[1];      // here e.g. " F"
             BIU     thermalReliefGap = biuParse( data += 2 , &data );  // +=2 for " F"
             BIU     thermalReliefCopperBridge = biuParse( data );
@@ -2655,13 +2655,6 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
             else
                 zc->SetFillMode( ZFM_POLYGONS );
 
-            // @todo ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF: don't really want pcbnew.h
-            // in here, after all, its a PLUGIN and global data is evil.
-            // put in accessor
-            if( arcsegcount >= 32 )
-                arcsegcount = 32;
-
-            zc->SetArcSegmentCount( arcsegcount );
             zc->SetIsFilled( fillstate == 'S' );
             zc->SetThermalReliefGap( thermalReliefGap );
             zc->SetThermalReliefCopperBridge( thermalReliefCopperBridge );
diff --git a/pcbnew/microwave/microwave_inductor.cpp b/pcbnew/microwave/microwave_inductor.cpp
index 2136a54b56..eea2fbf16e 100644
--- a/pcbnew/microwave/microwave_inductor.cpp
+++ b/pcbnew/microwave/microwave_inductor.cpp
@@ -26,9 +26,10 @@
 #include <wx/wx.h>
 
 #include <base_units.h>
-#include <validators.h>
 #include <dialog_text_entry.h>
+#include <geometry/geometry_utils.h>
 #include <pcb_edit_frame.h>
+#include <validators.h>
 
 #include <class_pad.h>
 #include <class_edge_mod.h>
@@ -52,12 +53,9 @@ static void gen_arc( std::vector <wxPoint>& aBuffer,
                      const wxPoint&         aCenter,
                      int                     a_ArcAngle )
 {
-    const int SEGM_COUNT_PER_360DEG = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;
-    auto    first_point = aStartPoint - aCenter;
-    int     seg_count   = ( ( abs( a_ArcAngle ) ) * SEGM_COUNT_PER_360DEG ) / 3600;
-
-    if( seg_count == 0 )
-        seg_count = 1;
+    auto first_point = aStartPoint - aCenter;
+    auto radius = KiROUND( EuclideanNorm( first_point ) );
+    int  seg_count = std::max( GetArcToSegmentCount( radius, ARC_HIGH_DEF, a_ArcAngle / 10.0 ), 3 );
 
     double increment_angle = (double) a_ArcAngle * M_PI / 1800 / seg_count;
 
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index 04ffca5cc7..2b22c1125f 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -3242,7 +3242,7 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER()
                     break;
 
                 case T_arc_segments:
-                    zone->SetArcSegmentCount( parseInt( "arc segment count" ) );
+                    static_cast<void>( parseInt( "arc segment count" ) );
                     NeedRIGHT();
                     break;
 
diff --git a/pcbnew/pcbnew.h b/pcbnew/pcbnew.h
index 3cfae2970c..cd9435c46e 100644
--- a/pcbnew/pcbnew.h
+++ b/pcbnew/pcbnew.h
@@ -36,15 +36,6 @@
 #include <convert_to_biu.h> // to define Mils2iu() conversion function
 #include <layers_id_colors_and_visibility.h>
 
-// Arcs are approximated by segments: define the number of segments per 360 deg (KiCad uses 0.1
-// deg approximation).  Be aware 3600 / ARC_APPROX_SEGMENTS_COUNT_LOW_DEF is an integer.
-#define ARC_APPROX_SEGMENTS_COUNT_LOW_DEF 16
-#define ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF 32
-
-// The new absolute-error-based algorithm uses the stored segment count as a hint on whether
-// to use ARC_HIGH_DEF or ARC_LOW_DEF.  This defines the crossover point.
-#define SEGMENT_COUNT_CROSSOVER 24
-
 /* Flag used in locate functions. The locate ref point is the on grid cursor or the off
  * grid mouse cursor. */
 #define CURSEUR_ON_GRILLE  (0 << 0)
diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp
index 3f1e843389..78aba8dea8 100644
--- a/pcbnew/plot_board_layers.cpp
+++ b/pcbnew/plot_board_layers.cpp
@@ -868,7 +868,6 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
     // However it is not complex, and fast enough for plot purposes (copy/convert data
     // is only a very small calculation time for these calculations)
     ZONE_CONTAINER zone( aBoard );
-    zone.SetArcSegmentCount( ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF );
     zone.SetMinThickness( 0 );      // trace polygons only
     zone.SetLayer ( layer );
     int numSegs = std::max( GetArcToSegmentCount( inflate, ARC_HIGH_DEF, 360.0 ), 6 );
diff --git a/pcbnew/zone_settings.cpp b/pcbnew/zone_settings.cpp
index c18e2e12da..1072194e37 100644
--- a/pcbnew/zone_settings.cpp
+++ b/pcbnew/zone_settings.cpp
@@ -59,10 +59,6 @@ ZONE_SETTINGS::ZONE_SETTINGS()
     m_Zone_HatchingStyle = ZONE_CONTAINER::DIAGONAL_EDGE;   // Option to show the zone area (outlines only,
                                                             //short hatches or full hatches
 
-    m_ArcToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; // Option to select number of segments to approximate a circle
-                                                                // ARC_APPROX_SEGMENTS_COUNT_LOW_DEF
-                                                                // or ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF segments
-
     // thickness of the gap in thermal reliefs:
     m_ThermalReliefGap = Mils2iu( ZONE_THERMAL_RELIEF_GAP_MIL );
     // thickness of the copper bridge in thermal reliefs:
@@ -95,7 +91,6 @@ ZONE_SETTINGS& ZONE_SETTINGS::operator << ( const ZONE_CONTAINER& aSource )
     m_HatchFillTypeSmoothingValue = aSource.GetHatchFillTypeSmoothingValue();
     m_NetcodeSelection   = aSource.GetNetCode();
     m_Zone_HatchingStyle = aSource.GetHatchStyle();
-    m_ArcToSegmentsCount = aSource.GetArcSegmentCount();
     m_ThermalReliefGap = aSource.GetThermalReliefGap();
     m_ThermalReliefCopperBridge = aSource.GetThermalReliefCopperBridge();
     m_PadConnection = aSource.GetPadConnection();
@@ -124,7 +119,6 @@ void ZONE_SETTINGS::ExportSetting( ZONE_CONTAINER& aTarget, bool aFullExport ) c
     aTarget.SetHatchFillTypeOrientation( m_HatchFillTypeOrientation );
     aTarget.SetHatchFillTypeSmoothingLevel( m_HatchFillTypeSmoothingLevel );
     aTarget.SetHatchFillTypeSmoothingValue( m_HatchFillTypeSmoothingValue );
-    aTarget.SetArcSegmentCount( m_ArcToSegmentsCount );
     aTarget.SetThermalReliefGap( m_ThermalReliefGap );
     aTarget.SetThermalReliefCopperBridge( m_ThermalReliefCopperBridge );
     aTarget.SetPadConnection( m_PadConnection );
diff --git a/pcbnew/zone_settings.h b/pcbnew/zone_settings.h
index 78732896b1..ea4cb14183 100644
--- a/pcbnew/zone_settings.h
+++ b/pcbnew/zone_settings.h
@@ -80,9 +80,6 @@ public:
     /// Option to show the zone area (outlines only, short hatches or full hatches
     int  m_Zone_HatchingStyle;
 
-    /// Option to select number of segments to approximate a circle 16 or 32 segments.
-    int  m_ArcToSegmentsCount;
-
     long m_ThermalReliefGap;            ///< thickness of the gap in thermal reliefs
     long m_ThermalReliefCopperBridge;   ///< thickness of the copper bridge in thermal reliefs
 
diff --git a/pcbnew/zones_functions_for_undo_redo.cpp b/pcbnew/zones_functions_for_undo_redo.cpp
index 36e4e59ac1..7b14cd7a20 100644
--- a/pcbnew/zones_functions_for_undo_redo.cpp
+++ b/pcbnew/zones_functions_for_undo_redo.cpp
@@ -88,9 +88,6 @@ bool ZONE_CONTAINER::IsSame( const ZONE_CONTAINER& aZoneToCompare )
             return false;
     }
 
-    if( m_ArcToSegmentsCount != aZoneToCompare.GetArcSegmentCount() )
-        return false;
-
     if( m_ZoneClearance != aZoneToCompare.m_ZoneClearance )
         return false;
 
diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp
index 4c7673d84e..3679395eb6 100644
--- a/pcbnew/zones_test_and_combine_areas.cpp
+++ b/pcbnew/zones_test_and_combine_areas.cpp
@@ -208,9 +208,6 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
             if( area_to_test->GetThermalReliefCopperBridge() != area2->GetThermalReliefCopperBridge() )
                 continue;
 
-            if( area_to_test->GetArcSegmentCount() != area2->GetArcSegmentCount() )
-                continue;
-
             if( area_to_test->GetZoneClearance() != area2->GetZoneClearance() )
                 continue;