From 3f98769a7750cb99f834cf633eab1ce534c875fd Mon Sep 17 00:00:00 2001
From: Jeff Young <jeff@rokeby.ie>
Date: Sat, 15 Jan 2022 00:20:02 +0000
Subject: [PATCH] More EDA_ANGLE.

Includes bug fix for catastrophic error in Add() for converting to
radians.

Includes bug fixes for the fact that the pcbnew test can't seem to
find the ANGLE_* objects (getting all 0's instead).
---
 common/widgets/unit_binder.cpp                | 27 ++++++
 gerbview/gerber_draw_item.cpp                 | 24 ++---
 include/widgets/unit_binder.h                 |  6 ++
 libs/kimath/include/geometry/eda_angle.h      | 17 +++-
 libs/kimath/include/trigo.h                   | 68 --------------
 .../dialogs/dialog_dimension_properties.cpp   |  4 +-
 .../dialogs/dialog_footprint_properties.cpp   |  4 +-
 pcbnew/dialogs/dialog_pad_properties.cpp      |  8 +-
 pcbnew/dialogs/dialog_text_properties.cpp     |  4 +-
 pcbnew/exporters/export_gencad.cpp            |  6 +-
 pcbnew/pad.cpp                                | 12 +--
 .../specctra_export.cpp                       | 10 +-
 qa/common/test_array_options.cpp              | 94 +++++++++----------
 qa/pcbnew/test_board_item.cpp                 |  9 +-
 14 files changed, 137 insertions(+), 156 deletions(-)

diff --git a/common/widgets/unit_binder.cpp b/common/widgets/unit_binder.cpp
index a84dff84b2..6632e8073b 100644
--- a/common/widgets/unit_binder.cpp
+++ b/common/widgets/unit_binder.cpp
@@ -274,6 +274,15 @@ void UNIT_BINDER::SetDoubleValue( double aValue )
 }
 
 
+void UNIT_BINDER::SetAngleValue( const EDA_ANGLE& aValue )
+{
+    if( m_units == EDA_UNITS::DEGREES )
+        SetDoubleValue( aValue.AsTenthsOfADegree() );   // Historical reasons.
+    else
+        SetDoubleValue( aValue.AsDegrees() );
+}
+
+
 void UNIT_BINDER::SetValue( const wxString& aValue )
 {
     wxTextEntry*  textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
@@ -316,6 +325,15 @@ void UNIT_BINDER::ChangeDoubleValue( double aValue )
 }
 
 
+void UNIT_BINDER::ChangeAngleValue( const EDA_ANGLE& aValue )
+{
+    if( m_units == EDA_UNITS::DEGREES )
+        ChangeDoubleValue( aValue.AsTenthsOfADegree() );   // Historical reasons.
+    else
+        ChangeDoubleValue( aValue.AsDegrees() );
+}
+
+
 void UNIT_BINDER::ChangeValue( const wxString& aValue )
 {
     wxTextEntry*  textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
@@ -406,6 +424,15 @@ double UNIT_BINDER::GetDoubleValue()
 }
 
 
+EDA_ANGLE UNIT_BINDER::GetAngleValue()
+{
+    if( m_units == EDA_UNITS::DEGREES )
+        return EDA_ANGLE( GetDoubleValue(), TENTHS_OF_A_DEGREE_T );     // historical reasons
+    else
+        return EDA_ANGLE( GetDoubleValue(), DEGREES_T );
+}
+
+
 bool UNIT_BINDER::IsIndeterminate() const
 {
     wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl );
diff --git a/gerbview/gerber_draw_item.cpp b/gerbview/gerber_draw_item.cpp
index 813149a4c0..c70a41c0e6 100644
--- a/gerbview/gerber_draw_item.cpp
+++ b/gerbview/gerber_draw_item.cpp
@@ -115,10 +115,9 @@ bool GERBER_DRAW_ITEM::GetTextD_CodePrms( int& aSize, VECTOR2I& aPos, EDA_ANGLE&
     else        // this item is a line
     {
         VECTOR2I delta = m_Start - m_End;
+        EDA_ANGLE angle( delta );
 
-        double deci = RAD2DECIDEG( atan2( (double)delta.y, (double)delta.x ) );
-        NORMALIZE_ANGLE_90( deci );
-        aOrientation = EDA_ANGLE( deci, TENTHS_OF_A_DEGREE_T );
+        aOrientation = angle.Normalize90();
 
         // A reasonable size for text is size/2 because text needs margin below and above it.
         // a margin = size/4 seems good, expecting the line len is large enough to show 3 chars,
@@ -848,23 +847,26 @@ bool GERBER_DRAW_ITEM::HitTest( const VECTOR2I& aRefPos, int aAccuracy ) const
         {
             // Now check that we are within the arc angle
 
-            VECTOR2D start = VECTOR2D( m_Start ) - VECTOR2D( m_ArcCentre );
-            VECTOR2D end = VECTOR2D( m_End ) - VECTOR2D( m_ArcCentre );
+            VECTOR2D  start = VECTOR2D( m_Start ) - VECTOR2D( m_ArcCentre );
+            VECTOR2D  end = VECTOR2D( m_End ) - VECTOR2D( m_ArcCentre );
+            EDA_ANGLE start_angle( start );
+            EDA_ANGLE end_angle( end );
 
-            double start_angle = NormalizeAngleRadiansPos( start.Angle() );
-            double end_angle = NormalizeAngleRadiansPos( end.Angle() );
+            start_angle.Normalize();
+            end_angle.Normalize();
 
             if( m_Start == m_End )
             {
-                start_angle = 0;
-                end_angle = 2 * M_PI;
+                start_angle = ANGLE_0;
+                end_angle = ANGLE_360;
             }
             else if( end_angle < start_angle )
             {
-                end_angle += 2 * M_PI;
+                end_angle += ANGLE_360;
             }
 
-            double test_angle = NormalizeAngleRadiansPos( test_radius.Angle() );
+            EDA_ANGLE test_angle( test_radius );
+            test_angle.Normalize();
 
             return ( test_angle > start_angle && test_angle < end_angle );
         }
diff --git a/include/widgets/unit_binder.h b/include/widgets/unit_binder.h
index 644723f0b3..6c24cb1cf3 100644
--- a/include/widgets/unit_binder.h
+++ b/include/widgets/unit_binder.h
@@ -96,6 +96,8 @@ public:
      */
     virtual void SetDoubleValue( double aValue );
 
+    virtual void SetAngleValue( const EDA_ANGLE& aValue );
+
     /**
      * Set new value (in Internal Units) for the text field, taking care of units conversion
      * WITHOUT triggering the update routine.
@@ -112,6 +114,8 @@ public:
      */
     virtual void ChangeDoubleValue( double aValue );
 
+    virtual void ChangeAngleValue( const EDA_ANGLE& aValue );
+
     /**
      * Return the current value in Internal Units.
      */
@@ -125,6 +129,8 @@ public:
      */
     virtual double GetDoubleValue();
 
+    virtual EDA_ANGLE GetAngleValue();
+
     /**
      * Return true if the control holds the indeterminate value (for instance, if it
      * represents a multiple selection of differing values).
diff --git a/libs/kimath/include/geometry/eda_angle.h b/libs/kimath/include/geometry/eda_angle.h
index 1f08bd4a8a..4d42ec2968 100644
--- a/libs/kimath/include/geometry/eda_angle.h
+++ b/libs/kimath/include/geometry/eda_angle.h
@@ -208,7 +208,7 @@ public:
             return EDA_ANGLE( newAngle / DEGREES_T, DEGREES_T );
 
         case RADIANS_T:
-            return EDA_ANGLE( newAngle / TENTHS_OF_A_DEGREE_TO_RADIANS, RADIANS_T );
+            return EDA_ANGLE( newAngle * TENTHS_OF_A_DEGREE_TO_RADIANS, RADIANS_T );
 
         default:
         case TENTHS_OF_A_DEGREE_T:
@@ -254,6 +254,21 @@ public:
         return *this;
     }
 
+    inline EDA_ANGLE Normalize90()
+    {
+        int angle = AsTenthsOfADegree();
+
+        while( angle < -900 )
+            angle += 1800;
+
+        while( angle > 900 )
+            angle -= 1800;
+
+        *this = EDA_ANGLE( angle, TENTHS_OF_A_DEGREE_T );
+
+        return *this;
+    }
+
     inline EDA_ANGLE Normalize180()
     {
         int angle = AsTenthsOfADegree();
diff --git a/libs/kimath/include/trigo.h b/libs/kimath/include/trigo.h
index 86b25f634f..e4fe6df1a2 100644
--- a/libs/kimath/include/trigo.h
+++ b/libs/kimath/include/trigo.h
@@ -254,20 +254,6 @@ template <class T> inline T NormalizeAngle360Max( T Angle )
     return Angle;
 }
 
-/// Normalize angle to be > -360.0 and < 360.0
-/// Angle equal to -360 or +360 are set to 0
-template <class T> inline T NormalizeAngle360Min( T Angle )
-{
-    while( Angle <= -3600 )
-        Angle += 3600;
-
-    while( Angle >= 3600 )
-        Angle -= 3600;
-
-    return Angle;
-}
-
-
 /// Normalize angle to be in the 0.0 .. -360.0 range: angle is in 1/10 degrees.
 template <class T>
 inline T NormalizeAngleNeg( T Angle )
@@ -311,23 +297,6 @@ inline double NormalizeAngleDegreesPos( double Angle )
 }
 
 
-inline void NORMALIZE_ANGLE_DEGREES_POS( double& Angle )
-{
-    Angle = NormalizeAngleDegreesPos( Angle );
-}
-
-
-inline double NormalizeAngleRadiansPos( double Angle )
-{
-    while( Angle < 0 )
-        Angle += (2 * M_PI );
-
-    while( Angle >= ( 2 * M_PI ) )
-        Angle -= ( 2 * M_PI );
-
-    return Angle;
-}
-
 /// Normalize angle to be aMin < angle <= aMax angle is in degrees.
 inline double NormalizeAngleDegrees( double Angle, double aMin, double aMax )
 {
@@ -351,43 +320,6 @@ template <class T, class T2> inline T AddAngles( T a1, T2 a2 )
 }
 
 
-template <class T> inline T NegateAndNormalizeAnglePos( T Angle )
-{
-    Angle = -Angle;
-
-    while( Angle < 0 )
-        Angle += 3600;
-
-    while( Angle >= 3600 )
-        Angle -= 3600;
-
-    return Angle;
-}
-
-template <class T> inline void NEGATE_AND_NORMALIZE_ANGLE_POS( T& Angle )
-{
-    Angle = NegateAndNormalizeAnglePos( Angle );
-}
-
-
-/// Normalize angle to be in the -90.0 .. 90.0 range
-template <class T> inline T NormalizeAngle90( T Angle )
-{
-    while( Angle < -900 )
-        Angle += 1800;
-
-    while( Angle > 900 )
-        Angle -= 1800;
-
-    return Angle;
-}
-
-template <class T> inline void NORMALIZE_ANGLE_90( T& Angle )
-{
-    Angle = NormalizeAngle90( Angle );
-}
-
-
 /// Normalize angle to be in the -180.0 .. 180.0 range
 template <class T> inline T NormalizeAngle180( T Angle )
 {
diff --git a/pcbnew/dialogs/dialog_dimension_properties.cpp b/pcbnew/dialogs/dialog_dimension_properties.cpp
index 0fdda618ba..151105e00d 100644
--- a/pcbnew/dialogs/dialog_dimension_properties.cpp
+++ b/pcbnew/dialogs/dialog_dimension_properties.cpp
@@ -245,7 +245,7 @@ bool DIALOG_DIMENSION_PROPERTIES::TransferDataToWindow()
         m_txtTextPosY->Disable();
     }
 
-    m_orientation.SetDoubleValue( text.GetTextAngle().AsTenthsOfADegree() );
+    m_orientation.SetAngleValue( text.GetTextAngle() );
 
     m_bold->Check( text.IsBold() );
     m_italic->Check( text.IsItalic() );
@@ -417,7 +417,7 @@ void DIALOG_DIMENSION_PROPERTIES::updateDimensionFromDialog( PCB_DIMENSION_BASE*
 
     aTarget->SetKeepTextAligned( m_cbKeepAligned->GetValue() );
 
-    text.SetTextAngle( EDA_ANGLE( m_orientation.GetDoubleValue(), TENTHS_OF_A_DEGREE_T ) );
+    text.SetTextAngle( m_orientation.GetAngleValue() );
     text.SetTextWidth( m_textWidth.GetValue() );
     text.SetTextHeight( m_textHeight.GetValue() );
     text.SetTextThickness( m_textThickness.GetValue() );
diff --git a/pcbnew/dialogs/dialog_footprint_properties.cpp b/pcbnew/dialogs/dialog_footprint_properties.cpp
index aa8a801cb5..ac3530f89a 100644
--- a/pcbnew/dialogs/dialog_footprint_properties.cpp
+++ b/pcbnew/dialogs/dialog_footprint_properties.cpp
@@ -246,7 +246,7 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataToWindow()
 
     m_BoardSideCtrl->SetSelection( (m_footprint->GetLayer() == B_Cu) ? 1 : 0 );
 
-    m_orientation.SetDoubleValue( m_footprint->GetOrientation().AsTenthsOfADegree() );
+    m_orientation.SetAngleValue( m_footprint->GetOrientation() );
 
     m_cbLocked->SetValue( m_footprint->IsLocked() );
     m_cbLocked->SetToolTip( _( "Locked footprints cannot be freely moved and oriented on the "
@@ -441,7 +441,7 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataFromWindow()
 
     m_footprint->SetAttributes( attributes );
 
-    EDA_ANGLE orient( m_orientation.GetDoubleValue(), TENTHS_OF_A_DEGREE_T );
+    EDA_ANGLE orient = m_orientation.GetAngleValue();
 
     if( m_footprint->GetOrientation() != orient )
         m_footprint->Rotate( m_footprint->GetPosition(), orient - m_footprint->GetOrientation() );
diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp
index e69b588c8a..a561923422 100644
--- a/pcbnew/dialogs/dialog_pad_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_properties.cpp
@@ -558,11 +558,11 @@ void DIALOG_PAD_PROPERTIES::initValues()
     m_clearance.ChangeValue( m_dummyPad->GetLocalClearance() );
     m_maskMargin.ChangeValue( m_dummyPad->GetLocalSolderMaskMargin() );
     m_spokeWidth.ChangeValue( m_dummyPad->GetThermalSpokeWidth() );
-    m_spokeAngle.ChangeDoubleValue( m_dummyPad->GetThermalSpokeAngle().AsTenthsOfADegree() );
+    m_spokeAngle.ChangeAngleValue( m_dummyPad->GetThermalSpokeAngle() );
     m_thermalGap.ChangeValue( m_dummyPad->GetThermalGap() );
     m_pasteMargin.ChangeValue( m_dummyPad->GetLocalSolderPasteMargin() );
     m_pasteMarginRatio.ChangeDoubleValue( m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 );
-    m_pad_orientation.ChangeDoubleValue( m_dummyPad->GetOrientation().AsTenthsOfADegree() );
+    m_pad_orientation.ChangeAngleValue( m_dummyPad->GetOrientation() );
 
     switch( m_dummyPad->GetZoneConnection() )
     {
@@ -1717,11 +1717,11 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
     aPad->SetLocalSolderPasteMargin( m_pasteMargin.GetValue() );
     aPad->SetLocalSolderPasteMarginRatio( m_pasteMarginRatio.GetDoubleValue() / 100.0 );
     aPad->SetThermalSpokeWidth( m_spokeWidth.GetValue() );
-    aPad->SetThermalSpokeAngle( EDA_ANGLE( m_spokeAngle.GetDoubleValue(), TENTHS_OF_A_DEGREE_T ) );
+    aPad->SetThermalSpokeAngle( m_spokeAngle.GetAngleValue() );
     aPad->SetThermalGap( m_thermalGap.GetValue() );
 
     // And rotation
-    aPad->SetOrientation( EDA_ANGLE( m_pad_orientation.GetDoubleValue(), TENTHS_OF_A_DEGREE_T ) );
+    aPad->SetOrientation( m_pad_orientation.GetAngleValue() );
 
     switch( m_ZoneConnectionChoice->GetSelection() )
     {
diff --git a/pcbnew/dialogs/dialog_text_properties.cpp b/pcbnew/dialogs/dialog_text_properties.cpp
index f3b6cd175d..8bcc0d4579 100644
--- a/pcbnew/dialogs/dialog_text_properties.cpp
+++ b/pcbnew/dialogs/dialog_text_properties.cpp
@@ -285,7 +285,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataToWindow()
 
     m_mirrored->Check( m_edaText->IsMirrored() );
 
-    m_orientation.SetDoubleValue( m_edaText->GetTextAngle().AsTenthsOfADegree() );
+    m_orientation.SetAngleValue( m_edaText->GetTextAngle() );
 
     return DIALOG_TEXT_PROPERTIES_BASE::TransferDataToWindow();
 }
@@ -419,7 +419,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataFromWindow()
         m_edaText->SetTextThickness( maxPenWidth );
     }
 
-    m_edaText->SetTextAngle( EDA_ANGLE( m_orientation.GetDoubleValue(), TENTHS_OF_A_DEGREE_T ) );
+    m_edaText->SetTextAngle( m_orientation.GetAngleValue() );
 
     m_edaText->SetVisible( m_Visible->GetValue() );
 
diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp
index 69796b0764..f7f3e7cb4f 100644
--- a/pcbnew/exporters/export_gencad.cpp
+++ b/pcbnew/exporters/export_gencad.cpp
@@ -861,13 +861,13 @@ static void CreateComponentsSection( FILE* aFile, BOARD* aPcb )
     {
         const char*   mirror;
         const char*   flip;
-        double        fp_orient = footprint->GetOrientation().AsTenthsOfADegree();
+        EDA_ANGLE     fp_orient = footprint->GetOrientation();
 
         if( footprint->GetFlag() )
         {
             mirror = "MIRRORX";
             flip   = "FLIP";
-            NEGATE_AND_NORMALIZE_ANGLE_POS( fp_orient );
+            fp_orient = fp_orient.Invert().Normalize();
         }
         else
         {
@@ -885,7 +885,7 @@ static void CreateComponentsSection( FILE* aFile, BOARD* aPcb )
         fprintf( aFile, "LAYER %s\n",
                  footprint->GetFlag() ? "BOTTOM" : "TOP" );
         fprintf( aFile, "ROTATION %g\n",
-                 fp_orient / 10.0 );
+                 fp_orient.AsDegrees() );
         fprintf( aFile, "SHAPE \"%s\" %s %s\n",
                  TO_UTF8( escapeString( getShapeName( footprint ) ) ),
                  mirror, flip );
diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp
index f81070b5e0..d4cb3d10a8 100644
--- a/pcbnew/pad.cpp
+++ b/pcbnew/pad.cpp
@@ -907,14 +907,14 @@ void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
         aList.emplace_back( _( "Height" ), MessageTextFromValue( units, m_size.y ) );
     }
 
-    double fp_orient_degrees = parentFootprint ? parentFootprint->GetOrientationDegrees() : 0;
-    double pad_orient_degrees = GetOrientationDegrees() - fp_orient_degrees;
-    pad_orient_degrees = NormalizeAngleDegrees( pad_orient_degrees, -180.0, +180.0 );
+    EDA_ANGLE fp_orient = parentFootprint ? parentFootprint->GetOrientation() : ANGLE_0;
+    EDA_ANGLE pad_orient = GetOrientation() - fp_orient;
+    pad_orient.Normalize180();
 
-    if( fp_orient_degrees != 0.0 )
-        msg.Printf( wxT( "%g(+ %g)" ), pad_orient_degrees, fp_orient_degrees );
+    if( !fp_orient.IsZero() )
+        msg.Printf( wxT( "%g(+ %g)" ), pad_orient.AsDegrees(), fp_orient.AsDegrees() );
     else
-        msg.Printf( wxT( "%g" ), GetOrientationDegrees() );
+        msg.Printf( wxT( "%g" ), GetOrientation().AsDegrees() );
 
     aList.emplace_back( _( "Rotation" ), msg );
 
diff --git a/pcbnew/specctra_import_export/specctra_export.cpp b/pcbnew/specctra_import_export/specctra_export.cpp
index bb5f0330a8..ae37b3973d 100644
--- a/pcbnew/specctra_import_export/specctra_export.cpp
+++ b/pcbnew/specctra_import_export/specctra_export.cpp
@@ -699,9 +699,8 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, FOOTPRINT* aFootprint )
 
             pin->padstack_id = padstack->padstack_id;
 
-            double angle = pad->GetOrientationDegrees() - aFootprint->GetOrientationDegrees();
-            NORMALIZE_ANGLE_DEGREES_POS( angle );
-            pin->SetRotation( angle );
+            EDA_ANGLE angle = pad->GetOrientation() - aFootprint->GetOrientation();
+            pin->SetRotation( angle.Normalize().AsDegrees() );
 
             wxPoint pos( pad->GetPos0() );
 
@@ -1573,9 +1572,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
             // footprint is flipped from bottom side, set side to T_back
             if( footprint->GetFlag() )
             {
-                double angle = 180.0 - footprint->GetOrientationDegrees();
-                NORMALIZE_ANGLE_DEGREES_POS( angle );
-                place->SetRotation( angle );
+                EDA_ANGLE angle = ANGLE_180 - footprint->GetOrientation();
+                place->SetRotation( angle.Normalize().AsDegrees() );
 
                 place->side = T_back;
             }
diff --git a/qa/common/test_array_options.cpp b/qa/common/test_array_options.cpp
index 6b59e01115..5b9c351527 100644
--- a/qa/common/test_array_options.cpp
+++ b/qa/common/test_array_options.cpp
@@ -130,12 +130,12 @@ static const std::vector<GRID_ARRAY_TEST_CASE> grid_geom_cases = {
         },
         { 0, 0 },
         {
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0 ), Millimeter2iu( 4 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 4 ) }, ANGLE_0 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
         },
     },
     {
@@ -153,12 +153,12 @@ static const std::vector<GRID_ARRAY_TEST_CASE> grid_geom_cases = {
         { 0, 0 },
         {
             // add the offsets for each positions
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 0.2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0.1 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2.1 ), Millimeter2iu( 2.2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0.2 ), Millimeter2iu( 4.0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2.2 ), Millimeter2iu( 4.2 ) }, ANGLE_0 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 0.2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0.1 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2.1 ), Millimeter2iu( 2.2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0.2 ), Millimeter2iu( 4.0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2.2 ), Millimeter2iu( 4.2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
         },
     },
     {
@@ -176,12 +176,12 @@ static const std::vector<GRID_ARRAY_TEST_CASE> grid_geom_cases = {
         { 0, 0 },
         {
             // add the offsets for each positions
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 3 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 1 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 4 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 4 ) }, ANGLE_0 },
-            { { Millimeter2iu( 5 ), Millimeter2iu( 4 ) }, ANGLE_0 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 3 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 1 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 4 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 5 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
         },
     },
     {
@@ -199,12 +199,12 @@ static const std::vector<GRID_ARRAY_TEST_CASE> grid_geom_cases = {
         { 0, 0 },
         {
             // add the offsets for each positions
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 3 ), Millimeter2iu( 1 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 3 ), Millimeter2iu( 3 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0 ), Millimeter2iu( 4 ) }, ANGLE_0 },
-            { { Millimeter2iu( 3 ), Millimeter2iu( 5 ) }, ANGLE_0 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 3 ), Millimeter2iu( 1 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 3 ), Millimeter2iu( 3 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 3 ), Millimeter2iu( 5 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
         },
     },
     {
@@ -221,12 +221,12 @@ static const std::vector<GRID_ARRAY_TEST_CASE> grid_geom_cases = {
         },
         { 0, 0 },
         {
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0 ), Millimeter2iu( 4 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 4 ) }, ANGLE_0 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
         },
     },
     {
@@ -243,12 +243,12 @@ static const std::vector<GRID_ARRAY_TEST_CASE> grid_geom_cases = {
         },
         { 0, 0 },
         {
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 0 ), Millimeter2iu( 4 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 2 ) }, ANGLE_0 },
-            { { Millimeter2iu( 2 ), Millimeter2iu( 4 ) }, ANGLE_0 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 2 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( 2 ), Millimeter2iu( 4 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
         },
     },
 };
@@ -311,10 +311,10 @@ static const std::vector<CIRC_ARRAY_TEST_CASE> circ_geom_cases = {
         { Millimeter2iu( 10 ), 0 },
         {
             // diamond shape
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( -10 ), Millimeter2iu( -10 ) }, ANGLE_0 },
-            { { Millimeter2iu( -20 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { {Millimeter2iu( -10 ), Millimeter2iu( 10 ) }, ANGLE_0 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( -10 ), Millimeter2iu( -10 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( -20 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { {Millimeter2iu( -10 ), Millimeter2iu( 10 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
         },
     },
     {
@@ -327,10 +327,10 @@ static const std::vector<CIRC_ARRAY_TEST_CASE> circ_geom_cases = {
         },
         { Millimeter2iu( 10 ), 0 },
         {
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
-            { { Millimeter2iu( -10 ), Millimeter2iu( -10 ) }, ANGLE_90 },
-            { { Millimeter2iu( -20 ), Millimeter2iu( 0 ) }, ANGLE_180 },
-            { {Millimeter2iu( -10 ), Millimeter2iu( 10 ) }, ANGLE_270 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
+            { { Millimeter2iu( -10 ), Millimeter2iu( -10 ) }, EDA_ANGLE( 90.0, DEGREES_T ) },
+            { { Millimeter2iu( -20 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 180.0, DEGREES_T ) },
+            { {Millimeter2iu( -10 ), Millimeter2iu( 10 ) }, EDA_ANGLE( 270.0, DEGREES_T ) },
         },
     },
     {
@@ -343,10 +343,10 @@ static const std::vector<CIRC_ARRAY_TEST_CASE> circ_geom_cases = {
         },
         { Millimeter2iu( 10 ), 0 },
         {
-            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, ANGLE_0 },
+            { { Millimeter2iu( 0 ), Millimeter2iu( 0 ) }, EDA_ANGLE( 0.0, DEGREES_T ) },
             // 10 * [ 1-sin(45), sin(45) ]
-            { { Millimeter2iu( -2.9289321881 ), Millimeter2iu( -7.0710678118 ) }, ANGLE_45 },
-            { { Millimeter2iu( -10 ), Millimeter2iu( -10 ) }, ANGLE_90 },
+            { { Millimeter2iu( -2.9289321881 ), Millimeter2iu( -7.0710678118 ) }, EDA_ANGLE( 45.0, DEGREES_T ) },
+            { { Millimeter2iu( -10 ), Millimeter2iu( -10 ) }, EDA_ANGLE( 90.0, DEGREES_T ) },
         },
     },
 };
diff --git a/qa/pcbnew/test_board_item.cpp b/qa/pcbnew/test_board_item.cpp
index cc8a2548b0..eaca9f96e2 100644
--- a/qa/pcbnew/test_board_item.cpp
+++ b/qa/pcbnew/test_board_item.cpp
@@ -194,6 +194,7 @@ BOOST_AUTO_TEST_CASE( Move )
                         item->Move( aRef );
 
                         FP_SHAPE* fpShape = dynamic_cast<FP_SHAPE*>( item.get() );
+
                         if( fpShape != nullptr )
                             fpShape->SetDrawCoord();
 
@@ -247,10 +248,10 @@ BOOST_AUTO_TEST_CASE( Rotate )
 
                         // Four equivalent 90 degree rotations are an identity.
 
-                        item->Rotate( aRef, ANGLE_90 );
-                        item->Rotate( aRef, ANGLE_90 );
-                        item->Rotate( aRef, ANGLE_90 );
-                        item->Rotate( aRef, ANGLE_90 );
+                        item->Rotate( aRef, EDA_ANGLE( 90.0, DEGREES_T ) );
+                        item->Rotate( aRef, EDA_ANGLE( 90.0, DEGREES_T ) );
+                        item->Rotate( aRef, EDA_ANGLE( 90.0, DEGREES_T ) );
+                        item->Rotate( aRef, EDA_ANGLE( 90.0, DEGREES_T ) );
 
                         FP_SHAPE* fpShape = dynamic_cast<FP_SHAPE*>( aOriginalItem );