From e61144d45ad6b93c22e11816cc6fb5931b9e4eaf Mon Sep 17 00:00:00 2001
From: Jeff Young <jeff@rokeby.ie>
Date: Sun, 16 Jan 2022 21:15:20 +0000
Subject: [PATCH] Finish with EDA_ANGLE.

---
 3d-viewer/3d_canvas/board_adapter.h           |  4 +--
 .../3d_canvas/create_3Dgraphic_brd_items.cpp  | 29 +++++++++----------
 common/drawing_sheet/drawing_sheet_parser.cpp |  2 +-
 common/drawing_sheet/ds_data_item.cpp         | 13 ++++-----
 common/drawing_sheet/ds_data_model_io.cpp     |  4 +--
 common/eda_rect.cpp                           | 29 +++++++++----------
 common/eda_shape.cpp                          | 22 ++++++--------
 common/eda_text.cpp                           |  2 +-
 common/plotters/GERBER_plotter.cpp            | 12 ++++----
 common/plotters/HPGL_plotter.cpp              |  4 +--
 common/plotters/PDF_plotter.cpp               | 12 ++++----
 common/plotters/plotter.cpp                   | 12 ++++----
 .../cadstar/cadstar_archive_parser.cpp        |  3 +-
 common/stroke_params.cpp                      |  6 ++--
 eeschema/lib_field.cpp                        |  2 +-
 eeschema/lib_pin.cpp                          | 10 +++----
 eeschema/lib_shape.cpp                        |  2 +-
 eeschema/lib_shape.h                          |  2 +-
 eeschema/lib_text.h                           |  2 +-
 eeschema/sch_bitmap.cpp                       |  2 +-
 eeschema/sch_bus_entry.cpp                    |  2 +-
 eeschema/sch_field.cpp                        |  2 +-
 eeschema/sch_junction.cpp                     |  2 +-
 eeschema/sch_line.cpp                         |  8 ++---
 eeschema/sch_no_connect.cpp                   |  2 +-
 eeschema/sch_painter.cpp                      |  2 +-
 .../sch_plugins/altium/sch_altium_plugin.cpp  |  4 +--
 eeschema/sch_shape.cpp                        |  2 +-
 eeschema/sch_shape.h                          |  2 +-
 eeschema/sch_sheet.cpp                        |  4 +--
 eeschema/sch_sheet_pin.cpp                    |  2 +-
 eeschema/sch_symbol.cpp                       |  2 +-
 eeschema/sch_text.cpp                         |  6 ++--
 eeschema/transform.cpp                        |  8 ++---
 include/drawing_sheet/ds_data_item.h          | 10 +++----
 include/eda_rect.h                            | 12 ++++----
 include/eda_shape.h                           |  4 +--
 .../include/convert_basic_shapes_to_polygon.h |  4 +--
 libs/kimath/include/geometry/shape_arc.h      |  2 +-
 libs/kimath/include/trigo.h                   |  3 +-
 .../src/convert_basic_shapes_to_polygon.cpp   | 12 ++++----
 libs/kimath/src/geometry/direction_45.cpp     | 10 +++----
 libs/kimath/src/geometry/shape_arc.cpp        | 14 ++++-----
 libs/kimath/src/geometry/shape_line_chain.cpp |  4 +--
 libs/kimath/src/trigo.cpp                     | 20 +++++++------
 .../dialogs/properties_frame.cpp              |  4 +--
 .../dialog_graphic_item_properties.cpp        | 19 +++++-------
 .../dialog_pad_basicshapes_properties.cpp     |  2 +-
 pcbnew/fp_text.cpp                            | 14 ++++-----
 pcbnew/pad.cpp                                |  4 +--
 pcbnew/pcb_edit_frame.cpp                     |  2 +-
 pcbnew/pcb_shape.cpp                          |  8 ++---
 pcbnew/pcb_shape.h                            |  2 +-
 pcbnew/pcb_text.cpp                           |  2 +-
 pcbnew/plugins/altium/altium_pcb.cpp          |  4 +--
 pcbnew/plugins/pcad/pcb_arc.cpp               |  4 +--
 pcbnew/router/pns_kicad_iface.cpp             |  2 +-
 pcbnew/router/pns_line_placer.cpp             |  2 +-
 pcbnew/router/pns_solid.h                     |  7 ++---
 pcbnew/zone.cpp                               |  4 +--
 60 files changed, 190 insertions(+), 207 deletions(-)

diff --git a/3d-viewer/3d_canvas/board_adapter.h b/3d-viewer/3d_canvas/board_adapter.h
index 244c435dbd..8a0d7ab3b9 100644
--- a/3d-viewer/3d_canvas/board_adapter.h
+++ b/3d-viewer/3d_canvas/board_adapter.h
@@ -488,8 +488,8 @@ private:
     void addSolidAreasShapes( const ZONE* aZoneContainer, CONTAINER_2D_BASE* aDstContainer,
                               PCB_LAYER_ID aLayerId );
 
-    void transformArcToSegments( const VECTOR2I& aCentre, const VECTOR2I& aStart, double aArcAngle,
-                                 int aCircleToSegmentsCount, int aWidth,
+    void transformArcToSegments( const VECTOR2I& aCentre, const VECTOR2I& aStart,
+                                 const EDA_ANGLE& aArcAngle, int aCircleToSegmentsCount, int aWidth,
                                  CONTAINER_2D_BASE* aDstContainer, const BOARD_ITEM& aBoardItem );
 
     void buildPadOutlineAsSegments( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer, int aWidth );
diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
index 6328823f5c..c344dab757 100644
--- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
+++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
@@ -260,9 +260,8 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
             circlesegcount = std::max( 1, std::min( circlesegcount, 128 ) );
         }
 
-        transformArcToSegments( VECTOR2I( center.x, center.y ), arc->GetStart(),
-                                arc_angle.AsTenthsOfADegree(), circlesegcount, arc->GetWidth(),
-                                aDstContainer, *arc );
+        transformArcToSegments( VECTOR2I( center.x, center.y ), arc->GetStart(), arc_angle,
+                                circlesegcount, arc->GetWidth(), aDstContainer, *arc );
         break;
     }
 
@@ -532,31 +531,30 @@ void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDs
 // based on TransformArcToPolygon function from
 // common/convert_basic_shapes_to_polygon.cpp
 void BOARD_ADAPTER::transformArcToSegments( const VECTOR2I& aCentre, const VECTOR2I& aStart,
-                                            double aArcAngle, int aCircleToSegmentsCount,
+                                            const EDA_ANGLE& aArcAngle, int aCircleToSegmentsCount,
                                             int aWidth, CONTAINER_2D_BASE* aDstContainer,
                                             const BOARD_ITEM& aBoardItem )
 {
-    VECTOR2I arc_start, arc_end;
-    int     delta = 3600 / aCircleToSegmentsCount;   // rotate angle in 0.1 degree
+    VECTOR2I  arc_start, arc_end;
+    EDA_ANGLE arcAngle( aArcAngle );
+    EDA_ANGLE delta = ANGLE_360 / aCircleToSegmentsCount;   // rotate angle
 
     arc_end = arc_start = aStart;
 
-    if( aArcAngle != 3600 )
-    {
-        RotatePoint( arc_end, aCentre, -aArcAngle );
-    }
+    if( arcAngle != ANGLE_360 )
+        RotatePoint( arc_end, aCentre, -arcAngle );
 
-    if( aArcAngle < 0 )
+    if( arcAngle < ANGLE_0 )
     {
         std::swap( arc_start, arc_end );
-        aArcAngle = -aArcAngle;
+        arcAngle = -arcAngle;
     }
 
     // Compute the ends of segments and creates poly
     VECTOR2I curr_end = arc_start;
     VECTOR2I curr_start = arc_start;
 
-    for( int ii = delta; ii < aArcAngle; ii += delta )
+    for( EDA_ANGLE ii = delta; ii < arcAngle; ii += delta )
     {
         curr_end = arc_start;
         RotatePoint( curr_end, aCentre, -ii );
@@ -659,9 +657,8 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstCo
     {
         unsigned int segCount = GetCircleSegmentCount( aShape->GetBoundingBox().GetSizeMax() );
 
-        transformArcToSegments( aShape->GetCenter(), aShape->GetStart(),
-                                aShape->GetArcAngle().AsTenthsOfADegree(), segCount, linewidth,
-                                aDstContainer, *aShape );
+        transformArcToSegments( aShape->GetCenter(), aShape->GetStart(), aShape->GetArcAngle(),
+                                segCount, linewidth, aDstContainer, *aShape );
     }
     break;
 
diff --git a/common/drawing_sheet/drawing_sheet_parser.cpp b/common/drawing_sheet/drawing_sheet_parser.cpp
index 059b8fe41d..8cc9e1cb97 100644
--- a/common/drawing_sheet/drawing_sheet_parser.cpp
+++ b/common/drawing_sheet/drawing_sheet_parser.cpp
@@ -388,7 +388,7 @@ void DRAWING_SHEET_PARSER::parsePolygon( DS_DATA_ITEM_POLYGONS * aItem )
             break;
 
         case T_rotate:
-            aItem->m_Orient = parseDouble();
+            aItem->m_Orient = EDA_ANGLE( parseDouble(), DEGREES_T );
             NeedRIGHT();
             break;
 
diff --git a/common/drawing_sheet/ds_data_item.cpp b/common/drawing_sheet/ds_data_item.cpp
index 5cd91b9664..9bc560c485 100644
--- a/common/drawing_sheet/ds_data_item.cpp
+++ b/common/drawing_sheet/ds_data_item.cpp
@@ -381,7 +381,6 @@ const wxString DS_DATA_ITEM::GetClassName() const
 DS_DATA_ITEM_POLYGONS::DS_DATA_ITEM_POLYGONS() :
         DS_DATA_ITEM( DS_POLYPOLYGON )
 {
-    m_Orient = 0.0;
 }
 
 
@@ -445,12 +444,12 @@ int DS_DATA_ITEM_POLYGONS::GetPenSizeUi()
 }
 
 
-const DPOINT DS_DATA_ITEM_POLYGONS::GetCornerPosition( unsigned aIdx, int aRepeat ) const
+const VECTOR2D DS_DATA_ITEM_POLYGONS::GetCornerPosition( unsigned aIdx, int aRepeat ) const
 {
-    DPOINT pos = m_Corners[aIdx];
+    VECTOR2D pos = m_Corners[aIdx];
 
     // Rotation:
-    RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
+    RotatePoint( &pos.x, &pos.y, m_Orient );
     pos += GetStartPos( aRepeat );
     return pos;
 }
@@ -465,15 +464,15 @@ void DS_DATA_ITEM_POLYGONS::SetBoundingBox()
         return;
     }
 
-    DPOINT pos;
+    VECTOR2I pos;
     pos = m_Corners[0];
-    RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
+    RotatePoint( &pos.x, &pos.y, m_Orient );
     m_minCoord = m_maxCoord = pos;
 
     for( unsigned ii = 1; ii < m_Corners.size(); ii++ )
     {
         pos = m_Corners[ii];
-        RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
+        RotatePoint( &pos.x, &pos.y, m_Orient );
 
         if( m_minCoord.x > pos.x )
             m_minCoord.x = pos.x;
diff --git a/common/drawing_sheet/ds_data_model_io.cpp b/common/drawing_sheet/ds_data_model_io.cpp
index 3532741674..e9d3e3e633 100644
--- a/common/drawing_sheet/ds_data_model_io.cpp
+++ b/common/drawing_sheet/ds_data_model_io.cpp
@@ -341,8 +341,8 @@ void DS_DATA_MODEL_IO::format( DS_DATA_ITEM_POLYGONS* aItem, int aNestLevel ) co
 
     formatRepeatParameters( aItem );
 
-    if( aItem->m_Orient )
-        m_out->Print( 0, " (rotate %s)", double2Str(aItem->m_Orient ).c_str() );
+    if( !aItem->m_Orient.IsZero() )
+        m_out->Print( 0, " (rotate %s)", double2Str( aItem->m_Orient.AsDegrees() ).c_str() );
 
     if( aItem->m_LineWidth )
         m_out->Print( 0, " (linewidth %s)\n", double2Str( aItem->m_LineWidth ).c_str() );
diff --git a/common/eda_rect.cpp b/common/eda_rect.cpp
index aef2af6c13..c52225c148 100644
--- a/common/eda_rect.cpp
+++ b/common/eda_rect.cpp
@@ -181,14 +181,16 @@ bool EDA_RECT::Intersects( const EDA_RECT& aRect ) const
 }
 
 
-bool EDA_RECT::Intersects( const EDA_RECT& aRect, double aRot ) const
+bool EDA_RECT::Intersects( const EDA_RECT& aRect, const EDA_ANGLE& aRotation ) const
 {
     if( !m_init )
         return false;
 
-    /* Most rectangles will be axis aligned.
-     * It is quicker to check for this case and pass the rect
-     * to the simpler intersection test
+    double rotation = aRotation.AsTenthsOfADegree();
+
+    /*
+     * Most rectangles will be axis aligned.  It is quicker to check for this case and pass
+     * the rect to the simpler intersection test.
      */
 
     // Prevent floating point comparison errors
@@ -197,21 +199,19 @@ bool EDA_RECT::Intersects( const EDA_RECT& aRect, double aRot ) const
     static const double ROT_PARALLEL[]      = { -3600, -1800, 0, 1800, 3600 };
     static const double ROT_PERPENDICULAR[] = { -2700, -900, 0, 900, 2700 };
 
-    NORMALIZE_ANGLE_POS<double>( aRot );
+    NORMALIZE_ANGLE_POS<double>( rotation );
 
     // Test for non-rotated rectangle
     for( int ii = 0; ii < 5; ii++ )
     {
-        if( std::fabs( aRot - ROT_PARALLEL[ii] ) < ROT_EPS )
-        {
+        if( std::fabs( rotation - ROT_PARALLEL[ii] ) < ROT_EPS )
             return Intersects( aRect );
-        }
     }
 
     // Test for rectangle rotated by multiple of 90 degrees
     for( int jj = 0; jj < 4; jj++ )
     {
-        if( std::fabs( aRot - ROT_PERPENDICULAR[jj] ) < ROT_EPS )
+        if( std::fabs( rotation - ROT_PERPENDICULAR[jj] ) < ROT_EPS )
         {
             EDA_RECT rotRect;
 
@@ -242,13 +242,11 @@ bool EDA_RECT::Intersects( const EDA_RECT& aRect, double aRot ) const
     for( int i = 0; i < 4; i++ )
     {
         VECTOR2I delta = corners[i] - rCentre;
-        RotatePoint( delta, -aRot );
+        RotatePoint( delta, -rotation );
         delta += rCentre;
 
         if( aRect.Contains( delta ) )
-        {
             return true;
-        }
     }
 
     /* Test B : Any corners of rotated rect exist in this one? */
@@ -264,13 +262,11 @@ bool EDA_RECT::Intersects( const EDA_RECT& aRect, double aRot ) const
     // Rotate and test each corner
     for( int j = 0; j < 4; j++ )
     {
-        RotatePoint( corners[j], aRot );
+        RotatePoint( corners[j], rotation );
         corners[j] += rCentre;
 
         if( Contains( corners[j] ) )
-        {
             return true;
-        }
     }
 
     /* Test C : Any sides of rotated rect intersect this */
@@ -510,7 +506,8 @@ EDA_RECT EDA_RECT::Common( const EDA_RECT& aRect ) const
 }
 
 
-const EDA_RECT EDA_RECT::GetBoundingBoxRotated( const VECTOR2I& aRotCenter, double aAngle ) const
+const EDA_RECT EDA_RECT::GetBoundingBoxRotated( const VECTOR2I& aRotCenter,
+                                                const EDA_ANGLE& aAngle ) const
 {
     VECTOR2I corners[4];
 
diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp
index 0b276c24e4..6df2602ea2 100644
--- a/common/eda_shape.cpp
+++ b/common/eda_shape.cpp
@@ -222,7 +222,7 @@ void EDA_SHAPE::scale( double aScale )
 }
 
 
-void EDA_SHAPE::rotate( const VECTOR2I& aRotCentre, double aAngle )
+void EDA_SHAPE::rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
 {
     switch( m_shape )
     {
@@ -239,7 +239,7 @@ void EDA_SHAPE::rotate( const VECTOR2I& aRotCentre, double aAngle )
         break;
 
     case SHAPE_T::RECT:
-        if( KiROUND( aAngle ) % 900 == 0 )
+        if( aAngle.IsCardinal() )
         {
             RotatePoint( m_start, aRotCentre, aAngle );
             RotatePoint( m_end, aRotCentre, aAngle );
@@ -258,7 +258,7 @@ void EDA_SHAPE::rotate( const VECTOR2I& aRotCentre, double aAngle )
         KI_FALLTHROUGH;
 
     case SHAPE_T::POLY:
-        m_poly.Rotate( -DECIDEG2RAD( aAngle ), VECTOR2I( aRotCentre ) );
+        m_poly.Rotate( -aAngle.AsRadians(), aRotCentre );
         break;
 
     case SHAPE_T::BEZIER:
@@ -878,14 +878,10 @@ bool EDA_SHAPE::hitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
             // Polygons in footprints use coordinates relative to the footprint.
             // Therefore, instead of using m_poly, we make a copy which is translated
             // to the actual location in the board.
-            double  orientation = 0.0;
             VECTOR2I offset = getParentPosition();
 
-            if( getParentOrientation() )
-                orientation = -DECIDEG2RAD( getParentOrientation() );
-
             SHAPE_LINE_CHAIN poly = m_poly.Outline( 0 );
-            poly.Rotate( orientation );
+            poly.Rotate( -getParentOrientation().AsRadians() );
             poly.Move( offset );
 
             int count = poly.GetPointCount();
@@ -966,7 +962,7 @@ std::vector<VECTOR2I> EDA_SHAPE::GetRectCorners() const
     VECTOR2I              botRight = GetEnd();
 
     // Un-rotate rect topLeft and botRight
-    if( KiROUND( getParentOrientation() ) % 900 != 0 )
+    if( !getParentOrientation().IsCardinal() )
     {
         topLeft -= getParentPosition();
         RotatePoint( topLeft, -getParentOrientation() );
@@ -982,7 +978,7 @@ std::vector<VECTOR2I> EDA_SHAPE::GetRectCorners() const
     pts.emplace_back( topLeft.x, botRight.y );
 
     // Now re-rotate the 4 corners to get a diamond
-    if( KiROUND( getParentOrientation() ) % 900 != 0 )
+    if( !getParentOrientation().IsCardinal() )
     {
         for( VECTOR2I& pt : pts )
         {
@@ -1137,7 +1133,7 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
     {
         SHAPE_LINE_CHAIN l = GetPolyShape().COutline( 0 );
 
-        l.Rotate( -DECIDEG2RAD( getParentOrientation() ) );
+        l.Rotate( -getParentOrientation().AsRadians() );
         l.Move( getParentPosition() );
 
         if( IsFilled() && !aEdgeOnly )
@@ -1547,8 +1543,8 @@ void EDA_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
             break;
 
         // The polygon is expected to be a simple polygon; not self intersecting, no hole.
-        double  orientation = getParentOrientation();
-        VECTOR2I offset = getParentPosition();
+        EDA_ANGLE orientation = getParentOrientation();
+        VECTOR2I  offset = getParentPosition();
 
         // Build the polygon with the actual position and orientation:
         std::vector<VECTOR2I> poly;
diff --git a/common/eda_text.cpp b/common/eda_text.cpp
index 7deb338040..094d474e00 100644
--- a/common/eda_text.cpp
+++ b/common/eda_text.cpp
@@ -627,7 +627,7 @@ bool EDA_TEXT::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy
     if( aContains )
         return rect.Contains( GetTextBox() );
 
-    return rect.Intersects( GetTextBox(), GetTextAngle().AsTenthsOfADegree() );
+    return rect.Intersects( GetTextBox(), GetTextAngle() );
 }
 
 
diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp
index 3ad227f009..5ce20b6953 100644
--- a/common/plotters/GERBER_plotter.cpp
+++ b/common/plotters/GERBER_plotter.cpp
@@ -871,16 +871,16 @@ void GERBER_PLOTTER::plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAn
                               const EDA_ANGLE& aEndAngle, int aRadius, bool aPlotInRegion )
 {
     VECTOR2I start, end;
-    start.x = aCenter.x + KiROUND( aRadius * cos( aStartAngle.AsRadians() ) );
-    start.y = aCenter.y - KiROUND( aRadius * sin( aStartAngle.AsRadians() ) );
+    start.x = aCenter.x + KiROUND( aRadius * aStartAngle.Cos() );
+    start.y = aCenter.y - KiROUND( aRadius * aStartAngle.Sin() );
 
     if( !aPlotInRegion )
         MoveTo( start );
     else
         LineTo( start );
 
-    end.x = aCenter.x + KiROUND( aRadius * cos( aEndAngle.AsRadians() ) );
-    end.y = aCenter.y - KiROUND( aRadius * sin( aEndAngle.AsRadians() ) );
+    end.x = aCenter.x + KiROUND( aRadius * aEndAngle.Cos() );
+    end.y = aCenter.y - KiROUND( aRadius * aEndAngle.Sin() );
     DPOINT devEnd = userToDeviceCoordinates( end );
     DPOINT devCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start );
 
@@ -1589,8 +1589,8 @@ void GERBER_PLOTTER::plotRoundRectAsRegion( const VECTOR2I& aRectCenter, const V
     // small difference, mainly for rotated pads.
     // calculate last point (end of last arc):
     VECTOR2I last_pt;
-    last_pt.x = arc_last_center.x + KiROUND( aCornerRadius * cos( arc_last_angle.AsRadians() ) );
-    last_pt.y = arc_last_center.y - KiROUND( aCornerRadius * sin( arc_last_angle.AsRadians() ) );
+    last_pt.x = arc_last_center.x + KiROUND( aCornerRadius * arc_last_angle.Cos() );
+    last_pt.y = arc_last_center.y - KiROUND( aCornerRadius * arc_last_angle.Sin() );
 
     VECTOR2I first_pt = rr_outline[0].m_start;
 
diff --git a/common/plotters/HPGL_plotter.cpp b/common/plotters/HPGL_plotter.cpp
index 2a77466170..db7e82b4af 100644
--- a/common/plotters/HPGL_plotter.cpp
+++ b/common/plotters/HPGL_plotter.cpp
@@ -593,8 +593,8 @@ void HPGL_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
     angle.Normalize180();
 
     // Calculate arc start point:
-    VECTOR2I cmap( aCenter.x + KiROUND( aRadius * cos( aStartAngle.AsRadians() ) ),
-                   aCenter.y - KiROUND( aRadius * sin( aStartAngle.AsRadians() ) ) );
+    VECTOR2I cmap( aCenter.x + KiROUND( aRadius * aStartAngle.Cos() ),
+                   aCenter.y - KiROUND( aRadius * aStartAngle.Sin() ) );
     VECTOR2D cmap_dev = userToDeviceCoordinates( cmap );
 
     startOrAppendItem( cmap_dev, wxString::Format( "AA %.0f,%.0f,%.0f,%g",
diff --git a/common/plotters/PDF_plotter.cpp b/common/plotters/PDF_plotter.cpp
index 83834e967a..da026c67eb 100644
--- a/common/plotters/PDF_plotter.cpp
+++ b/common/plotters/PDF_plotter.cpp
@@ -288,21 +288,21 @@ void PDF_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
     SetCurrentLineWidth( aWidth );
 
     // Usual trig arc plotting routine...
-    start.x = aCenter.x + KiROUND( aRadius * cos( -startAngle.AsRadians() ) );
-    start.y = aCenter.y + KiROUND( aRadius * sin( -startAngle.AsRadians() ) );
+    start.x = aCenter.x + KiROUND( aRadius * -startAngle.Cos() );
+    start.y = aCenter.y + KiROUND( aRadius * -startAngle.Sin() );
     DPOINT pos_dev = userToDeviceCoordinates( start );
     fprintf( workFile, "%g %g m ", pos_dev.x, pos_dev.y );
 
     for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta )
     {
-        end.x = aCenter.x + KiROUND( aRadius * cos( -ii.AsRadians() ) );
-        end.y = aCenter.y + KiROUND( aRadius * sin( -ii.AsRadians() ) );
+        end.x = aCenter.x + KiROUND( aRadius * -ii.Cos() );
+        end.y = aCenter.y + KiROUND( aRadius * -ii.Sin() );
         pos_dev = userToDeviceCoordinates( end );
         fprintf( workFile, "%g %g l ", pos_dev.x, pos_dev.y );
     }
 
-    end.x = aCenter.x + KiROUND( aRadius * cos( -endAngle.AsRadians() ) );
-    end.y = aCenter.y + KiROUND( aRadius * sin( -endAngle.AsRadians() ) );
+    end.x = aCenter.x + KiROUND( aRadius * -endAngle.Cos() );
+    end.y = aCenter.y + KiROUND( aRadius * -endAngle.Sin() );
     pos_dev = userToDeviceCoordinates( end );
     fprintf( workFile, "%g %g l ", pos_dev.x, pos_dev.y );
 
diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp
index 6b6043fcf2..9e4c81060e 100644
--- a/common/plotters/plotter.cpp
+++ b/common/plotters/plotter.cpp
@@ -168,8 +168,8 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
     SetCurrentLineWidth( aWidth );
 
     /* Please NOTE the different sign due to Y-axis flip */
-    start.x = aCenter.x + KiROUND( aRadius * cos( -startAngle.AsRadians() ) );
-    start.y = aCenter.y + KiROUND( aRadius * sin( -startAngle.AsRadians() ) );
+    start.x = aCenter.x + KiROUND( aRadius * -startAngle.Cos() );
+    start.y = aCenter.y + KiROUND( aRadius * -startAngle.Sin() );
 
     if( aFill != FILL_T::NO_FILL )
     {
@@ -183,13 +183,13 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
 
     for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta )
     {
-        end.x = aCenter.x + KiROUND( aRadius * cos( -ii.AsRadians() ) );
-        end.y = aCenter.y + KiROUND( aRadius * sin( -ii.AsRadians() ) );
+        end.x = aCenter.x + KiROUND( aRadius * -ii.Cos() );
+        end.y = aCenter.y + KiROUND( aRadius * -ii.Sin() );
         LineTo( end );
     }
 
-    end.x = aCenter.x + KiROUND( aRadius * cos( -endAngle.AsRadians() ) );
-    end.y = aCenter.y + KiROUND( aRadius * sin( -endAngle.AsRadians() ) );
+    end.x = aCenter.x + KiROUND( aRadius * -endAngle.Cos() );
+    end.y = aCenter.y + KiROUND( aRadius * -endAngle.Sin() );
 
     if( aFill != FILL_T::NO_FILL )
     {
diff --git a/common/plugins/cadstar/cadstar_archive_parser.cpp b/common/plugins/cadstar/cadstar_archive_parser.cpp
index a9f0806a36..908909aa7a 100644
--- a/common/plugins/cadstar/cadstar_archive_parser.cpp
+++ b/common/plugins/cadstar/cadstar_archive_parser.cpp
@@ -2618,9 +2618,8 @@ void CADSTAR_ARCHIVE_PARSER::FixTextPositionNoAlignment( EDA_TEXT* aKiCadTextIte
 {
     if( !aKiCadTextItem->GetText().IsEmpty() )
     {
-        int     txtAngleDecideg = aKiCadTextItem->GetTextAngle().AsTenthsOfADegree();
         VECTOR2I positionOffset( 0, aKiCadTextItem->GetInterline() );
-        RotatePoint( positionOffset, txtAngleDecideg );
+        RotatePoint( positionOffset, aKiCadTextItem->GetTextAngle() );
 
         EDA_ITEM* textEdaItem = dynamic_cast<EDA_ITEM*>( aKiCadTextItem );
 
diff --git a/common/stroke_params.cpp b/common/stroke_params.cpp
index 208fab7a79..d57b265c2a 100644
--- a/common/stroke_params.cpp
+++ b/common/stroke_params.cpp
@@ -152,10 +152,8 @@ void STROKE_PARAMS::Stroke( const SHAPE* aShape, PLOT_DASH_TYPE aLineStyle, int
 
             if( i % 2 == 0 )
             {
-                VECTOR2I a( center.x + r * cos( startAngle.AsRadians() ),
-                            center.y + r * sin( startAngle.AsRadians() ) );
-                VECTOR2I b( center.x + r * cos( endAngle.AsRadians() ),
-                            center.y + r * sin( endAngle.AsRadians() ) );
+                VECTOR2I a( center.x + r * startAngle.Cos(), center.y + r * startAngle.Sin() );
+                VECTOR2I b( center.x + r * endAngle.Cos(),   center.y + r * endAngle.Sin() );
 
                 aStroker( a, b );
             }
diff --git a/eeschema/lib_field.cpp b/eeschema/lib_field.cpp
index ef650796bc..8fb0861d7e 100644
--- a/eeschema/lib_field.cpp
+++ b/eeschema/lib_field.cpp
@@ -285,7 +285,7 @@ void LIB_FIELD::MirrorVertical( const VECTOR2I& center )
 
 void LIB_FIELD::Rotate( const VECTOR2I& center, bool aRotateCCW )
 {
-    int rot_angle = aRotateCCW ? -900 : 900;
+    EDA_ANGLE rot_angle = aRotateCCW ? -ANGLE_90 : ANGLE_90;
 
     VECTOR2I pt = GetTextPos();
     RotatePoint( pt, center, rot_angle );
diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp
index a6f32687c6..d0413c4d4f 100644
--- a/eeschema/lib_pin.cpp
+++ b/eeschema/lib_pin.cpp
@@ -1004,7 +1004,7 @@ void LIB_PIN::MirrorVertical( const VECTOR2I& aCenter )
 
 void LIB_PIN::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
 {
-    int rot_angle = aRotateCCW ? -900 : 900;
+    EDA_ANGLE rot_angle = aRotateCCW ? -ANGLE_90 : ANGLE_90;
 
     RotatePoint( m_position, aCenter, rot_angle );
 
@@ -1162,13 +1162,13 @@ const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly )
     {
     case PIN_UP:
         // Pin is rotated and texts positions are mirrored
-        RotatePoint( begin, VECTOR2I( 0, 0 ), -900 );
-        RotatePoint( end, VECTOR2I( 0, 0 ), -900 );
+        RotatePoint( begin, VECTOR2I( 0, 0 ), -ANGLE_90 );
+        RotatePoint( end, VECTOR2I( 0, 0 ), -ANGLE_90 );
         break;
 
     case PIN_DOWN:
-        RotatePoint( begin, VECTOR2I( 0, 0 ), 900 );
-        RotatePoint( end, VECTOR2I( 0, 0 ), 900 );
+        RotatePoint( begin, VECTOR2I( 0, 0 ), ANGLE_90 );
+        RotatePoint( end, VECTOR2I( 0, 0 ), ANGLE_90 );
         begin.x = -begin.x;
         end.x = -end.x;
         break;
diff --git a/eeschema/lib_shape.cpp b/eeschema/lib_shape.cpp
index 0a16b044d6..eda5d81f9a 100644
--- a/eeschema/lib_shape.cpp
+++ b/eeschema/lib_shape.cpp
@@ -102,7 +102,7 @@ void LIB_SHAPE::MirrorVertical( const VECTOR2I& aCenter )
 
 void LIB_SHAPE::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
 {
-    int rot_angle = aRotateCCW ? -900 : 900;
+    EDA_ANGLE rot_angle = aRotateCCW ? -ANGLE_90 : ANGLE_90;
 
     rotate( aCenter, rot_angle );
 }
diff --git a/eeschema/lib_shape.h b/eeschema/lib_shape.h
index c6d3dcd728..ca3d8d10ad 100644
--- a/eeschema/lib_shape.h
+++ b/eeschema/lib_shape.h
@@ -120,7 +120,7 @@ private:
     void print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset, void* aData,
                 const TRANSFORM& aTransform ) override;
 
-    double getParentOrientation() const override { return 0.0; }
+    EDA_ANGLE getParentOrientation() const override { return ANGLE_0; }
     VECTOR2I getParentPosition() const override { return VECTOR2I(); }
 };
 
diff --git a/eeschema/lib_text.h b/eeschema/lib_text.h
index 7e96685e21..98544db295 100644
--- a/eeschema/lib_text.h
+++ b/eeschema/lib_text.h
@@ -74,7 +74,7 @@ public:
         if( aContained )
             return rect.Contains( textBox );
 
-        return rect.Intersects( textBox, GetTextAngle().AsTenthsOfADegree() );
+        return rect.Intersects( textBox, GetTextAngle() );
     }
 
     int GetPenWidth() const override;
diff --git a/eeschema/sch_bitmap.cpp b/eeschema/sch_bitmap.cpp
index 713dcafa2a..af222ed370 100644
--- a/eeschema/sch_bitmap.cpp
+++ b/eeschema/sch_bitmap.cpp
@@ -144,7 +144,7 @@ void SCH_BITMAP::MirrorHorizontally( int aCenter )
 
 void SCH_BITMAP::Rotate( const VECTOR2I& aCenter )
 {
-    RotatePoint( m_pos, aCenter, 900 );
+    RotatePoint( m_pos, aCenter, ANGLE_90 );
     m_image->Rotate( false );
 }
 
diff --git a/eeschema/sch_bus_entry.cpp b/eeschema/sch_bus_entry.cpp
index 6f39d7d464..e0e0720e06 100644
--- a/eeschema/sch_bus_entry.cpp
+++ b/eeschema/sch_bus_entry.cpp
@@ -308,7 +308,7 @@ void SCH_BUS_ENTRY_BASE::MirrorHorizontally( int aCenter )
 void SCH_BUS_ENTRY_BASE::Rotate( const VECTOR2I& aCenter )
 {
     RotatePoint( m_pos, aCenter, 900 );
-    RotatePoint( &m_size.x, &m_size.y, 900 );
+    RotatePoint( &m_size.x, &m_size.y, ANGLE_90 );
 }
 
 
diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp
index cf08ee1b3d..4f555199ee 100644
--- a/eeschema/sch_field.cpp
+++ b/eeschema/sch_field.cpp
@@ -686,7 +686,7 @@ bool SCH_FIELD::Replace( const wxFindReplaceData& aSearchData, void* aAuxData )
 void SCH_FIELD::Rotate( const VECTOR2I& aCenter )
 {
     VECTOR2I pt = GetPosition();
-    RotatePoint( pt, aCenter, 900 );
+    RotatePoint( pt, aCenter, ANGLE_90 );
     SetPosition( pt );
 }
 
diff --git a/eeschema/sch_junction.cpp b/eeschema/sch_junction.cpp
index 7d3a9dd9e2..4d278ff5de 100644
--- a/eeschema/sch_junction.cpp
+++ b/eeschema/sch_junction.cpp
@@ -145,7 +145,7 @@ void SCH_JUNCTION::MirrorHorizontally( int aCenter )
 
 void SCH_JUNCTION::Rotate( const VECTOR2I& aCenter )
 {
-    RotatePoint( m_pos, aCenter, 900 );
+    RotatePoint( m_pos, aCenter, ANGLE_90 );
 }
 
 
diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp
index 93efe869a4..947d85ce77 100644
--- a/eeschema/sch_line.cpp
+++ b/eeschema/sch_line.cpp
@@ -418,22 +418,22 @@ void SCH_LINE::MirrorHorizontally( int aCenter )
 void SCH_LINE::Rotate( const VECTOR2I& aCenter )
 {
     if( m_flags & STARTPOINT )
-        RotatePoint( m_start, aCenter, 900 );
+        RotatePoint( m_start, aCenter, ANGLE_90 );
 
     if( m_flags & ENDPOINT )
-        RotatePoint( m_end, aCenter, 900 );
+        RotatePoint( m_end, aCenter, ANGLE_90 );
 }
 
 
 void SCH_LINE::RotateStart( const VECTOR2I& aCenter )
 {
-    RotatePoint( m_start, aCenter, 900 );
+    RotatePoint( m_start, aCenter, ANGLE_90 );
 }
 
 
 void SCH_LINE::RotateEnd( const VECTOR2I& aCenter )
 {
-    RotatePoint( m_end, aCenter, 900 );
+    RotatePoint( m_end, aCenter, ANGLE_90 );
 }
 
 
diff --git a/eeschema/sch_no_connect.cpp b/eeschema/sch_no_connect.cpp
index 0fb62979b8..5f311a002f 100644
--- a/eeschema/sch_no_connect.cpp
+++ b/eeschema/sch_no_connect.cpp
@@ -129,7 +129,7 @@ void SCH_NO_CONNECT::MirrorHorizontally( int aCenter )
 
 void SCH_NO_CONNECT::Rotate( const VECTOR2I& aCenter )
 {
-    RotatePoint( m_pos, aCenter, 900 );
+    RotatePoint( m_pos, aCenter, ANGLE_90 );
 }
 
 
diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp
index cf89bbf5dd..f62fcb395a 100644
--- a/eeschema/sch_painter.cpp
+++ b/eeschema/sch_painter.cpp
@@ -501,7 +501,7 @@ void SCH_PAINTER::boxText( const wxString& aText, const VECTOR2D& aPosition,
     box.Inflate( 0, aAttrs.m_StrokeWidth * 1.5 );
 
     box.Normalize();       // Make h and v sizes always >= 0
-    box = box.GetBoundingBoxRotated( (VECTOR2I) aPosition, aAttrs.m_Angle.AsTenthsOfADegree() );
+    box = box.GetBoundingBoxRotated( (VECTOR2I) aPosition, aAttrs.m_Angle );
     box.RevertYAxis();
 
     m_gal->SetIsFill( true );
diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
index 487e77b27f..f7e3df97ef 100644
--- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
+++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
@@ -1321,8 +1321,8 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aPropertie
             SCH_SHAPE* arc = new SCH_SHAPE( SHAPE_T::ARC, SCH_LAYER_ID::LAYER_NOTES );
             EDA_ANGLE  includedAngle( elem.endAngle - elem.startAngle, DEGREES_T );
             EDA_ANGLE  startAngle( elem.endAngle, DEGREES_T );
-            VECTOR2I   startOffset( KiROUND( elem.radius * cos( startAngle.AsRadians() ) ),
-                                   -KiROUND( elem.radius * sin( startAngle.AsRadians() ) ) );
+            VECTOR2I   startOffset( KiROUND( elem.radius * startAngle.Cos() ),
+                                   -KiROUND( elem.radius * startAngle.Sin() ) );
 
             arc->SetCenter( elem.center + m_sheetOffset );
             arc->SetStart( elem.center + startOffset + m_sheetOffset );
diff --git a/eeschema/sch_shape.cpp b/eeschema/sch_shape.cpp
index 3f90ee1304..f87282ed23 100644
--- a/eeschema/sch_shape.cpp
+++ b/eeschema/sch_shape.cpp
@@ -83,7 +83,7 @@ void SCH_SHAPE::MirrorVertically( int aCenter )
 
 void SCH_SHAPE::Rotate( const VECTOR2I& aCenter )
 {
-    rotate( aCenter, 900 );
+    rotate( aCenter, ANGLE_90 );
 }
 
 
diff --git a/eeschema/sch_shape.h b/eeschema/sch_shape.h
index ba99c025ff..72b2bf4528 100644
--- a/eeschema/sch_shape.h
+++ b/eeschema/sch_shape.h
@@ -111,7 +111,7 @@ public:
 private:
     void Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset ) override;
 
-    double getParentOrientation() const override { return 0.0; }
+    EDA_ANGLE getParentOrientation() const override { return ANGLE_0; }
     VECTOR2I getParentPosition() const override { return VECTOR2I(); }
 };
 
diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp
index c037a84759..cd64a902f6 100644
--- a/eeschema/sch_sheet.cpp
+++ b/eeschema/sch_sheet.cpp
@@ -774,8 +774,8 @@ void SCH_SHEET::Rotate( const VECTOR2I& aCenter )
 {
     VECTOR2I prev = m_pos;
 
-    RotatePoint( m_pos, aCenter, 900 );
-    RotatePoint( &m_size.x, &m_size.y, 900 );
+    RotatePoint( m_pos, aCenter, ANGLE_90 );
+    RotatePoint( &m_size.x, &m_size.y, ANGLE_90 );
 
     if( m_size.x < 0 )
     {
diff --git a/eeschema/sch_sheet_pin.cpp b/eeschema/sch_sheet_pin.cpp
index 0e367fe9f9..698d2212de 100644
--- a/eeschema/sch_sheet_pin.cpp
+++ b/eeschema/sch_sheet_pin.cpp
@@ -252,7 +252,7 @@ void SCH_SHEET_PIN::Rotate( const VECTOR2I& aCenter )
     VECTOR2I pt = GetTextPos();
     VECTOR2I delta = pt - aCenter;
 
-    RotatePoint( pt, aCenter, 900 );
+    RotatePoint( pt, aCenter, ANGLE_90 );
 
     SHEET_SIDE oldSide = GetSide();
     ConstrainOnEdge( pt );
diff --git a/eeschema/sch_symbol.cpp b/eeschema/sch_symbol.cpp
index ffbff1aa50..48c21a5c07 100644
--- a/eeschema/sch_symbol.cpp
+++ b/eeschema/sch_symbol.cpp
@@ -1488,7 +1488,7 @@ void SCH_SYMBOL::Rotate( const VECTOR2I& aCenter )
 {
     VECTOR2I prev = m_pos;
 
-    RotatePoint( m_pos, aCenter, 900 );
+    RotatePoint( m_pos, aCenter, ANGLE_90 );
 
     SetOrientation( SYM_ROTATE_COUNTERCLOCKWISE );
 
diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp
index aa7b51961c..9f5973f7e9 100644
--- a/eeschema/sch_text.cpp
+++ b/eeschema/sch_text.cpp
@@ -269,7 +269,7 @@ void SCH_TEXT::MirrorVertically( int aCenter )
 void SCH_TEXT::Rotate( const VECTOR2I& aCenter )
 {
     VECTOR2I pt = GetTextPos();
-    RotatePoint( pt, aCenter, 900 );
+    RotatePoint( pt, aCenter, ANGLE_90 );
     VECTOR2I offset = pt - GetTextPos();
 
     Rotate90( false );
@@ -746,7 +746,7 @@ VECTOR2I SCH_LABEL_BASE::GetSchematicTextOffset( const RENDER_SETTINGS* aSetting
 void SCH_LABEL_BASE::Rotate( const VECTOR2I& aCenter )
 {
     VECTOR2I pt = GetTextPos();
-    RotatePoint( pt, aCenter, 900 );
+    RotatePoint( pt, aCenter, ANGLE_90 );
     VECTOR2I offset = pt - GetTextPos();
 
     Rotate90( false );
@@ -804,7 +804,7 @@ void SCH_LABEL_BASE::Rotate90( bool aClockwise )
             }
 
             VECTOR2I pos = field.GetTextPos();
-            RotatePoint( pos, GetPosition(), aClockwise ? -900 : 900 );
+            RotatePoint( pos, GetPosition(), aClockwise ? -ANGLE_90 : ANGLE_90 );
             field.SetTextPos( pos );
         }
     }
diff --git a/eeschema/transform.cpp b/eeschema/transform.cpp
index f8dcf49434..7237ea5695 100644
--- a/eeschema/transform.cpp
+++ b/eeschema/transform.cpp
@@ -95,13 +95,13 @@ bool TRANSFORM::MapAngles( EDA_ANGLE* aAngle1, EDA_ANGLE* aAngle2 ) const
         *aAngle2 += epsilon;
     }
 
-    x = cos( aAngle1->AsRadians() );
-    y = sin( aAngle1->AsRadians() );
+    x = aAngle1->Cos();
+    y = aAngle1->Sin();
     v = VECTOR2D( x * x1 + y * y1, x * x2 + y * y2 );
     *aAngle1 = EDA_ANGLE( v );
 
-    x = cos( aAngle2->AsRadians() );
-    y = sin( aAngle2->AsRadians() );
+    x = aAngle2->Cos();
+    y = aAngle2->Sin();
     v = VECTOR2D( x * x1 + y * y1, x * x2 + y * y2 );
     *aAngle2 = EDA_ANGLE( v );
 
diff --git a/include/drawing_sheet/ds_data_item.h b/include/drawing_sheet/ds_data_item.h
index 05bc0e5cbb..47c13e1a3c 100644
--- a/include/drawing_sheet/ds_data_item.h
+++ b/include/drawing_sheet/ds_data_item.h
@@ -269,7 +269,7 @@ public:
     /**
      * @return the coordinate (in mm) of the corner \a aIdx and the repeated item \a aRepeat
      */
-    const DPOINT GetCornerPosition( unsigned aIdx, int aRepeat = 0 ) const;
+    const VECTOR2D GetCornerPosition( unsigned aIdx, int aRepeat = 0 ) const;
 
     /**
      * @return the coordinate (in draw/plot units) of the corner \a aIdx and the repeated
@@ -284,13 +284,13 @@ public:
 
     bool IsInsidePage( int ii ) const override;
 
-    double                m_Orient;         // Orientation in degrees
-    std::vector<DPOINT>   m_Corners;        // corner list
+    EDA_ANGLE             m_Orient;         // Orientation
+    std::vector<VECTOR2D> m_Corners;        // corner list
 
 private:
     std::vector<unsigned> m_polyIndexEnd;   // index of the last point of each polygon
-    DPOINT                m_minCoord;       // min coord of corners, relative to m_Pos
-    DPOINT                m_maxCoord;       // max coord of corners, relative to m_Pos
+    VECTOR2D              m_minCoord;       // min coord of corners, relative to m_Pos
+    VECTOR2D              m_maxCoord;       // max coord of corners, relative to m_Pos
 };
 
 
diff --git a/include/eda_rect.h b/include/eda_rect.h
index efe14a9b56..d9033927d8 100644
--- a/include/eda_rect.h
+++ b/include/eda_rect.h
@@ -31,6 +31,7 @@
 
 #include <wx/gdicmn.h>
 #include <math/box2.h>
+#include <geometry/eda_angle.h>
 
 /**
  * Handle the component boundary box.
@@ -228,9 +229,9 @@ public:
      * Tests for a common area between this rectangle, and a rectangle with arbitrary rotation
      *
      * @param aRect a rectangle to test intersection with.
-     * @param aRot rectangle rotation (in 1/10 degrees).
+     * @param aRot rectangle rotation.
      */
-    bool Intersects( const EDA_RECT& aRect, double aRot ) const;
+    bool Intersects( const EDA_RECT& aRect, const EDA_ANGLE& aRotation ) const;
 
     /**
      * Test for a common area between a segment and this rectangle.
@@ -349,13 +350,12 @@ public:
     EDA_RECT Common( const EDA_RECT& aRect ) const;
 
     /**
-     * Useful to calculate bounding box of rotated items, when rotation if not k*90 degrees.
+     * Useful to calculate bounding box of rotated items, when rotation is not k*90 degrees.
      *
-     * @param aAngle the rotation angle in 0.1 deg.
-     * @param aRotCenter the rotation point.
      * @return the bounding box of this, after rotation.
      */
-    const EDA_RECT GetBoundingBoxRotated( const VECTOR2I& aRotCenter, double aAngle ) const;
+    const EDA_RECT GetBoundingBoxRotated( const VECTOR2I& aRotCenter,
+                                          const EDA_ANGLE& aAngle ) const;
 
 private:
     VECTOR2I m_pos;      // Rectangle Origin
diff --git a/include/eda_shape.h b/include/eda_shape.h
index bf0f1f7b38..45477780f9 100644
--- a/include/eda_shape.h
+++ b/include/eda_shape.h
@@ -275,12 +275,12 @@ protected:
     VECTOR2I getPosition() const;
 
     void move( const VECTOR2I& aMoveVector );
-    void rotate( const VECTOR2I& aRotCentre, double aAngle );
+    void rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle );
     void flip( const VECTOR2I& aCentre, bool aFlipLeftRight );
     void scale( double aScale );
 
     // To be implemented by concrete classes
-    virtual double getParentOrientation() const = 0;
+    virtual EDA_ANGLE getParentOrientation() const = 0;
     virtual VECTOR2I getParentPosition() const = 0;
 
     const EDA_RECT getBoundingBox() const;
diff --git a/libs/kimath/include/convert_basic_shapes_to_polygon.h b/libs/kimath/include/convert_basic_shapes_to_polygon.h
index 36a041461b..5d6e050239 100644
--- a/libs/kimath/include/convert_basic_shapes_to_polygon.h
+++ b/libs/kimath/include/convert_basic_shapes_to_polygon.h
@@ -128,8 +128,8 @@ void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aSta
  * @param aErrorLoc determines if the approximation error be placed outside or inside the polygon.
  */
 void TransformTrapezoidToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aPosition,
-                                  const VECTOR2I& aSize, double aRotation, int aDeltaX, int aDeltaY,
-                                  int aInflate, int aError, ERROR_LOC aErrorLoc );
+                                  const VECTOR2I& aSize, const EDA_ANGLE& aRotation, int aDeltaX,
+                                  int aDeltaY, int aInflate, int aError, ERROR_LOC aErrorLoc );
 
 /**
  * Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
diff --git a/libs/kimath/include/geometry/shape_arc.h b/libs/kimath/include/geometry/shape_arc.h
index 3bd294fe96..ec591a59a1 100644
--- a/libs/kimath/include/geometry/shape_arc.h
+++ b/libs/kimath/include/geometry/shape_arc.h
@@ -94,7 +94,7 @@ public:
      * @return this arc.
      */
     SHAPE_ARC& ConstructFromStartEndAngle( const VECTOR2I& aStart, const VECTOR2I& aEnd,
-                                           double aAngle, double aWidth = 0 );
+                                           const EDA_ANGLE& aAngle, double aWidth = 0 );
 
     /**
      * Constructs this arc from the given start, end and center.
diff --git a/libs/kimath/include/trigo.h b/libs/kimath/include/trigo.h
index a7d02cc2ad..404288e674 100644
--- a/libs/kimath/include/trigo.h
+++ b/libs/kimath/include/trigo.h
@@ -138,7 +138,8 @@ inline void RotatePoint( VECTOR2D& point, const VECTOR2D& aCenter, const EDA_ANG
  */
 const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd );
 const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd );
-const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd, double aAngle );
+const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd,
+                              const EDA_ANGLE& aAngle );
 
 /**
  * Return the subtended angle for a given arc.
diff --git a/libs/kimath/src/convert_basic_shapes_to_polygon.cpp b/libs/kimath/src/convert_basic_shapes_to_polygon.cpp
index 8cf077de4f..8049b895b0 100644
--- a/libs/kimath/src/convert_basic_shapes_to_polygon.cpp
+++ b/libs/kimath/src/convert_basic_shapes_to_polygon.cpp
@@ -362,8 +362,8 @@ void CornerListRemoveDuplicates( std::vector<ROUNDED_CORNER>& aCorners )
 
 
 void TransformTrapezoidToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aPosition,
-                                  const VECTOR2I& aSize, double aRotation, int aDeltaX, int aDeltaY,
-                                  int aInflate, int aError, ERROR_LOC aErrorLoc )
+                                  const VECTOR2I& aSize, const EDA_ANGLE& aRotation, int aDeltaX,
+                                  int aDeltaY, int aInflate, int aError, ERROR_LOC aErrorLoc )
 {
     SHAPE_POLY_SET              outline;
     VECTOR2I                    size( aSize / 2 );
@@ -426,8 +426,8 @@ void TransformTrapezoidToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I&
 
     CornerListToPolygon( outline, corners, aInflate, aError, aErrorLoc );
 
-    if( aRotation != 0.0 )
-        outline.Rotate( DECIDEG2RAD( -aRotation ), VECTOR2I( 0, 0 ) );
+    if( !aRotation.IsZero() )
+        outline.Rotate( -aRotation.AsRadians(), VECTOR2I( 0, 0 ) );
 
     outline.Move( VECTOR2I( aPosition ) );
     aCornerBuffer.Append( outline );
@@ -522,8 +522,8 @@ int ConvertArcToPolyline( SHAPE_LINE_CHAIN& aPolyline, VECTOR2I aCenter, int aRa
         EDA_ANGLE rot = aStartAngle;
         rot += ( aArcAngle * i ) / n;
 
-        double x = aCenter.x + aRadius * cos( rot.AsRadians() );
-        double y = aCenter.y + aRadius * sin( rot.AsRadians() );
+        double x = aCenter.x + aRadius * rot.Cos();
+        double y = aCenter.y + aRadius * rot.Sin();
 
         aPolyline.Append( KiROUND( x ), KiROUND( y ) );
     }
diff --git a/libs/kimath/src/geometry/direction_45.cpp b/libs/kimath/src/geometry/direction_45.cpp
index 5a73785c7c..97fd119886 100644
--- a/libs/kimath/src/geometry/direction_45.cpp
+++ b/libs/kimath/src/geometry/direction_45.cpp
@@ -143,7 +143,7 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con
             {
                 // Positive tangentLength, diagonal start: arc goes at the start
                 arcEndpoint = aP1 - mp0.Resize( tangentLength );
-                arc.ConstructFromStartEndAngle( aP0, arcEndpoint, 45 * rotationSign );
+                arc.ConstructFromStartEndAngle( aP0, arcEndpoint, ANGLE_45 * rotationSign );
 
                 if( arc.GetP0() == arc.GetP1() )
                     pl.Append( aP0 );
@@ -156,7 +156,7 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con
             {
                 // Negative tangentLength, diagonal start: arc goes at the end
                 arcEndpoint = aP0 + mp1.Resize( std::abs( tangentLength ) );
-                arc.ConstructFromStartEndAngle( arcEndpoint, aP1, 45 * rotationSign );
+                arc.ConstructFromStartEndAngle( arcEndpoint, aP1, ANGLE_45 * rotationSign );
 
                 pl.Append( aP0 );
 
@@ -175,7 +175,7 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con
             {
                 // Positive tangentLength: arc goes at the end
                 arcEndpoint = aP0 + mp0.Resize( tangentLength );
-                arc.ConstructFromStartEndAngle( arcEndpoint, aP1, 45 * rotationSign );
+                arc.ConstructFromStartEndAngle( arcEndpoint, aP1, ANGLE_45 * rotationSign );
 
                 pl.Append( aP0 );
 
@@ -198,12 +198,12 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con
                 if( std::abs( endpoint.y - aP1.y ) < SHAPE_ARC::MIN_PRECISION_IU )
                 {
                     VECTOR2I fixedEnd( endpoint.x, aP1.y );
-                    ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, 45 * rotationSign );
+                    ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, ANGLE_45 * rotationSign );
                 }
                 else if( std::abs( endpoint.x - aP1.x ) < SHAPE_ARC::MIN_PRECISION_IU )
                 {
                     VECTOR2I fixedEnd( aP1.x, endpoint.y );
-                    ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, 45 * rotationSign );
+                    ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, ANGLE_45 * rotationSign );
                 }
 
                 if( ca.GetP0() == ca.GetP1() )
diff --git a/libs/kimath/src/geometry/shape_arc.cpp b/libs/kimath/src/geometry/shape_arc.cpp
index 3ce74cadf2..45f20e086a 100644
--- a/libs/kimath/src/geometry/shape_arc.cpp
+++ b/libs/kimath/src/geometry/shape_arc.cpp
@@ -126,7 +126,7 @@ SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, i
         m_mid   = m_start;
 
         VECTOR2I arcCenter = aSegmentA.Center();
-        RotatePoint( m_mid, arcCenter, 900.0 ); // mid point at 90 degrees
+        RotatePoint( m_mid, arcCenter, ANGLE_90 ); // mid point at 90 degrees
     }
     else
     {
@@ -148,8 +148,8 @@ SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, i
         EDA_ANGLE angPC  = pToAangle - alpha / 2;
         VECTOR2I  arcCenter;
 
-        arcCenter.x = p.get().x + KiROUND( distPC * cos( angPC.AsRadians() ) );
-        arcCenter.y = p.get().y + KiROUND( distPC * sin( angPC.AsRadians() ) );
+        arcCenter.x = p.get().x + KiROUND( distPC * angPC.Cos() );
+        arcCenter.y = p.get().y + KiROUND( distPC * angPC.Sin() );
 
         // The end points of the arc are the orthogonal projected lines from the line segments
         // to the center of the arc
@@ -184,7 +184,7 @@ SHAPE_ARC::SHAPE_ARC( const SHAPE_ARC& aOther )
 
 
 SHAPE_ARC& SHAPE_ARC::ConstructFromStartEndAngle( const VECTOR2I& aStart, const VECTOR2I& aEnd,
-                                                  double aAngle, double aWidth )
+                                                  const EDA_ANGLE& aAngle, double aWidth )
 {
     m_start = aStart;
     m_mid   = aStart;
@@ -193,7 +193,7 @@ SHAPE_ARC& SHAPE_ARC::ConstructFromStartEndAngle( const VECTOR2I& aStart, const
 
     VECTOR2I center( CalcArcCenter( aStart, aEnd, aAngle ) );
 
-    RotatePoint( m_mid, center, -aAngle * 10.0 / 2.0 );
+    RotatePoint( m_mid, center, -aAngle / 2.0 );
 
     update_bbox();
 
@@ -498,8 +498,8 @@ const SHAPE_LINE_CHAIN SHAPE_ARC::ConvertToPolyline( double aAccuracy,
         if( n != 0 )
             a += ( ca * i ) / n;
 
-        double x = c.x + r * cos( a.AsRadians() );
-        double y = c.y + r * sin( a.AsRadians() );
+        double x = c.x + r * a.Cos();
+        double y = c.y + r * a.Sin();
 
         rv.Append( KiROUND( x ), KiROUND( y ) );
     }
diff --git a/libs/kimath/src/geometry/shape_line_chain.cpp b/libs/kimath/src/geometry/shape_line_chain.cpp
index d8715da107..dcfd2bdceb 100644
--- a/libs/kimath/src/geometry/shape_line_chain.cpp
+++ b/libs/kimath/src/geometry/shape_line_chain.cpp
@@ -423,14 +423,14 @@ bool SHAPE_LINE_CHAIN::Collide( const VECTOR2I& aP, int aClearance, int* aActual
 
 void SHAPE_LINE_CHAIN::Rotate( double aAngle, const VECTOR2I& aCenter )
 {
-    for( auto& pt : m_points )
+    for( VECTOR2I& pt : m_points )
     {
         pt -= aCenter;
         pt = pt.Rotate( aAngle );
         pt += aCenter;
     }
 
-    for( auto& arc : m_arcs )
+    for( SHAPE_ARC& arc : m_arcs )
         arc.Rotate( aAngle, aCenter );
 }
 
diff --git a/libs/kimath/src/trigo.cpp b/libs/kimath/src/trigo.cpp
index d7c4a536b6..9d9fb4296a 100644
--- a/libs/kimath/src/trigo.cpp
+++ b/libs/kimath/src/trigo.cpp
@@ -360,29 +360,31 @@ void RotatePoint( double* pX, double* pY, double angle )
 }
 
 
-const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd, double aAngle )
+const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd,
+                              const EDA_ANGLE& aAngle )
 {
-    VECTOR2I start = aStart;
-    VECTOR2I end = aEnd;
+    EDA_ANGLE angle( aAngle );
+    VECTOR2I  start = aStart;
+    VECTOR2I  end = aEnd;
 
-    if( aAngle < 0 )
+    if( angle < ANGLE_0 )
     {
         std::swap( start, end );
-        aAngle = abs( aAngle );
+        angle = -angle;
     }
 
-    if( aAngle > 180 )
+    if( angle > ANGLE_180 )
     {
         std::swap( start, end );
-        aAngle = 360 - aAngle;
+        angle = ANGLE_360 - angle;
     }
 
     int chord = ( start - end ).EuclideanNorm();
-    int r = ( chord / 2 ) / sin( aAngle * M_PI / 360.0 );
+    int r = ( chord / 2 ) / angle.Sin();
 
     VECTOR2I vec = end - start;
     vec = vec.Resize( r );
-    vec = vec.Rotate( ( 180.0 - aAngle ) * M_PI / 360.0 );
+    vec = vec.Rotate( ( ANGLE_180 - angle ).AsRadians() );
 
     return (VECTOR2I) ( start + vec );
 }
diff --git a/pagelayout_editor/dialogs/properties_frame.cpp b/pagelayout_editor/dialogs/properties_frame.cpp
index 9dc1104f66..7e563553b7 100644
--- a/pagelayout_editor/dialogs/properties_frame.cpp
+++ b/pagelayout_editor/dialogs/properties_frame.cpp
@@ -287,7 +287,7 @@ void PROPERTIES_FRAME::CopyPrmsFromItemToPanel( DS_DATA_ITEM* aItem )
         DS_DATA_ITEM_POLYGONS* item = static_cast<DS_DATA_ITEM_POLYGONS*>( aItem );
 
         // Rotation (poly and text)
-        msg.Printf( wxT("%.3f"), item->m_Orient );
+        msg.Printf( wxT("%.3f"), item->m_Orient.AsDegrees() );
         m_textCtrlRotation->SetValue( msg );
     }
 
@@ -507,7 +507,7 @@ bool PROPERTIES_FRAME::CopyPrmsFromPanelToItem( DS_DATA_ITEM* aItem )
         DS_DATA_ITEM_POLYGONS* item = static_cast<DS_DATA_ITEM_POLYGONS*>( aItem );
 
         msg = m_textCtrlRotation->GetValue();
-        item->m_Orient = DoubleValueFromString( EDA_UNITS::UNSCALED, msg );
+        item->m_Orient = EDA_ANGLE( DoubleValueFromString( EDA_UNITS::UNSCALED, msg ), DEGREES_T );
     }
 
     if( aItem->GetType() == DS_DATA_ITEM::DS_BITMAP )
diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp
index 42971662d9..afa31ed606 100644
--- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp
+++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp
@@ -59,9 +59,6 @@ private:
 
     bool                  m_flipStartEnd;
 
-    wxFloatingPointValidator<double>    m_AngleValidator;
-    double                m_AngleValue;
-
 public:
     DIALOG_GRAPHIC_ITEM_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, BOARD_ITEM* aItem );
     ~DIALOG_GRAPHIC_ITEM_PROPERTIES() {};
@@ -97,9 +94,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES::DIALOG_GRAPHIC_ITEM_PROPERTIES( PCB_BASE_EDIT_FR
     m_bezierCtrl1Y( aParent, m_BezierPointC1YLabel, m_BezierC1Y_Ctrl, m_BezierPointC1YUnit ),
     m_bezierCtrl2X( aParent, m_BezierPointC2XLabel, m_BezierC2X_Ctrl, m_BezierPointC2XUnit ),
     m_bezierCtrl2Y( aParent, m_BezierPointC2YLabel, m_BezierC2Y_Ctrl, m_BezierPointC2YUnit ),
-    m_flipStartEnd( false ),
-    m_AngleValidator( 1, &m_AngleValue ),
-    m_AngleValue( 0.0 )
+    m_flipStartEnd( false )
 {
     m_parent = aParent;
     m_item = dynamic_cast<PCB_SHAPE*>( aItem );
@@ -116,9 +111,6 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES::DIALOG_GRAPHIC_ITEM_PROPERTIES( PCB_BASE_EDIT_FR
     m_bezierCtrl2Y.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
 
     m_angle.SetUnits( EDA_UNITS::DEGREES );
-    m_AngleValidator.SetRange( -360.0, 360.0 );
-    m_angleCtrl->SetValidator( m_AngleValidator );
-    m_AngleValidator.SetWindow( m_angleCtrl );
 
     // Do not allow locking items in the footprint editor
     m_locked->Show( dynamic_cast<PCB_EDIT_FRAME*>( aParent ) != nullptr );
@@ -228,7 +220,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataToWindow()
 
     case SHAPE_T::ARC:
         SetTitle( _( "Arc Properties" ) );
-        m_AngleValue = m_item->GetArcAngle().AsDegrees();
+        m_angle.SetAngleValue( m_item->GetArcAngle() );
         m_filledCtrl->Show( false );
         break;
 
@@ -365,7 +357,10 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow()
     }
 
     if( m_item->GetShape() == SHAPE_T::ARC )
-        m_item->SetCenter( CalcArcCenter( m_item->GetStart(), m_item->GetEnd(), m_AngleValue ) );
+    {
+        m_item->SetCenter( CalcArcCenter( m_item->GetStart(), m_item->GetEnd(),
+                                          m_angle.GetAngleValue() ) );
+    }
 
     if( m_fp_item )
     {
@@ -430,7 +425,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate()
     {
     case SHAPE_T::ARC:
         // Check angle of arc.
-        if( m_angle.GetValue() == 0 )
+        if( m_angle.GetAngleValue() == ANGLE_0 )
             error_msgs.Add( _( "The arc angle cannot be zero." ) );
 
         KI_FALLTHROUGH;
diff --git a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
index b5564ba787..9fa26d5941 100644
--- a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
@@ -119,7 +119,7 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
         m_endY.SetValue( m_shape->GetCenter().y );
         m_radiusLabel->SetLabel( _( "Angle:" ) );
         m_radius.SetUnits( EDA_UNITS::DEGREES );
-        m_radius.SetValue( m_shape->GetArcAngle().AsTenthsOfADegree() );
+        m_radius.SetAngleValue( m_shape->GetArcAngle() );
         m_ctrl1X.Show( false, true );
         m_ctrl1Y.Show( false, true );
         m_ctrl2X.Show( false, true );
diff --git a/pcbnew/fp_text.cpp b/pcbnew/fp_text.cpp
index 8ae0f0daf2..b0f47736aa 100644
--- a/pcbnew/fp_text.cpp
+++ b/pcbnew/fp_text.cpp
@@ -94,7 +94,7 @@ bool FP_TEXT::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy
     if( aContains )
         return rect.Contains( GetBoundingBox() );
     else
-        return rect.Intersects( GetTextBox(), GetDrawRotation().AsTenthsOfADegree() );
+        return rect.Intersects( GetTextBox(), GetDrawRotation() );
 }
 
 
@@ -218,10 +218,10 @@ void FP_TEXT::SetLocalCoord()
 
 const EDA_RECT FP_TEXT::GetBoundingBox() const
 {
-    double   angle = GetDrawRotation().AsTenthsOfADegree();
-    EDA_RECT text_area = GetTextBox();
+    EDA_ANGLE angle = GetDrawRotation();
+    EDA_RECT  text_area = GetTextBox();
 
-    if( angle )
+    if( !angle.IsZero() )
         text_area = text_area.GetBoundingBoxRotated( GetTextPos(), angle );
 
     return text_area;
@@ -336,10 +336,10 @@ EDA_ITEM* FP_TEXT::Clone() const
 
 const BOX2I FP_TEXT::ViewBBox() const
 {
-    double   angle = GetDrawRotation().AsTenthsOfADegree();
-    EDA_RECT text_area = GetTextBox();
+    EDA_ANGLE angle = GetDrawRotation();
+    EDA_RECT  text_area = GetTextBox();
 
-    if( angle )
+    if( !angle.IsZero() )
         text_area = text_area.GetBoundingBoxRotated( GetTextPos(), angle );
 
     return BOX2I( text_area.GetPosition(), text_area.GetSize() );
diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp
index 49f3ce54a9..75bdd7f80d 100644
--- a/pcbnew/pad.cpp
+++ b/pcbnew/pad.cpp
@@ -1538,8 +1538,8 @@ void PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
         int  ddy = GetShape() == PAD_SHAPE::TRAPEZOID ? m_deltaSize.y / 2 : 0;
 
         SHAPE_POLY_SET outline;
-        TransformTrapezoidToPolygon( outline, padShapePos, m_size, m_orient.AsTenthsOfADegree(),
-                                     ddx, ddy, aClearanceValue, aError, aErrorLoc );
+        TransformTrapezoidToPolygon( outline, padShapePos, m_size, m_orient, ddx, ddy,
+                                     aClearanceValue, aError, aErrorLoc );
         aCornerBuffer.Append( outline );
         break;
     }
diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp
index 4dec609300..cce94917ba 100644
--- a/pcbnew/pcb_edit_frame.cpp
+++ b/pcbnew/pcb_edit_frame.cpp
@@ -1059,7 +1059,7 @@ void PCB_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     PCB_BASE_FRAME::SaveSettings( aCfg );
 
-    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
     wxASSERT( cfg );
 
     if( cfg )
diff --git a/pcbnew/pcb_shape.cpp b/pcbnew/pcb_shape.cpp
index f7ca3ed6f6..6dfeaddeaa 100644
--- a/pcbnew/pcb_shape.cpp
+++ b/pcbnew/pcb_shape.cpp
@@ -108,7 +108,7 @@ void PCB_SHAPE::Scale( double aScale )
 
 void PCB_SHAPE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
 {
-    rotate( aRotCentre, aAngle.AsTenthsOfADegree() );
+    rotate( aRotCentre, aAngle );
 }
 
 
@@ -129,12 +129,12 @@ FOOTPRINT* PCB_SHAPE::GetParentFootprint() const
 }
 
 
-double PCB_SHAPE::getParentOrientation() const
+EDA_ANGLE PCB_SHAPE::getParentOrientation() const
 {
     if( GetParentFootprint() )
-        return GetParentFootprint()->GetOrientation().AsTenthsOfADegree();
+        return GetParentFootprint()->GetOrientation();
     else
-        return 0.0;
+        return ANGLE_0;
 }
 
 
diff --git a/pcbnew/pcb_shape.h b/pcbnew/pcb_shape.h
index 6be1fbe24a..1519733983 100644
--- a/pcbnew/pcb_shape.h
+++ b/pcbnew/pcb_shape.h
@@ -160,7 +160,7 @@ public:
 #endif
 
 protected:
-    double getParentOrientation() const override;
+    EDA_ANGLE getParentOrientation() const override;
     VECTOR2I getParentPosition() const override;
 };
 
diff --git a/pcbnew/pcb_text.cpp b/pcbnew/pcb_text.cpp
index bf1085242d..80a560d1b9 100644
--- a/pcbnew/pcb_text.cpp
+++ b/pcbnew/pcb_text.cpp
@@ -130,7 +130,7 @@ const EDA_RECT PCB_TEXT::GetBoundingBox() const
     EDA_RECT rect = GetTextBox();
 
     if( !GetTextAngle().IsZero() )
-        rect = rect.GetBoundingBoxRotated( GetTextPos(), GetTextAngle().AsTenthsOfADegree() );
+        rect = rect.GetBoundingBoxRotated( GetTextPos(), GetTextAngle() );
 
     return rect;
 }
diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp
index ab5b487c60..7d92a8451b 100644
--- a/pcbnew/plugins/altium/altium_pcb.cpp
+++ b/pcbnew/plugins/altium/altium_pcb.cpp
@@ -1929,8 +1929,8 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
                 EDA_ANGLE includedAngle( elem.endangle - elem.startangle, DEGREES_T );
                 EDA_ANGLE startAngle( elem.endangle, DEGREES_T );
 
-                VECTOR2I startOffset( KiROUND( elem.radius * cos( startAngle.AsRadians() ) ),
-                                     -KiROUND( elem.radius * sin( startAngle.AsRadians() ) ) );
+                VECTOR2I startOffset( KiROUND( elem.radius * startAngle.Cos() ),
+                                     -KiROUND( elem.radius * startAngle.Sin() ) );
 
                 shape.SetCenter( elem.center );
                 shape.SetStart( elem.center + startOffset );
diff --git a/pcbnew/plugins/pcad/pcb_arc.cpp b/pcbnew/plugins/pcad/pcb_arc.cpp
index 3d44e6ee58..ff9f278f19 100644
--- a/pcbnew/plugins/pcad/pcb_arc.cpp
+++ b/pcbnew/plugins/pcad/pcb_arc.cpp
@@ -147,8 +147,8 @@ void PCB_ARC::Parse( XNODE* aNode, int aLayer, const wxString& aDefaultUnits,
         if( lNode )
             m_Angle = EDA_ANGLE( StrToInt1Units( lNode->GetNodeContent() ), TENTHS_OF_A_DEGREE_T );
 
-        m_StartX = m_positionX + KiROUND( r * cos( a.AsRadians() ) );
-        m_StartY = m_positionY - KiROUND( r * sin( a.AsRadians() ) );
+        m_StartX = m_positionX + KiROUND( r * a.Cos() );
+        m_StartY = m_positionY - KiROUND( r * a.Sin() );
     }
 }
 
diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp
index f5fbc2e3d4..604c6801e8 100644
--- a/pcbnew/router/pns_kicad_iface.cpp
+++ b/pcbnew/router/pns_kicad_iface.cpp
@@ -930,7 +930,7 @@ std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
     solid->SetNet( aPad->GetNetCode() );
     solid->SetParent( aPad );
     solid->SetPadToDie( aPad->GetPadToDieLength() );
-    solid->SetOrientation( aPad->GetOrientation().AsTenthsOfADegree() );
+    solid->SetOrientation( aPad->GetOrientation() );
 
     VECTOR2I wx_c = aPad->ShapePos();
     VECTOR2I offset = aPad->GetOffset();
diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp
index a2ed9cda44..4929fcea9f 100644
--- a/pcbnew/router/pns_line_placer.cpp
+++ b/pcbnew/router/pns_line_placer.cpp
@@ -1146,7 +1146,7 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
     else if( aStartItem && aStartItem->Kind() == ITEM::SOLID_T &&
              static_cast<SOLID*>( aStartItem )->Parent()->Type() == PCB_PAD_T )
     {
-        double angle = static_cast<SOLID*>( aStartItem )->GetOrientation() / 10.0;
+        double angle = static_cast<SOLID*>( aStartItem )->GetOrientation().AsDegrees();
         angle        = ( angle + 22.5 ) / 45.0;
         initialDir   = DIRECTION_45( static_cast<DIRECTION_45::Directions>( int( angle ) ) );
     }
diff --git a/pcbnew/router/pns_solid.h b/pcbnew/router/pns_solid.h
index 8c3647bdf3..3ea0e4fa40 100644
--- a/pcbnew/router/pns_solid.h
+++ b/pcbnew/router/pns_solid.h
@@ -42,7 +42,6 @@ public:
     {
         m_movable = false;
         m_padToDie = 0;
-        m_orientation = 0;
     }
 
     ~SOLID()
@@ -117,8 +116,8 @@ public:
     VECTOR2I Offset() const { return m_offset; }
     void SetOffset( const VECTOR2I& aOffset ) { m_offset = aOffset; }
 
-    double GetOrientation() const { return m_orientation; }
-    void SetOrientation( double aOrientation ) { m_orientation = aOrientation; }
+    EDA_ANGLE GetOrientation() const { return m_orientation; }
+    void SetOrientation( const EDA_ANGLE& aOrientation ) { m_orientation = aOrientation; }
 
 private:
     VECTOR2I    m_pos;
@@ -126,7 +125,7 @@ private:
     SHAPE*      m_hole;
     VECTOR2I    m_offset;
     int         m_padToDie;
-    double      m_orientation;  // in 1/10 degrees, matching PAD
+    EDA_ANGLE   m_orientation;
 };
 
 }
diff --git a/pcbnew/zone.cpp b/pcbnew/zone.cpp
index 00b488e351..5c8606f40b 100644
--- a/pcbnew/zone.cpp
+++ b/pcbnew/zone.cpp
@@ -697,11 +697,11 @@ void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
         for( SEG& seg : pair.second )
         {
             VECTOR2I a( seg.A );
-            RotatePoint( a, aCentre, -aAngle.AsRadians() );
+            RotatePoint( a, aCentre, -aAngle );
             seg.A = a;
 
             VECTOR2I b( seg.B );
-            RotatePoint( b, aCentre, -aAngle.AsRadians() );
+            RotatePoint( b, aCentre, -aAngle );
             seg.B = a;
         }
     }