From b11e315d10099121986373a3aebb7b9c00862332 Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@craftyjon.com>
Date: Tue, 8 Sep 2020 23:17:08 -0400
Subject: [PATCH] Refactor DIMENSION to hide internal details; add some new
 properties

This is a board file format change to account for the new properties.
Also, we now only store the critical information about the dimension's
geometry in the board, rather than storing every drawn line.

The DIMENSION object is now an abstract base, and ALIGNED_DIMENSION
is the implementation that exists today (we will add more dimension
types in the future)
---
 .../3d_canvas/create_3Dgraphic_brd_items.cpp  |  21 +-
 common/pcb.keywords                           |  16 +
 include/board_design_settings.h               |   2 +-
 pcbnew/board_design_settings.cpp              |   2 +-
 pcbnew/class_dimension.cpp                    | 558 +++++++++---------
 pcbnew/class_dimension.h                      | 420 ++++++++-----
 .../dialogs/dialog_dimension_properties.cpp   |  64 +-
 .../dialog_dimension_properties_base.cpp      |   2 +-
 .../dialog_dimension_properties_base.fbp      |   2 +-
 pcbnew/dialogs/dialog_text_properties.cpp     | 115 +---
 pcbnew/dialogs/dialog_text_properties.h       |   2 -
 .../dialogs/dialog_text_properties_base.cpp   |  29 -
 .../dialogs/dialog_text_properties_base.fbp   | 270 ---------
 pcbnew/dialogs/dialog_text_properties_base.h  |   9 +-
 .../dialogs/panel_setup_text_and_graphics.cpp |   2 +
 .../panel_setup_text_and_graphics_base.cpp    |   4 +-
 .../panel_setup_text_and_graphics_base.fbp    |   4 +-
 pcbnew/eagle_plugin.cpp                       |  19 +-
 pcbnew/kicad_plugin.cpp                       |  79 ++-
 pcbnew/kicad_plugin.h                         |   7 +-
 pcbnew/legacy_plugin.cpp                      |  61 +-
 pcbnew/pcb_painter.cpp                        |  15 +-
 pcbnew/pcb_parser.cpp                         | 210 ++++++-
 pcbnew/plot_brditems_plotter.cpp              |  35 +-
 pcbnew/plugins/altium/altium_pcb.cpp          |  19 +-
 .../cadstar/cadstar_pcb_archive_loader.cpp    |  12 +-
 pcbnew/tools/drawing_tool.cpp                 |  43 +-
 pcbnew/tools/grid_helper.cpp                  |  10 +-
 pcbnew/tools/point_editor.cpp                 |  94 ++-
 29 files changed, 983 insertions(+), 1143 deletions(-)

diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
index 72f48e81ec..0ebbe541a2 100644
--- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
+++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
@@ -136,24 +136,15 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const DIMENSION* aDimensio
 {
     AddShapeWithClearanceToContainer(&aDimension->Text(), aDstContainer, aLayerId, aClearanceValue);
 
-    const int linewidth = aDimension->GetWidth() + (2 * aClearanceValue);
+    const int linewidth = aDimension->GetLineThickness() + (2 * aClearanceValue);
 
-    std::pair<wxPoint const *, wxPoint const *> segs[] = {
-        {&aDimension->m_crossBarO,     &aDimension->m_crossBarF},
-        {&aDimension->m_featureLineGO, &aDimension->m_featureLineGF},
-        {&aDimension->m_featureLineDO, &aDimension->m_featureLineDF},
-        {&aDimension->m_crossBarF,     &aDimension->m_arrowD1F},
-        {&aDimension->m_crossBarF,     &aDimension->m_arrowD2F},
-        {&aDimension->m_crossBarO,     &aDimension->m_arrowG1F},
-        {&aDimension->m_crossBarO,     &aDimension->m_arrowG2F}};
-
-    for( auto const & ii : segs )
+    for( const SEG& seg : aDimension->GetLines() )
     {
-        const SFVEC2F start3DU(  ii.first->x * m_biuTo3Dunits,
-                                -ii.first->y * m_biuTo3Dunits );
+        const SFVEC2F start3DU(  seg.A.x * m_biuTo3Dunits,
+                                -seg.A.y * m_biuTo3Dunits );
 
-        const SFVEC2F end3DU  (  ii.second->x * m_biuTo3Dunits,
-                                -ii.second->y * m_biuTo3Dunits );
+        const SFVEC2F end3DU  (  seg.B.x * m_biuTo3Dunits,
+                                -seg.B.y * m_biuTo3Dunits );
 
         aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
                                                  end3DU,
diff --git a/common/pcb.keywords b/common/pcb.keywords
index bd598fe394..eb62d34e02 100644
--- a/common/pcb.keywords
+++ b/common/pcb.keywords
@@ -26,6 +26,7 @@
 
 add_net
 addsublayer
+aligned
 allowed
 anchor
 angle
@@ -36,6 +37,7 @@ arrow1a
 arrow1b
 arrow2a
 arrow2b
+arrow_length
 at
 attr
 autoplace_cost90
@@ -93,6 +95,8 @@ end
 epsilon_r
 exclude_from_pos_files
 exclude_from_bom
+extension_height
+extension_offset
 fab_layers_line_width
 fab_layers_text_dims
 feature1
@@ -103,6 +107,7 @@ filled_polygon
 filled_areas_thickness
 fillet
 font
+format
 footprints
 fp_arc
 fp_circle
@@ -130,6 +135,7 @@ hatch_smoothing_level
 hatch_smoothing_value
 hatch_border_algorithm
 hatch_min_hole_area
+height
 hide
 hole_to_hole_min
 id
@@ -146,6 +152,7 @@ last_trace_width
 layer
 layers
 left
+linear
 links
 locked
 loss_tangent
@@ -178,6 +185,7 @@ options
 other_layers_line_width
 other_layers_text_dims
 oval
+override_value
 pad
 pads
 pad_drill
@@ -203,6 +211,8 @@ placed
 plus
 polygon
 portrait
+precision
+prefix
 primitives
 priority
 pts
@@ -233,11 +243,15 @@ solder_paste_ratio
 stackup
 start
 status
+style
+suffix
+suppress_zeroes
 tags
 target
 title
 title_block
 tedit
+text_position_mode
 thermal_width
 thermal_gap
 thermal_bridge_width
@@ -257,6 +271,8 @@ thru_hole
 thru_hole_only
 tstamp
 type
+units
+units_format
 unlocked
 user
 user_diff_pair
diff --git a/include/board_design_settings.h b/include/board_design_settings.h
index bc6fe280b3..7f04c05623 100644
--- a/include/board_design_settings.h
+++ b/include/board_design_settings.h
@@ -270,7 +270,7 @@ public:
     bool       m_TextUpright[ LAYER_CLASS_COUNT ];
 
     int        m_DimensionUnits;
-    int        m_DimensionPrecision;
+    int        m_DimensionPrecision;    ///< Number of digits after the decimal
 
     // Miscellaneous
     wxPoint    m_AuxOrigin;                 ///< origin for plot exports
diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp
index 9500d67d19..133ef9f852 100644
--- a/pcbnew/board_design_settings.cpp
+++ b/pcbnew/board_design_settings.cpp
@@ -119,7 +119,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
     m_TextUpright[ LAYER_CLASS_OTHERS ] = false;
 
     m_DimensionUnits = 0;       // Inches
-    m_DimensionPrecision = 1;   // 0.001mm / 0.1 mil
+    m_DimensionPrecision = 4;
 
     m_useCustomTrackVia = false;
     m_customTrackWidth  = Millimeter2iu( DEFAULT_CUSTOMTRACKWIDTH );
diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp
index 4ab192a1d8..fd4fd5db5d 100644
--- a/pcbnew/class_dimension.cpp
+++ b/pcbnew/class_dimension.cpp
@@ -38,78 +38,112 @@
 
 DIMENSION::DIMENSION( BOARD_ITEM* aParent )
         : BOARD_ITEM( aParent, PCB_DIMENSION_T ),
-          m_Width( Millimeter2iu( 0.2 ) ),
-          m_Unit( EDA_UNITS::INCHES ),
-          m_UseMils( false ),
-          m_Value( 0 ),
-          m_Height( 0 ),
-          m_Text( this )
+          m_units( EDA_UNITS::INCHES ),
+          m_useMils( false ),
+          m_autoUnits( false ),
+          m_unitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX ),
+          m_precision( 4 ),
+          m_suppressZeroes( false ),
+          m_lineThickness( Millimeter2iu( 0.2 ) ),
+          m_arrowLength( Mils2iu( 50 ) ),
+          m_extensionOffset( 0 ),
+          m_textPosition( DIM_TEXT_POSITION::OUTSIDE ),
+          m_keepTextAligned( true ),
+          m_text( this ),
+          m_measuredValue( 0 )
 {
     m_Layer = Dwgs_User;
-    m_Shape = 0;
-}
-
-
-DIMENSION::~DIMENSION()
-{
 }
 
 
 void DIMENSION::SetPosition( const wxPoint& aPos )
 {
-    m_Text.SetTextPos( aPos );
+    m_text.SetTextPos( aPos );
 }
 
 
 wxPoint DIMENSION::GetPosition() const
 {
-    return m_Text.GetTextPos();
+    return m_text.GetTextPos();
+}
+
+
+DIM_UNITS_MODE DIMENSION::GetUnitsMode() const
+{
+    if( m_autoUnits )
+        return DIM_UNITS_MODE::AUTOMATIC;
+    else if( m_units == EDA_UNITS::MILLIMETRES )
+        return DIM_UNITS_MODE::MILLIMETRES;
+    else if( m_useMils )
+        return DIM_UNITS_MODE::MILS;
+    else
+        return DIM_UNITS_MODE::INCHES;
+}
+
+
+void DIMENSION::SetUnitsMode( DIM_UNITS_MODE aMode )
+{
+    m_units     = EDA_UNITS::INCHES;
+    m_autoUnits = false;
+    m_useMils   = false;
+
+    switch( aMode )
+    {
+    case DIM_UNITS_MODE::INCHES:
+        break;
+
+    case DIM_UNITS_MODE::MILS:
+        m_useMils = true;
+        break;
+
+    case DIM_UNITS_MODE::MILLIMETRES:
+        m_units = EDA_UNITS::MILLIMETRES;
+        break;
+
+    case DIM_UNITS_MODE::AUTOMATIC:
+        m_autoUnits = true;
+        break;
+    }
 }
 
 
 void DIMENSION::SetText( const wxString& aNewText )
 {
-    m_Text.SetText( aNewText );
+    m_text.SetText( aNewText );
 }
 
 
 const wxString DIMENSION::GetText() const
 {
-    return m_Text.GetText();
+    return m_text.GetText();
 }
 
 
 void DIMENSION::SetLayer( PCB_LAYER_ID aLayer )
 {
     m_Layer = aLayer;
-    m_Text.SetLayer( aLayer );
+    m_text.SetLayer( aLayer );
 }
 
 
 void DIMENSION::Move( const wxPoint& offset )
 {
-    m_Text.Offset( offset );
+    m_text.Offset( offset );
 
-    m_crossBarO     += offset;
-    m_crossBarF     += offset;
-    m_featureLineGO += offset;
-    m_featureLineGF += offset;
-    m_featureLineDO += offset;
-    m_featureLineDF += offset;
-    m_arrowG1F  += offset;
-    m_arrowG2F  += offset;
-    m_arrowD1F  += offset;
-    m_arrowD2F  += offset;
+    m_start += offset;
+    m_end   += offset;
+
+    updateGeometry();
 }
 
 
 void DIMENSION::Rotate( const wxPoint& aRotCentre, double aAngle )
 {
-    wxPoint tmp = m_Text.GetTextPos();
+    wxPoint tmp = m_text.GetTextPos();
     RotatePoint( &tmp, aRotCentre, aAngle );
-    m_Text.SetTextPos( tmp );
+    m_text.SetTextPos( tmp );
 
-    double newAngle = m_Text.GetTextAngle() + aAngle;
+    double newAngle = m_text.GetTextAngle() + aAngle;
 
     if( newAngle >= 3600 )
         newAngle -= 3600;
@@ -117,18 +151,12 @@ void DIMENSION::Rotate( const wxPoint& aRotCentre, double aAngle )
     if( newAngle > 900  &&  newAngle < 2700 )
         newAngle -= 1800;
 
-    m_Text.SetTextAngle( newAngle );
+    m_text.SetTextAngle( newAngle );
 
-    RotatePoint( &m_crossBarO, aRotCentre, aAngle );
-    RotatePoint( &m_crossBarF, aRotCentre, aAngle );
-    RotatePoint( &m_featureLineGO, aRotCentre, aAngle );
-    RotatePoint( &m_featureLineGF, aRotCentre, aAngle );
-    RotatePoint( &m_featureLineDO, aRotCentre, aAngle );
-    RotatePoint( &m_featureLineDF, aRotCentre, aAngle );
-    RotatePoint( &m_arrowG1F, aRotCentre, aAngle );
-    RotatePoint( &m_arrowG2F, aRotCentre, aAngle );
-    RotatePoint( &m_arrowD1F, aRotCentre, aAngle );
-    RotatePoint( &m_arrowD2F, aRotCentre, aAngle );
+    RotatePoint( &m_start, aRotCentre, aAngle );
+    RotatePoint( &m_end, aRotCentre, aAngle );
+
+    updateGeometry();
 }
 
 
@@ -145,247 +173,70 @@ void DIMENSION::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
 void DIMENSION::Mirror( const wxPoint& axis_pos, bool aMirrorLeftRight )
 {
     int axis = aMirrorLeftRight ? axis_pos.x : axis_pos.y;
-    wxPoint newPos = m_Text.GetTextPos();
+    wxPoint newPos = m_text.GetTextPos();
 
-#define INVERT( pos ) (pos) = axis - ( (pos) - axis )
+#define INVERT( pos ) ( ( pos ) = axis - ( ( pos ) - axis ) )
 
     if( aMirrorLeftRight )
         INVERT( newPos.x );
     else
         INVERT( newPos.y );
 
-    m_Text.SetTextPos( newPos );
+    m_text.SetTextPos( newPos );
 
     // invert angle
-    m_Text.SetTextAngle( -m_Text.GetTextAngle() );
+    m_text.SetTextAngle( -m_text.GetTextAngle() );
 
     if( aMirrorLeftRight )
     {
-        INVERT( m_crossBarO.y );
-        INVERT( m_crossBarF.y );
-        INVERT( m_featureLineGO.y );
-        INVERT( m_featureLineGF.y );
-        INVERT( m_featureLineDO.y );
-        INVERT( m_featureLineDF.y );
-        INVERT( m_arrowG1F.y );
-        INVERT( m_arrowG2F.y );
-        INVERT( m_arrowD1F.y );
-        INVERT( m_arrowD2F.y );
+        INVERT( m_start.x );
+        INVERT( m_end.x );
     }
     else
     {
-        INVERT( m_crossBarO.y );
-        INVERT( m_crossBarF.y );
-        INVERT( m_featureLineGO.y );
-        INVERT( m_featureLineGF.y );
-        INVERT( m_featureLineDO.y );
-        INVERT( m_featureLineDF.y );
-        INVERT( m_arrowG1F.y );
-        INVERT( m_arrowG2F.y );
-        INVERT( m_arrowD1F.y );
-        INVERT( m_arrowD2F.y );
-    }
-}
-
-
-void DIMENSION::SetOrigin( const wxPoint& aOrigin, int aPrecision )
-{
-    m_featureLineGO = aOrigin;
-
-    AdjustDimensionDetails( aPrecision );
-}
-
-
-void DIMENSION::SetEnd( const wxPoint& aEnd, int aPrecision )
-{
-    m_featureLineDO = aEnd;
-
-    AdjustDimensionDetails( aPrecision );
-}
-
-
-void DIMENSION::SetHeight( int aHeight, int aPrecision )
-{
-    m_Height = aHeight;
-
-    AdjustDimensionDetails( aPrecision );
-}
-
-
-void DIMENSION::UpdateHeight()
-{
-    VECTOR2D featureLine( m_crossBarO - m_featureLineGO );
-    VECTOR2D crossBar( m_featureLineDO - m_featureLineGO );
-
-    if( featureLine.Cross( crossBar ) > 0 )
-        m_Height = -featureLine.EuclideanNorm();
-    else
-        m_Height = featureLine.EuclideanNorm();
-}
-
-
-void DIMENSION::AdjustDimensionDetails( int aPrecision )
-{
-    const int   arrowz = Mils2iu( 50 );             // size of arrows
-    int         ii;
-    int         measure, deltax, deltay;            // value of the measure on X and Y axes
-    int         arrow_up_X  = 0, arrow_up_Y = 0;    // coordinates of arrow line /
-    int         arrow_dw_X  = 0, arrow_dw_Y = 0;    // coordinates of arrow line '\'
-    int         hx, hy;                             // dimension line interval
-    double      angle, angle_f;
-
-    // Init layer :
-    m_Text.SetLayer( GetLayer() );
-
-    // calculate the size of the dimension (text + line above the text)
-    ii = m_Text.GetTextHeight() + m_Text.GetEffectiveTextPenWidth() + m_Width;
-
-    deltax  = m_featureLineDO.x - m_featureLineGO.x;
-    deltay  = m_featureLineDO.y - m_featureLineGO.y;
-
-    // Calculate dimension value
-    measure = KiROUND( hypot( deltax, deltay ) );
-
-    angle = atan2( (double)deltay, (double)deltax );
-
-    // Calculation of parameters X and Y dimensions of the arrows and lines.
-    hx = hy = ii;
-
-    // Taking into account the slope of the side lines.
-    if( measure )
-    {
-        hx  = abs( KiROUND( ( (double) deltay * hx ) / measure ) );
-        hy  = abs( KiROUND( ( (double) deltax * hy ) / measure ) );
-
-        if( m_featureLineGO.x > m_crossBarO.x )
-            hx = -hx;
-
-        if( m_featureLineGO.x == m_crossBarO.x )
-            hx = 0;
-
-        if( m_featureLineGO.y > m_crossBarO.y )
-            hy = -hy;
-
-        if( m_featureLineGO.y == m_crossBarO.y )
-            hy = 0;
-
-        angle_f     = angle + DEG2RAD( 27.5 );
-        arrow_up_X  = wxRound( arrowz * cos( angle_f ) );
-        arrow_up_Y  = wxRound( arrowz * sin( angle_f ) );
-        angle_f     = angle - DEG2RAD( 27.5 );
-        arrow_dw_X  = wxRound( arrowz * cos( angle_f ) );
-        arrow_dw_Y  = wxRound( arrowz * sin( angle_f ) );
+        INVERT( m_start.y );
+        INVERT( m_end.y );
     }
 
-    int dx = KiROUND( m_Height * cos( angle + M_PI / 2 ) );
-    int dy = KiROUND( m_Height * sin( angle + M_PI / 2 ) );
-    m_crossBarO.x   = m_featureLineGO.x + dx;
-    m_crossBarO.y   = m_featureLineGO.y + dy;
-    m_crossBarF.x   = m_featureLineDO.x + dx;
-    m_crossBarF.y   = m_featureLineDO.y + dy;
-
-    m_arrowG1F.x    = m_crossBarO.x + arrow_up_X;
-    m_arrowG1F.y    = m_crossBarO.y + arrow_up_Y;
-
-    m_arrowG2F.x    = m_crossBarO.x + arrow_dw_X;
-    m_arrowG2F.y    = m_crossBarO.y + arrow_dw_Y;
-
-    /* The right arrow is symmetrical to the left.
-     *  / = -\  and  \ = -/
-     */
-    m_arrowD1F.x    = m_crossBarF.x - arrow_dw_X;
-    m_arrowD1F.y    = m_crossBarF.y - arrow_dw_Y;
-
-    m_arrowD2F.x    = m_crossBarF.x - arrow_up_X;
-    m_arrowD2F.y    = m_crossBarF.y - arrow_up_Y;
-
-    // Length of feature lines
-    double radius = ( m_Height +
-                      ( std::copysign( 1.0, m_Height ) *
-                      arrowz * sin( DEG2RAD( 27.5 ) ) ) );
-
-    m_featureLineGF.x = m_featureLineGO.x - wxRound( radius * sin( angle ) );
-    m_featureLineGF.y = m_featureLineGO.y + wxRound( radius * cos( angle ) );
-
-    m_featureLineDF.x = m_featureLineDO.x - wxRound( radius * sin( angle ) );
-    m_featureLineDF.y = m_featureLineDO.y + wxRound( radius * cos( angle ) );
-
-    // Calculate the better text position and orientation:
-    radius = ( std::copysign( 1.0, m_Height ) * ii );
-
-    wxPoint textPos;
-    textPos.x  = ( m_crossBarF.x + m_crossBarO.x ) / 2;
-    textPos.y  = ( m_crossBarF.y + m_crossBarO.y ) / 2;
-
-    textPos.x -= KiROUND( radius * sin( angle ) );
-    textPos.y += KiROUND( radius * cos( angle ) );
-
-    m_Text.SetTextPos( textPos );
-
-    double newAngle = -RAD2DECIDEG( angle );
-
-    NORMALIZE_ANGLE_POS( newAngle );
-
-    if( newAngle > 900  &&  newAngle < 2700 )
-        newAngle -= 1800;
-
-    m_Text.SetTextAngle( newAngle );
-
-    m_Value = measure;
-
-    if( m_Unit == EDA_UNITS::MILLIMETRES )
-        aPrecision += 2;
-    else if( !m_UseMils )
-        aPrecision += 3;
-
-    wxString text;
-    wxString format = wxT( "%." ) + wxString::Format( "%i", aPrecision ) + wxT( "f" );
-
-    text.Printf( format, To_User_Unit( m_Unit, m_Value, m_UseMils ) );
-    text += " ";
-    text += GetAbbreviatedUnitsLabel( m_Unit, m_UseMils );
-
-    SetText( text );
+    updateGeometry();
+}
+
+
+void DIMENSION::SetStart( const wxPoint& aOrigin )
+{
+    m_start = aOrigin;
+    updateGeometry();
+}
+
+
+void DIMENSION::SetEnd( const wxPoint& aEnd )
+{
+    m_end = aEnd;
+    updateGeometry();
 }
 
 
-// see class_cotation.h
 void DIMENSION::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     // for now, display only the text within the DIMENSION using class TEXTE_PCB.
-    m_Text.GetMsgPanelInfo( aFrame, aList );
+    m_text.GetMsgPanelInfo( aFrame, aList );
 }
 
 
 bool DIMENSION::HitTest( const wxPoint& aPosition, int aAccuracy ) const
 {
-    if( m_Text.TextHitTest( aPosition ) )
+    if( m_text.TextHitTest( aPosition ) )
         return true;
 
-    int dist_max = aAccuracy + ( m_Width / 2 );
+    int dist_max = aAccuracy + ( m_lineThickness / 2 );
 
     // Locate SEGMENTS
 
-    if( TestSegmentHit( aPosition, m_crossBarO, m_crossBarF, dist_max ) )
-        return true;
-
-    if( TestSegmentHit( aPosition, m_featureLineGO, m_featureLineGF, dist_max ) )
-        return true;
-
-    if( TestSegmentHit( aPosition, m_featureLineDO, m_featureLineDF, dist_max ) )
-        return true;
-
-    if( TestSegmentHit( aPosition, m_crossBarF, m_arrowD1F, dist_max ) )
-        return true;
-
-    if( TestSegmentHit( aPosition, m_crossBarF, m_arrowD2F, dist_max ) )
-        return true;
-
-    if( TestSegmentHit( aPosition, m_crossBarO, m_arrowG1F, dist_max ) )
-        return true;
-
-    if( TestSegmentHit( aPosition, m_crossBarO, m_arrowG2F, dist_max ) )
-        return true;
+    for( const SEG& seg : GetLines() )
+    {
+        if( TestSegmentHit( aPosition, wxPoint( seg.A ), wxPoint( seg.B ), dist_max ) )
+            return true;
+    }
 
     return false;
 }
@@ -412,38 +263,23 @@ const EDA_RECT DIMENSION::GetBoundingBox() const
     EDA_RECT    bBox;
     int         xmin, xmax, ymin, ymax;
 
-    bBox    = m_Text.GetTextBox();
+    bBox    = m_text.GetTextBox();
     xmin    = bBox.GetX();
     xmax    = bBox.GetRight();
     ymin    = bBox.GetY();
     ymax    = bBox.GetBottom();
 
-    xmin    = std::min( xmin, m_crossBarO.x );
-    xmin    = std::min( xmin, m_crossBarF.x );
-    ymin    = std::min( ymin, m_crossBarO.y );
-    ymin    = std::min( ymin, m_crossBarF.y );
-    xmax    = std::max( xmax, m_crossBarO.x );
-    xmax    = std::max( xmax, m_crossBarF.x );
-    ymax    = std::max( ymax, m_crossBarO.y );
-    ymax    = std::max( ymax, m_crossBarF.y );
-
-    xmin    = std::min( xmin, m_featureLineGO.x );
-    xmin    = std::min( xmin, m_featureLineGF.x );
-    ymin    = std::min( ymin, m_featureLineGO.y );
-    ymin    = std::min( ymin, m_featureLineGF.y );
-    xmax    = std::max( xmax, m_featureLineGO.x );
-    xmax    = std::max( xmax, m_featureLineGF.x );
-    ymax    = std::max( ymax, m_featureLineGO.y );
-    ymax    = std::max( ymax, m_featureLineGF.y );
-
-    xmin    = std::min( xmin, m_featureLineDO.x );
-    xmin    = std::min( xmin, m_featureLineDF.x );
-    ymin    = std::min( ymin, m_featureLineDO.y );
-    ymin    = std::min( ymin, m_featureLineDF.y );
-    xmax    = std::max( xmax, m_featureLineDO.x );
-    xmax    = std::max( xmax, m_featureLineDF.x );
-    ymax    = std::max( ymax, m_featureLineDO.y );
-    ymax    = std::max( ymax, m_featureLineDF.y );
+    for( const SEG& seg : GetLines() )
+    {
+        xmin = std::min( xmin, seg.A.x );
+        xmin = std::min( xmin, seg.B.x );
+        xmax = std::max( xmax, seg.A.x );
+        xmax = std::max( xmax, seg.B.x );
+        ymin = std::min( ymin, seg.A.y );
+        ymin = std::min( ymin, seg.B.y );
+        ymax = std::max( ymax, seg.A.y );
+        ymax = std::max( ymax, seg.B.y );
+    }
 
     bBox.SetX( xmin );
     bBox.SetY( ymin );
@@ -472,26 +308,12 @@ const BOX2I DIMENSION::ViewBBox() const
 {
     BOX2I dimBBox = BOX2I( VECTOR2I( GetBoundingBox().GetPosition() ),
                            VECTOR2I( GetBoundingBox().GetSize() ) );
-    dimBBox.Merge( m_Text.ViewBBox() );
+    dimBBox.Merge( m_text.ViewBBox() );
 
     return dimBBox;
 }
 
 
-EDA_ITEM* DIMENSION::Clone() const
-{
-    return new DIMENSION( *this );
-}
-
-
-void DIMENSION::SwapData( BOARD_ITEM* aImage )
-{
-    assert( aImage->Type() == PCB_DIMENSION_T );
-
-    std::swap( *((DIMENSION*) this), *((DIMENSION*) aImage) );
-}
-
-
 static struct DIMENSION_DESC
 {
     DIMENSION_DESC()
@@ -503,3 +325,155 @@ static struct DIMENSION_DESC
                     //&DIMENSION::SetHeight, &DIMENSION::GetHeight, PROPERTY_DISPLAY::DISTANCE ) );
     }
 } _DIMENSION_DESC;
+
+
+ALIGNED_DIMENSION::ALIGNED_DIMENSION( BOARD_ITEM* aParent ) :
+        DIMENSION( aParent ),
+        m_height( 0 )
+{
+    // To preserve look of old dimensions, initialize extension height based on default arrow length
+    m_extensionHeight = m_arrowLength * std::sin( DEG2RAD( s_arrowAngle ) );
+}
+
+
+EDA_ITEM* ALIGNED_DIMENSION::Clone() const
+{
+    return new ALIGNED_DIMENSION( *this );
+}
+
+
+void ALIGNED_DIMENSION::SwapData( BOARD_ITEM* aImage )
+{
+    assert( aImage->Type() == PCB_DIMENSION_T );
+
+    std::swap( *static_cast<ALIGNED_DIMENSION*>( this ), *static_cast<ALIGNED_DIMENSION*>( aImage ) );
+}
+
+
+void ALIGNED_DIMENSION::SetHeight( int aHeight )
+{
+    m_height = aHeight;
+    updateGeometry();
+}
+
+
+void ALIGNED_DIMENSION::UpdateHeight( const wxPoint& aCrossbarStart, const wxPoint& aCrossbarEnd )
+{
+    VECTOR2D height( aCrossbarStart - GetStart() );
+    VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
+
+    if( height.Cross( crossBar ) > 0 )
+        m_height = -height.EuclideanNorm();
+    else
+        m_height = height.EuclideanNorm();
+
+    updateGeometry();
+}
+
+
+void ALIGNED_DIMENSION::updateGeometry()
+{
+    m_lines.clear();
+
+    VECTOR2I dimension( m_end - m_start );
+
+    m_measuredValue = KiROUND( dimension.EuclideanNorm() );
+
+    VECTOR2I extension;
+
+    if( m_height > 0 )
+        extension = VECTOR2I( -dimension.y, dimension.x );
+    else
+        extension = VECTOR2I( dimension.y, -dimension.x );
+
+    // Add extension lines
+    int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
+
+    VECTOR2I extensionStart( m_start );
+    extensionStart += extension.Resize( m_extensionOffset );
+
+    m_lines.emplace_back( SEG( extensionStart,
+                               extensionStart + extension.Resize( extensionHeight ) ) );
+
+    extensionStart = VECTOR2I( m_end );
+    extensionStart += extension.Resize( m_extensionOffset );
+
+    m_lines.emplace_back( SEG( extensionStart,
+                               extensionStart + extension.Resize( extensionHeight ) ) );
+
+    // Add crossbar
+    VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
+    m_crossBarStart = m_start + wxPoint( crossBarDistance );
+    m_crossBarEnd   = m_end + wxPoint( crossBarDistance );
+
+    // Update text after calculating crossbar position but before adding crossbar lines
+    updateText();
+
+    // Now that we have the text updated, we can determine if the crossbar needs to be broken
+    if( m_textPosition == DIM_TEXT_POSITION::INLINE )
+    {
+
+    }
+
+    m_lines.emplace_back( SEG( m_crossBarStart, m_crossBarEnd ) );
+
+    // Add arrows
+    VECTOR2I arrowEnd( m_arrowLength, 0 );
+
+    double arrowRotPos = dimension.Angle() + DEG2RAD( s_arrowAngle );
+    double arrowRotNeg = dimension.Angle() - DEG2RAD( s_arrowAngle );
+
+    m_lines.emplace_back( SEG( m_crossBarStart,
+                               m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
+
+    m_lines.emplace_back( SEG( m_crossBarStart,
+                               m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
+
+    m_lines.emplace_back( SEG( m_crossBarEnd,
+                               m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
+
+    m_lines.emplace_back( SEG( m_crossBarEnd,
+                               m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
+}
+
+
+void ALIGNED_DIMENSION::updateText()
+{
+    VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
+
+    if( m_textPosition != DIM_TEXT_POSITION::MANUAL )
+    {
+        int textOffsetDistance = m_text.GetEffectiveTextPenWidth() + m_text.GetTextHeight();
+
+        double rotation = std::copysign( DEG2RAD( 90 ), m_height );
+        VECTOR2I textOffset = crossbarCenter.Rotate( rotation ).Resize( textOffsetDistance );
+        textOffset += crossbarCenter;
+
+        m_text.SetTextPos( m_crossBarStart + wxPoint( textOffset ) );
+    }
+
+    if( m_keepTextAligned )
+    {
+        double textAngle = 3600 - RAD2DECIDEG( crossbarCenter.Angle() );
+
+        NORMALIZE_ANGLE_POS( textAngle );
+
+        if( textAngle > 900 && textAngle < 2700 )
+            textAngle -= 1800;
+
+        m_text.SetTextAngle( textAngle );
+    }
+    else
+    {
+        m_text.SetTextAngle( 0 );
+    }
+
+    wxString text;
+    wxString format = wxT( "%." ) + wxString::Format( "%i", m_precision ) + wxT( "f" );
+
+    text.Printf( format, To_User_Unit( m_units, m_measuredValue, m_useMils ) );
+    text += " ";
+    text += GetAbbreviatedUnitsLabel( m_units, m_useMils );
+
+    SetText( text );
+}
diff --git a/pcbnew/class_dimension.h b/pcbnew/class_dimension.h
index 64384e7c24..99d6b2797e 100644
--- a/pcbnew/class_dimension.h
+++ b/pcbnew/class_dimension.h
@@ -40,48 +40,262 @@ class TEXTE_PCB;
 class MSG_PANEL_ITEM;
 
 
+/// How to display the units in a dimension's text
+enum class DIM_UNITS_FORMAT
+{
+    NO_SUFFIX,      // 1234.0
+    BARE_SUFFIX,    // 1234.0 mm
+    PAREN_SUFFIX    // 1234.0 (mm)
+};
+
+/// Where to place the text on a dimension
+enum class DIM_TEXT_POSITION
+{
+    OUTSIDE,    ///< Text appears outside the dimension line (default)
+    INLINE,     ///< Text appears in line with the dimension line
+    MANUAL      ///< Text placement is manually set by the user
+};
+
 /**
- * DIMENSION
+ * Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it
+ */
+enum class DIM_UNITS_MODE
+{
+    INCHES,
+    MILS,
+    MILLIMETRES,
+    AUTOMATIC
+};
+
+/**
+ * Abstract dimension API
  *
- * For better understanding of the points that make a dimension:
+ * Some notes about dimension nomenclature:
  *
- *            m_featureLineGO  m_featureLineDO
- *            |                              |
- *            |                              |
- *            |                              |
- *            |  m_arrowG2F      m_arrowD2F  |
- *            | /                          \ |
- * m_crossBarO|/____________________________\|m_crossBarF
- *            |\           m_Text           /|
- *            | \                          / |
- *            |  m_arrowG1F      m_arrowD1F  |
- *            |                              |
- *            m_featureLineGF  m_featureLineDF
+ * - "feature points" are the points being measured by the dimension.  For an example, the start
+ *   and end points of a line to be measured.  These are the first points picked when drawing a
+ *   new dimension.  Dimensions can have one or more feature points: linear dimensions (the only
+ *   type supported in KiCad 5 and earlier) have two feature points; leader dimensions have one;
+ *   and ordinate dimensions can have in theory an unlimited number of feature points.
+ *
+ * - "feature lines" are lines that coincide with feature points.  Not all dimension types have
+ *   feature lines.  The actual start and end of feature lines is calculated from dimension style
+ *   properties (offset from feature point to start of feature line, height of crossbar, and height
+ *   of feature line past crossbar, for example in linear dimensions)
+ *
+ * - "crossbar" refers to the perpendicular line (usually with arrows at each end) between feature
+ *   lines on linear dimensions
  */
 class DIMENSION : public BOARD_ITEM
 {
-    int         m_Width;        ///< Line width
-    int         m_Shape;        ///< Currently always 0.
-    EDA_UNITS   m_Unit;         ///< 0 = inches, 1 = mm
-    bool        m_UseMils;      ///< If inches, use mils.
-    int         m_Value;        ///< value of PCB dimensions.
-    int         m_Height;       ///< length of feature lines
-    TEXTE_PCB   m_Text;
+public:
+    DIMENSION( BOARD_ITEM* aParent );
+
+    /**
+     * The dimension's origin is the first feature point for the dimension.  Every dimension has
+     * one or more feature points, so every dimension has at least an origin.
+     * @return the origin point of this dimension
+     */
+    virtual const wxPoint& GetStart() const { return m_start; }
+    virtual void SetStart( const wxPoint& aPoint );
+
+    virtual const wxPoint& GetEnd() const { return m_end; }
+    virtual void SetEnd( const wxPoint& aPoint );
+
+    // These deal with the text position
+    wxPoint GetPosition() const override;
+    void SetPosition( const wxPoint& aPos ) override;
+
+    bool GetOverrideValue() const { return m_overrideValue; }
+    void SetOverrideValue( bool aOverride ) { m_overrideValue = aOverride; }
+
+    int GetMeasuredValue() const { return m_measuredValue; }
+
+    wxString GetDisplayedValue() const
+    {
+        return m_text.GetText();
+    }
+
+    wxString GetPrefix() const { return m_prefix; }
+    void SetPrefix( const wxString& aPrefix ) { m_prefix = aPrefix; }
+
+    wxString GetSuffix() const { return m_suffix; }
+    void SetSuffix( const wxString& aSuffix ) { m_suffix = aSuffix; }
+
+    void GetUnits( EDA_UNITS& aUnits, bool& aUseMils ) const
+    {
+        aUnits = m_units;
+        aUseMils = m_useMils;
+    }
+
+    void SetUnits( EDA_UNITS aUnits, bool aUseMils )
+    {
+        m_units = aUnits;
+        m_useMils = aUseMils;
+    }
+
+    DIM_UNITS_MODE GetUnitsMode() const;
+    void SetUnitsMode( DIM_UNITS_MODE aMode );
+
+    void SetAutoUnits( bool aAuto = true ) { m_autoUnits = aAuto; }
+
+    DIM_UNITS_FORMAT GetUnitsFormat() const { return m_unitsFormat; }
+    void SetUnitsFormat( const DIM_UNITS_FORMAT aFormat ) { m_unitsFormat = aFormat; }
+
+    int GetPrecision() const { return m_precision; }
+    void SetPrecision( int aPrecision ) { m_precision = aPrecision; }
+
+    bool GetSuppressZeroes() const { return m_suppressZeroes; }
+    void SetSuppressZeroes( bool aSuppress ) { m_suppressZeroes = aSuppress; }
+
+    bool GetKeepTextAligned() const { return m_keepTextAligned; }
+    void SetKeepTextAligned( bool aKeepAligned ) { m_keepTextAligned = aKeepAligned; }
+
+    void SetTextPositionMode( DIM_TEXT_POSITION aMode ) { m_textPosition = aMode; }
+    DIM_TEXT_POSITION GetTextPositionMode() const { return m_textPosition; }
+
+    int GetArrowLength() const { return m_arrowLength; }
+    void SetArrowLength( int aLength ) { m_arrowLength = aLength; }
+
+    void SetExtensionOffset( int aOffset ) { m_extensionOffset = aOffset; }
+    int GetExtensionOffset() const { return m_extensionOffset; }
+
+    int GetLineThickness() const        { return m_lineThickness; }
+    void SetLineThickness( int aWidth ) { m_lineThickness = aWidth; }
+
+    void SetLayer( PCB_LAYER_ID aLayer ) override;
+
+    void SetTextSize( const wxSize& aTextSize )
+    {
+        m_text.SetTextSize( aTextSize );
+    }
+
+    void           SetText( const wxString& aNewText );
+    const wxString GetText() const;
+
+    TEXTE_PCB&     Text() { return m_text; }
+    TEXTE_PCB&     Text() const { return *( const_cast<TEXTE_PCB*> ( &m_text ) ); }
+
+    /**
+     * @return a list of line segments that make up this dimension (for drawing, plotting, etc)
+     */
+    const std::vector<SEG>& GetLines() const { return m_lines; }
+
+    // BOARD_ITEM overrides
+
+    void Move( const wxPoint& offset ) override;
+    void Rotate( const wxPoint& aRotCentre, double aAngle ) override;
+    void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override;
+
+    /**
+     * Mirror the Dimension , relative to a given horizontal axis
+     * the text is not mirrored. only its position (and angle) is mirrored
+     * the layer is not changed
+     * @param axis_pos : vertical axis position
+     */
+    void Mirror( const wxPoint& axis_pos, bool aMirrorLeftRight = false );
+
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
+
+    bool HitTest( const wxPoint& aPosition, int aAccuracy ) const override;
+    bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
+
+    const EDA_RECT GetBoundingBox() const override;
+
+    wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
+
+    BITMAP_DEF GetMenuImage() const override;
+
+    virtual const BOX2I ViewBBox() const override;
+
+#if defined(DEBUG)
+    virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
+#endif
+
+protected:
+
+    /**
+     * Updates the cached geometry of the dimension after changing any of its properties
+     */
+    virtual void updateGeometry() = 0;
+
+    /**
+     * Updates the text field value from the current geometry (called by updateGeometry normally)
+     */
+    virtual void updateText() {}
+
+    // Value format
+    bool              m_overrideValue;   ///< Manually specify the displayed measurement value
+    wxString          m_prefix;          ///< String prepended to the value
+    wxString          m_suffix;          ///< String appended to the value
+    EDA_UNITS         m_units;           ///< 0 = inches, 1 = mm
+    bool              m_useMils;         ///< If inches, use mils.
+    bool              m_autoUnits;       ///< If true, follow the currently selected UI units
+    DIM_UNITS_FORMAT  m_unitsFormat;     ///< How to render the units suffix
+    int               m_precision;       ///< Number of digits to display after decimal
+    bool              m_suppressZeroes;  ///< Suppress trailing zeroes
+
+    // Geometry
+    int               m_lineThickness;    ///< Thickness used for all graphics in the dimension
+    int               m_arrowLength;      ///< Length of arrow shapes
+    int               m_extensionOffset;  ///< Distance from feature points to extension line start
+    DIM_TEXT_POSITION m_textPosition;     ///< How to position the text
+    bool              m_keepTextAligned;  ///< Calculate text orientation to match dimension
+
+    // Internal
+    TEXTE_PCB         m_text;             ///< The actual text object
+    int               m_measuredValue;    ///< value of PCB dimensions
+    wxPoint           m_start;
+    wxPoint           m_end;
+
+    std::vector<SEG>  m_lines;            ///< Internal cache of drawn lines
+};
+
+/**
+ * For better understanding of the points that make a dimension:
+ *
+ * Note: historically KiCad called extension lines "feature lines", and also note that what we
+ * call the "crossbar line" here is more commonly called the "dimension line"
+ *
+ *              Start (feature point 1)         End (feature point 2)
+ *                |                              |
+ *                |   <-- extension lines -->    |
+ *                |                              |
+ *                |  m_arrowG2F      m_arrowD2F  |
+ *                | /                          \ |
+ * Crossbar start |/_______crossbar line________\| Crossbar end
+ *                |\           m_text           /|
+ *                | \                          / |
+ *                |  m_arrowG1F      m_arrowD1F  |
+ *                |                              |
+ *                m_featureLineGF  m_featureLineDF
+ */
+
+/**
+ * An aligned dimension measures the distance between two feature points.  It has a crossbar
+ * (dimension line) that stays parallel with the vector between the feature points.
+ *
+ * The height (distance from features to crossbar) can be set directly, or set by manipulating the
+ * crossbar start or end point (with the point editor).
+ */
+class ALIGNED_DIMENSION : public DIMENSION
+{
+    // Geometry
+    int          m_height;           ///< Perpendicular distance from features to crossbar
+    int          m_extensionHeight;  ///< Length of extension lines past the crossbar
+
+    wxPoint      m_crossBarStart;    ///< Crossbar start control point
+    wxPoint      m_crossBarEnd;      ///< Crossbar end control point
+
+    static constexpr float s_arrowAngle = 27.5;
 
 public:
-// TODO private: These member should be private. they are public only due to legacy code
-    wxPoint     m_crossBarO, m_crossBarF;
-    wxPoint     m_featureLineGO, m_featureLineGF;
-    wxPoint     m_featureLineDO, m_featureLineDF;
-    wxPoint     m_arrowD1F, m_arrowD2F;
-    wxPoint     m_arrowG1F, m_arrowG2F;
-
-    DIMENSION( BOARD_ITEM* aParent );
+    ALIGNED_DIMENSION( BOARD_ITEM* aParent );
 
     // Do not create a copy constructor & operator=.
     // The ones generated by the compiler are adequate.
 
-    ~DIMENSION();
+    ~ALIGNED_DIMENSION() = default;
 
     static inline bool ClassOf( const EDA_ITEM* aItem )
     {
@@ -102,83 +316,29 @@ public:
         return false;
     }
 
-    void SetValue( int aValue ) { m_Value = aValue; }
+    EDA_ITEM* Clone() const override;
 
-    int GetValue() const { return m_Value; }
+    virtual void SwapData( BOARD_ITEM* aImage ) override;
 
-    wxPoint GetPosition() const override;
+    const wxPoint& GetCrossbarStart() const { return m_crossBarStart; }
 
-    void SetPosition( const wxPoint& aPos ) override;
-
-    void SetTextSize( const wxSize& aTextSize )
-    {
-        m_Text.SetTextSize( aTextSize );
-    }
-
-    void SetLayer( PCB_LAYER_ID aLayer ) override;
-
-    void SetShape( int aShape )         { m_Shape = aShape; }
-    int GetShape() const                { return m_Shape; }
-
-    int GetWidth() const                { return m_Width; }
-    void SetWidth( int aWidth )         { m_Width = aWidth; }
+    const wxPoint& GetCrossbarEnd() const { return m_crossBarEnd; }
 
     /**
-     * Function SetOrigin
-     * Sets a new origin of the crossbar line. All remaining lines are adjusted after that.
-     * @param aOrigin is the new point to be used as the new origin of the crossbar line.
-     * @param aPrecision number of decimal places for mils (scaled appropriately for other units).
-     */
-    void SetOrigin( const wxPoint& aOrigin, int aPrecision );
-
-    /**
-     * Function GetOrigin
-     * @return Origin of the crossbar line.
-     */
-    const wxPoint& GetOrigin() const
-    {
-        return m_featureLineGO;
-    }
-
-    /**
-     * Function SetEnd
-     * Sets a new end of the crossbar line. All remaining lines are adjusted after that.
-     * @param aEnd is the new point to be used as the new end of the crossbar line.
-     * @param aPrecision number of decimal places for mils (scaled appropriately for other units).
-     */
-    void SetEnd( const wxPoint& aEnd, int aPrecision );
-
-    /**
-     * Function GetEnd
-     * @return End of the crossbar line.
-     */
-    const wxPoint& GetEnd()
-    {
-        return m_featureLineDO;
-    }
-
-    /**
-     * Function SetHeight
-     * Sets the length of feature lines.
+     * Sets the distance from the feature points to the crossbar line
      * @param aHeight is the new height.
-     * @param aPrecision number of decimal places for mils (scaled appropriately for other units).
      */
-    void SetHeight( int aHeight, int aPrecision );
+    void SetHeight( int aHeight );
+    int GetHeight() const {  return m_height; }
 
     /**
-     * Function GetHeight
-     * Returns the length of feature lines.
-     */
-    int GetHeight() const
-    {
-        return m_Height;
-    }
-
-    /**
-     * Function UpdateHeight
      * Updates stored height basing on points coordinates.
+     * @param aCrossbarStart is the start point of the crossbar
      */
-    void UpdateHeight();
+    void UpdateHeight( const wxPoint& aCrossbarStart, const wxPoint& aCrossbarEnd );
+
+    void SetExtensionHeight( int aHeight ) { m_extensionHeight = aHeight; }
+    int GetExtensionHeight() const { return m_extensionHeight; }
 
     /**
      * Function GetAngle
@@ -187,79 +347,21 @@ public:
      */
     double GetAngle() const
     {
-        wxPoint delta( m_featureLineDO - m_featureLineGO );
+        wxPoint delta( m_end - m_start );
 
         return atan2( (double)delta.y, (double)delta.x );
     }
 
-    /**
-     * Function AdjustDimensionDetails
-     * Calculate coordinates of segments used to draw the dimension.
-     * @param aPrecision number of decimal places for mils (scaled appropriately for other units).
-     */
-    void AdjustDimensionDetails( int aPrecision );
-
-    void GetUnits( EDA_UNITS& aUnits, bool& aUseMils ) const
-    {
-        aUnits = m_Unit;
-        aUseMils = m_UseMils;
-    }
-
-    void SetUnits( EDA_UNITS aUnits, bool aUseMils )
-    {
-        m_Unit = aUnits;
-        m_UseMils = aUseMils;
-    }
-
-    void            SetText( const wxString& NewText );
-    const wxString  GetText() const;
-
-    TEXTE_PCB&      Text()  { return m_Text; }
-    TEXTE_PCB&      Text() const  { return *(const_cast<TEXTE_PCB*> (&m_Text)); }
-
-    /**
-     * Function Move
-     * @param offset : moving vector
-     */
-    void            Move( const wxPoint& offset ) override;
-    void            Rotate( const wxPoint& aRotCentre, double aAngle ) override;
-    void            Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override;
-
-    /**
-     * Function Mirror
-     * Mirror the Dimension , relative to a given horizontal axis
-     * the text is not mirrored. only its position (and angle) is mirrored
-     * the layer is not changed
-     * @param axis_pos : vertical axis position
-     */
-    void Mirror( const wxPoint& axis_pos, bool aMirrorLeftRight = false );
-
-    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
-
-    bool HitTest( const wxPoint& aPosition, int aAccuracy ) const override;
-    bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
-
     wxString GetClass() const override
     {
-        return wxT( "DIMENSION" );
+        return wxT( "ALIGNED_DIMENSION" );
     }
 
-    // Virtual function
-    const EDA_RECT GetBoundingBox() const override;
+protected:
 
-    wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
+    void updateGeometry() override;
 
-    BITMAP_DEF GetMenuImage() const override;
-
-    EDA_ITEM* Clone() const override;
-
-    virtual const BOX2I ViewBBox() const override;
-
-    virtual void SwapData( BOARD_ITEM* aImage ) override;
-
-#if defined(DEBUG)
-    virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
-#endif
+    void updateText() override;
 };
 
 #endif    // DIMENSION_H_
diff --git a/pcbnew/dialogs/dialog_dimension_properties.cpp b/pcbnew/dialogs/dialog_dimension_properties.cpp
index c4ae034f90..eb4486e42f 100644
--- a/pcbnew/dialogs/dialog_dimension_properties.cpp
+++ b/pcbnew/dialogs/dialog_dimension_properties.cpp
@@ -94,7 +94,8 @@ bool DIALOG_DIMENSION_PROPERTIES::TransferDataToWindow()
 
     m_cbUnits->SetSelection( units == EDA_UNITS::MILLIMETRES ? 2 : useMils ? 1 : 0 );
 
-    m_lineThickness.SetValue( m_dimension->GetWidth() );
+    m_txtPrefix->SetValue( m_dimension->GetPrefix() );
+    m_txtSuffix->SetValue( m_dimension->GetSuffix() );
 
     if( m_cbLayer->SetLayerSelection( m_dimension->GetLayer() ) < 0 )
     {
@@ -117,11 +118,72 @@ bool DIALOG_DIMENSION_PROPERTIES::TransferDataToWindow()
     m_orientValue = text.GetTextAngleDegrees();
     m_cbMirrored->SetValue( text.IsMirrored() );
 
+    m_lineThickness.SetValue( m_dimension->GetLineThickness() );
+
     return DIALOG_DIMENSION_PROPERTIES_BASE::TransferDataToWindow();
 }
 
 
 bool DIALOG_DIMENSION_PROPERTIES::TransferDataFromWindow()
 {
+#if 0
+    switch( m_DimensionUnitsOpt->GetSelection() )
+        {
+        case 0:
+            dimension->SetUnits( EDA_UNITS::INCHES, false );
+            break;
+        case 1:
+            dimension->SetUnits( EDA_UNITS::INCHES, true );
+            break;
+        case 2:
+            dimension->SetUnits( EDA_UNITS::MILLIMETRES, false );
+            break;
+        default: break;
+        }
+#endif
     return true;
 }
+
+#if 0
+void DIALOG_TEXT_PROPERTIES::OnDimensionTextChange( wxCommandEvent& event )
+{
+    EDA_UNITS units = EDA_UNITS::UNSCALED;
+    bool useMils;
+
+    FetchUnitsFromString( m_DimensionText->GetValue(), units, useMils );
+
+    if( units != EDA_UNITS::UNSCALED )
+        m_DimensionUnitsOpt->SetSelection( units == EDA_UNITS::MILLIMETRES ? 2 : useMils ? 1 : 0 );
+}
+
+void DIALOG_TEXT_PROPERTIES::OnDimensionUnitsChange( wxCommandEvent& event )
+{
+    DIMENSION* dimension = (DIMENSION*) m_item;
+    EDA_UNITS  units;
+    bool useMils;
+
+    // Get default units in case dimension text doesn't contain units.
+    dimension->GetUnits( units, useMils );
+
+    double value = ValueFromString( units, m_DimensionText->GetValue(), useMils );
+
+    switch( event.GetSelection() )
+    {
+    case 0:
+        units = EDA_UNITS::INCHES;
+        useMils = false;
+        break;
+    case 1:
+        units = EDA_UNITS::INCHES;
+        useMils = true;
+        break;
+    case 2:
+        units = EDA_UNITS::MILLIMETRES;
+        useMils = false;
+        break;
+    default: break;
+    }
+
+    m_DimensionText->SetValue( StringFromValue( units, value, true, useMils ) );
+}
+#endif
diff --git a/pcbnew/dialogs/dialog_dimension_properties_base.cpp b/pcbnew/dialogs/dialog_dimension_properties_base.cpp
index e21300d915..2ba5008149 100644
--- a/pcbnew/dialogs/dialog_dimension_properties_base.cpp
+++ b/pcbnew/dialogs/dialog_dimension_properties_base.cpp
@@ -52,7 +52,7 @@ DIALOG_DIMENSION_PROPERTIES_BASE::DIALOG_DIMENSION_PROPERTIES_BASE( wxWindow* pa
 
 	gbSizerFormat->Add( m_lblUnits, wxGBPosition( 0, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
 
-	wxString m_cbUnitsChoices[] = { _("Inches"), _("Mils"), _("Millimeters") };
+	wxString m_cbUnitsChoices[] = { _("Inches"), _("Mils"), _("Millimeters"), _("Automatic") };
 	int m_cbUnitsNChoices = sizeof( m_cbUnitsChoices ) / sizeof( wxString );
 	m_cbUnits = new wxChoice( sbSizerFormat->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, m_cbUnitsNChoices, m_cbUnitsChoices, 0 );
 	m_cbUnits->SetSelection( 0 );
diff --git a/pcbnew/dialogs/dialog_dimension_properties_base.fbp b/pcbnew/dialogs/dialog_dimension_properties_base.fbp
index 26db49c55d..90d16e782a 100644
--- a/pcbnew/dialogs/dialog_dimension_properties_base.fbp
+++ b/pcbnew/dialogs/dialog_dimension_properties_base.fbp
@@ -383,7 +383,7 @@
                                         <property name="caption"></property>
                                         <property name="caption_visible">1</property>
                                         <property name="center_pane">0</property>
-                                        <property name="choices">&quot;Inches&quot; &quot;Mils&quot; &quot;Millimeters&quot;</property>
+                                        <property name="choices">&quot;Inches&quot; &quot;Mils&quot; &quot;Millimeters&quot; &quot;Automatic&quot;</property>
                                         <property name="close_button">1</property>
                                         <property name="context_help"></property>
                                         <property name="context_menu">1</property>
diff --git a/pcbnew/dialogs/dialog_text_properties.cpp b/pcbnew/dialogs/dialog_text_properties.cpp
index 7fc02111a8..1cdb2c9e86 100644
--- a/pcbnew/dialogs/dialog_text_properties.cpp
+++ b/pcbnew/dialogs/dialog_text_properties.cpp
@@ -30,7 +30,6 @@
 #include <widgets/unit_binder.h>
 #include <board_commit.h>
 #include <class_board.h>
-#include <class_dimension.h>
 #include <class_module.h>
 #include <class_pcb_text.h>
 #include <class_text_mod.h>
@@ -70,34 +69,7 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, BO
     m_MultiLineText->SetScrollWidth( 1 );
     m_MultiLineText->SetScrollWidthTracking( true );
 
-    m_linesThickness.Show( m_item->Type() == PCB_DIMENSION_T );
-
-    if( m_item->Type() == PCB_DIMENSION_T )
-    {
-        title = _( "Dimension Properties" );
-
-        DIMENSION* dimension = (DIMENSION*) m_item;
-        m_edaText = &dimension->Text();
-        m_pcbText = &dimension->Text();
-
-        // Since this is really the object properties for a dimension (rather than just the
-        // text properties), make some of the propertie labels more explicit.
-        for( wxStaticText* label : { m_SizeXLabel, m_SizeYLabel, m_ThicknessLabel,
-                                     m_PositionXLabel, m_PositionYLabel, m_OrientLabel } )
-        {
-            label->SetLabel( label->GetToolTipText() + wxT( ":" ) );
-        }
-
-        m_Mirrored->SetLabel( m_Mirrored->GetToolTipText() );
-
-        SetInitialFocus( m_DimensionText );
-        m_SingleLineSizer->Show( false );
-        m_MultiLineSizer->Show( false );
-
-        m_KeepUpright->Show( false );
-        m_statusLine->Show( false );
-    }
-    else if( m_item->Type() == PCB_MODULE_TEXT_T )
+    if( m_item->Type() == PCB_MODULE_TEXT_T )
     {
         title = _( "Footprint Text Properties" );
 
@@ -113,7 +85,6 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, BO
 
         SetInitialFocus( m_SingleLineText );
         m_MultiLineSizer->Show( false );
-        m_DimensionTextSizer->Show( false );
     }
     else
     {
@@ -124,7 +95,6 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, BO
 
         SetInitialFocus( m_MultiLineText );
         m_SingleLineSizer->Show( false );
-        m_DimensionTextSizer->Show( false );
 
         // This option make sense only for footprint texts,
         // Texts on board are always visible:
@@ -258,50 +228,6 @@ void DIALOG_TEXT_PROPERTIES::OnCharHook( wxKeyEvent& aEvent )
 }
 
 
-void DIALOG_TEXT_PROPERTIES::OnDimensionTextChange( wxCommandEvent& event )
-{
-    EDA_UNITS units = EDA_UNITS::UNSCALED;
-    bool useMils;
-
-    FetchUnitsFromString( m_DimensionText->GetValue(), units, useMils );
-
-    if( units != EDA_UNITS::UNSCALED )
-        m_DimensionUnitsOpt->SetSelection( units == EDA_UNITS::MILLIMETRES ? 2 : useMils ? 1 : 0 );
-}
-
-
-void DIALOG_TEXT_PROPERTIES::OnDimensionUnitsChange( wxCommandEvent& event )
-{
-    DIMENSION* dimension = (DIMENSION*) m_item;
-    EDA_UNITS  units;
-    bool useMils;
-
-    // Get default units in case dimension text doesn't contain units.
-    dimension->GetUnits( units, useMils );
-
-    double value = ValueFromString( units, m_DimensionText->GetValue(), useMils );
-
-    switch( event.GetSelection() )
-    {
-    case 0:
-        units = EDA_UNITS::INCHES;
-        useMils = false;
-        break;
-    case 1:
-        units = EDA_UNITS::INCHES;
-        useMils = true;
-        break;
-    case 2:
-        units = EDA_UNITS::MILLIMETRES;
-        useMils = false;
-        break;
-    default: break;
-    }
-
-    m_DimensionText->SetValue( StringFromValue( units, value, true, useMils ) );
-}
-
-
 wxString DIALOG_TEXT_PROPERTIES::convertKIIDsToReferences( const wxString& aSource )
 {
     wxString newbuf;
@@ -417,20 +343,6 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataToWindow()
         m_MultiLineText->SetValue( convertKIIDsToReferences( m_edaText->GetText() ) );
         m_MultiLineText->SetSelection( -1, -1 );
     }
-    else if (m_DimensionText->IsShown() )
-    {
-        m_DimensionText->SetValue( m_edaText->GetText() );
-        m_DimensionText->SetSelection( -1, -1 );
-
-        DIMENSION* dimension = (DIMENSION*) m_item;
-        EDA_UNITS  units;
-        bool       useMils;
-        dimension->GetUnits( units, useMils );
-
-        m_DimensionUnitsOpt->SetSelection( units == EDA_UNITS::MILLIMETRES ? 2 : useMils ? 1 : 0 );
-
-        m_linesThickness.SetValue( dimension->GetWidth() );
-    }
 
     if( m_item->Type() == PCB_MODULE_TEXT_T && m_modText )
     {
@@ -524,31 +436,6 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataFromWindow()
             m_edaText->SetText( txt );
         }
     }
-    else if( m_DimensionText->IsShown() )
-    {
-        if( !m_DimensionText->GetValue().IsEmpty() )
-            m_edaText->SetText( m_DimensionText->GetValue() );
-
-        DIMENSION* dimension = (DIMENSION*) m_item;
-
-        switch( m_DimensionUnitsOpt->GetSelection() )
-        {
-        case 0:
-            dimension->SetUnits( EDA_UNITS::INCHES, false );
-            break;
-        case 1:
-            dimension->SetUnits( EDA_UNITS::INCHES, true );
-            break;
-        case 2:
-            dimension->SetUnits( EDA_UNITS::MILLIMETRES, false );
-            break;
-        default: break;
-        }
-
-        dimension->SetWidth( m_linesThickness.GetValue() );
-        dimension->AdjustDimensionDetails(
-                m_Parent->GetBoard()->GetDesignSettings().m_DimensionPrecision );
-    }
 
     m_item->SetLayer( ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ) );
 
diff --git a/pcbnew/dialogs/dialog_text_properties.h b/pcbnew/dialogs/dialog_text_properties.h
index f06038ac7a..6a324b89d5 100644
--- a/pcbnew/dialogs/dialog_text_properties.h
+++ b/pcbnew/dialogs/dialog_text_properties.h
@@ -67,8 +67,6 @@ private:
     bool TransferDataFromWindow() override;
 
     void OnCharHook( wxKeyEvent& aEvent );
-    void OnDimensionTextChange( wxCommandEvent& event ) override;
-    void OnDimensionUnitsChange( wxCommandEvent& event ) override;
 };
 
 
diff --git a/pcbnew/dialogs/dialog_text_properties_base.cpp b/pcbnew/dialogs/dialog_text_properties_base.cpp
index 98c184f764..d257c21702 100644
--- a/pcbnew/dialogs/dialog_text_properties_base.cpp
+++ b/pcbnew/dialogs/dialog_text_properties_base.cpp
@@ -73,31 +73,6 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
 
 	bMainSizer->Add( m_SingleLineSizer, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 );
 
-	m_DimensionTextSizer = new wxFlexGridSizer( 0, 4, 1, 5 );
-	m_DimensionTextSizer->AddGrowableCol( 1 );
-	m_DimensionTextSizer->SetFlexibleDirection( wxBOTH );
-	m_DimensionTextSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
-
-	m_DimensionTextLabel = new wxStaticText( this, wxID_ANY, _("Dimension text:"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_DimensionTextLabel->Wrap( -1 );
-	m_DimensionTextSizer->Add( m_DimensionTextLabel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
-
-	m_DimensionText = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
-	m_DimensionTextSizer->Add( m_DimensionText, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
-
-	m_staticText18 = new wxStaticText( this, wxID_ANY, _("Units:"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_staticText18->Wrap( -1 );
-	m_DimensionTextSizer->Add( m_staticText18, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
-
-	wxString m_DimensionUnitsOptChoices[] = { _("Inches"), _("Mils"), _("Millimeters") };
-	int m_DimensionUnitsOptNChoices = sizeof( m_DimensionUnitsOptChoices ) / sizeof( wxString );
-	m_DimensionUnitsOpt = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_DimensionUnitsOptNChoices, m_DimensionUnitsOptChoices, 0 );
-	m_DimensionUnitsOpt->SetSelection( 0 );
-	m_DimensionTextSizer->Add( m_DimensionUnitsOpt, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
-
-
-	bMainSizer->Add( m_DimensionTextSizer, 0, wxEXPAND|wxALL, 10 );
-
 	wxFlexGridSizer* fgSizerSetup;
 	fgSizerSetup = new wxFlexGridSizer( 0, 5, 4, 0 );
 	fgSizerSetup->AddGrowableCol( 1 );
@@ -291,8 +266,6 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
 	// Connect Events
 	this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnInitDlg ) );
 	m_SingleLineText->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnOkClick ), NULL, this );
-	m_DimensionText->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnDimensionTextChange ), NULL, this );
-	m_DimensionUnitsOpt->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnDimensionUnitsChange ), NULL, this );
 	m_SizeXCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnOkClick ), NULL, this );
 	m_SizeYCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnOkClick ), NULL, this );
 	m_ThicknessCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnOkClick ), NULL, this );
@@ -308,8 +281,6 @@ DIALOG_TEXT_PROPERTIES_BASE::~DIALOG_TEXT_PROPERTIES_BASE()
 	// Disconnect Events
 	this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnInitDlg ) );
 	m_SingleLineText->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnOkClick ), NULL, this );
-	m_DimensionText->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnDimensionTextChange ), NULL, this );
-	m_DimensionUnitsOpt->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnDimensionUnitsChange ), NULL, this );
 	m_SizeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnOkClick ), NULL, this );
 	m_SizeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnOkClick ), NULL, this );
 	m_ThicknessCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TEXT_PROPERTIES_BASE::OnOkClick ), NULL, this );
diff --git a/pcbnew/dialogs/dialog_text_properties_base.fbp b/pcbnew/dialogs/dialog_text_properties_base.fbp
index 1164ebd405..5a2b6b664c 100644
--- a/pcbnew/dialogs/dialog_text_properties_base.fbp
+++ b/pcbnew/dialogs/dialog_text_properties_base.fbp
@@ -334,276 +334,6 @@
                         </object>
                     </object>
                 </object>
-                <object class="sizeritem" expanded="1">
-                    <property name="border">10</property>
-                    <property name="flag">wxEXPAND|wxALL</property>
-                    <property name="proportion">0</property>
-                    <object class="wxFlexGridSizer" expanded="1">
-                        <property name="cols">4</property>
-                        <property name="flexible_direction">wxBOTH</property>
-                        <property name="growablecols">1</property>
-                        <property name="growablerows"></property>
-                        <property name="hgap">5</property>
-                        <property name="minimum_size"></property>
-                        <property name="name">m_DimensionTextSizer</property>
-                        <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
-                        <property name="permission">protected</property>
-                        <property name="rows">0</property>
-                        <property name="vgap">1</property>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">5</property>
-                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT</property>
-                            <property name="proportion">0</property>
-                            <object class="wxStaticText" expanded="1">
-                                <property name="BottomDockable">1</property>
-                                <property name="LeftDockable">1</property>
-                                <property name="RightDockable">1</property>
-                                <property name="TopDockable">1</property>
-                                <property name="aui_layer"></property>
-                                <property name="aui_name"></property>
-                                <property name="aui_position"></property>
-                                <property name="aui_row"></property>
-                                <property name="best_size"></property>
-                                <property name="bg"></property>
-                                <property name="caption"></property>
-                                <property name="caption_visible">1</property>
-                                <property name="center_pane">0</property>
-                                <property name="close_button">1</property>
-                                <property name="context_help"></property>
-                                <property name="context_menu">1</property>
-                                <property name="default_pane">0</property>
-                                <property name="dock">Dock</property>
-                                <property name="dock_fixed">0</property>
-                                <property name="docking">Left</property>
-                                <property name="enabled">1</property>
-                                <property name="fg"></property>
-                                <property name="floatable">1</property>
-                                <property name="font"></property>
-                                <property name="gripper">0</property>
-                                <property name="hidden">0</property>
-                                <property name="id">wxID_ANY</property>
-                                <property name="label">Dimension text:</property>
-                                <property name="markup">0</property>
-                                <property name="max_size"></property>
-                                <property name="maximize_button">0</property>
-                                <property name="maximum_size"></property>
-                                <property name="min_size"></property>
-                                <property name="minimize_button">0</property>
-                                <property name="minimum_size"></property>
-                                <property name="moveable">1</property>
-                                <property name="name">m_DimensionTextLabel</property>
-                                <property name="pane_border">1</property>
-                                <property name="pane_position"></property>
-                                <property name="pane_size"></property>
-                                <property name="permission">protected</property>
-                                <property name="pin_button">1</property>
-                                <property name="pos"></property>
-                                <property name="resize">Resizable</property>
-                                <property name="show">1</property>
-                                <property name="size"></property>
-                                <property name="style"></property>
-                                <property name="subclass">; forward_declare</property>
-                                <property name="toolbar_pane">0</property>
-                                <property name="tooltip"></property>
-                                <property name="window_extra_style"></property>
-                                <property name="window_name"></property>
-                                <property name="window_style"></property>
-                                <property name="wrap">-1</property>
-                            </object>
-                        </object>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">5</property>
-                            <property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property>
-                            <property name="proportion">0</property>
-                            <object class="wxTextCtrl" expanded="1">
-                                <property name="BottomDockable">1</property>
-                                <property name="LeftDockable">1</property>
-                                <property name="RightDockable">1</property>
-                                <property name="TopDockable">1</property>
-                                <property name="aui_layer"></property>
-                                <property name="aui_name"></property>
-                                <property name="aui_position"></property>
-                                <property name="aui_row"></property>
-                                <property name="best_size"></property>
-                                <property name="bg"></property>
-                                <property name="caption"></property>
-                                <property name="caption_visible">1</property>
-                                <property name="center_pane">0</property>
-                                <property name="close_button">1</property>
-                                <property name="context_help"></property>
-                                <property name="context_menu">1</property>
-                                <property name="default_pane">0</property>
-                                <property name="dock">Dock</property>
-                                <property name="dock_fixed">0</property>
-                                <property name="docking">Left</property>
-                                <property name="enabled">1</property>
-                                <property name="fg"></property>
-                                <property name="floatable">1</property>
-                                <property name="font"></property>
-                                <property name="gripper">0</property>
-                                <property name="hidden">0</property>
-                                <property name="id">wxID_ANY</property>
-                                <property name="max_size"></property>
-                                <property name="maximize_button">0</property>
-                                <property name="maximum_size"></property>
-                                <property name="maxlength"></property>
-                                <property name="min_size"></property>
-                                <property name="minimize_button">0</property>
-                                <property name="minimum_size"></property>
-                                <property name="moveable">1</property>
-                                <property name="name">m_DimensionText</property>
-                                <property name="pane_border">1</property>
-                                <property name="pane_position"></property>
-                                <property name="pane_size"></property>
-                                <property name="permission">protected</property>
-                                <property name="pin_button">1</property>
-                                <property name="pos"></property>
-                                <property name="resize">Resizable</property>
-                                <property name="show">1</property>
-                                <property name="size"></property>
-                                <property name="style"></property>
-                                <property name="subclass">; forward_declare</property>
-                                <property name="toolbar_pane">0</property>
-                                <property name="tooltip"></property>
-                                <property name="validator_data_type"></property>
-                                <property name="validator_style">wxFILTER_NONE</property>
-                                <property name="validator_type">wxDefaultValidator</property>
-                                <property name="validator_variable"></property>
-                                <property name="value"></property>
-                                <property name="window_extra_style"></property>
-                                <property name="window_name"></property>
-                                <property name="window_style"></property>
-                                <event name="OnText">OnDimensionTextChange</event>
-                            </object>
-                        </object>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">5</property>
-                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT</property>
-                            <property name="proportion">0</property>
-                            <object class="wxStaticText" expanded="1">
-                                <property name="BottomDockable">1</property>
-                                <property name="LeftDockable">1</property>
-                                <property name="RightDockable">1</property>
-                                <property name="TopDockable">1</property>
-                                <property name="aui_layer"></property>
-                                <property name="aui_name"></property>
-                                <property name="aui_position"></property>
-                                <property name="aui_row"></property>
-                                <property name="best_size"></property>
-                                <property name="bg"></property>
-                                <property name="caption"></property>
-                                <property name="caption_visible">1</property>
-                                <property name="center_pane">0</property>
-                                <property name="close_button">1</property>
-                                <property name="context_help"></property>
-                                <property name="context_menu">1</property>
-                                <property name="default_pane">0</property>
-                                <property name="dock">Dock</property>
-                                <property name="dock_fixed">0</property>
-                                <property name="docking">Left</property>
-                                <property name="enabled">1</property>
-                                <property name="fg"></property>
-                                <property name="floatable">1</property>
-                                <property name="font"></property>
-                                <property name="gripper">0</property>
-                                <property name="hidden">0</property>
-                                <property name="id">wxID_ANY</property>
-                                <property name="label">Units:</property>
-                                <property name="markup">0</property>
-                                <property name="max_size"></property>
-                                <property name="maximize_button">0</property>
-                                <property name="maximum_size"></property>
-                                <property name="min_size"></property>
-                                <property name="minimize_button">0</property>
-                                <property name="minimum_size"></property>
-                                <property name="moveable">1</property>
-                                <property name="name">m_staticText18</property>
-                                <property name="pane_border">1</property>
-                                <property name="pane_position"></property>
-                                <property name="pane_size"></property>
-                                <property name="permission">protected</property>
-                                <property name="pin_button">1</property>
-                                <property name="pos"></property>
-                                <property name="resize">Resizable</property>
-                                <property name="show">1</property>
-                                <property name="size"></property>
-                                <property name="style"></property>
-                                <property name="subclass">; forward_declare</property>
-                                <property name="toolbar_pane">0</property>
-                                <property name="tooltip"></property>
-                                <property name="window_extra_style"></property>
-                                <property name="window_name"></property>
-                                <property name="window_style"></property>
-                                <property name="wrap">-1</property>
-                            </object>
-                        </object>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">5</property>
-                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property>
-                            <property name="proportion">0</property>
-                            <object class="wxChoice" expanded="1">
-                                <property name="BottomDockable">1</property>
-                                <property name="LeftDockable">1</property>
-                                <property name="RightDockable">1</property>
-                                <property name="TopDockable">1</property>
-                                <property name="aui_layer"></property>
-                                <property name="aui_name"></property>
-                                <property name="aui_position"></property>
-                                <property name="aui_row"></property>
-                                <property name="best_size"></property>
-                                <property name="bg"></property>
-                                <property name="caption"></property>
-                                <property name="caption_visible">1</property>
-                                <property name="center_pane">0</property>
-                                <property name="choices">&quot;Inches&quot; &quot;Mils&quot; &quot;Millimeters&quot;</property>
-                                <property name="close_button">1</property>
-                                <property name="context_help"></property>
-                                <property name="context_menu">1</property>
-                                <property name="default_pane">0</property>
-                                <property name="dock">Dock</property>
-                                <property name="dock_fixed">0</property>
-                                <property name="docking">Left</property>
-                                <property name="enabled">1</property>
-                                <property name="fg"></property>
-                                <property name="floatable">1</property>
-                                <property name="font"></property>
-                                <property name="gripper">0</property>
-                                <property name="hidden">0</property>
-                                <property name="id">wxID_ANY</property>
-                                <property name="max_size"></property>
-                                <property name="maximize_button">0</property>
-                                <property name="maximum_size"></property>
-                                <property name="min_size"></property>
-                                <property name="minimize_button">0</property>
-                                <property name="minimum_size">-1,-1</property>
-                                <property name="moveable">1</property>
-                                <property name="name">m_DimensionUnitsOpt</property>
-                                <property name="pane_border">1</property>
-                                <property name="pane_position"></property>
-                                <property name="pane_size"></property>
-                                <property name="permission">protected</property>
-                                <property name="pin_button">1</property>
-                                <property name="pos"></property>
-                                <property name="resize">Resizable</property>
-                                <property name="selection">0</property>
-                                <property name="show">1</property>
-                                <property name="size"></property>
-                                <property name="style"></property>
-                                <property name="subclass">; forward_declare</property>
-                                <property name="toolbar_pane">0</property>
-                                <property name="tooltip"></property>
-                                <property name="validator_data_type"></property>
-                                <property name="validator_style">wxFILTER_NONE</property>
-                                <property name="validator_type">wxDefaultValidator</property>
-                                <property name="validator_variable"></property>
-                                <property name="window_extra_style"></property>
-                                <property name="window_name"></property>
-                                <property name="window_style"></property>
-                                <event name="OnChoice">OnDimensionUnitsChange</event>
-                            </object>
-                        </object>
-                    </object>
-                </object>
                 <object class="sizeritem" expanded="1">
                     <property name="border">10</property>
                     <property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
diff --git a/pcbnew/dialogs/dialog_text_properties_base.h b/pcbnew/dialogs/dialog_text_properties_base.h
index 066e19fb45..f4f5d05582 100644
--- a/pcbnew/dialogs/dialog_text_properties_base.h
+++ b/pcbnew/dialogs/dialog_text_properties_base.h
@@ -22,9 +22,9 @@ class PCB_LAYER_BOX_SELECTOR;
 #include <wx/stc/stc.h>
 #include <wx/sizer.h>
 #include <wx/textctrl.h>
-#include <wx/choice.h>
 #include <wx/bmpcbox.h>
 #include <wx/checkbox.h>
+#include <wx/choice.h>
 #include <wx/combobox.h>
 #include <wx/statline.h>
 #include <wx/button.h>
@@ -46,11 +46,6 @@ class DIALOG_TEXT_PROPERTIES_BASE : public DIALOG_SHIM
 		wxBoxSizer* m_SingleLineSizer;
 		wxStaticText* m_TextLabel;
 		wxTextCtrl* m_SingleLineText;
-		wxFlexGridSizer* m_DimensionTextSizer;
-		wxStaticText* m_DimensionTextLabel;
-		wxTextCtrl* m_DimensionText;
-		wxStaticText* m_staticText18;
-		wxChoice* m_DimensionUnitsOpt;
 		wxStaticText* m_LayerLabel;
 		PCB_LAYER_BOX_SELECTOR* m_LayerSelectionCtrl;
 		wxCheckBox* m_Visible;
@@ -88,8 +83,6 @@ class DIALOG_TEXT_PROPERTIES_BASE : public DIALOG_SHIM
 		// Virtual event handlers, overide them in your derived class
 		virtual void OnInitDlg( wxInitDialogEvent& event ) { event.Skip(); }
 		virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); }
-		virtual void OnDimensionTextChange( wxCommandEvent& event ) { event.Skip(); }
-		virtual void OnDimensionUnitsChange( wxCommandEvent& event ) { event.Skip(); }
 
 
 	public:
diff --git a/pcbnew/dialogs/panel_setup_text_and_graphics.cpp b/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
index 1fc2a6a2b2..302c21402d 100644
--- a/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
+++ b/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
@@ -132,6 +132,8 @@ bool PANEL_SETUP_TEXT_AND_GRAPHICS::TransferDataToWindow()
 
     Layout();
 
+    wxASSERT_MSG( m_BrdSettings->m_DimensionPrecision <= 4, "Unhandled dimension precision!" );
+
     m_dimensionUnits->SetSelection( m_BrdSettings->m_DimensionUnits );
     m_dimensionPrecision->SetSelection( m_BrdSettings->m_DimensionPrecision );
 
diff --git a/pcbnew/dialogs/panel_setup_text_and_graphics_base.cpp b/pcbnew/dialogs/panel_setup_text_and_graphics_base.cpp
index 50e0e2f829..5671325403 100644
--- a/pcbnew/dialogs/panel_setup_text_and_graphics_base.cpp
+++ b/pcbnew/dialogs/panel_setup_text_and_graphics_base.cpp
@@ -94,10 +94,10 @@ PANEL_SETUP_TEXT_AND_GRAPHICS_BASE::PANEL_SETUP_TEXT_AND_GRAPHICS_BASE( wxWindow
 	m_dimensionPrecisionLabel->Wrap( -1 );
 	fgSizer1->Add( m_dimensionPrecisionLabel, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
 
-	wxString m_dimensionPrecisionChoices[] = { _("0.01 mm / 1 mil"), _("0.001 mm / 0.1 mil"), _("0.0001mm / 0.01 mil") };
+	wxString m_dimensionPrecisionChoices[] = { _("0"), _("0.0"), _("0.00"), _("0.000"), _("0.0000") };
 	int m_dimensionPrecisionNChoices = sizeof( m_dimensionPrecisionChoices ) / sizeof( wxString );
 	m_dimensionPrecision = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_dimensionPrecisionNChoices, m_dimensionPrecisionChoices, 0 );
-	m_dimensionPrecision->SetSelection( 0 );
+	m_dimensionPrecision->SetSelection( 4 );
 	fgSizer1->Add( m_dimensionPrecision, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
 
 
diff --git a/pcbnew/dialogs/panel_setup_text_and_graphics_base.fbp b/pcbnew/dialogs/panel_setup_text_and_graphics_base.fbp
index 79adb904c6..edb62cd284 100644
--- a/pcbnew/dialogs/panel_setup_text_and_graphics_base.fbp
+++ b/pcbnew/dialogs/panel_setup_text_and_graphics_base.fbp
@@ -503,7 +503,7 @@
                                         <property name="caption"></property>
                                         <property name="caption_visible">1</property>
                                         <property name="center_pane">0</property>
-                                        <property name="choices">&quot;0.01 mm / 1 mil&quot; &quot;0.001 mm / 0.1 mil&quot; &quot;0.0001mm / 0.01 mil&quot;</property>
+                                        <property name="choices">&quot;0&quot; &quot;0.0&quot; &quot;0.00&quot; &quot;0.000&quot; &quot;0.0000&quot;</property>
                                         <property name="close_button">1</property>
                                         <property name="context_help"></property>
                                         <property name="context_menu">1</property>
@@ -533,7 +533,7 @@
                                         <property name="pin_button">1</property>
                                         <property name="pos"></property>
                                         <property name="resize">Resizable</property>
-                                        <property name="selection">0</property>
+                                        <property name="selection">4</property>
                                         <property name="show">1</property>
                                         <property name="size"></property>
                                         <property name="style"></property>
diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp
index 8b73bed992..e172acce62 100644
--- a/pcbnew/eagle_plugin.cpp
+++ b/pcbnew/eagle_plugin.cpp
@@ -859,7 +859,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
             if( layer != UNDEFINED_LAYER )
             {
                 const BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
-                DIMENSION* dimension = new DIMENSION( m_board );
+                ALIGNED_DIMENSION* dimension = new ALIGNED_DIMENSION( m_board );
                 m_board->Add( dimension, ADD_MODE::APPEND );
 
                 if( d.dimensionType )
@@ -881,14 +881,13 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
                 }
 
                 dimension->SetLayer( layer );
+                dimension->SetPrecision( DIMENSION_PRECISION );
                 // The origin and end are assumed to always be in this order from eagle
-                dimension->SetOrigin( wxPoint( kicad_x( d.x1 ), kicad_y( d.y1 ) ),
-                                      DIMENSION_PRECISION );
-                dimension->SetEnd( wxPoint( kicad_x( d.x2 ), kicad_y( d.y2 ) ),
-                                   DIMENSION_PRECISION );
+                dimension->SetStart( wxPoint( kicad_x( d.x1 ), kicad_y( d.y1 ) ) );
+                dimension->SetEnd( wxPoint( kicad_x( d.x2 ), kicad_y( d.y2 ) ) );
                 dimension->Text().SetTextSize( designSettings.GetTextSize( layer ) );
-                dimension->Text().SetTextThickness( designSettings.GetTextThickness( layer ));
-                dimension->SetWidth( designSettings.GetLineThickness( layer ) );
+                dimension->Text().SetTextThickness( designSettings.GetTextThickness( layer ) );
+                dimension->SetLineThickness( designSettings.GetLineThickness( layer ) );
                 dimension->SetUnits( EDA_UNITS::MILLIMETRES, false );
 
                 // check which axis the dimension runs in
@@ -896,11 +895,9 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
                 // Note the check is just if two axes are close enough to each other
                 // Eagle appears to have some rounding errors
                 if( abs( ( d.x1 - d.x2 ).ToPcbUnits() ) < 50000 )   // 50000 nm = 0.05 mm
-                    dimension->SetHeight( kicad_x( d.x3 - d.x1 ), DIMENSION_PRECISION );
+                    dimension->SetHeight( kicad_x( d.x3 - d.x1 ) );
                 else
-                    dimension->SetHeight( kicad_y( d.y3 - d.y1 ), DIMENSION_PRECISION );
-
-                dimension->AdjustDimensionDetails( DIMENSION_PRECISION );
+                    dimension->SetHeight( kicad_y( d.y3 - d.y1 ) );
             }
         }
 
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index 0dee3ed727..d0aa2837b3 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -399,7 +399,7 @@ void PCB_IO::Format( BOARD_ITEM* aItem, int aNestLevel ) const
         break;
 
     case PCB_DIMENSION_T:
-        format( static_cast<DIMENSION*>( aItem ), aNestLevel );
+        format( static_cast<ALIGNED_DIMENSION*>( aItem ), aNestLevel );
         break;
 
     case PCB_LINE_T:
@@ -659,11 +659,9 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
 }
 
 
-void PCB_IO::format( DIMENSION* aDimension, int aNestLevel ) const
+void PCB_IO::format( ALIGNED_DIMENSION* aDimension, int aNestLevel ) const
 {
-    m_out->Print( aNestLevel, "(dimension %s (width %s)",
-                  FormatInternalUnits( aDimension->GetValue() ).c_str(),
-                  FormatInternalUnits( aDimension->GetWidth() ).c_str() );
+    m_out->Print( aNestLevel, "(dimension (type aligned)" );
 
     formatLayer( aDimension );
 
@@ -671,49 +669,50 @@ void PCB_IO::format( DIMENSION* aDimension, int aNestLevel ) const
 
     m_out->Print( 0, "\n" );
 
+    m_out->Print( aNestLevel+1, "(pts (xy %s %s) (xy %s %s))\n",
+                  FormatInternalUnits( aDimension->GetStart().x ).c_str(),
+                  FormatInternalUnits( aDimension->GetStart().y ).c_str(),
+                  FormatInternalUnits( aDimension->GetEnd().x ).c_str(),
+                  FormatInternalUnits( aDimension->GetEnd().y ).c_str() );
+
+    m_out->Print( aNestLevel+1, "(height %s)\n",
+                  FormatInternalUnits( aDimension->GetHeight() ).c_str() );
+
     Format( &aDimension->Text(), aNestLevel+1 );
 
-    m_out->Print( aNestLevel+1, "(feature1 (pts (xy %s %s) (xy %s %s)))\n",
-                  FormatInternalUnits( aDimension->m_featureLineDO.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_featureLineDO.y ).c_str(),
-                  FormatInternalUnits( aDimension->m_featureLineDF.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_featureLineDF.y ).c_str() );
+    m_out->Print( aNestLevel+1, "(format" );
 
-    m_out->Print( aNestLevel+1, "(feature2 (pts (xy %s %s) (xy %s %s)))\n",
-                  FormatInternalUnits( aDimension->m_featureLineGO.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_featureLineGO.y ).c_str(),
-                  FormatInternalUnits( aDimension->m_featureLineGF.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_featureLineGF.y ).c_str() );
+    if( !aDimension->GetPrefix().IsEmpty() )
+        m_out->Print( 0, " (prefix %s)", TO_UTF8( aDimension->GetPrefix() ) );
 
-    m_out->Print( aNestLevel+1, "(crossbar (pts (xy %s %s) (xy %s %s)))\n",
-                  FormatInternalUnits( aDimension->m_crossBarO.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_crossBarO.y ).c_str(),
-                  FormatInternalUnits( aDimension->m_crossBarF.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_crossBarF.y ).c_str() );
+    if( !aDimension->GetSuffix().IsEmpty() )
+        m_out->Print( 0, " (suffix %s)", TO_UTF8( aDimension->GetSuffix() ) );
 
-    m_out->Print( aNestLevel+1, "(arrow1a (pts (xy %s %s) (xy %s %s)))\n",
-                  FormatInternalUnits( aDimension->m_crossBarF.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_crossBarF.y ).c_str(),
-                  FormatInternalUnits( aDimension->m_arrowD1F.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_arrowD1F.y ).c_str() );
+    m_out->Print( 0, " (units %d) (units_format %d) (precision %d)",
+                  static_cast<int>( aDimension->GetUnitsMode() ),
+                  static_cast<int>( aDimension->GetUnitsFormat() ), aDimension->GetPrecision() );
 
-    m_out->Print( aNestLevel+1, "(arrow1b (pts (xy %s %s) (xy %s %s)))\n",
-                  FormatInternalUnits( aDimension->m_crossBarF.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_crossBarF.y ).c_str(),
-                  FormatInternalUnits( aDimension->m_arrowD2F.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_arrowD2F.y ).c_str() );
+    if( aDimension->GetOverrideValue() )
+        m_out->Print( 0, " override_value" );
 
-    m_out->Print( aNestLevel+1, "(arrow2a (pts (xy %s %s) (xy %s %s)))\n",
-                  FormatInternalUnits( aDimension->m_crossBarO.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_crossBarO.y ).c_str(),
-                  FormatInternalUnits( aDimension->m_arrowG1F.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_arrowG1F.y ).c_str() );
+    if( aDimension->GetSuppressZeroes() )
+        m_out->Print( 0, " suppress_zeroes" );
 
-    m_out->Print( aNestLevel+1, "(arrow2b (pts (xy %s %s) (xy %s %s)))\n",
-                  FormatInternalUnits( aDimension->m_crossBarO.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_crossBarO.y ).c_str(),
-                  FormatInternalUnits( aDimension->m_arrowG2F.x ).c_str(),
-                  FormatInternalUnits( aDimension->m_arrowG2F.y ).c_str() );
+    m_out->Print( 0, ")\n" );
+
+    m_out->Print( aNestLevel+1, "(style (thickness %s) (arrow_length %s) (text_position_mode %d)",
+                  FormatInternalUnits( aDimension->GetLineThickness() ).c_str(),
+                  FormatInternalUnits( aDimension->GetArrowLength() ).c_str(),
+                  static_cast<int>( aDimension->GetTextPositionMode() ) );
+
+    m_out->Print( 0, " (extension_height %s) (extension_offset %s)",
+                  FormatInternalUnits( aDimension->GetExtensionHeight() ).c_str(),
+                  FormatInternalUnits( aDimension->GetExtensionOffset() ).c_str() );
+
+    if( !aDimension->GetKeepTextAligned() )
+        m_out->Print( 0, " keep_upright" );
+
+    m_out->Print( 0, ")\n" );
 
     m_out->Print( aNestLevel, ")\n" );
 }
diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h
index 5de7ded02c..136d7dc2cb 100644
--- a/pcbnew/kicad_plugin.h
+++ b/pcbnew/kicad_plugin.h
@@ -35,7 +35,7 @@ class FP_CACHE;
 class PCB_PARSER;
 class NETINFO_MAPPING;
 class BOARD_DESIGN_SETTINGS;
-class DIMENSION;
+class ALIGNED_DIMENSION;
 class EDGE_MODULE;
 class DRAWSEGMENT;
 class PCB_TARGET;
@@ -82,7 +82,8 @@ class TEXTE_PCB;
 //#define SEXPR_BOARD_FILE_VERSION    20200819  // Add board-level properties
 //#define SEXPR_BOARD_FILE_VERSION    20200825  // Remove host information
 //#define SEXPR_BOARD_FILE_VERSION    20200828  // Add new fabrication attributes
-#define SEXPR_BOARD_FILE_VERSION    20200829  // Remove library name from exported footprints
+//#define SEXPR_BOARD_FILE_VERSION    20200829  // Remove library name from exported footprints
+#define SEXPR_BOARD_FILE_VERSION      20200909  // Change DIMENSION format
 
 #define BOARD_FILE_HOST_VERSION     20200825    ///< Earlier files than this include the host tag
 
@@ -251,7 +252,7 @@ protected:
 private:
     void format( BOARD* aBoard, int aNestLevel = 0 ) const;
 
-    void format( DIMENSION* aDimension, int aNestLevel = 0 ) const;
+    void format( ALIGNED_DIMENSION* aDimension, int aNestLevel = 0 ) const;
 
     void format( EDGE_MODULE* aModuleDrawing, int aNestLevel = 0 ) const;
 
diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp
index 6b64cdd0f0..67ea887ff5 100644
--- a/pcbnew/legacy_plugin.cpp
+++ b/pcbnew/legacy_plugin.cpp
@@ -2732,7 +2732,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
 
 void LEGACY_PLUGIN::loadDIMENSION()
 {
-    unique_ptr<DIMENSION> dim( new DIMENSION( m_board ) );
+    unique_ptr<ALIGNED_DIMENSION> dim( new ALIGNED_DIMENSION( m_board ) );
 
     char*   line;
 
@@ -2749,7 +2749,8 @@ void LEGACY_PLUGIN::loadDIMENSION()
         else if( TESTLINE( "Va" ) )
         {
             BIU value = biuParse( line + SZ( "Va" ) );
-            dim->SetValue( value );
+            // unused; dimension value is calculated from coordinates
+            ( void )value;
         }
 
         else if( TESTLINE( "Ge" ) )
@@ -2761,7 +2762,8 @@ void LEGACY_PLUGIN::loadDIMENSION()
 
             dim->SetLayer( leg_layer2new( m_cu_count,  layer_num ) );
             const_cast<KIID&>( dim->m_Uuid ) = KIID( uuid );
-            dim->SetShape( shape );
+            // not used
+            ( void )shape;
         }
 
         else if( TESTLINE( "Te" ) )
@@ -2801,11 +2803,9 @@ void LEGACY_PLUGIN::loadDIMENSION()
             BIU crossBarFy = biuParse( data, &data );
             BIU width      = biuParse( data );
 
-            dim->m_crossBarO.x = crossBarOx;
-            dim->m_crossBarO.y = crossBarOy;
-            dim->m_crossBarF.x = crossBarFx;
-            dim->m_crossBarF.y = crossBarFy;
-            dim->SetWidth( width );
+            dim->SetLineThickness( width );
+            dim->UpdateHeight( wxPoint( crossBarFx, crossBarFy ),
+                               wxPoint( crossBarOx, crossBarOy ) );
             (void) ignore;
         }
 
@@ -2817,11 +2817,10 @@ void LEGACY_PLUGIN::loadDIMENSION()
             BIU featureLineDFx = biuParse( data, &data );
             BIU featureLineDFy = biuParse( data );
 
-            dim->m_featureLineDO.x = featureLineDOx;
-            dim->m_featureLineDO.y = featureLineDOy;
-            dim->m_featureLineDF.x = featureLineDFx;
-            dim->m_featureLineDF.y = featureLineDFy;
-            (void) ignore;
+            dim->SetStart( wxPoint( featureLineDOx, featureLineDOy ) );
+            ( void )ignore;
+            ( void )featureLineDFx;
+            ( void )featureLineDFy;
         }
 
         else if( TESTLINE( "Sg" ) )
@@ -2832,62 +2831,58 @@ void LEGACY_PLUGIN::loadDIMENSION()
             BIU featureLineGFx = biuParse( data, &data );
             BIU featureLineGFy = biuParse( data );
 
-            dim->m_featureLineGO.x = featureLineGOx;
-            dim->m_featureLineGO.y = featureLineGOy;
-            dim->m_featureLineGF.x = featureLineGFx;
-            dim->m_featureLineGF.y = featureLineGFy;
             (void) ignore;
+            dim->SetEnd( wxPoint( featureLineGOx, featureLineGOy ) );
+            ( void )ignore;
+            ( void )featureLineGFx;
+            ( void )featureLineGFy;
         }
 
+        // Arrow: no longer imported
         else if( TESTLINE( "S1" ) )
         {
             int ignore      = intParse( line + SZ( "S1" ), &data );
             biuParse( data, &data );    // skipping excessive data
             biuParse( data, &data );    // skipping excessive data
-            BIU arrowD1Fx   = biuParse( data, &data );
-            BIU arrowD1Fy   = biuParse( data );
+            biuParse( data, &data );
+            biuParse( data );
 
-            dim->m_arrowD1F.x = arrowD1Fx;
-            dim->m_arrowD1F.y = arrowD1Fy;
             (void) ignore;
         }
 
+        // Arrow: no longer imported
         else if( TESTLINE( "S2" ) )
         {
             int ignore    = intParse( line + SZ( "S2" ), &data );
             biuParse( data, &data );    // skipping excessive data
             biuParse( data, &data );    // skipping excessive data
-            BIU arrowD2Fx = biuParse( data, &data );
-            BIU arrowD2Fy = biuParse( data, &data );
+            biuParse( data, &data );
+            biuParse( data, &data );
 
-            dim->m_arrowD2F.x = arrowD2Fx;
-            dim->m_arrowD2F.y = arrowD2Fy;
             (void) ignore;
         }
 
+        // Arrow: no longer imported
         else if( TESTLINE( "S3" ) )
         {
             int ignore    = intParse( line + SZ( "S3" ), &data );
             biuParse( data, &data );    // skipping excessive data
             biuParse( data, &data );    // skipping excessive data
-            BIU arrowG1Fx = biuParse( data, &data );
-            BIU arrowG1Fy = biuParse( data, &data );
+            biuParse( data, &data );
+            biuParse( data, &data );
 
-            dim->m_arrowG1F.x = arrowG1Fx;
-            dim->m_arrowG1F.y = arrowG1Fy;
             (void) ignore;
         }
 
+        // Arrow: no longer imported
         else if( TESTLINE( "S4" ) )
         {
             int ignore    = intParse( line + SZ( "S4" ), &data );
             biuParse( data, &data );    // skipping excessive data
             biuParse( data, &data );    // skipping excessive data
-            BIU arrowG2Fx = biuParse( data, &data );
-            BIU arrowG2Fy = biuParse( data, &data );
+            biuParse( data, &data );
+            biuParse( data, &data );
 
-            dim->m_arrowG2F.x = arrowG2Fx;
-            dim->m_arrowG2F.y = arrowG2Fy;
             (void) ignore;
         }
     }
diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp
index 21ecce2e86..5732e50528 100644
--- a/pcbnew/pcb_painter.cpp
+++ b/pcbnew/pcb_painter.cpp
@@ -1273,19 +1273,12 @@ void PCB_PAINTER::draw( const DIMENSION* aDimension, int aLayer )
     else
     {
         // Filled mode
-        m_gal->SetLineWidth( getLineThickness( aDimension->GetWidth() ) );
+        m_gal->SetLineWidth( getLineThickness( aDimension->GetLineThickness() ) );
     }
 
-    // Draw an arrow
-    m_gal->DrawLine( VECTOR2D( aDimension->m_crossBarO ), VECTOR2D( aDimension->m_crossBarF ) );
-    m_gal->DrawLine( VECTOR2D( aDimension->m_featureLineGO ),
-                     VECTOR2D( aDimension->m_featureLineGF ) );
-    m_gal->DrawLine( VECTOR2D( aDimension->m_featureLineDO ),
-                     VECTOR2D( aDimension->m_featureLineDF ) );
-    m_gal->DrawLine( VECTOR2D( aDimension->m_crossBarF ), VECTOR2D( aDimension->m_arrowD1F ) );
-    m_gal->DrawLine( VECTOR2D( aDimension->m_crossBarF ), VECTOR2D( aDimension->m_arrowD2F ) );
-    m_gal->DrawLine( VECTOR2D( aDimension->m_crossBarO ), VECTOR2D( aDimension->m_arrowG1F ) );
-    m_gal->DrawLine( VECTOR2D( aDimension->m_crossBarO ), VECTOR2D( aDimension->m_arrowG2F ) );
+    // Draw dimension shapes
+    for( const SEG& seg : aDimension->GetLines() )
+        m_gal->DrawLine( seg.A, seg.B );
 
     // Draw text
     TEXTE_PCB& text = aDimension->Text();
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index 5305b6f5a8..56992cd52a 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -2353,17 +2353,30 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
 
     T token;
 
-    std::unique_ptr<DIMENSION> dimension( new DIMENSION( NULL ) );
+    std::unique_ptr<ALIGNED_DIMENSION> dimension( new ALIGNED_DIMENSION( nullptr ) );
+
+    // skip value that used to be saved
+    if( NextTok() != T_LEFT )
+        NeedLEFT();
 
-    dimension->SetValue( parseBoardUnits( "dimension value" ) );
-    NeedLEFT();
     token = NextTok();
 
-    if( token != T_width )
-        Expecting( T_width );
+    // Old format
+    if( token == T_width )
+    {
+        dimension->SetLineThickness( parseBoardUnits( "dimension width value" ) );
+        NeedRIGHT();
+    }
+    else if( token != T_type )
+    {
+        Expecting( T_type );
 
-    dimension->SetWidth( parseBoardUnits( "dimension width value" ) );
-    NeedRIGHT();
+        // This function only parses aligned dimensions for now
+        if( NextTok() != T_aligned )
+            Expecting( T_aligned );
+
+        NeedRIGHT();
+    }
 
     for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
     {
@@ -2405,49 +2418,185 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
             break;
         }
 
+        // New format: feature points
+        case T_pts:
+        {
+            wxPoint point;
+
+            parseXY( &point.x, &point.y );
+            dimension->SetStart( point );
+            parseXY( &point.x, &point.y );
+            dimension->SetEnd( point );
+
+            NeedRIGHT();
+            break;
+        }
+
+        case T_height:
+            dimension->SetHeight( parseBoardUnits( "dimension height value" ) );
+            NeedRIGHT();
+            break;
+
+        case T_format:
+        {
+            for( token = NextTok(); token != T_RIGHT; token = NextTok() )
+            {
+                switch( token )
+                {
+                case T_LEFT:
+                    continue;
+
+                case T_prefix:
+                    NeedSYMBOLorNUMBER();
+                    dimension->SetPrefix( FromUTF8() );
+                    NeedRIGHT();
+                    break;
+
+                case T_suffix:
+                    NeedSYMBOLorNUMBER();
+                    dimension->SetSuffix( FromUTF8() );
+                    NeedRIGHT();
+                    break;
+
+                case T_units:
+                {
+                    int mode = parseInt( "dimension units mode" );
+                    dimension->SetUnitsMode( static_cast<DIM_UNITS_MODE>( mode ) );
+                    NeedRIGHT();
+                    break;
+                }
+
+                case T_units_format:
+                {
+                    int format = parseInt( "dimension units format" );
+                    dimension->SetUnitsFormat( static_cast<DIM_UNITS_FORMAT>( format ) );
+                    NeedRIGHT();
+                    break;
+                }
+
+                case T_precision:
+                    dimension->SetPrecision( parseInt( "dimension precision" ) );
+                    NeedRIGHT();
+                    break;
+
+                case T_override_value:
+                    dimension->SetOverrideValue( true );
+                    break;
+
+                default:
+                    Expecting( "prefix, suffix, units, units_format, precision, override_value" );
+                }
+            }
+            break;
+        }
+
+        case T_style:
+        {
+            for( token = NextTok(); token != T_RIGHT; token = NextTok() )
+            {
+                switch( token )
+                {
+                case T_LEFT:
+                    continue;
+
+                case T_thickness:
+                    dimension->SetLineThickness( parseBoardUnits( "extension line thickness" ) );
+                    NeedRIGHT();
+                    break;
+
+                case T_arrow_length:
+                    dimension->SetArrowLength( parseBoardUnits( "arrow length" ) );
+                    NeedRIGHT();
+                    break;
+
+                case T_text_position_mode:
+                {
+                    int mode = parseInt( "dimension text position mode" );
+                    dimension->SetTextPositionMode( static_cast<DIM_TEXT_POSITION>( mode ) );
+                    NeedRIGHT();
+                    break;
+                }
+
+                case T_extension_height:
+                    dimension->SetExtensionHeight( parseBoardUnits( "extension height" ) );
+                    NeedRIGHT();
+                    break;
+
+                case T_extension_offset:
+                    dimension->SetExtensionOffset( parseBoardUnits( "extension offset" ) );
+                    NeedRIGHT();
+                    break;
+
+                default:
+                    Expecting( "thickness, arrow_length, text_position_mode, extension_height, "
+                               "extension_offset" );
+                }
+            }
+
+            break;
+        }
+
+        // Old format: feature1 stores a feature line.  We only care about the origin.
         case T_feature1:
+        {
             NeedLEFT();
             token = NextTok();
 
             if( token != T_pts )
                 Expecting( T_pts );
 
-            parseXY( &dimension->m_featureLineDO.x, &dimension->m_featureLineDO.y );
-            parseXY( &dimension->m_featureLineDF.x, &dimension->m_featureLineDF.y );
-            dimension->UpdateHeight();
+            wxPoint point;
+
+            parseXY( &point.x, &point.y );
+            dimension->SetStart( point );
+
+            parseXY( nullptr, nullptr ); // Ignore second point
             NeedRIGHT();
             NeedRIGHT();
             break;
+        }
 
+        // Old format: feature2 stores a feature line.  We only care about the end point.
         case T_feature2:
+        {
             NeedLEFT();
             token = NextTok();
 
             if( token != T_pts )
                 Expecting( T_pts );
 
-            parseXY( &dimension->m_featureLineGO.x, &dimension->m_featureLineGO.y );
-            parseXY( &dimension->m_featureLineGF.x, &dimension->m_featureLineGF.y );
-            dimension->UpdateHeight();
+            wxPoint point;
+
+            parseXY( &point.x, &point.y );
+            dimension->SetEnd( point );
+
+            parseXY( nullptr, nullptr ); // Ignore second point
+
             NeedRIGHT();
             NeedRIGHT();
             break;
-
+        }
 
         case T_crossbar:
+        {
             NeedLEFT();
             token = NextTok();
 
-            if( token != T_pts )
-                Expecting( T_pts );
+            if( token == T_pts )
+            {
+                // Old style: calculate height from crossbar
+                wxPoint point1, point2;
+                parseXY( &point1.x, &point1.y );
+                parseXY( &point2.x, &point2.y );
+                dimension->UpdateHeight( point2, point1 ); // Yes, backwards intentionally
+                NeedRIGHT();
+            }
 
-            parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
-            parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
-            dimension->UpdateHeight();
-            NeedRIGHT();
             NeedRIGHT();
             break;
+        }
 
+        // Arrow: no longer saved; no-op
         case T_arrow1a:
             NeedLEFT();
             token = NextTok();
@@ -2455,12 +2604,13 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
             if( token != T_pts )
                 Expecting( T_pts );
 
-            parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
-            parseXY( &dimension->m_arrowD1F.x, &dimension->m_arrowD1F.y );
+            parseXY( nullptr, nullptr );
+            parseXY( nullptr, nullptr );
             NeedRIGHT();
             NeedRIGHT();
             break;
 
+        // Arrow: no longer saved; no-op
         case T_arrow1b:
             NeedLEFT();
             token = NextTok();
@@ -2468,12 +2618,13 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
             if( token != T_pts )
                 Expecting( T_pts );
 
-            parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
-            parseXY( &dimension->m_arrowD2F.x, &dimension->m_arrowD2F.y );
+            parseXY( nullptr, nullptr );
+            parseXY( nullptr, nullptr );
             NeedRIGHT();
             NeedRIGHT();
             break;
 
+        // Arrow: no longer saved; no-op
         case T_arrow2a:
             NeedLEFT();
             token = NextTok();
@@ -2481,12 +2632,13 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
             if( token != T_pts )
                 Expecting( T_pts );
 
-            parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
-            parseXY( &dimension->m_arrowG1F.x, &dimension->m_arrowG1F.y );
+            parseXY( nullptr, nullptr );
+            parseXY( nullptr, nullptr );
             NeedRIGHT();
             NeedRIGHT();
             break;
 
+        // Arrow: no longer saved; no-op
         case T_arrow2b:
             NeedLEFT();
             token = NextTok();
@@ -2494,14 +2646,14 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
             if( token != T_pts )
                 Expecting( T_pts );
 
-            parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
-            parseXY( &dimension->m_arrowG2F.x, &dimension->m_arrowG2F.y );
+            parseXY( nullptr, nullptr );
+            parseXY( nullptr, nullptr );
             NeedRIGHT();
             NeedRIGHT();
             break;
 
         default:
-            Expecting( "layer, tstamp, gr_text, feature1, feature2 crossbar, arrow1a, "
+            Expecting( "layer, tstamp, gr_text, feature1, feature2, crossbar, arrow1a, "
                        "arrow1b, arrow2a, or arrow2b" );
         }
     }
diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp
index c14d8c5fc6..69b3cb78b0 100644
--- a/pcbnew/plot_brditems_plotter.cpp
+++ b/pcbnew/plot_brditems_plotter.cpp
@@ -360,7 +360,7 @@ void BRDITEMS_PLOTTER::PlotDimension( DIMENSION* aDim )
 
     DRAWSEGMENT draw;
 
-    draw.SetWidth( aDim->GetWidth() );
+    draw.SetWidth( aDim->GetLineThickness() );
     draw.SetLayer( aDim->GetLayer() );
 
     COLOR4D color = ColorSettings()->GetColor( aDim->GetLayer() );
@@ -371,33 +371,12 @@ void BRDITEMS_PLOTTER::PlotDimension( DIMENSION* aDim )
 
     PlotTextePcb( &aDim->Text() );
 
-    draw.SetStart( aDim->m_crossBarO );
-    draw.SetEnd( aDim->m_crossBarF );
-    PlotDrawSegment( &draw );
-
-    draw.SetStart( aDim->m_featureLineGO);
-    draw.SetEnd( aDim->m_featureLineGF );
-    PlotDrawSegment( &draw );
-
-    draw.SetStart( aDim->m_featureLineDO );
-    draw.SetEnd( aDim->m_featureLineDF );
-    PlotDrawSegment( &draw );
-
-    draw.SetStart( aDim->m_crossBarF );
-    draw.SetEnd( aDim->m_arrowD1F );
-    PlotDrawSegment( &draw );
-
-    draw.SetStart( aDim->m_crossBarF );
-    draw.SetEnd( aDim->m_arrowD2F );
-    PlotDrawSegment( &draw );
-
-    draw.SetStart( aDim->m_crossBarO );
-    draw.SetEnd( aDim->m_arrowG1F );
-    PlotDrawSegment( &draw );
-
-    draw.SetStart( aDim->m_crossBarO );
-    draw.SetEnd( aDim->m_arrowG2F );
-    PlotDrawSegment( &draw );
+    for( const SEG& seg : aDim->GetLines() )
+    {
+        draw.SetStart( wxPoint( seg.A ) );
+        draw.SetEnd( wxPoint( seg.B ) );
+        PlotDrawSegment( &draw );
+    }
 }
 
 
diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp
index 134e09762f..76f31b3d81 100644
--- a/pcbnew/plugins/altium/altium_pcb.cpp
+++ b/pcbnew/plugins/altium/altium_pcb.cpp
@@ -901,6 +901,7 @@ void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
     }
 
     PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
+
     if( klayer == UNDEFINED_LAYER )
     {
         wxLogWarning( wxString::Format(
@@ -912,11 +913,13 @@ void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
     wxPoint referencePoint0 = aElem.referencePoint.at( 0 );
     wxPoint referencePoint1 = aElem.referencePoint.at( 1 );
 
-    DIMENSION* dimension = new DIMENSION( m_board );
+    ALIGNED_DIMENSION* dimension = new ALIGNED_DIMENSION( m_board );
     m_board->Add( dimension, ADD_MODE::APPEND );
 
+    dimension->SetPrecision( aElem.textprecission );
     dimension->SetLayer( klayer );
-    dimension->SetOrigin( referencePoint0, aElem.textprecission );
+    dimension->SetStart( referencePoint0 );
+
     if( referencePoint0 != aElem.xy1 )
     {
         /**
@@ -933,21 +936,23 @@ void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
         SEG     segm1( referencePoint0, referencePoint0 + directionNormalVector );
         SEG     segm2( referencePoint1, referencePoint1 + direction );
         wxPoint intersection( segm1.Intersect( segm2, true, true ).get() );
-        dimension->SetEnd( intersection, aElem.textprecission );
+        dimension->SetEnd( intersection );
 
         int height = static_cast<int>( EuclideanNorm( direction ) );
+
         if( direction.x <= 0 && direction.y <= 0 ) // TODO: I suspect this is not always correct
         {
             height = -height;
         }
-        dimension->SetHeight( height, aElem.textprecission );
+
+        dimension->SetHeight( height );
     }
     else
     {
-        dimension->SetEnd( referencePoint1, aElem.textprecission );
+        dimension->SetEnd( referencePoint1 );
     }
 
-    dimension->SetWidth( aElem.linewidth );
+    dimension->SetLineThickness( aElem.linewidth );
 
     dimension->Text().SetTextThickness( aElem.textlinewidth );
     dimension->Text().SetTextSize( wxSize( aElem.textheight, aElem.textheight ) );
@@ -969,8 +974,6 @@ void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
     default:
         break;
     }
-
-    dimension->AdjustDimensionDetails( aElem.textprecission );
 }
 
 void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem )
diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp
index 2ded051c93..c4d66133d2 100644
--- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp
+++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp
@@ -793,14 +793,14 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadDimensions()
             case DIMENSION::SUBTYPE::DIRECT:
             case DIMENSION::SUBTYPE::ORTHOGONAL:
             {
-                ::DIMENSION* dimension = new ::DIMENSION( mBoard );
-                TEXTCODE     dimText   = getTextCode( csDim.Text.TextCodeID );
+                ::ALIGNED_DIMENSION* dimension = new ::ALIGNED_DIMENSION( mBoard );
+                TEXTCODE             dimText   = getTextCode( csDim.Text.TextCodeID );
                 mBoard->Add( dimension, ADD_MODE::APPEND );
 
                 dimension->SetLayer( getKiCadLayer( csDim.LayerID ) );
-                dimension->SetOrigin(
-                        getKiCadPoint( csDim.Line.Start ), csDim.Precision );
-                dimension->SetEnd( getKiCadPoint( csDim.Line.End ), csDim.Precision );
+                dimension->SetPrecision( csDim.Precision );
+                dimension->SetStart( getKiCadPoint( csDim.Line.Start ) );
+                dimension->SetEnd( getKiCadPoint( csDim.Line.End ) );
                 dimension->Text().SetTextThickness( getKiCadLength( dimText.LineWidth ) );
                 dimension->Text().SetTextSize( wxSize(
                         getKiCadLength( dimText.Width ), getKiCadLength( dimText.Height ) ) );
@@ -822,8 +822,6 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadDimensions()
                     dimension->SetUnits( EDA_UNITS::INCHES, true );
                     break;
                 }
-
-                dimension->AdjustDimensionDetails( csDim.Precision );
             }
                 continue;
 
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index 361704fcfa..ad8c9f17cf 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -593,10 +593,9 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
 
 void DRAWING_TOOL::constrainDimension( DIMENSION* aDim )
 {
-    const VECTOR2I lineVector{ aDim->GetEnd() - aDim->GetOrigin() };
+    const VECTOR2I lineVector{ aDim->GetEnd() - aDim->GetStart() };
 
-    aDim->SetEnd( wxPoint( VECTOR2I( aDim->GetOrigin() ) + GetVectorSnapped45( lineVector ) ),
-                  board()->GetDesignSettings().m_DimensionPrecision );
+    aDim->SetEnd( wxPoint( VECTOR2I( aDim->GetStart() ) + GetVectorSnapped45( lineVector ) ) );
 }
 
 
@@ -605,10 +604,10 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
     if( m_editModules && !m_frame->GetModel() )
         return 0;
 
-    POINT_EDITOR* pointEditor = m_toolMgr->GetTool<POINT_EDITOR>();
-    DIMENSION*    dimension = NULL;
-    BOARD_COMMIT  commit( m_frame );
-    GRID_HELPER   grid( m_toolMgr, m_frame->GetMagneticItemsSettings() );
+    POINT_EDITOR*     pointEditor = m_toolMgr->GetTool<POINT_EDITOR>();
+    ALIGNED_DIMENSION* dimension   = nullptr;
+    BOARD_COMMIT      commit( m_frame );
+    GRID_HELPER       grid( m_toolMgr, m_frame->GetMagneticItemsSettings() );
 
     const BOARD_DESIGN_SETTINGS& boardSettings = m_board->GetDesignSettings();
 
@@ -700,7 +699,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
         else if( evt->IsAction( &PCB_ACTIONS::incWidth ) && step != SET_ORIGIN )
         {
             m_lineWidth += WIDTH_STEP;
-            dimension->SetWidth( m_lineWidth );
+            dimension->SetLineThickness( m_lineWidth );
             m_view->Update( &preview );
             frame()->SetMsgPanel( dimension );
         }
@@ -709,7 +708,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
             if( m_lineWidth > WIDTH_STEP )
             {
                 m_lineWidth -= WIDTH_STEP;
-                dimension->SetWidth( m_lineWidth );
+                dimension->SetLineThickness( m_lineWidth );
                 m_view->Update( &preview );
                 frame()->SetMsgPanel( dimension );
             }
@@ -732,18 +731,18 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
                     layer = Dwgs_User;
 
                 // Init the new item attributes
-                dimension = new DIMENSION( m_board );
+                dimension = new ALIGNED_DIMENSION( m_board );
                 dimension->SetLayer( layer );
-                dimension->SetOrigin( (wxPoint) cursorPos, boardSettings.m_DimensionPrecision );
-                dimension->SetEnd( (wxPoint) cursorPos, boardSettings.m_DimensionPrecision );
+                dimension->SetPrecision( boardSettings.m_DimensionPrecision );
                 dimension->Text().SetTextSize( boardSettings.GetTextSize( layer ) );
                 dimension->Text().SetTextThickness( boardSettings.GetTextThickness( layer ) );
                 dimension->Text().SetItalic( boardSettings.GetTextItalic( layer ) );
-                dimension->SetWidth( boardSettings.GetLineThickness( layer ) );
+                dimension->SetLineThickness( boardSettings.GetLineThickness( layer ) );
                 dimension->SetUnits( boardSettings.m_DimensionUnits == 2 ? EDA_UNITS::MILLIMETRES :
                                                                            EDA_UNITS::INCHES,
-                        boardSettings.m_DimensionUnits == 1 );
-                dimension->AdjustDimensionDetails( boardSettings.m_DimensionPrecision );
+                                     boardSettings.m_DimensionUnits == 1 );
+                dimension->SetStart( (wxPoint) cursorPos );
+                dimension->SetEnd( (wxPoint) cursorPos );
 
                 preview.Add( dimension );
 
@@ -753,13 +752,13 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
             break;
 
             case SET_END:
-                dimension->SetEnd( (wxPoint) cursorPos, boardSettings.m_DimensionPrecision );
+                dimension->SetEnd( (wxPoint) cursorPos );
 
                 if( !!evt->Modifier( MD_CTRL ) )
                     constrainDimension( dimension );
 
                 // Dimensions that have origin and end in the same spot are not valid
-                if( dimension->GetOrigin() == dimension->GetEnd() )
+                if( dimension->GetStart() == dimension->GetEnd() )
                     --step;
 
                 break;
@@ -768,8 +767,8 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
             {
                 if( (wxPoint) cursorPos != dimension->GetPosition() )
                 {
-                    assert( dimension->GetOrigin() != dimension->GetEnd() );
-                    assert( dimension->GetWidth() > 0 );
+                    assert( dimension->GetStart() != dimension->GetEnd() );
+                    assert( dimension->GetLineThickness() > 0 );
 
                     preview.Remove( dimension );
 
@@ -794,7 +793,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
             switch( step )
             {
             case SET_END:
-                dimension->SetEnd( (wxPoint) cursorPos, boardSettings.m_DimensionPrecision );
+                dimension->SetEnd( (wxPoint) cursorPos );
 
                 if( !!evt->Modifier( MD_CTRL ) )
                     constrainDimension( dimension );
@@ -806,9 +805,9 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
                 // Calculating the direction of travel perpendicular to the selected axis
                 double angle = dimension->GetAngle() + ( M_PI / 2 );
 
-                wxPoint delta( (wxPoint) cursorPos - dimension->m_featureLineDO );
+                wxPoint delta( (wxPoint) cursorPos - dimension->GetEnd() );
                 double  height = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) );
-                dimension->SetHeight( height, boardSettings.m_DimensionPrecision );
+                dimension->SetHeight( height );
             }
             break;
             }
diff --git a/pcbnew/tools/grid_helper.cpp b/pcbnew/tools/grid_helper.cpp
index 969ed48eca..3cc50b293e 100644
--- a/pcbnew/tools/grid_helper.cpp
+++ b/pcbnew/tools/grid_helper.cpp
@@ -551,11 +551,11 @@ void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bo
 
         case PCB_DIMENSION_T:
         {
-            const DIMENSION* dim = static_cast<const DIMENSION*>( aItem );
-            addAnchor( dim->m_crossBarF, CORNER | SNAPPABLE, aItem );
-            addAnchor( dim->m_crossBarO, CORNER | SNAPPABLE, aItem );
-            addAnchor( dim->m_featureLineGO, CORNER | SNAPPABLE, aItem );
-            addAnchor( dim->m_featureLineDO, CORNER | SNAPPABLE, aItem );
+            const ALIGNED_DIMENSION* dim = static_cast<const ALIGNED_DIMENSION*>( aItem );
+            addAnchor( dim->GetCrossbarStart(), CORNER | SNAPPABLE, aItem );
+            addAnchor( dim->GetCrossbarEnd(), CORNER | SNAPPABLE, aItem );
+            addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
+            addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
             break;
         }
 
diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp
index 2a30a27c90..ea5dd3af38 100644
--- a/pcbnew/tools/point_editor.cpp
+++ b/pcbnew/tools/point_editor.cpp
@@ -76,10 +76,10 @@ enum BEZIER_CURVE_POINTS
 
 enum DIMENSION_POINTS
 {
-    DIM_CROSSBARO,
-    DIM_CROSSBARF,
-    DIM_FEATUREGO,
-    DIM_FEATUREDO,
+    DIM_CROSSBARSTART,
+    DIM_CROSSBAREND,
+    DIM_START,
+    DIM_END,
 };
 
 class EDIT_POINTS_FACTORY
@@ -245,18 +245,18 @@ public:
 
         case PCB_DIMENSION_T:
         {
-            const DIMENSION* dimension = static_cast<const DIMENSION*>( aItem );
+            const ALIGNED_DIMENSION* dimension = static_cast<const ALIGNED_DIMENSION*>( aItem );
 
-            points->AddPoint( dimension->m_crossBarO );
-            points->AddPoint( dimension->m_crossBarF );
-            points->AddPoint( dimension->m_featureLineGO );
-            points->AddPoint( dimension->m_featureLineDO );
+            points->AddPoint( dimension->GetCrossbarStart() );
+            points->AddPoint( dimension->GetCrossbarEnd() );
+            points->AddPoint( dimension->GetStart() );
+            points->AddPoint( dimension->GetEnd() );
 
             // Dimension height setting - edit points should move only along the feature lines
-            points->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARO ),
-                                                                       points->Point( DIM_FEATUREGO ) ) );
-            points->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARF ),
-                                                                       points->Point( DIM_FEATUREDO ) ) );
+            points->Point( DIM_CROSSBARSTART ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARSTART ),
+                                                                       points->Point( DIM_START ) ) );
+            points->Point( DIM_CROSSBAREND ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBAREND ),
+                                                                       points->Point( DIM_END ) ) );
         }
             break;
 
@@ -970,8 +970,6 @@ void POINT_EDITOR::updateItem() const
 {
     EDA_ITEM* item = m_editPoints->GetParent();
 
-    const BOARD_DESIGN_SETTINGS& boardSettings = board()->GetDesignSettings();
-
     if( !item )
         return;
 
@@ -1254,49 +1252,49 @@ void POINT_EDITOR::updateItem() const
 
     case PCB_DIMENSION_T:
     {
-        DIMENSION* dimension = static_cast<DIMENSION*>( item );
+        ALIGNED_DIMENSION* dimension = static_cast<ALIGNED_DIMENSION*>( item );
 
         // Check which point is currently modified and updated dimension's points respectively
-        if( isModified( m_editPoints->Point( DIM_CROSSBARO ) ) )
+        if( isModified( m_editPoints->Point( DIM_CROSSBARSTART ) ) )
         {
-            VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetOrigin() );
-            VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
+            VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetStart() );
+            VECTOR2D crossBar( dimension->GetEnd() - dimension->GetStart() );
 
             if( featureLine.Cross( crossBar ) > 0 )
-                dimension->SetHeight( -featureLine.EuclideanNorm(), boardSettings.m_DimensionPrecision );
+                dimension->SetHeight( -featureLine.EuclideanNorm() );
             else
-                dimension->SetHeight( featureLine.EuclideanNorm(), boardSettings.m_DimensionPrecision );
+                dimension->SetHeight( featureLine.EuclideanNorm() );
         }
 
-        else if( isModified( m_editPoints->Point( DIM_CROSSBARF ) ) )
+        else if( isModified( m_editPoints->Point( DIM_CROSSBAREND ) ) )
         {
             VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetEnd() );
-            VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
+            VECTOR2D crossBar( dimension->GetEnd() - dimension->GetStart() );
 
             if( featureLine.Cross( crossBar ) > 0 )
-                dimension->SetHeight( -featureLine.EuclideanNorm(), boardSettings.m_DimensionPrecision );
+                dimension->SetHeight( -featureLine.EuclideanNorm() );
             else
-                dimension->SetHeight( featureLine.EuclideanNorm(), boardSettings.m_DimensionPrecision );
+                dimension->SetHeight( featureLine.EuclideanNorm() );
         }
 
-        else if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
+        else if( isModified( m_editPoints->Point( DIM_START ) ) )
         {
-            dimension->SetOrigin( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ),
-                                  boardSettings.m_DimensionPrecision );
-            m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
-                                                                             m_editPoints->Point( DIM_FEATUREGO ) ) );
-            m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
-                                                                             m_editPoints->Point( DIM_FEATUREDO ) ) );
+            dimension->SetStart( wxPoint( m_editedPoint->GetPosition().x,
+                                          m_editedPoint->GetPosition().y ) );
+            m_editPoints->Point( DIM_CROSSBARSTART ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARSTART ),
+                                                                             m_editPoints->Point( DIM_START ) ) );
+            m_editPoints->Point( DIM_CROSSBAREND ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBAREND ),
+                                                                             m_editPoints->Point( DIM_END ) ) );
         }
 
-        else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
+        else if( isModified( m_editPoints->Point( DIM_END ) ) )
         {
-            dimension->SetEnd( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) ,
-                               boardSettings.m_DimensionPrecision );
-            m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
-                                                                             m_editPoints->Point( DIM_FEATUREGO ) ) );
-            m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
-                                                                             m_editPoints->Point( DIM_FEATUREDO ) ) );
+            dimension->SetEnd( wxPoint( m_editedPoint->GetPosition().x,
+                                        m_editedPoint->GetPosition().y ) );
+            m_editPoints->Point( DIM_CROSSBARSTART ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARSTART ),
+                                                                             m_editPoints->Point( DIM_START ) ) );
+            m_editPoints->Point( DIM_CROSSBAREND ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBAREND ),
+                                                                             m_editPoints->Point( DIM_END ) ) );
         }
 
         break;
@@ -1521,12 +1519,12 @@ void POINT_EDITOR::updatePoints()
 
     case PCB_DIMENSION_T:
     {
-        const DIMENSION* dimension = static_cast<const DIMENSION*>( item );
+        const ALIGNED_DIMENSION* dimension = static_cast<const ALIGNED_DIMENSION*>( item );
 
-        m_editPoints->Point( DIM_CROSSBARO ).SetPosition( dimension->m_crossBarO );
-        m_editPoints->Point( DIM_CROSSBARF ).SetPosition( dimension->m_crossBarF );
-        m_editPoints->Point( DIM_FEATUREGO ).SetPosition( dimension->m_featureLineGO );
-        m_editPoints->Point( DIM_FEATUREDO ).SetPosition( dimension->m_featureLineDO );
+        m_editPoints->Point( DIM_CROSSBARSTART ).SetPosition( dimension->GetCrossbarStart() );
+        m_editPoints->Point( DIM_CROSSBAREND ).SetPosition( dimension->GetCrossbarEnd() );
+        m_editPoints->Point( DIM_START ).SetPosition( dimension->GetStart() );
+        m_editPoints->Point( DIM_END ).SetPosition( dimension->GetEnd() );
         break;
     }
 
@@ -1627,11 +1625,11 @@ EDIT_POINT POINT_EDITOR::get45DegConstrainer() const
     case PCB_DIMENSION_T:
     {
         // Constraint for crossbar
-        if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
-            return m_editPoints->Point( DIM_FEATUREDO );
+        if( isModified( m_editPoints->Point( DIM_START ) ) )
+            return m_editPoints->Point( DIM_END );
 
-        else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
-            return m_editPoints->Point( DIM_FEATUREGO );
+        else if( isModified( m_editPoints->Point( DIM_END ) ) )
+            return m_editPoints->Point( DIM_START );
 
         else
             return EDIT_POINT( m_editedPoint->GetPosition() );      // no constraint