diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp index 7fbc8f2211..1d4ac15b63 100644 --- a/common/advanced_config.cpp +++ b/common/advanced_config.cpp @@ -67,6 +67,13 @@ namespace AC_KEYS */ static const wxChar ExtraFillMargin[] = wxT( "ExtraFillMargin" ); +/** + * A fudge factor for DRC. Required to prevent false positives due to rounding errors, errors + * in polygonalization, etc. + * Previous versions hard-coded various values from 0.000005mm to 0.002mm. + */ +static const wxChar DRCEpsilon[] = wxT( "DRCEpsilon" ); + /** * Testing mode for new connectivity algorithm. Setting this to on will cause all modifications * to the netlist to be recalculated on the fly. This may be slower than the standard process @@ -203,6 +210,9 @@ ADVANCED_CFG::ADVANCED_CFG() m_DrawTriangulationOutlines = false; m_PluginAltiumSch = false; + m_extraClearance = 0.0005; + m_DRCEpsilon = 0.0005; // 500nm is small enough not to materially violate + // any constraints. loadFromConfigFile(); } @@ -244,7 +254,10 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg ) &m_realTimeConnectivity, true ) ); configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::ExtraFillMargin, - &m_extraClearance, 0.001, 0.0, 1.0 ) ); + &m_extraClearance, 0.0005, 0.0, 1.0 ) ); + + configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCEpsilon, + &m_DRCEpsilon, 0.0005, 0.0, 1.0 ) ); configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::CoroutineStackSize, &m_coroutineStackSize, AC_STACK::default_stack, diff --git a/include/advanced_config.h b/include/advanced_config.h index 177191e4ee..410b1104a7 100644 --- a/include/advanced_config.h +++ b/include/advanced_config.h @@ -83,10 +83,17 @@ public: double m_drawArcCenterMaxAngle; /** - * Extra fill clearance for zone fills + * Extra fill clearance for zone fills. Note that for zone tests this is essentially + * additive with m_DRCEpsilon. */ double m_extraClearance; + /** + * Epsilon for DRC tests. Note that for zone tests this is essentially additive with + * m_extraClearance. + */ + double m_DRCEpsilon; + /** * Do real-time connectivity */ diff --git a/include/board_design_settings.h b/include/board_design_settings.h index 36c770393f..5ef0766406 100644 --- a/include/board_design_settings.h +++ b/include/board_design_settings.h @@ -89,8 +89,8 @@ #define MINIMUM_ERROR_SIZE_MM 0.001 #define MAXIMUM_ERROR_SIZE_MM 0.1 -#define DRC_EPSILON 5; // An epsilon to account for rounding errors, etc. - // 5nm is small enough not to materially violate +#define DRC_EPSILON 500; // An epsilon to account for rounding errors, etc. + // 500nm is small enough not to materially violate // any constraints. /** @@ -797,10 +797,10 @@ public: /* * Function GetDRCEpsilon - * an epsilon which accounts for rounding errors, etc. While currently a global, going - * through this API allows us to easily change it to board-specific if so desired. + * an epsilon which accounts for rounding errors, etc. While currently an advanced cfg, + * going through this API allows us to easily change it to board-specific if so desired. */ - int GetDRCEpsilon() const { return DRC_EPSILON; } + int GetDRCEpsilon() const; /** * Function GetLineThickness diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp index 73324859aa..9c9f2730dc 100644 --- a/pcbnew/board_design_settings.cpp +++ b/pcbnew/board_design_settings.cpp @@ -33,7 +33,7 @@ #include #include #include - +#include const int bdsSchemaVersion = 0; @@ -960,6 +960,12 @@ int BOARD_DESIGN_SETTINGS::GetLayerClass( PCB_LAYER_ID aLayer ) const } +int BOARD_DESIGN_SETTINGS::GetDRCEpsilon() const +{ + return Millimeter2iu( ADVANCED_CFG::GetCfg().m_DRCEpsilon ); +} + + int BOARD_DESIGN_SETTINGS::GetLineThickness( PCB_LAYER_ID aLayer ) const { return m_LineThickness[ GetLayerClass( aLayer ) ]; diff --git a/pcbnew/drc/drc_clearance_test_functions.cpp b/pcbnew/drc/drc_clearance_test_functions.cpp index 11ed5ace6d..09df34a7a5 100644 --- a/pcbnew/drc/drc_clearance_test_functions.cpp +++ b/pcbnew/drc/drc_clearance_test_functions.cpp @@ -33,7 +33,6 @@ #include #include #include -#include void DRC::doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia ) { @@ -419,7 +418,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS if( !m_reportAllTrackErrors ) return; } - else if( refSeg.Collide( &trackSeg, minClearance, &actual ) ) + else if( refSeg.Collide( &trackSeg, minClearance - bds.GetDRCEpsilon(), &actual ) ) { wxPoint pos = GetLocation( aRefSeg, trackSeg.GetSeg() ); std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); @@ -458,14 +457,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS if( zone->GetFilledPolysList( aLayer ).IsEmpty() ) continue; - // to avoid false positive, due to rounding issues and approxiamtions - // in distance and clearance calculations, use a small threshold for distance - // (1 micron) - #define THRESHOLD_DIST Millimeter2iu( 0.001 ) - - int minClearance = aRefSeg->GetClearance( aLayer, zone, &m_clearanceSource ); - int allowedDist = minClearance + halfWidth - THRESHOLD_DIST; + int allowedDist = minClearance + halfWidth - bds.GetDRCEpsilon(); int actual; if( zone->GetFilledPolysList( aLayer ).Collide( testSeg, allowedDist, &actual ) ) @@ -502,7 +495,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS aRefSeg->GetRuleClearance( &dummyEdge, aRefSeg->GetLayer(), &minClearance, &m_clearanceSource ); - int center2centerAllowed = minClearance + halfWidth; + int center2centerAllowed = minClearance + halfWidth - bds.GetDRCEpsilon(); for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ ) { @@ -534,7 +527,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS // Best-efforts search for edge segment BOARD::IterateForward( m_pcb->Drawings(), inspector, nullptr, types ); - int actual = std::max( 0.0, sqrt( center2center_squared ) - halfWidth ); + int actual = std::max( 0.0, sqrt( center2center_squared ) - halfWidth ); std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_COPPER_EDGE_CLEARANCE ); m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),