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