From 1ae47b6069e54da89fa43896ab25a18f68e985b3 Mon Sep 17 00:00:00 2001
From: Jeff Young <jeff@rokeby.ie>
Date: Fri, 5 Apr 2019 17:10:59 +0100
Subject: [PATCH] Implement a copper-to-edge-clearance setting.

For legacy boards, the setting is picked up from the board outline
thickness.  If the board outline has mixed thicknesses, then the
max is used and a warning is displayed.

Fixes: lp:1797787
* https://bugs.launchpad.net/kicad/+bug/1797787
---
 3d-viewer/3d_canvas/create_layer_items.cpp    |   2 +-
 include/board_design_settings.h               |  11 +
 pcbnew/board_design_settings.cpp              |  26 +-
 ...board_items_to_polygon_shape_transform.cpp |   2 +-
 .../panel_setup_feature_constraints.cpp       |   7 +-
 .../dialogs/panel_setup_feature_constraints.h |   1 +
 .../panel_setup_feature_constraints_base.cpp  |  22 +-
 .../panel_setup_feature_constraints_base.fbp  | 288 +++++++++++++++++-
 .../panel_setup_feature_constraints_base.h    |   5 +-
 pcbnew/drc_clearance_test_functions.cpp       |   8 +-
 pcbnew/files.cpp                              |  48 +++
 pcbnew/pcb_edit_frame.h                       |   5 +
 pcbnew/zone_filler.cpp                        |  16 +-
 template/kicad.pro                            |   3 +-
 14 files changed, 417 insertions(+), 27 deletions(-)

diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp
index e0d3a72ec6..313b470400 100644
--- a/3d-viewer/3d_canvas/create_layer_items.cpp
+++ b/3d-viewer/3d_canvas/create_layer_items.cpp
@@ -690,7 +690,7 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter )
 
             switch( item->Type() )
             {
-            case PCB_LINE_T:  // should not exist on copper layers
+            case PCB_LINE_T:
             {
                 AddShapeWithClearanceToContainer( (DRAWSEGMENT*)item,
                                                   layerContainer,
diff --git a/include/board_design_settings.h b/include/board_design_settings.h
index 58cc0d0413..38060c5a48 100644
--- a/include/board_design_settings.h
+++ b/include/board_design_settings.h
@@ -66,6 +66,10 @@
 #define DEFAULT_MICROVIASMINDRILL     0.1     // micro vias (not vias) min drill diameter
 #define DEFAULT_HOLETOHOLEMIN         0.25    // separation between drilled hole edges
 
+#define DEFAULT_COPPEREDGECLEARANCE   0.01    // clearance between copper items and edge cuts
+#define LEGACY_COPPEREDGECLEARANCE   -0.01    // A flag to indicate the legacy method (based
+                                              // on edge cut line thicknesses) should be used.
+
 /**
  * Struct VIA_DIMENSION
  * is a small helper container to handle a stock of specific vias each with
@@ -189,6 +193,7 @@ public:
     int        m_ViasMinDrill;              ///< vias (not micro vias) min drill diameter
     int        m_MicroViasMinSize;          ///< micro vias (not vias) min diameter
     int        m_MicroViasMinDrill;         ///< micro vias (not vias) min drill diameter
+    int        m_CopperEdgeClearance;
 
     // Global mask margins:
     int        m_SolderMaskMargin;          ///< Solder mask margin
@@ -631,6 +636,12 @@ public:
      */
     void SetMinHoleSeparation( int aDistance );
 
+    /**
+     * Function SetCopperEdgeClearance
+     * @param aValue The minimum distance between copper items and board edges.
+     */
+    void SetCopperEdgeClearance( int aDistance );
+
     /**
      * Function SetRequireCourtyardDefinitions
      * @param aRequire Set to true to generate DRC violations from missing courtyards.
diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp
index d9512d854c..732eef8244 100644
--- a/pcbnew/board_design_settings.cpp
+++ b/pcbnew/board_design_settings.cpp
@@ -489,11 +489,12 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() :
     m_customDiffPair.m_Gap = Millimeter2iu( DEFAULT_CUSTOMDPAIRGAP );
     m_customDiffPair.m_ViaGap = Millimeter2iu( DEFAULT_CUSTOMDPAIRVIAGAP );
 
-    m_TrackMinWidth     = Millimeter2iu( DEFAULT_TRACKMINWIDTH );
-    m_ViasMinSize       = Millimeter2iu( DEFAULT_VIASMINSIZE );
-    m_ViasMinDrill      = Millimeter2iu( DEFAULT_VIASMINDRILL );
-    m_MicroViasMinSize  = Millimeter2iu( DEFAULT_MICROVIASMINSIZE );
-    m_MicroViasMinDrill = Millimeter2iu( DEFAULT_MICROVIASMINDRILL );
+    m_TrackMinWidth       = Millimeter2iu( DEFAULT_TRACKMINWIDTH );
+    m_ViasMinSize         = Millimeter2iu( DEFAULT_VIASMINSIZE );
+    m_ViasMinDrill        = Millimeter2iu( DEFAULT_VIASMINDRILL );
+    m_MicroViasMinSize    = Millimeter2iu( DEFAULT_MICROVIASMINSIZE );
+    m_MicroViasMinDrill   = Millimeter2iu( DEFAULT_MICROVIASMINDRILL );
+    m_CopperEdgeClearance = Millimeter2iu( DEFAULT_COPPEREDGECLEARANCE );
 
     // Global mask margins:
     m_SolderMaskMargin  = Millimeter2iu( DEFAULT_SOLDERMASK_CLEARANCE );
@@ -564,7 +565,14 @@ void BOARD_DESIGN_SETTINGS::AppendConfigs( BOARD* aBoard, PARAM_CFG_ARRAY* aResu
 
     aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "MinHoleToHole" ),
           &m_HoleToHoleMin,
-          Millimeter2iu( DEFAULT_HOLETOHOLEMIN ), 0, Millimeter2iu( 10.0 ),
+          Millimeter2iu( DEFAULT_HOLETOHOLEMIN ), Millimeter2iu( 0.0 ), Millimeter2iu( 10.0 ),
+          nullptr, MM_PER_IU ) );
+
+    // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
+    // based on the edge cut thicknesses.
+    aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "CopperEdgeClearance" ),
+          &m_CopperEdgeClearance,
+          Millimeter2iu( LEGACY_COPPEREDGECLEARANCE ), Millimeter2iu( -0.01 ), Millimeter2iu( 25.0 ),
           nullptr, MM_PER_IU ) );
 
     aResult->push_back( new PARAM_CFG_TRACKWIDTHS( &m_TrackWidthList ) );
@@ -850,6 +858,12 @@ void BOARD_DESIGN_SETTINGS::SetMinHoleSeparation( int aDistance )
 }
 
 
+void BOARD_DESIGN_SETTINGS::SetCopperEdgeClearance( int aDistance )
+{
+    m_CopperEdgeClearance = aDistance;
+}
+
+
 void BOARD_DESIGN_SETTINGS::SetRequireCourtyardDefinitions( bool aRequire )
 {
     m_RequireCourtyards = aRequire;
diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp
index ec9de9285b..695dc93a00 100644
--- a/pcbnew/board_items_to_polygon_shape_transform.cpp
+++ b/pcbnew/board_items_to_polygon_shape_transform.cpp
@@ -123,7 +123,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
 
         switch( item->Type() )
         {
-        case PCB_LINE_T:    // should not exist on copper layers
+        case PCB_LINE_T:
             ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
                 aOutlines, 0, segcountforcircle, correctionFactor );
             break;
diff --git a/pcbnew/dialogs/panel_setup_feature_constraints.cpp b/pcbnew/dialogs/panel_setup_feature_constraints.cpp
index a949a3592d..6074e98be8 100644
--- a/pcbnew/dialogs/panel_setup_feature_constraints.cpp
+++ b/pcbnew/dialogs/panel_setup_feature_constraints.cpp
@@ -37,7 +37,8 @@ PANEL_SETUP_FEATURE_CONSTRAINTS::PANEL_SETUP_FEATURE_CONSTRAINTS( PAGED_DIALOG*
         m_viaMinDrill( aFrame, m_ViaMinDrillTitle, m_SetViasMinDrillCtrl, m_ViaMinDrillUnits, true ),
         m_uviaMinSize( aFrame, m_uviaMinSizeLabel, m_uviaMinSizeCtrl, m_uviaMinSizeUnits, true ),
         m_uviaMinDrill( aFrame, m_uviaMinDrillLabel, m_uviaMinDrillCtrl, m_uviaMinDrillUnits, true ),
-        m_holeToHoleMin( aFrame, m_HoleToHoleTitle, m_SetHoleToHoleCtrl, m_HoleToHoleUnits, true )
+        m_holeToHoleMin( aFrame, m_HoleToHoleTitle, m_SetHoleToHoleCtrl, m_HoleToHoleUnits, true ),
+        m_edgeClearance( aFrame, m_EdgeClearanceLabel, m_EdgeClearanceCtrl, m_EdgeClearanceUnits, true )
 {
     m_Frame = aFrame;
     m_BrdSettings = &m_Frame->GetBoard()->GetDesignSettings();
@@ -58,6 +59,8 @@ bool PANEL_SETUP_FEATURE_CONSTRAINTS::TransferDataToWindow()
 
     m_holeToHoleMin.SetValue( m_BrdSettings->m_HoleToHoleMin );
 
+    m_edgeClearance.SetValue( m_BrdSettings->m_CopperEdgeClearance );
+
     m_OptRequireCourtyards->SetValue( m_BrdSettings->m_RequireCourtyards );
     m_OptOverlappingCourtyards->SetValue( m_BrdSettings->m_ProhibitOverlappingCourtyards );
 
@@ -83,6 +86,8 @@ bool PANEL_SETUP_FEATURE_CONSTRAINTS::TransferDataFromWindow()
 
     m_BrdSettings->SetMinHoleSeparation( m_holeToHoleMin.GetValue() );
 
+    m_BrdSettings->SetCopperEdgeClearance( m_edgeClearance.GetValue() );
+
     m_BrdSettings->SetRequireCourtyardDefinitions( m_OptRequireCourtyards->GetValue() );
     m_BrdSettings->SetProhibitOverlappingCourtyards( m_OptOverlappingCourtyards->GetValue() );
 
diff --git a/pcbnew/dialogs/panel_setup_feature_constraints.h b/pcbnew/dialogs/panel_setup_feature_constraints.h
index 5c17315d1e..cb52de17da 100644
--- a/pcbnew/dialogs/panel_setup_feature_constraints.h
+++ b/pcbnew/dialogs/panel_setup_feature_constraints.h
@@ -47,6 +47,7 @@ public:
     UNIT_BINDER             m_uviaMinSize;
     UNIT_BINDER             m_uviaMinDrill;
     UNIT_BINDER             m_holeToHoleMin;
+    UNIT_BINDER             m_edgeClearance;
 
 public:
     PANEL_SETUP_FEATURE_CONSTRAINTS( PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFrame );
diff --git a/pcbnew/dialogs/panel_setup_feature_constraints_base.cpp b/pcbnew/dialogs/panel_setup_feature_constraints_base.cpp
index 2408dd134b..f5573a8121 100644
--- a/pcbnew/dialogs/panel_setup_feature_constraints_base.cpp
+++ b/pcbnew/dialogs/panel_setup_feature_constraints_base.cpp
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun  5 2018)
+// C++ code generated with wxFormBuilder (version Dec 30 2017)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO *NOT* EDIT THIS FILE!
@@ -143,6 +143,26 @@ PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWi
 	fgFeatureConstraints->Add( m_HoleToHoleUnits, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 );
 	
 	
+	fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
+	
+	
+	fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
+	
+	
+	fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
+	
+	m_EdgeClearanceLabel = new wxStaticText( this, wxID_ANY, _("Copper edge clearance:"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_EdgeClearanceLabel->Wrap( -1 );
+	fgFeatureConstraints->Add( m_EdgeClearanceLabel, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 );
+	
+	m_EdgeClearanceCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+	fgFeatureConstraints->Add( m_EdgeClearanceCtrl, 0, wxALL|wxEXPAND, 5 );
+	
+	m_EdgeClearanceUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_EdgeClearanceUnits->Wrap( -1 );
+	fgFeatureConstraints->Add( m_EdgeClearanceUnits, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 );
+	
+	
 	sbFeatureConstraints->Add( fgFeatureConstraints, 1, wxEXPAND|wxTOP|wxLEFT, 5 );
 	
 	
diff --git a/pcbnew/dialogs/panel_setup_feature_constraints_base.fbp b/pcbnew/dialogs/panel_setup_feature_constraints_base.fbp
index 95329ccec1..fe2bc0f2c5 100644
--- a/pcbnew/dialogs/panel_setup_feature_constraints_base.fbp
+++ b/pcbnew/dialogs/panel_setup_feature_constraints_base.fbp
@@ -14,7 +14,6 @@
         <property name="file">panel_setup_feature_constraints_base</property>
         <property name="first_id">1000</property>
         <property name="help_provider">none</property>
-        <property name="indent_with_spaces"></property>
         <property name="internationalize">1</property>
         <property name="name">panel_setup_feature_constraints_base</property>
         <property name="namespace"></property>
@@ -2124,6 +2123,293 @@
                                         <event name="OnUpdateUI"></event>
                                     </object>
                                 </object>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxEXPAND</property>
+                                    <property name="proportion">1</property>
+                                    <object class="spacer" expanded="1">
+                                        <property name="height">0</property>
+                                        <property name="permission">protected</property>
+                                        <property name="width">0</property>
+                                    </object>
+                                </object>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxEXPAND</property>
+                                    <property name="proportion">1</property>
+                                    <object class="spacer" expanded="1">
+                                        <property name="height">0</property>
+                                        <property name="permission">protected</property>
+                                        <property name="width">0</property>
+                                    </object>
+                                </object>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxEXPAND</property>
+                                    <property name="proportion">1</property>
+                                    <object class="spacer" expanded="1">
+                                        <property name="height">0</property>
+                                        <property name="permission">protected</property>
+                                        <property name="width">0</property>
+                                    </object>
+                                </object>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxTOP|wxBOTTOM|wxRIGHT</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">Copper edge clearance:</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_EdgeClearanceLabel</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>
+                                        <event name="OnChar"></event>
+                                        <event name="OnEnterWindow"></event>
+                                        <event name="OnEraseBackground"></event>
+                                        <event name="OnKeyDown"></event>
+                                        <event name="OnKeyUp"></event>
+                                        <event name="OnKillFocus"></event>
+                                        <event name="OnLeaveWindow"></event>
+                                        <event name="OnLeftDClick"></event>
+                                        <event name="OnLeftDown"></event>
+                                        <event name="OnLeftUp"></event>
+                                        <event name="OnMiddleDClick"></event>
+                                        <event name="OnMiddleDown"></event>
+                                        <event name="OnMiddleUp"></event>
+                                        <event name="OnMotion"></event>
+                                        <event name="OnMouseEvents"></event>
+                                        <event name="OnMouseWheel"></event>
+                                        <event name="OnPaint"></event>
+                                        <event name="OnRightDClick"></event>
+                                        <event name="OnRightDown"></event>
+                                        <event name="OnRightUp"></event>
+                                        <event name="OnSetFocus"></event>
+                                        <event name="OnSize"></event>
+                                        <event name="OnUpdateUI"></event>
+                                    </object>
+                                </object>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxALL|wxEXPAND</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_EdgeClearanceCtrl</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="OnChar"></event>
+                                        <event name="OnEnterWindow"></event>
+                                        <event name="OnEraseBackground"></event>
+                                        <event name="OnKeyDown"></event>
+                                        <event name="OnKeyUp"></event>
+                                        <event name="OnKillFocus"></event>
+                                        <event name="OnLeaveWindow"></event>
+                                        <event name="OnLeftDClick"></event>
+                                        <event name="OnLeftDown"></event>
+                                        <event name="OnLeftUp"></event>
+                                        <event name="OnMiddleDClick"></event>
+                                        <event name="OnMiddleDown"></event>
+                                        <event name="OnMiddleUp"></event>
+                                        <event name="OnMotion"></event>
+                                        <event name="OnMouseEvents"></event>
+                                        <event name="OnMouseWheel"></event>
+                                        <event name="OnPaint"></event>
+                                        <event name="OnRightDClick"></event>
+                                        <event name="OnRightDown"></event>
+                                        <event name="OnRightUp"></event>
+                                        <event name="OnSetFocus"></event>
+                                        <event name="OnSize"></event>
+                                        <event name="OnText"></event>
+                                        <event name="OnTextEnter"></event>
+                                        <event name="OnTextMaxLen"></event>
+                                        <event name="OnTextURL"></event>
+                                        <event name="OnUpdateUI"></event>
+                                    </object>
+                                </object>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxTOP|wxBOTTOM|wxRIGHT</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">mm</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_EdgeClearanceUnits</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>
+                                        <event name="OnChar"></event>
+                                        <event name="OnEnterWindow"></event>
+                                        <event name="OnEraseBackground"></event>
+                                        <event name="OnKeyDown"></event>
+                                        <event name="OnKeyUp"></event>
+                                        <event name="OnKillFocus"></event>
+                                        <event name="OnLeaveWindow"></event>
+                                        <event name="OnLeftDClick"></event>
+                                        <event name="OnLeftDown"></event>
+                                        <event name="OnLeftUp"></event>
+                                        <event name="OnMiddleDClick"></event>
+                                        <event name="OnMiddleDown"></event>
+                                        <event name="OnMiddleUp"></event>
+                                        <event name="OnMotion"></event>
+                                        <event name="OnMouseEvents"></event>
+                                        <event name="OnMouseWheel"></event>
+                                        <event name="OnPaint"></event>
+                                        <event name="OnRightDClick"></event>
+                                        <event name="OnRightDown"></event>
+                                        <event name="OnRightUp"></event>
+                                        <event name="OnSetFocus"></event>
+                                        <event name="OnSize"></event>
+                                        <event name="OnUpdateUI"></event>
+                                    </object>
+                                </object>
                             </object>
                         </object>
                     </object>
diff --git a/pcbnew/dialogs/panel_setup_feature_constraints_base.h b/pcbnew/dialogs/panel_setup_feature_constraints_base.h
index ce42aba445..ea21254f1e 100644
--- a/pcbnew/dialogs/panel_setup_feature_constraints_base.h
+++ b/pcbnew/dialogs/panel_setup_feature_constraints_base.h
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun  5 2018)
+// C++ code generated with wxFormBuilder (version Dec 30 2017)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO *NOT* EDIT THIS FILE!
@@ -55,6 +55,9 @@ class PANEL_SETUP_FEATURE_CONSTRAINTS_BASE : public wxPanel
 		wxStaticText* m_HoleToHoleTitle;
 		wxTextCtrl* m_SetHoleToHoleCtrl;
 		wxStaticText* m_HoleToHoleUnits;
+		wxStaticText* m_EdgeClearanceLabel;
+		wxTextCtrl* m_EdgeClearanceCtrl;
+		wxStaticText* m_EdgeClearanceUnits;
 	
 	public:
 		
diff --git a/pcbnew/drc_clearance_test_functions.cpp b/pcbnew/drc_clearance_test_functions.cpp
index e8e7a60b1f..678bb844b9 100644
--- a/pcbnew/drc_clearance_test_functions.cpp
+++ b/pcbnew/drc_clearance_test_functions.cpp
@@ -737,10 +737,10 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool aTestPads, bool aTestZ
     {
         SEG test_seg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
 
-        // the minimum distance = clearance plus half the reference track
-        // width.  Board edges do not have width or clearance values, so we
-        // look for simple crossing.
-        SEG::ecoord w_dist = aRefSeg->GetClearance() + aRefSeg->GetWidth() / 2;
+        int clearance = std::max( aRefSeg->GetClearance(), dsnSettings.m_CopperEdgeClearance );
+
+        // the minimum distance = clearance plus half the reference track width
+        SEG::ecoord w_dist = clearance + aRefSeg->GetWidth() / 2;
         w_dist *= w_dist;
 
         for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp
index 939fe4830d..1dc1f587ca 100644
--- a/pcbnew/files.cpp
+++ b/pcbnew/files.cpp
@@ -384,6 +384,48 @@ IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
 }
 
 
+int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard )
+{
+    PCB_LAYER_COLLECTOR collector;
+
+    collector.SetLayerId( Edge_Cuts );
+    collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
+
+    int  edgeWidth = -1;
+    bool mixed = false;
+
+    for( int i = 0; i < collector.GetCount(); i++ )
+    {
+        if( collector[i]->Type() == PCB_LINE_T )
+        {
+            int itemWidth = static_cast<DRAWSEGMENT*>( collector[i] )->GetWidth();
+
+            if( edgeWidth != -1 && edgeWidth != itemWidth )
+            {
+                mixed = true;
+                edgeWidth = std::max( edgeWidth, itemWidth );
+            }
+            else
+            {
+                edgeWidth = itemWidth;
+            }
+        }
+    }
+
+    if( mixed )
+    {
+        // If they had different widths then we can't ensure that fills will be the same.
+        wxMessageBox( _( "If the zones on this board are refilled the Copper Edge Clearance\n"
+                         "setting will be used (see Board Setup > Design Rules).  This may\n"
+                         "result in different fills from previous Kicad versions which used\n"
+                         "the line thickness of the board boundary on the Edge Cuts layer." ),
+                      _( "Edge Clearance Warning" ), wxOK|wxICON_WARNING, this );
+    }
+
+    return std::max( 0, edgeWidth / 2 );
+}
+
+
 bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
 {
     // This is for python:
@@ -518,6 +560,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
         std::copy( configBds.m_TextItalic,  configBds.m_TextItalic + 4,  bds.m_TextItalic );
         std::copy( configBds.m_TextUpright, configBds.m_TextUpright + 4, bds.m_TextUpright );
         bds.m_DiffPairDimensionsList            = configBds.m_DiffPairDimensionsList;
+        bds.m_CopperEdgeClearance               = configBds.m_CopperEdgeClearance;
 
         bds.SetElementVisibility( LAYER_GRID,     configBds.IsElementVisible( LAYER_GRID ) );
         bds.SetElementVisibility( LAYER_RATSNEST, configBds.IsElementVisible( LAYER_RATSNEST ) );
@@ -528,6 +571,11 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
         loadedBoard->BuildListOfNets();
         loadedBoard->SynchronizeNetsAndNetClasses();
 
+        // If this is a legacy board then we set the copper edge clearance to 1/2 the edge-cut
+        // line width (which was a legacy kludge for implementing edge clearances).
+        if( bds.m_CopperEdgeClearance == Millimeter2iu( LEGACY_COPPEREDGECLEARANCE ) )
+            bds.SetCopperEdgeClearance( inferLegacyEdgeClearance( loadedBoard ) );
+
         GetScreen()->ClrModify();
 
         if( pluginType == IO_MGR::LEGACY &&
diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h
index a916893b27..13d0c0ff6a 100644
--- a/pcbnew/pcb_edit_frame.h
+++ b/pcbnew/pcb_edit_frame.h
@@ -264,6 +264,11 @@ protected:
      */
     bool importFile( const wxString& aFileName, int aFileType );
 
+    /**
+     * Use the existing edge_cut line thicknesses to infer the edge clearace.
+     */
+    int inferLegacyEdgeClearance( BOARD* aBoard );
+
     /**
      * Rematch orphaned zones and vias to schematic nets.
      */
diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp
index c7bf8308ac..1ae0c2d05c 100644
--- a/pcbnew/zone_filler.cpp
+++ b/pcbnew/zone_filler.cpp
@@ -332,15 +332,15 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone,
 
     aFeatures.RemoveAllContours();
 
-    int outline_half_thickness = aZone->GetMinThickness() / 2;
+    int zone_clearance = aZone->GetClearance();
+    int edgeClearance = m_board->GetDesignSettings().m_CopperEdgeClearance;
+    int zone_to_edgecut_clearance = std::max( aZone->GetZoneClearance(), edgeClearance );
 
     // When removing holes, the holes must be expanded by outline_half_thickness
     // to take in account the thickness of the zone outlines
-    int zone_clearance = aZone->GetClearance() + outline_half_thickness;
-
-    // When holes are created by non copper items (edge cut items), use only
-    // the m_ZoneClearance parameter (zone clearance with no netclass clearance)
-    int zone_to_edgecut_clearance = aZone->GetZoneClearance() + outline_half_thickness;
+    int outline_half_thickness = aZone->GetMinThickness() / 2;
+    zone_clearance += outline_half_thickness;
+    zone_to_edgecut_clearance += outline_half_thickness;
 
     /* store holes (i.e. tracks and pads areas as polygons outlines)
      * in a polygon list
@@ -531,12 +531,8 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone,
             // the netclass value, because we do not have a copper item
             zclearance = zone_to_edgecut_clearance;
 
-#if 0
-// 6.0 TODO: we're leaving this off for 5.1 so that people can continue to use the board
-// edge width as a hack for edge clearance.
             // edge cuts by definition don't have a width
             ignoreLineWidth = true;
-#endif
         }
 
         switch( aItem->Type() )
diff --git a/template/kicad.pro b/template/kicad.pro
index 152769cb72..5cd098305b 100644
--- a/template/kicad.pro
+++ b/template/kicad.pro
@@ -1,4 +1,4 @@
-update=22/05/2015 07:44:53
+update=05/04/2019 20:44:53
 version=1
 last_client=kicad
 [general]
@@ -24,6 +24,7 @@ SolderMaskMinWidth=0.000000000000
 DrawSegmentWidth=0.200000000000
 BoardOutlineThickness=0.100000000000
 ModuleOutlineThickness=0.150000000000
+CopperEdgeClearance=0.000000000000
 [cvpcb]
 version=1
 NetIExt=net