From cc86630f11a864f9f46cdc8fae05229487d02a32 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 11 Sep 2020 16:04:11 +0100 Subject: [PATCH] Start pulling new DRC engine into Kicad. --- pcbnew/CMakeLists.txt | 2 + pcbnew/board_connected_item.cpp | 4 +- pcbnew/board_design_settings.cpp | 2 +- pcbnew/class_track.cpp | 10 +- pcbnew/class_zone.cpp | 54 +- .../dialog_cleanup_tracks_and_vias.cpp | 2 +- pcbnew/drc/drc.h | 63 +- pcbnew/drc/drc_clearance_test_functions.cpp | 12 +- pcbnew/drc/drc_courtyard_tester.cpp | 2 +- pcbnew/drc/drc_courtyard_tester.h | 4 +- pcbnew/drc/drc_drilled_hole_tester.cpp | 8 +- pcbnew/drc/drc_drilled_hole_tester.h | 4 +- pcbnew/drc/drc_engine.cpp | 279 ++-- pcbnew/drc/drc_engine.h | 99 +- pcbnew/drc/drc_item.cpp | 17 +- pcbnew/drc/drc_item.h | 21 +- pcbnew/drc/drc_keepout_tester.cpp | 54 +- pcbnew/drc/drc_keepout_tester.h | 4 +- pcbnew/drc/drc_results_provider.h | 11 +- pcbnew/drc/drc_rule.cpp | 37 +- pcbnew/drc/drc_rule.h | 115 +- pcbnew/drc/drc_rule_parser.cpp | 58 +- pcbnew/drc/drc_rule_parser.h | 2 +- pcbnew/drc/drc_test_provider.cpp | 59 +- pcbnew/drc/drc_test_provider.h | 53 +- pcbnew/drc/drc_textvar_tester.cpp | 2 +- pcbnew/drc/drc_textvar_tester.h | 4 +- qa/drc_proto/CMakeLists.txt | 10 +- qa/drc_proto/drc.cpp | 1439 ----------------- qa/drc_proto/drc.h | 373 ----- qa/drc_proto/drc_clearance_test_functions.cpp | 1001 ------------ qa/drc_proto/drc_courtyard_tester.cpp | 189 --- qa/drc_proto/drc_courtyard_tester.h | 43 - qa/drc_proto/drc_drilled_hole_tester.cpp | 283 ---- qa/drc_proto/drc_drilled_hole_tester.h | 68 - qa/drc_proto/drc_item.cpp | 255 --- qa/drc_proto/drc_keepout_tester.cpp | 351 ---- qa/drc_proto/drc_keepout_tester.h | 61 - qa/drc_proto/drc_marker_pcb.h | 115 -- qa/drc_proto/drc_netclass_tester.cpp | 162 -- qa/drc_proto/drc_netclass_tester.h | 54 - qa/drc_proto/drc_proto_test.cpp | 51 +- qa/drc_proto/drc_rule_parser.cpp | 466 ------ qa/drc_proto/drc_rule_parser.h | 71 - qa/drc_proto/drc_test_provider_annulus.cpp | 24 +- .../drc_test_provider_clearance_base.cpp | 8 +- .../drc_test_provider_clearance_base.h | 10 +- .../drc_test_provider_connectivity.cpp | 16 +- .../drc_test_provider_copper_clearance.cpp | 47 +- .../drc_test_provider_courtyard_clearance.cpp | 14 +- qa/drc_proto/drc_test_provider_disallow.cpp | 46 +- .../drc_test_provider_edge_clearance.cpp | 33 +- .../drc_test_provider_hole_clearance.cpp | 34 +- qa/drc_proto/drc_test_provider_hole_size.cpp | 18 +- qa/drc_proto/drc_test_provider_lvs.cpp | 15 +- qa/drc_proto/drc_test_provider_misc.cpp | 15 +- .../drc_test_provider_silk_to_pad.cpp | 38 +- .../drc_test_provider_track_width.cpp | 25 +- .../drc_test_provider_via_diameter.cpp | 24 +- qa/drc_proto/drc_textvar_tester.h | 2 +- qa/drc_proto/footprint_tester.cpp | 90 -- qa/drc_proto/footprint_tester.h | 34 - qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp | 14 +- 63 files changed, 743 insertions(+), 5738 deletions(-) delete mode 100644 qa/drc_proto/drc.cpp delete mode 100644 qa/drc_proto/drc.h delete mode 100644 qa/drc_proto/drc_clearance_test_functions.cpp delete mode 100644 qa/drc_proto/drc_courtyard_tester.cpp delete mode 100644 qa/drc_proto/drc_courtyard_tester.h delete mode 100644 qa/drc_proto/drc_drilled_hole_tester.cpp delete mode 100644 qa/drc_proto/drc_drilled_hole_tester.h delete mode 100644 qa/drc_proto/drc_item.cpp delete mode 100644 qa/drc_proto/drc_keepout_tester.cpp delete mode 100644 qa/drc_proto/drc_keepout_tester.h delete mode 100644 qa/drc_proto/drc_marker_pcb.h delete mode 100644 qa/drc_proto/drc_netclass_tester.cpp delete mode 100644 qa/drc_proto/drc_netclass_tester.h delete mode 100644 qa/drc_proto/drc_rule_parser.cpp delete mode 100644 qa/drc_proto/drc_rule_parser.h delete mode 100644 qa/drc_proto/footprint_tester.cpp delete mode 100644 qa/drc_proto/footprint_tester.h diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 353f7a95d7..ea37fb2a2d 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -236,6 +236,8 @@ set( PCBNEW_DRC_SRCS drc/drc_textvar_tester.cpp drc/drc.cpp drc/drc_clearance_test_functions.cpp + drc/drc_engine.cpp + drc/drc_test_provider.cpp drc/drc_rule_parser.cpp drc/footprint_tester.cpp ) diff --git a/pcbnew/board_connected_item.cpp b/pcbnew/board_connected_item.cpp index ba1895d10d..27a52f8417 100644 --- a/pcbnew/board_connected_item.cpp +++ b/pcbnew/board_connected_item.cpp @@ -156,8 +156,8 @@ bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLa int* aClearance, wxString* aSource, REPORTER* aReporter ) const { - const DRC_CONSTRAINT* constraint = GetConstraint( this, aItem, DRC_RULE_ID_CLEARANCE, aLayer, - aSource, aReporter ); + const DRC_CONSTRAINT* constraint = GetConstraint( this, aItem, DRC_CONSTRAINT_TYPE_CLEARANCE, + aLayer, aSource, aReporter ); if( constraint ) { diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp index fd6bded85a..9500d67d19 100644 --- a/pcbnew/board_design_settings.cpp +++ b/pcbnew/board_design_settings.cpp @@ -836,7 +836,7 @@ int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue() { for( const DRC_CONSTRAINT& constraint : rule->m_Constraints ) { - if( constraint.m_Type == DRC_RULE_ID_CLEARANCE ) + if( constraint.m_Type == DRC_CONSTRAINT_TYPE_CLEARANCE ) clearance = std::max( clearance, constraint.m_Value.Min() ); } } diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index f5a0e89c89..addbf96916 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -139,8 +139,9 @@ void TRACK::GetWidthConstraints( int* aMin, int* aMax, wxString* aSource ) const // Not currently implemented // LEVEL 2: Rules - const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_TRACK, m_Layer, - aSource ); + const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, + DRC_CONSTRAINT_TYPE_TRACK_WIDTH, + m_Layer, aSource ); if( constraint ) { @@ -177,8 +178,9 @@ int VIA::GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const return 0; } - const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_ANNULUS, aLayer, - aSource ); + const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, + DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, + aLayer, aSource ); if( constraint ) { diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 56bd990508..3f2119a4da 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -372,58 +372,58 @@ int ZONE_CONTAINER::GetKeepouts( PCB_LAYER_ID aLayer, std::map* a source = _( "zone properties" ); if( m_doNotAllowTracks ) - setFlag( DISALLOW_TRACKS ); + setFlag( DRC_DISALLOW_TRACKS ); if( m_doNotAllowVias ) - setFlag( DISALLOW_VIAS ); + setFlag( DRC_DISALLOW_VIAS ); if( m_doNotAllowPads ) - setFlag( DISALLOW_PADS ); + setFlag( DRC_DISALLOW_PADS ); if( m_doNotAllowFootprints ) - setFlag( DISALLOW_FOOTPRINTS ); + setFlag( DRC_DISALLOW_FOOTPRINTS ); if( m_doNotAllowCopperPour ) - setFlag( DISALLOW_ZONES ); + setFlag( DRC_DISALLOW_ZONES ); } - const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_DISALLOW, aLayer, - &source ); + const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_CONSTRAINT_TYPE_DISALLOW, + aLayer, &source ); if( constraint ) { if( aSources ) source = wxString::Format( _( "'%s' rule" ), source ); - if( ( constraint->m_DisallowFlags & DISALLOW_VIAS ) > 0 ) - setFlag( DISALLOW_VIAS ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_VIAS ) > 0 ) + setFlag( DRC_DISALLOW_VIAS ); - if( ( constraint->m_DisallowFlags & DISALLOW_MICRO_VIAS ) > 0 ) - setFlag( DISALLOW_MICRO_VIAS ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_MICRO_VIAS ) > 0 ) + setFlag( DRC_DISALLOW_MICRO_VIAS ); - if( ( constraint->m_DisallowFlags & DISALLOW_BB_VIAS ) > 0 ) - setFlag( DISALLOW_BB_VIAS ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_BB_VIAS ) > 0 ) + setFlag( DRC_DISALLOW_BB_VIAS ); - if( ( constraint->m_DisallowFlags & DISALLOW_TRACKS ) > 0 ) - setFlag( DISALLOW_TRACKS ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_TRACKS ) > 0 ) + setFlag( DRC_DISALLOW_TRACKS ); - if( ( constraint->m_DisallowFlags & DISALLOW_PADS ) > 0 ) - setFlag( DISALLOW_PADS ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_PADS ) > 0 ) + setFlag( DRC_DISALLOW_PADS ); - if( ( constraint->m_DisallowFlags & DISALLOW_ZONES ) > 0 ) - setFlag( DISALLOW_ZONES ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_ZONES ) > 0 ) + setFlag( DRC_DISALLOW_ZONES ); - if( ( constraint->m_DisallowFlags & DISALLOW_TEXTS ) > 0 ) - setFlag( DISALLOW_TEXTS ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_TEXTS ) > 0 ) + setFlag( DRC_DISALLOW_TEXTS ); - if( ( constraint->m_DisallowFlags & DISALLOW_GRAPHICS ) > 0 ) - setFlag( DISALLOW_GRAPHICS ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_GRAPHICS ) > 0 ) + setFlag( DRC_DISALLOW_GRAPHICS ); - if( ( constraint->m_DisallowFlags & DISALLOW_HOLES ) > 0 ) - setFlag( DISALLOW_HOLES ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_HOLES ) > 0 ) + setFlag( DRC_DISALLOW_HOLES ); - if( ( constraint->m_DisallowFlags & DISALLOW_FOOTPRINTS ) > 0 ) - setFlag( DISALLOW_FOOTPRINTS ); + if( ( constraint->m_DisallowFlags & DRC_DISALLOW_FOOTPRINTS ) > 0 ) + setFlag( DRC_DISALLOW_FOOTPRINTS ); } return keepouts; diff --git a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp index b4a3276a86..e5a3236a8e 100644 --- a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include DIALOG_CLEANUP_TRACKS_AND_VIAS::DIALOG_CLEANUP_TRACKS_AND_VIAS( PCB_EDIT_FRAME* aParentFrame ) : diff --git a/pcbnew/drc/drc.h b/pcbnew/drc/drc.h index 3f18068657..3d63533f88 100644 --- a/pcbnew/drc/drc.h +++ b/pcbnew/drc/drc.h @@ -39,38 +39,41 @@ /// DRC error codes: enum PCB_DRC_CODE { DRCE_FIRST = 1, - DRCE_UNCONNECTED_ITEMS = DRCE_FIRST, ///< items are unconnected - DRCE_SHORTING_ITEMS, ///< items short two nets but are not a net tie - DRCE_ALLOWED_ITEMS, ///< a disallowed item has been used - DRCE_CLEARANCE, ///< items are too close together - DRCE_TRACKS_CROSSING, ///< tracks are crossing - DRCE_COPPER_EDGE_CLEARANCE, ///< a copper item is too close to the board edge - DRCE_ZONES_INTERSECT, ///< copper area outlines intersect - DRCE_ZONE_HAS_EMPTY_NET, ///< copper area has a net but no pads in nets, which is suspicious - DRCE_DANGLING_VIA, ///< via which isn't connected to anything - DRCE_DANGLING_TRACK, ///< track with at least one end not connected to anything - DRCE_DRILLED_HOLES_TOO_CLOSE, ///< overlapping drilled holes break drill bits - DRCE_TRACK_WIDTH, ///< Track width is too small or too large - DRCE_TOO_SMALL_VIA, ///< Too small via size - DRCE_VIA_ANNULUS, ///< Via size and drill leave annulus too small or too large - DRCE_TOO_SMALL_DRILL, ///< Too small via or pad drill - DRCE_VIA_HOLE_BIGGER, ///< via's hole is bigger than its diameter - DRCE_PADSTACK, ///< something is wrong with a pad or via stackup - DRCE_TOO_SMALL_MICROVIA, ///< Too small micro via size - DRCE_TOO_SMALL_MICROVIA_DRILL, ///< Too small micro via drill - DRCE_KEEPOUT, ///< A disallowed object is inside a keepout - DRCE_OVERLAPPING_FOOTPRINTS, ///< footprint courtyards overlap - DRCE_MISSING_COURTYARD, ///< footprint has no courtyard defined - DRCE_MALFORMED_COURTYARD, ///< footprint has a courtyard but malformed - ///< (not convertible to a closed polygon with holes) + DRCE_UNCONNECTED_ITEMS = DRCE_FIRST, // items are unconnected + DRCE_SHORTING_ITEMS, // items short two nets but are not a net-tie + DRCE_ALLOWED_ITEMS, // a disallowed item has been used + DRCE_CLEARANCE, // items are too close together + DRCE_TRACKS_CROSSING, // tracks are crossing + DRCE_COPPER_EDGE_CLEARANCE, // a copper item is too close to the board edge + DRCE_ZONES_INTERSECT, // copper area outlines intersect + DRCE_ZONE_HAS_EMPTY_NET, // copper area has a net but no pads in nets, which is suspicious + DRCE_DANGLING_VIA, // via which isn't connected to anything + DRCE_DANGLING_TRACK, // track with at least one end not connected to anything + DRCE_DRILLED_HOLES_TOO_CLOSE, // overlapping drilled holes break drill bits + DRCE_HOLE_CLEARANCE, // + DRCE_TRACK_WIDTH, // Track width is too small or too large + DRCE_TOO_SMALL_VIA, // Too small via size + DRCE_ANNULUS, // Via size and drill leave annulus too small or too large + DRCE_TOO_SMALL_DRILL, // Too small via or pad drill + DRCE_VIA_HOLE_BIGGER, // via's hole is bigger than its diameter + DRCE_VIA_DIAMETER, // Via diameter checks (min/max) + DRCE_PADSTACK, // something is wrong with a pad or via stackup + DRCE_TOO_SMALL_MICROVIA, // Too small micro via size + DRCE_TOO_SMALL_MICROVIA_DRILL, // Too small micro via drill + DRCE_KEEPOUT, // A disallowed object is inside a keepout + DRCE_OVERLAPPING_FOOTPRINTS, // footprint courtyards overlap + DRCE_MISSING_COURTYARD, // footprint has no courtyard defined + DRCE_MALFORMED_COURTYARD, // footprint has a courtyard but malformed + // (not convertible to a closed polygon with holes) DRCE_PTH_IN_COURTYARD, DRCE_NPTH_IN_COURTYARD, - DRCE_DISABLED_LAYER_ITEM, ///< item on a disabled layer - DRCE_INVALID_OUTLINE, ///< invalid board outline - DRCE_MISSING_FOOTPRINT, ///< footprint not found for netlist item - DRCE_DUPLICATE_FOOTPRINT, ///< more than one footprints found for netlist item - DRCE_EXTRA_FOOTPRINT, ///< netlist item not found for footprint - DRCE_NET_CONFLICT, ///< pad net doesn't match netlist + DRCE_DISABLED_LAYER_ITEM, // item on a disabled layer + DRCE_INVALID_OUTLINE, // invalid board outline + + DRCE_MISSING_FOOTPRINT, // footprint not found for netlist item + DRCE_DUPLICATE_FOOTPRINT, // more than one footprints found for netlist item + DRCE_EXTRA_FOOTPRINT, // netlist item not found for footprint + DRCE_NET_CONFLICT, // pad net doesn't match netlist DRCE_UNRESOLVED_VARIABLE, diff --git a/pcbnew/drc/drc_clearance_test_functions.cpp b/pcbnew/drc/drc_clearance_test_functions.cpp index b6f30874f6..7ee64f8ebd 100644 --- a/pcbnew/drc/drc_clearance_test_functions.cpp +++ b/pcbnew/drc/drc_clearance_test_functions.cpp @@ -43,7 +43,7 @@ void DRC::doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia ) { if( aRefVia->GetWidth() < bds.m_MicroViasMinSize ) { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ANNULUS ); m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ), MessageTextFromValue( userUnits(), bds.m_MicroViasMinSize, true ), @@ -60,7 +60,7 @@ void DRC::doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia ) { if( aRefVia->GetWidth() < bds.m_ViasMinSize ) { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ANNULUS ); m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ), MessageTextFromValue( userUnits(), bds.m_ViasMinSize, true ), @@ -231,7 +231,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS { if( viaAnnulus < minAnnulus ) { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ANNULUS ); m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ), m_clearanceSource, @@ -255,7 +255,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS if( viaAnnulus < minAnnulus ) { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ANNULUS ); m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ), m_clearanceSource, @@ -303,8 +303,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS { const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape(); const DRC_CONSTRAINT* constraint = GetConstraint( aRefSeg, pad, - DRC_RULE_ID_CLEARANCE, aLayer, - &m_clearanceSource ); + DRC_CONSTRAINT_TYPE_CLEARANCE, + aLayer, &m_clearanceSource ); int minClearance; int actual; diff --git a/pcbnew/drc/drc_courtyard_tester.cpp b/pcbnew/drc/drc_courtyard_tester.cpp index 3bf8e6a90a..f6728ea45e 100644 --- a/pcbnew/drc/drc_courtyard_tester.cpp +++ b/pcbnew/drc/drc_courtyard_tester.cpp @@ -35,7 +35,7 @@ #include DRC_COURTYARD_TESTER::DRC_COURTYARD_TESTER( MARKER_HANDLER aMarkerHandler ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ) + LEGACY_DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ) { } diff --git a/pcbnew/drc/drc_courtyard_tester.h b/pcbnew/drc/drc_courtyard_tester.h index 4ba70b09d3..225cda3e36 100644 --- a/pcbnew/drc/drc_courtyard_tester.h +++ b/pcbnew/drc/drc_courtyard_tester.h @@ -25,12 +25,12 @@ #ifndef DRC_COURTYARD_OVERLAP__H #define DRC_COURTYARD_OVERLAP__H -#include +#include class BOARD; -class DRC_COURTYARD_TESTER : public DRC_TEST_PROVIDER +class DRC_COURTYARD_TESTER : public LEGACY_DRC_TEST_PROVIDER { public: DRC_COURTYARD_TESTER( MARKER_HANDLER aMarkerHandler ); diff --git a/pcbnew/drc/drc_drilled_hole_tester.cpp b/pcbnew/drc/drc_drilled_hole_tester.cpp index eb5536155c..14a22ca927 100644 --- a/pcbnew/drc/drc_drilled_hole_tester.cpp +++ b/pcbnew/drc/drc_drilled_hole_tester.cpp @@ -31,7 +31,7 @@ DRC_DRILLED_HOLE_TESTER::DRC_DRILLED_HOLE_TESTER( MARKER_HANDLER aMarkerHandler ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), + LEGACY_DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), m_units( EDA_UNITS::MILLIMETRES ), m_board( nullptr ), m_largestRadius( 0 ) @@ -94,7 +94,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad ) if( !bds.Ignore( DRCE_TOO_SMALL_DRILL ) ) { int minHole; - const DRC_CONSTRAINT* constraint = GetConstraint( aPad, nullptr, DRC_RULE_ID_HOLE_SIZE, + const DRC_CONSTRAINT* constraint = GetConstraint( aPad, nullptr, DRC_CONSTRAINT_TYPE_HOLE_SIZE, layer, &m_source ); if( constraint ) @@ -145,7 +145,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkVia( VIA* via ) if( !bds.Ignore( DRCE_TOO_SMALL_DRILL ) ) { int minHole; - const DRC_CONSTRAINT* constraint = GetConstraint( via, nullptr, DRC_RULE_ID_HOLE_SIZE, + const DRC_CONSTRAINT* constraint = GetConstraint( via, nullptr, DRC_CONSTRAINT_TYPE_HOLE_SIZE, layer, &m_source ); if( constraint ) @@ -197,7 +197,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkMicroVia( VIA* via ) if( !bds.Ignore( DRCE_TOO_SMALL_MICROVIA_DRILL ) ) { int minHole; - const DRC_CONSTRAINT* constraint = GetConstraint( via, nullptr, DRC_RULE_ID_HOLE_SIZE, + const DRC_CONSTRAINT* constraint = GetConstraint( via, nullptr, DRC_CONSTRAINT_TYPE_HOLE_SIZE, layer, &m_source ); if( constraint ) diff --git a/pcbnew/drc/drc_drilled_hole_tester.h b/pcbnew/drc/drc_drilled_hole_tester.h index 7f3f463b58..eeeba0aa71 100644 --- a/pcbnew/drc/drc_drilled_hole_tester.h +++ b/pcbnew/drc/drc_drilled_hole_tester.h @@ -25,14 +25,14 @@ #ifndef DRC_DRILLED_HOLE_TESTER__H #define DRC_DRILLED_HOLE_TESTER__H -#include +#include class BOARD; class BOARD_ITEM; -class DRC_DRILLED_HOLE_TESTER : public DRC_TEST_PROVIDER +class DRC_DRILLED_HOLE_TESTER : public LEGACY_DRC_TEST_PROVIDER { public: DRC_DRILLED_HOLE_TESTER( MARKER_HANDLER aMarkerHandler ); diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 858dc5cf22..48e8c3974d 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -30,16 +30,17 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include void drcPrintDebugMessage( int level, wxString msg, const char *function, int line ) { wxString valueStr; + if( wxGetEnv( "DRC_DEBUG", &valueStr ) ) { int setLevel = wxAtoi( valueStr ); @@ -51,29 +52,28 @@ void drcPrintDebugMessage( int level, wxString msg, const char *function, int li } -test::DRC_ENGINE::DRC_ENGINE( BOARD* aBoard, BOARD_DESIGN_SETTINGS *aSettings ) : - m_board( aBoard ), +DRC_ENGINE::DRC_ENGINE( BOARD* aBoard, BOARD_DESIGN_SETTINGS *aSettings ) : m_designSettings ( aSettings ), + m_board( aBoard ), m_worksheet( nullptr ), m_schematicNetlist( nullptr ), m_reporter( nullptr ), m_progressReporter( nullptr ) { - } -test::DRC_ENGINE::~DRC_ENGINE() +DRC_ENGINE::~DRC_ENGINE() { } -test::DRC_REPORT::~DRC_REPORT() +DRC_REPORT::~DRC_REPORT() { } -/*void test::DRC_ENGINE::AddMarker( MARKER_PCB* aMarker ) +/*void DRC_ENGINE::AddMarker( MARKER_PCB* aMarker ) { if( m_designSettings->Ignore( aMarker->GetRCItem()->GetErrorCode() ) ) { @@ -85,49 +85,11 @@ test::DRC_REPORT::~DRC_REPORT() }*/ -bool test::DRC_ENGINE::LoadRules( wxFileName aPath ) -{ - - if( aPath.FileExists() ) - { - m_ruleConditions.clear(); - m_rules.clear(); - - FILE* fp = wxFopen( aPath.GetFullPath(), wxT( "rt" ) ); - - if( fp ) - { - try - { - DRC_RULES_PARSER parser( m_board, fp, aPath.GetFullPath() ); - parser.Parse( m_rules, m_reporter ); - } - catch( PARSE_ERROR& pe ) - { - // Don't leave possibly malformed stuff around for us to trip over - m_ruleConditions.clear(); - m_rules.clear(); - - //wxSafeYield( m_editFrame ); - //m_editFrame->ShowBoardSetupDialog( _( "Rules" ), pe.What(), ID_RULES_EDITOR, - // pe.lineNumber, pe.byteIndex ); - - throw; - - return false; - } - } - } - - return true; -} - - -test::DRC_RULE* test::DRC_ENGINE::createInferredRule( const wxString& name, std::set items, int priority ) +DRC_RULE* DRC_ENGINE::createInferredRule( const wxString& name, std::set items, int priority ) { DRC_RULE *rule = new DRC_RULE; - rule->SetName( name ); + rule->m_Name = name; if (! items.empty() ) rule->FillSpecificItemSet( items ); @@ -212,7 +174,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem, #endif -void test::DRC_ENGINE::inferLegacyRules() +void DRC_ENGINE::inferLegacyRules() { int priorityRangeMin = INT_MIN + 10000; int priorityRangeMax = INT_MAX - 10000; @@ -221,38 +183,38 @@ void test::DRC_ENGINE::inferLegacyRules() // 1) global defaults - test::DRC_RULE* rule = createInferredRule( "inferred-defaults", {}, priorityRangeMin ); + DRC_RULE* rule = createInferredRule( "inferred-defaults", {}, priorityRangeMin ); BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - DRC_CONSTRAINT clearanceConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE ); + DRC_CONSTRAINT clearanceConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE ); clearanceConstraint.Value().SetMin( bds.m_MinClearance ); rule->AddConstraint( clearanceConstraint ); - DRC_CONSTRAINT widthConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH ); + DRC_CONSTRAINT widthConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH ); widthConstraint.Value().SetMin( bds.m_TrackMinWidth ); rule->AddConstraint( widthConstraint ); - DRC_CONSTRAINT drillConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE ); + DRC_CONSTRAINT drillConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE ); drillConstraint.Value().SetMin( bds.m_MinThroughDrill ); rule->AddConstraint( drillConstraint ); - DRC_CONSTRAINT annulusConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH ); + DRC_CONSTRAINT annulusConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH ); annulusConstraint.Value().SetMin( bds.m_ViasMinAnnulus ); rule->AddConstraint( annulusConstraint ); - DRC_CONSTRAINT diameterConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ); + DRC_CONSTRAINT diameterConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ); diameterConstraint.Value().SetMin( bds.m_ViasMinSize ); rule->AddConstraint( diameterConstraint ); - DRC_CONSTRAINT edgeClearanceConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE ); + DRC_CONSTRAINT edgeClearanceConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE ); edgeClearanceConstraint.Value().SetMin( bds.m_CopperEdgeClearance ); rule->AddConstraint( edgeClearanceConstraint ); - DRC_CONSTRAINT holeClearanceConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE ); + DRC_CONSTRAINT holeClearanceConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE ); holeClearanceConstraint.Value().SetMin( bds.m_HoleToHoleMin ); rule->AddConstraint( holeClearanceConstraint ); - DRC_CONSTRAINT courtyardClearanceConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE ); + DRC_CONSTRAINT courtyardClearanceConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE ); holeClearanceConstraint.Value().SetMin( 0 ); rule->AddConstraint( courtyardClearanceConstraint ); @@ -261,24 +223,24 @@ void test::DRC_ENGINE::inferLegacyRules() priorityRangeMin++; auto isMicroViaCondition = new DRC_RULE_CONDITION ( "A.type == 'Via' && A.isMicroVia()" ); - test::DRC_RULE* uViaRule = createInferredRule( "inferred-microvia-defaults", {}, priorityRangeMin ); + DRC_RULE* uViaRule = createInferredRule( "inferred-microvia-defaults", {}, priorityRangeMin ); - uViaRule->SetCondition( isMicroViaCondition ); + uViaRule->m_Condition = isMicroViaCondition; - DRC_CONSTRAINT uViaDrillConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE ); + DRC_CONSTRAINT uViaDrillConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE ); uViaDrillConstraint.Value().SetMin( bds.m_MicroViasMinDrill ); uViaRule->AddConstraint( uViaDrillConstraint ); - DRC_CONSTRAINT uViaDiameterConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ); + DRC_CONSTRAINT uViaDiameterConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ); uViaDiameterConstraint.Value().SetMin( bds.m_MicroViasMinSize ); uViaRule->AddConstraint( uViaDiameterConstraint ); auto isBlindBuriedViaCondition = new DRC_RULE_CONDITION ( "A.type == 'Via' && A.isBlindBuriedVia()" ); - test::DRC_RULE* blindBuriedViaRule = createInferredRule( "inferred-blind-buried-via-defaults", {}, priorityRangeMin ); + DRC_RULE* blindBuriedViaRule = createInferredRule( "inferred-blind-buried-via-defaults", {}, priorityRangeMin ); - DRC_CONSTRAINT disallowConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW ); + DRC_CONSTRAINT disallowConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW ); - blindBuriedViaRule->SetCondition ( isBlindBuriedViaCondition ); + blindBuriedViaRule->m_Condition = isBlindBuriedViaCondition; if( !bds.m_MicroViasAllowed ) { @@ -310,14 +272,14 @@ void test::DRC_ENGINE::inferLegacyRules() netclasses.push_back( bds.GetNetClasses().GetDefault() ); - for( auto netclass : bds.GetNetClasses() ) + for( const auto& netclass : bds.GetNetClasses() ) netclasses.push_back( netclass.second ); ReportAux( wxString::Format( "Importing %d legacy net classes", (int) netclasses.size() ) ); int i = 0; - for( auto &nc : netclasses ) + for( const NETCLASSPTR& nc : netclasses ) { wxString className = nc->GetName(); @@ -325,10 +287,10 @@ void test::DRC_ENGINE::inferLegacyRules() auto inNetclassCondition = new DRC_RULE_CONDITION ( expr ); - test::DRC_RULE* netclassRule = createInferredRule( wxString::Format( "inferred-netclass-clearance-%s", className ), + DRC_RULE* netclassRule = createInferredRule( wxString::Format( "inferred-netclass-clearance-%s", className ), {}, priorityRangeMin + i ); - netclassRule->SetCondition( inNetclassCondition ); + netclassRule->m_Condition = inNetclassCondition; DRC_CONSTRAINT ncClearanceConstraint ( DRC_CONSTRAINT_TYPE_CLEARANCE ); ncClearanceConstraint.Value().SetMin( nc->GetClearance() ); @@ -337,7 +299,7 @@ void test::DRC_ENGINE::inferLegacyRules() netclassRule = createInferredRule( wxString::Format( "inferred-netclass-width-%s", className ), {}, priorityRangeMin + i ); - netclassRule->SetCondition( inNetclassCondition ); + netclassRule->m_Condition = inNetclassCondition; DRC_CONSTRAINT ncWidthConstraint ( DRC_CONSTRAINT_TYPE_TRACK_WIDTH ); ncWidthConstraint.Value().SetMin( nc->GetTrackWidth() ); @@ -347,25 +309,22 @@ void test::DRC_ENGINE::inferLegacyRules() i++; } - - - //clearanceConstraint.SetMin( ) //rule->AddConstraint( ) } -static wxString formatConstraint( const test::DRC_CONSTRAINT& constraint ) +static wxString formatConstraint( const DRC_CONSTRAINT& constraint ) { struct Formatter { - test::DRC_CONSTRAINT_TYPE_T type; + DRC_CONSTRAINT_TYPE_T type; wxString name; - std::function formatter; + std::function formatter; }; - auto formatMinMax = []( const test::DRC_CONSTRAINT& c ) -> wxString { + auto formatMinMax = []( const DRC_CONSTRAINT& c ) -> wxString { wxString str; const auto value = c.GetValue(); @@ -380,23 +339,23 @@ static wxString formatConstraint( const test::DRC_CONSTRAINT& constraint ) }; std::vector formats = { - { test::DRC_CONSTRAINT_TYPE_UNKNOWN, "unknown", nullptr }, - { test::DRC_CONSTRAINT_TYPE_CLEARANCE, "clearance", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, "hole_clearance", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, "edge_clearance", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_HOLE_SIZE, "hole_size", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE, "courtyard_clearance", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_SILK_TO_PAD, "silk_to_pad", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_SILK_TO_SILK, "silk_to_silk", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_TRACK_WIDTH, "track_width", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, "annulus_width", formatMinMax }, - { test::DRC_CONSTRAINT_TYPE_DISALLOW, "disallow", nullptr }, // fixme - { test::DRC_CONSTRAINT_TYPE_VIA_DIAMETER, "via_diameter", formatMinMax } + { DRC_CONSTRAINT_TYPE_UNKNOWN, "unknown", nullptr }, + { DRC_CONSTRAINT_TYPE_CLEARANCE, "clearance", formatMinMax }, + { DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, "hole_clearance", formatMinMax }, + { DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, "edge_clearance", formatMinMax }, + { DRC_CONSTRAINT_TYPE_HOLE_SIZE, "hole_size", formatMinMax }, + { DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE, "courtyard_clearance", formatMinMax }, + { DRC_CONSTRAINT_TYPE_SILK_TO_PAD, "silk_to_pad", formatMinMax }, + { DRC_CONSTRAINT_TYPE_SILK_TO_SILK, "silk_to_silk", formatMinMax }, + { DRC_CONSTRAINT_TYPE_TRACK_WIDTH, "track_width", formatMinMax }, + { DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, "annulus_width", formatMinMax }, + { DRC_CONSTRAINT_TYPE_DISALLOW, "disallow", nullptr }, // fixme + { DRC_CONSTRAINT_TYPE_VIA_DIAMETER, "via_diameter", formatMinMax } }; for( auto& fmt : formats) { - if( fmt.type == constraint.GetType() ) + if( fmt.type == constraint.m_Type ) { wxString rv = fmt.name + " "; if( fmt.formatter ) @@ -409,11 +368,13 @@ static wxString formatConstraint( const test::DRC_CONSTRAINT& constraint ) } -bool test::DRC_ENGINE::CompileRules() +bool DRC_ENGINE::CompileRules() { - ReportAux( wxString::Format( "Compiling Rules (%d rules, %d conditions): ", (int)m_rules.size(), (int)m_ruleConditions.size() ) ); + ReportAux( wxString::Format( "Compiling Rules (%d rules, %d conditions): ", + (int) m_rules.size(), + (int) m_ruleConditions.size() ) ); - for( auto provider : m_testProviders ) + for( DRC_TEST_PROVIDER* provider : m_testProviders ) { ReportAux( wxString::Format( "- Provider: '%s': ", provider->GetName() ) ); drc_dbg(7, "do prov %s", provider->GetName() ); @@ -428,52 +389,52 @@ bool test::DRC_ENGINE::CompileRules() for( auto rule : m_rules ) { - test::DRC_RULE_CONDITION* condition = nullptr; + DRC_RULE_CONDITION* condition = nullptr; bool compileOk = false; - std::vector matchingConstraints; - drc_dbg(7, "Scan provider %s, rule %s", provider->GetName(), rule->GetName() ); + std::vector matchingConstraints; + drc_dbg(7, "Scan provider %s, rule %s", provider->GetName(), rule->m_Name ); - if( ! rule->IsEnabled() ) - continue; - - - if( rule->IsConditional() ) + if( !rule->m_Condition->GetExpression().IsEmpty() ) { - condition = rule->Condition(); + condition = rule->m_Condition; compileOk = condition->Compile( nullptr, 0, 0 ); // fixme } - for( auto& constraint : rule->Constraints() ) + for( const DRC_CONSTRAINT& constraint : rule->m_Constraints ) { - drc_dbg(7, "scan constraint id %d\n", constraint.GetType() ); - if( constraint.GetType() != id ) + drc_dbg(7, "scan constraint id %d\n", constraint.m_Type ); + + if( constraint.m_Type != id ) continue; + CONSTRAINT_WITH_CONDITIONS* rcons = new CONSTRAINT_WITH_CONDITIONS; - auto rcons = new CONSTRAINT_WITH_CONDITIONS; + if( condition ) + rcons->conditions.push_back( condition ); - if( condition ) - { - rcons->conditions.push_back( condition ); - } - - matchingConstraints.push_back( constraint ); - - rcons->constraint = constraint; - rcons->parentRule = rule; - m_constraintMap[ id ]->sortedConstraints.push_back( rcons ); + matchingConstraints.push_back( constraint ); + rcons->constraint = constraint; + rcons->parentRule = rule; + m_constraintMap[ id ]->sortedConstraints.push_back( rcons ); } if( !matchingConstraints.empty() ) { - ReportAux( wxString::Format( " |- Rule: '%s' ", rule->GetName() ) ); - if( condition ) - ReportAux( wxString::Format( " |- condition: '%s' compile: %s", condition->GetExpression(), compileOk ? "OK" : "ERROR") ); + ReportAux( wxString::Format( " |- Rule: '%s' ", + rule->m_Name ) ); - for (const auto& constraint : matchingConstraints ) + if( condition ) { - ReportAux( wxString::Format( " |- constraint: %s", formatConstraint( constraint ) ) ); + ReportAux( wxString::Format( " |- condition: '%s' compile: %s", + condition->GetExpression(), + compileOk ? "OK" : "ERROR" ) ); + } + + for (const DRC_CONSTRAINT& constraint : matchingConstraints ) + { + ReportAux( wxString::Format( " |- constraint: %s", + formatConstraint( constraint ) ) ); } } @@ -486,9 +447,9 @@ bool test::DRC_ENGINE::CompileRules() } -void test::DRC_ENGINE::RunTests( ) +void DRC_ENGINE::RunTests( ) { - m_drcReport.reset( new test::DRC_REPORT ); + m_drcReport.reset( new DRC_REPORT ); m_testProviders = DRC_TEST_PROVIDER_REGISTRY::Instance().GetTestProviders(); for( auto provider : m_testProviders ) @@ -497,7 +458,6 @@ void test::DRC_ENGINE::RunTests( ) provider->SetDRCEngine( this ); } - inferLegacyRules(); CompileRules(); @@ -512,7 +472,8 @@ void test::DRC_ENGINE::RunTests( ) { if( !HasCorrectRulesForId( ruleID ) ) { - ReportAux( wxString::Format( "DRC provider '%s' has no rules provided. Skipping run.", provider->GetName() ) ); + ReportAux( wxString::Format( "DRC provider '%s' has no rules provided. Skipping run.", + provider->GetName() ) ); skipProvider = true; break; } @@ -529,31 +490,34 @@ void test::DRC_ENGINE::RunTests( ) } -const test::DRC_CONSTRAINT& test::DRC_ENGINE::EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T aConstraintId, BOARD_ITEM* a, BOARD_ITEM* b, PCB_LAYER_ID aLayer ) +const DRC_CONSTRAINT& DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintId, + BOARD_ITEM* a, BOARD_ITEM* b, + PCB_LAYER_ID aLayer ) { - test::DRC_RULE* rv; + DRC_RULE* rv; auto ruleset = m_constraintMap[ aConstraintId ]; - for( auto rcond : ruleset->sortedConstraints ) + for( const auto& rcond : ruleset->sortedConstraints ) { if( rcond->conditions.size() == 0 ) // uconditional { drc_dbg( 8, " -> rule '%s' matches (unconditional)\n", - rcond->constraint.GetParentRule()->GetName() - ); + rcond->constraint.GetParentRule()->m_Name ); return rcond->constraint; } - for( auto condition : rcond->conditions ) + + for( const auto& condition : rcond->conditions ) { drc_dbg( 8, " -> check condition '%s'\n", - condition->GetExpression() ); + condition->GetExpression() ); + + bool result = condition->EvaluateFor( a, b, aLayer ); - bool result = condition->EvaluateFor( a, b, aLayer ); // FIXME: need the actual layer if( result ) { drc_dbg( 8, " -> rule '%s' matches, triggered by condition '%s'\n", - rcond->constraint.GetParentRule()->GetName(), - condition->GetExpression() ); + rcond->constraint.GetParentRule()->m_Name, + condition->GetExpression() ); return rcond->constraint; } @@ -562,43 +526,43 @@ const test::DRC_CONSTRAINT& test::DRC_ENGINE::EvalRulesForItems( test::DRC_CONST // fixme: return optional, let the particular test decide what to do if no matching constraint // is found - static test::DRC_CONSTRAINT nullConstraint; + static DRC_CONSTRAINT nullConstraint; nullConstraint.m_DisallowFlags = 0; - nullConstraint.m_LayerCondition.reset(); return nullConstraint; } -void test::DRC_ENGINE::Report( std::shared_ptr aItem, ::MARKER_PCB *aMarker ) +void DRC_ENGINE::Report( std::shared_ptr aItem, MARKER_PCB *aMarker ) { m_drcReport->AddItem( aItem, aMarker ); if( m_reporter ) { wxString msg = wxString::Format( "Test '%s': %s (code %d)", - aItem->GetViolatingTest()->GetName(), - aItem->GetErrorMessage(), - aItem->GetErrorCode() ); + aItem->GetViolatingTest()->GetName(), + aItem->GetErrorMessage(), + aItem->GetErrorCode() ); auto rule = aItem->GetViolatingRule(); if( rule ) - msg += wxString::Format( ", violating rule: '%s'", rule->GetName() ); + msg += wxString::Format( ", violating rule: '%s'", rule->m_Name ); - m_reporter->Report ( msg, RPT_SEVERITY_ERROR /* fixme */ ); + m_reporter->Report( msg ); wxString violatingItemsStr = "Violating items: "; if( aMarker ) { - m_reporter->Report( wxString::Format( " |- violating position (%d, %d)", aMarker->GetPos().x, aMarker->GetPos().y ), - RPT_SEVERITY_ERROR /* fixme */ ); + m_reporter->Report( wxString::Format( " |- violating position (%d, %d)", + aMarker->GetPos().x, + aMarker->GetPos().y ) ); } } } -void test::DRC_ENGINE::ReportAux ( const wxString& aStr ) +void DRC_ENGINE::ReportAux ( const wxString& aStr ) { if( !m_reporter ) return; @@ -607,7 +571,7 @@ void test::DRC_ENGINE::ReportAux ( const wxString& aStr ) } -void test::DRC_ENGINE::ReportProgress( double aProgress ) +void DRC_ENGINE::ReportProgress( double aProgress ) { if( !m_progressReporter ) return; @@ -616,7 +580,7 @@ void test::DRC_ENGINE::ReportProgress( double aProgress ) } -void test::DRC_ENGINE::ReportStage ( const wxString& aStageName, int index, int total ) +void DRC_ENGINE::ReportStage ( const wxString& aStageName, int index, int total ) { if( !m_progressReporter ) return; @@ -628,7 +592,7 @@ void test::DRC_ENGINE::ReportStage ( const wxString& aStageName, int index, int #if 0 -test::DRC_CONSTRAINT test::DRC_ENGINE::GetWorstGlobalConstraint( test::DRC_CONSTRAINT_TYPE_T ruleID ) +DRC_CONSTRAINT DRC_ENGINE::GetWorstGlobalConstraint( DRC_CONSTRAINT_TYPE_T ruleID ) { DRC_CONSTRAINT rv; @@ -648,27 +612,30 @@ test::DRC_CONSTRAINT test::DRC_ENGINE::GetWorstGlobalConstraint( test::DRC_CONST #endif -std::vector test::DRC_ENGINE::QueryConstraintsById( test::DRC_CONSTRAINT_TYPE_T constraintID ) +std::vector DRC_ENGINE::QueryConstraintsById( DRC_CONSTRAINT_TYPE_T constraintID ) { - std::vector rv; + std::vector rv; for ( auto c : m_constraintMap[constraintID]->sortedConstraints ) rv.push_back(c->constraint); return rv; } -bool test::DRC_ENGINE::HasCorrectRulesForId( test::DRC_CONSTRAINT_TYPE_T constraintID ) +bool DRC_ENGINE::HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T constraintID ) { //drc_dbg(10,"hascorrect id %d size %d\n", ruleID, m_ruleMap[ruleID]->sortedRules.size( ) ); return m_constraintMap[constraintID]->sortedConstraints.size() != 0; } -bool test::DRC_ENGINE::QueryWorstConstraint( test::DRC_CONSTRAINT_TYPE_T aConstraintId, test::DRC_CONSTRAINT& aConstraint, test::DRC_CONSTRAINT_QUERY_T aQueryType ) +bool DRC_ENGINE::QueryWorstConstraint( DRC_CONSTRAINT_TYPE_T aConstraintId, + DRC_CONSTRAINT& aConstraint, + DRC_CONSTRAINT_QUERY_T aQueryType ) { if( aQueryType == DRCCQ_LARGEST_MINIMUM ) { int worst = 0; + for( const auto constraint : QueryConstraintsById( aConstraintId ) ) { if( constraint.GetValue().HasMin() ) diff --git a/pcbnew/drc/drc_engine.h b/pcbnew/drc/drc_engine.h index b5fc429c13..8df6ce0511 100644 --- a/pcbnew/drc/drc_engine.h +++ b/pcbnew/drc/drc_engine.h @@ -34,8 +34,8 @@ #include #include +#include -#include class BOARD_DESIGN_SETTINGS; class PCB_EDIT_FRAME; @@ -67,13 +67,10 @@ void drcPrintDebugMessage( int level, wxString msg, const char *function, int li //#define drc_dbg(level, fmt, ...) \ // wxLogTrace("DUPA", fmt, __VA_ARGS__); -namespace test -{ - class DRC_RULE_CONDITION; class DRC_ITEM; class DRC_RULE; -class DRC_TEST_PROVIDER; +class LEGACY_DRC_TEST_PROVIDER; class DRC_CONSTRAINT; enum DRC_CONSTRAINT_QUERY_T @@ -82,47 +79,6 @@ enum DRC_CONSTRAINT_QUERY_T // fixme: more to come I guess... }; -/// DRC error codes: -enum PCB_DRC_CODE -{ - DRCE_FIRST = 1, - DRCE_UNCONNECTED_ITEMS = DRCE_FIRST, ///< items are unconnected - DRCE_SHORTING_ITEMS, ///< items shorting two nets but not a net-tie - DRCE_ALLOWED_ITEMS, ///< a disallowed item has been used - DRCE_CLEARANCE, ///< items are too close together - DRCE_TRACKS_CROSSING, ///< tracks are crossing - DRCE_COPPER_EDGE_CLEARANCE, ///< a copper item is too close to the board edge - DRCE_ZONES_INTERSECT, ///< copper area outlines intersect - DRCE_ZONE_HAS_EMPTY_NET, ///< copper area has a net but no pads in nets, which is suspicious - DRCE_DANGLING_VIA, ///< via which isn't connected to anything - DRCE_DANGLING_TRACK, ///< track with at least one end not connected to anything - DRCE_HOLE_CLEARANCE, ///< overlapping drilled holes break drill bits - DRCE_TRACK_WIDTH, ///< Track width is too small or too large - DRCE_TOO_SMALL_VIA, ///< Too small via size - DRCE_ANNULUS, ///< Via size and drill leave annulus too small or too large - DRCE_TOO_SMALL_DRILL, ///< Too small via or pad drill - DRCE_VIA_HOLE_BIGGER, ///< via's hole is bigger than its diameter - DRCE_PADSTACK, ///< something is wrong with a pad or via stackup - DRCE_TOO_SMALL_MICROVIA, ///< Too small micro via size - DRCE_TOO_SMALL_MICROVIA_DRILL, ///< Too small micro via drill - DRCE_KEEPOUT, ///< A disallowed object is inside a keepout - DRCE_OVERLAPPING_FOOTPRINTS, ///< footprint courtyards overlap - DRCE_MISSING_COURTYARD, ///< footprint has no courtyard defined - DRCE_MALFORMED_COURTYARD, ///< footprint has a courtyard but malformed - ///< (not convertible to a closed polygon with holes) - DRCE_PTH_IN_COURTYARD, - DRCE_NPTH_IN_COURTYARD, - DRCE_DISABLED_LAYER_ITEM, ///< item on a disabled layer - DRCE_INVALID_OUTLINE, ///< invalid board outline - DRCE_MISSING_FOOTPRINT, ///< footprint not found for netlist item - DRCE_DUPLICATE_FOOTPRINT, ///< more than one footprints found for netlist item - DRCE_EXTRA_FOOTPRINT, ///< netlist item not found for footprint - - DRCE_UNRESOLVED_VARIABLE, - DRCE_VIA_DIAMETER, ///< Via diameter checks (min/max) - - DRCE_LAST = DRCE_UNRESOLVED_VARIABLE -}; class DRC_REPORT { @@ -197,7 +153,6 @@ public: m_reporter = aReporter; } - bool LoadRules( wxFileName aPath ); void RunTests(); void SetErrorLimit( int aLimit ); @@ -212,14 +167,13 @@ public: return m_board; } + const DRC_CONSTRAINT& EvalRulesForItems( DRC_CONSTRAINT_TYPE_T ruleID, BOARD_ITEM* a, + BOARD_ITEM* b = nullptr, + PCB_LAYER_ID aLayer = UNDEFINED_LAYER ); + std::vector QueryConstraintsById( DRC_CONSTRAINT_TYPE_T ruleID ); - const DRC_CONSTRAINT& EvalRulesForItems( - DRC_CONSTRAINT_TYPE_T ruleID, BOARD_ITEM* a, BOARD_ITEM* b = nullptr, PCB_LAYER_ID aLayer = UNDEFINED_LAYER ); - - std::vector QueryConstraintsById( test::DRC_CONSTRAINT_TYPE_T ruleID ); - - bool HasCorrectRulesForId( test::DRC_CONSTRAINT_TYPE_T ruleID ); + bool HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T ruleID ); EDA_UNITS UserUnits() const { @@ -235,12 +189,11 @@ public: std::shared_ptr GetReport() const { return m_drcReport; } - bool QueryWorstConstraint( DRC_CONSTRAINT_TYPE_T aRuleId, test::DRC_CONSTRAINT& aConstraint, DRC_CONSTRAINT_QUERY_T aQueryType ); - + bool QueryWorstConstraint( DRC_CONSTRAINT_TYPE_T aRuleId, DRC_CONSTRAINT& aConstraint, + DRC_CONSTRAINT_QUERY_T aQueryType ); private: - - void addRule( test::DRC_RULE* rule ) + void addRule( DRC_RULE* rule ) { m_rules.push_back(rule); } @@ -249,42 +202,40 @@ private: struct CONSTRAINT_WITH_CONDITIONS { - std::vector conditions; - test::DRC_RULE* parentRule; - test::DRC_CONSTRAINT constraint; + std::vector conditions; + DRC_RULE* parentRule; + DRC_CONSTRAINT constraint; }; struct CONSTRAINT_SET { std::vector sortedConstraints; - DRC_TEST_PROVIDER* provider; + DRC_TEST_PROVIDER* provider; }; - typedef std::unordered_map CONSTRAINT_MAP; - + typedef std::unordered_map CONSTRAINT_MAP; void inferLegacyRules(); void loadTestProviders(); - test::DRC_RULE* createInferredRule( const wxString& name, std::set items, int priority ); + DRC_RULE* createInferredRule( const wxString& name, std::set items, int priority ); - BOARD_DESIGN_SETTINGS* m_designSettings; - BOARD* m_board; - KIGFX::WS_PROXY_VIEW_ITEM* m_worksheet; - NETLIST* m_schematicNetlist; +protected: + BOARD_DESIGN_SETTINGS* m_designSettings; + BOARD* m_board; + KIGFX::WS_PROXY_VIEW_ITEM* m_worksheet; + NETLIST* m_schematicNetlist; - std::shared_ptr m_drcReport; + std::shared_ptr m_drcReport; std::vector m_ruleConditions; std::vector m_rules; std::vector m_testProviders; std::unordered_map m_implicitRules; - CONSTRAINT_MAP m_constraintMap; - REPORTER* m_reporter; - PROGRESS_REPORTER* m_progressReporter; + CONSTRAINT_MAP m_constraintMap; + REPORTER* m_reporter; + PROGRESS_REPORTER* m_progressReporter; // condition -> rule -> provider }; -}; // namespace test - #endif // DRC_H diff --git a/pcbnew/drc/drc_item.cpp b/pcbnew/drc/drc_item.cpp index ab5209ccec..bd4fa0be9e 100644 --- a/pcbnew/drc/drc_item.cpp +++ b/pcbnew/drc/drc_item.cpp @@ -79,6 +79,10 @@ DRC_ITEM DRC_ITEM::trackDangling( DRCE_DANGLING_TRACK, _( "Track has unconnected end" ), wxT( "track_dangling" ) ); +DRC_ITEM DRC_ITEM::holeClearance( DRCE_HOLE_CLEARANCE, + _( "Hole clearance" ), + wxT( "hole_clearance" ) ); + DRC_ITEM DRC_ITEM::holeNearHole( DRCE_DRILLED_HOLES_TOO_CLOSE, _( "Drilled holes too close together" ), wxT( "hole_near_hole" ) ); @@ -91,9 +95,9 @@ DRC_ITEM DRC_ITEM::viaTooSmall( DRCE_TOO_SMALL_VIA, _( "Via size too small" ), wxT( "via_too_small" ) ); -DRC_ITEM DRC_ITEM::viaAnnulus( DRCE_VIA_ANNULUS, - _( "Via annulus" ), - wxT( "via_annulus" ) ); +DRC_ITEM DRC_ITEM::annulus( DRCE_ANNULUS, + _( "Annulus" ), + wxT( "annulus" ) ); DRC_ITEM DRC_ITEM::drillTooSmall( DRCE_TOO_SMALL_DRILL, _( "Drill too small" ), @@ -180,9 +184,10 @@ std::vector> DRC_ITEM::allItemTypes( { DRC_ITEM::viaDangling, DRC_ITEM::trackDangling, DRC_ITEM::holeNearHole, + DRC_ITEM::holeClearance, DRC_ITEM::trackWidth, DRC_ITEM::viaTooSmall, - DRC_ITEM::viaAnnulus, + DRC_ITEM::annulus, DRC_ITEM::drillTooSmall, DRC_ITEM::viaHoleLargerThanPad, DRC_ITEM::padstack, @@ -199,6 +204,7 @@ std::vector> DRC_ITEM::allItemTypes( { DRC_ITEM::duplicateFootprints, DRC_ITEM::missingFootprint, DRC_ITEM::extraFootprint, + DRC_ITEM::netConflict, DRC_ITEM::unresolvedVariable } ); @@ -218,9 +224,10 @@ std::shared_ptr DRC_ITEM::Create( int aErrorCode ) case DRCE_DANGLING_VIA: return std::make_shared( viaDangling ); case DRCE_DANGLING_TRACK: return std::make_shared( trackDangling ); case DRCE_DRILLED_HOLES_TOO_CLOSE: return std::make_shared( holeNearHole ); + case DRCE_HOLE_CLEARANCE: return std::make_shared( holeClearance ); case DRCE_TRACK_WIDTH: return std::make_shared( trackWidth ); case DRCE_TOO_SMALL_VIA: return std::make_shared( viaTooSmall ); - case DRCE_VIA_ANNULUS: return std::make_shared( viaAnnulus ); + case DRCE_ANNULUS: return std::make_shared( annulus ); case DRCE_TOO_SMALL_DRILL: return std::make_shared( drillTooSmall ); case DRCE_VIA_HOLE_BIGGER: return std::make_shared( viaHoleLargerThanPad ); case DRCE_PADSTACK: return std::make_shared( padstack ); diff --git a/pcbnew/drc/drc_item.h b/pcbnew/drc/drc_item.h index 69997eff8c..7f7fed8374 100644 --- a/pcbnew/drc/drc_item.h +++ b/pcbnew/drc/drc_item.h @@ -28,6 +28,8 @@ #include class PCB_BASE_FRAME; +class DRC_RULE; +class DRC_TEST_PROVIDER; class DRC_ITEM : public RC_ITEM { @@ -55,7 +57,14 @@ public: * Translates this object into a fragment of HTML suitable for the wxHtmlListBox class. * @return wxString - the html text. */ - wxString ShowHtml( PCB_BASE_FRAME* aFrame ) const; + wxString ShowHtml( PCB_BASE_FRAME* aFrame ) const; // JEY TODO + wxString FormatHtml( ) const { return ""; } // fixme + + void SetViolatingRule ( DRC_RULE *aRule ) { m_violatingRule = aRule; } + DRC_RULE* GetViolatingRule() const { return m_violatingRule; } + + void SetViolatingTest( DRC_TEST_PROVIDER *aProvider ) { m_violatingTest = aProvider; } + DRC_TEST_PROVIDER* GetViolatingTest() const { return m_violatingTest; } private: DRC_ITEM( int aErrorCode = 0, const wxString& aTitle = "", const wxString& aSettingsKey = "" ) @@ -78,10 +87,11 @@ private: static DRC_ITEM zoneHasEmptyNet; static DRC_ITEM viaDangling; static DRC_ITEM trackDangling; - static DRC_ITEM holeNearHole; + static DRC_ITEM holeNearHole; // JEY TODO + static DRC_ITEM holeClearance; // JEY TODO static DRC_ITEM trackWidth; static DRC_ITEM viaTooSmall; - static DRC_ITEM viaAnnulus; + static DRC_ITEM annulus; static DRC_ITEM drillTooSmall; static DRC_ITEM viaHoleLargerThanPad; static DRC_ITEM padstack; @@ -100,7 +110,10 @@ private: static DRC_ITEM extraFootprint; static DRC_ITEM netConflict; static DRC_ITEM unresolvedVariable; + +private: + DRC_RULE* m_violatingRule = nullptr; + DRC_TEST_PROVIDER* m_violatingTest = nullptr; }; - #endif // DRC_ITEM_H diff --git a/pcbnew/drc/drc_keepout_tester.cpp b/pcbnew/drc/drc_keepout_tester.cpp index 5bdcff4ba7..04d074eba5 100644 --- a/pcbnew/drc/drc_keepout_tester.cpp +++ b/pcbnew/drc/drc_keepout_tester.cpp @@ -29,7 +29,7 @@ #include DRC_KEEPOUT_TESTER::DRC_KEEPOUT_TESTER( MARKER_HANDLER aMarkerHandler ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), + LEGACY_DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), m_units( EDA_UNITS::MILLIMETRES ), m_board( nullptr ), m_zone( nullptr ), @@ -71,9 +71,9 @@ bool DRC_KEEPOUT_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) bool DRC_KEEPOUT_TESTER::checkTracksAndVias() { - constexpr int VIA_MASK = DISALLOW_VIAS | DISALLOW_MICRO_VIAS | DISALLOW_BB_VIAS; - constexpr int CHECK_VIAS_MASK = VIA_MASK | DISALLOW_HOLES; - constexpr int CHECK_TRACKS_AND_VIAS_MASK = CHECK_VIAS_MASK | DISALLOW_TRACKS; + constexpr int VIA_MASK = DRC_DISALLOW_VIAS | DRC_DISALLOW_MICRO_VIAS | DRC_DISALLOW_BB_VIAS; + constexpr int CHECK_VIAS_MASK = VIA_MASK | DRC_DISALLOW_HOLES; + constexpr int CHECK_TRACKS_AND_VIAS_MASK = CHECK_VIAS_MASK | DRC_DISALLOW_TRACKS; if(( m_keepoutFlags & CHECK_TRACKS_AND_VIAS_MASK ) == 0 ) return true; @@ -85,7 +85,7 @@ bool DRC_KEEPOUT_TESTER::checkTracksAndVias() if( !m_zoneBBox.Intersects( segm->GetBoundingBox() ) ) continue; - if( segm->Type() == PCB_TRACE_T && ( m_keepoutFlags & DISALLOW_TRACKS ) != 0 ) + if( segm->Type() == PCB_TRACE_T && ( m_keepoutFlags & DRC_DISALLOW_TRACKS ) != 0 ) { // Ignore if the keepout zone is not on the same layer PCB_LAYER_ID layer = segm->GetLayer(); @@ -100,7 +100,7 @@ bool DRC_KEEPOUT_TESTER::checkTracksAndVias() std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_KEEPOUT ); m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), - m_sources.at( DISALLOW_TRACKS ) ); + m_sources.at( DRC_DISALLOW_TRACKS ) ); drcItem->SetErrorMessage( m_msg ); drcItem->SetItems( segm, m_zone ); @@ -116,23 +116,23 @@ bool DRC_KEEPOUT_TESTER::checkTracksAndVias() int test = 0; int clearance = via->GetWidth() / 2; - if( ( m_keepoutFlags & DISALLOW_VIAS ) > 0 ) + if( ( m_keepoutFlags & DRC_DISALLOW_VIAS ) > 0 ) { - test = DISALLOW_VIAS; + test = DRC_DISALLOW_VIAS; } else if( via->GetViaType() == VIATYPE::MICROVIA - && ( m_keepoutFlags & DISALLOW_MICRO_VIAS ) > 0 ) + && ( m_keepoutFlags & DRC_DISALLOW_MICRO_VIAS ) > 0 ) { - test = DISALLOW_MICRO_VIAS; + test = DRC_DISALLOW_MICRO_VIAS; } else if( via->GetViaType() == VIATYPE::BLIND_BURIED - && ( m_keepoutFlags & DISALLOW_BB_VIAS ) > 0 ) + && ( m_keepoutFlags & DRC_DISALLOW_BB_VIAS ) > 0 ) { - test = DISALLOW_BB_VIAS; + test = DRC_DISALLOW_BB_VIAS; } - else if( ( m_keepoutFlags & DISALLOW_HOLES ) > 0 ) + else if( ( m_keepoutFlags & DRC_DISALLOW_HOLES ) > 0 ) { - test = DISALLOW_HOLES; + test = DRC_DISALLOW_HOLES; clearance = via->GetDrillValue() / 2; } else @@ -157,8 +157,8 @@ bool DRC_KEEPOUT_TESTER::checkTracksAndVias() bool DRC_KEEPOUT_TESTER::checkFootprints() { - constexpr int CHECK_PADS_MASK = DISALLOW_PADS | DISALLOW_HOLES; - constexpr int CHECK_FOOTPRINTS_MASK = CHECK_PADS_MASK | DISALLOW_FOOTPRINTS; + constexpr int CHECK_PADS_MASK = DRC_DISALLOW_PADS | DRC_DISALLOW_HOLES; + constexpr int CHECK_FOOTPRINTS_MASK = CHECK_PADS_MASK | DRC_DISALLOW_FOOTPRINTS; if(( m_keepoutFlags & CHECK_FOOTPRINTS_MASK ) == 0 ) return true; @@ -173,7 +173,7 @@ bool DRC_KEEPOUT_TESTER::checkFootprints() if( !m_zoneBBox.Intersects( fp->GetBoundingBox() ) ) continue; - if( ( m_keepoutFlags & DISALLOW_FOOTPRINTS ) > 0 + if( ( m_keepoutFlags & DRC_DISALLOW_FOOTPRINTS ) > 0 && ( fp->IsFlipped() ? m_zone->CommonLayerExists( LSET::BackMask() ) : m_zone->CommonLayerExists( LSET::FrontMask() ) ) ) { @@ -195,7 +195,7 @@ bool DRC_KEEPOUT_TESTER::checkFootprints() std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_KEEPOUT ); m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), - m_sources.at( DISALLOW_FOOTPRINTS ) ); + m_sources.at( DRC_DISALLOW_FOOTPRINTS ) ); drcItem->SetErrorMessage( m_msg ); drcItem->SetItems( fp, m_zone ); @@ -231,7 +231,7 @@ bool DRC_KEEPOUT_TESTER::checkPads( MODULE* aModule ) if( !m_zoneBBox.Intersects( padBBox ) ) continue; - if( ( m_keepoutFlags & DISALLOW_PADS ) > 0 ) + if( ( m_keepoutFlags & DRC_DISALLOW_PADS ) > 0 ) { SHAPE_POLY_SET outline = *pad->GetEffectivePolygon(); @@ -245,7 +245,7 @@ bool DRC_KEEPOUT_TESTER::checkPads( MODULE* aModule ) std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_KEEPOUT ); m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), - m_sources.at( DISALLOW_PADS ) ); + m_sources.at( DRC_DISALLOW_PADS ) ); drcItem->SetErrorMessage( m_msg ); drcItem->SetItems( pad, m_zone ); @@ -254,7 +254,7 @@ bool DRC_KEEPOUT_TESTER::checkPads( MODULE* aModule ) success = false; } } - else if( ( m_keepoutFlags & DISALLOW_HOLES ) > 0 ) + else if( ( m_keepoutFlags & DRC_DISALLOW_HOLES ) > 0 ) { const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape(); @@ -263,7 +263,7 @@ bool DRC_KEEPOUT_TESTER::checkPads( MODULE* aModule ) std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_KEEPOUT ); m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), - m_sources.at( DISALLOW_HOLES ) ); + m_sources.at( DRC_DISALLOW_HOLES ) ); drcItem->SetErrorMessage( m_msg ); drcItem->SetItems( pad, m_zone ); @@ -280,7 +280,7 @@ bool DRC_KEEPOUT_TESTER::checkPads( MODULE* aModule ) bool DRC_KEEPOUT_TESTER::checkDrawings() { - constexpr int CHECK_DRAWINGS_MASK = DISALLOW_TEXTS | DISALLOW_GRAPHICS; + constexpr int CHECK_DRAWINGS_MASK = DRC_DISALLOW_TEXTS | DRC_DISALLOW_GRAPHICS; constexpr KICAD_T graphicTypes[] = { PCB_LINE_T, PCB_DIMENSION_T, PCB_TARGET_T, EOT }; if(( m_keepoutFlags & CHECK_DRAWINGS_MASK ) == 0 ) @@ -295,10 +295,10 @@ bool DRC_KEEPOUT_TESTER::checkDrawings() int sourceId = 0; - if( drawing->IsType( graphicTypes ) && ( m_keepoutFlags & DISALLOW_GRAPHICS ) > 0 ) - sourceId = DISALLOW_GRAPHICS; - else if( drawing->Type() == PCB_TEXT_T && ( m_keepoutFlags & DISALLOW_TEXTS ) > 0 ) - sourceId = DISALLOW_TEXTS; + if( drawing->IsType( graphicTypes ) && ( m_keepoutFlags & DRC_DISALLOW_GRAPHICS ) > 0 ) + sourceId = DRC_DISALLOW_GRAPHICS; + else if( drawing->Type() == PCB_TEXT_T && ( m_keepoutFlags & DRC_DISALLOW_TEXTS ) > 0 ) + sourceId = DRC_DISALLOW_TEXTS; else continue; diff --git a/pcbnew/drc/drc_keepout_tester.h b/pcbnew/drc/drc_keepout_tester.h index c7cdf93019..d8d484a40b 100644 --- a/pcbnew/drc/drc_keepout_tester.h +++ b/pcbnew/drc/drc_keepout_tester.h @@ -25,13 +25,13 @@ #ifndef DRC_KEEPOUT_TESTER__H #define DRC_KEEPOUT_TESTER__H -#include +#include class BOARD; -class DRC_KEEPOUT_TESTER : public DRC_TEST_PROVIDER +class DRC_KEEPOUT_TESTER : public LEGACY_DRC_TEST_PROVIDER { public: DRC_KEEPOUT_TESTER( MARKER_HANDLER aMarkerHandler ); diff --git a/pcbnew/drc/drc_results_provider.h b/pcbnew/drc/drc_results_provider.h index 73fdb160b5..22f93f21f6 100644 --- a/pcbnew/drc/drc_results_provider.h +++ b/pcbnew/drc/drc_results_provider.h @@ -35,11 +35,14 @@ /** - * DRC_TEST_PROVIDER + * LEGACY_DRC_TEST_PROVIDER * is a base class that represents a DRC "provider" which runs some DRC functions over a * #BOARD and spits out #PCB_MARKERs as needed. + * + * JEY TODO: to remove + * */ -class DRC_TEST_PROVIDER +class LEGACY_DRC_TEST_PROVIDER { public: /** @@ -55,10 +58,10 @@ public: */ virtual bool RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) = 0; - virtual ~DRC_TEST_PROVIDER() {} + virtual ~LEGACY_DRC_TEST_PROVIDER() {} protected: - DRC_TEST_PROVIDER( MARKER_HANDLER aMarkerHandler ) : + LEGACY_DRC_TEST_PROVIDER( MARKER_HANDLER aMarkerHandler ) : m_marker_handler( std::move( aMarkerHandler ) ) { } diff --git a/pcbnew/drc/drc_rule.cpp b/pcbnew/drc/drc_rule.cpp index 8d56367aec..bfd2188930 100644 --- a/pcbnew/drc/drc_rule.cpp +++ b/pcbnew/drc/drc_rule.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -34,7 +35,7 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName, REPORTER* aReporter ) { - BOARD* board = aItem->GetBoard(); + BOARD* board = aItem->GetBoard(); if( !board ) return nullptr; @@ -80,10 +81,10 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* if( aReporter ) { aReporter->Report( wxString::Format( _( "Checking rule condition \"%s\"." ), - rule->m_Condition.m_Expression ) ); + rule->m_Condition->GetExpression() ) ); } - if( rule->m_Condition.EvaluateFor( aItem, bItem, aLayer ) ) + if( rule->m_Condition->EvaluateFor( aItem, bItem, aLayer ) ) { if( aReporter ) aReporter->Report( "Rule applied." ); @@ -94,7 +95,7 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* return constraint; } - if( bItem && rule->m_Condition.EvaluateFor( bItem, aItem, aLayer ) ) + if( bItem && rule->m_Condition->EvaluateFor( bItem, aItem, aLayer ) ) { if( aReporter ) aReporter->Report( "Rule applied." ); @@ -118,32 +119,43 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* DRC_RULE::DRC_RULE() : - m_LayerCondition( LSET::AllLayersMask() ) + m_Unary( false ), + m_LayerCondition( LSET::AllLayersMask() ), + m_Priority( 0 ), + m_Severity( SEVERITY::RPT_SEVERITY_ERROR ) { } DRC_RULE::~DRC_RULE() { + delete m_Condition; } -DRC_RULE_CONDITION::DRC_RULE_CONDITION() +void DRC_RULE::AddConstraint( DRC_CONSTRAINT& aConstraint ) +{ + aConstraint.SetParentRule( this ); + m_Constraints.push_back( aConstraint ); +} + + +DRC_RULE_CONDITION::DRC_RULE_CONDITION( const wxString& aExpression ) : + m_expression( aExpression ), + m_ucode ( nullptr ) { - m_ucode = nullptr; } DRC_RULE_CONDITION::~DRC_RULE_CONDITION() { - delete m_ucode; } bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer, REPORTER* aReporter ) { - if( m_Expression.IsEmpty() ) + if( GetExpression().IsEmpty() ) { if( aReporter ) aReporter->Report( _( "Unconditional constraint." ) ); @@ -152,7 +164,7 @@ bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM } if( aReporter ) - aReporter->Report( _( "Evaluating expression \"" + m_Expression + "\"." ) ); + aReporter->Report( _( "Evaluating expression \"" + GetExpression() + "\"." ) ); if( !m_ucode ) { @@ -195,12 +207,11 @@ bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSou PCB_EXPR_COMPILER compiler; compiler.SetErrorCallback( errorHandler ); - if (!m_ucode) - m_ucode = new PCB_EXPR_UCODE; + m_ucode = std::make_unique(); PCB_EXPR_CONTEXT preflightContext( F_Cu ); - bool ok = compiler.Compile( m_Expression.ToUTF8().data(), m_ucode, &preflightContext ); + bool ok = compiler.Compile( GetExpression().ToUTF8().data(), m_ucode.get(), &preflightContext ); return ok; } diff --git a/pcbnew/drc/drc_rule.h b/pcbnew/drc/drc_rule.h index 67ef5b6800..cc26b67382 100644 --- a/pcbnew/drc/drc_rule.h +++ b/pcbnew/drc/drc_rule.h @@ -21,39 +21,49 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef DRC_RULE_H -#define DRC_RULE_H +#ifndef DRC_RULE_PROTO_H +#define DRC_RULE_PROTO_H #include #include #include #include - class BOARD_ITEM; + class PCB_EXPR_UCODE; - -#define DISALLOW_VIAS (1 << 0) -#define DISALLOW_MICRO_VIAS (1 << 1) -#define DISALLOW_BB_VIAS (1 << 2) -#define DISALLOW_TRACKS (1 << 3) -#define DISALLOW_PADS (1 << 4) -#define DISALLOW_ZONES (1 << 5) -#define DISALLOW_TEXTS (1 << 6) -#define DISALLOW_GRAPHICS (1 << 7) -#define DISALLOW_HOLES (1 << 8) -#define DISALLOW_FOOTPRINTS (1 << 9) - +class DRC_RULE; +class DRC_RULE_CONDITION; enum DRC_CONSTRAINT_TYPE_T { - DRC_RULE_ID_UNKNOWN = -1, - DRC_RULE_ID_CLEARANCE = 0, - DRC_RULE_ID_HOLE_SIZE, - DRC_RULE_ID_ANNULUS, - DRC_RULE_ID_TRACK, - DRC_RULE_ID_DISALLOW + DRC_CONSTRAINT_TYPE_UNKNOWN = -1, + DRC_CONSTRAINT_TYPE_CLEARANCE = 0, + DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, + DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, + DRC_CONSTRAINT_TYPE_HOLE_SIZE, + DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE, + DRC_CONSTRAINT_TYPE_SILK_TO_PAD, + DRC_CONSTRAINT_TYPE_SILK_TO_SILK, + DRC_CONSTRAINT_TYPE_TRACK_WIDTH, + DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, + DRC_CONSTRAINT_TYPE_DISALLOW, + DRC_CONSTRAINT_TYPE_VIA_DIAMETER +}; + +enum DRC_DISALLOW_T +{ + DRC_DISALLOW_VIAS = (1 << 0), + DRC_DISALLOW_MICRO_VIAS = (1 << 1), + DRC_DISALLOW_BB_VIAS = (1 << 2), + DRC_DISALLOW_TRACKS = (1 << 3), + DRC_DISALLOW_PADS = (1 << 4), + DRC_DISALLOW_ZONES = (1 << 5), + DRC_DISALLOW_TEXTS = (1 << 6), + DRC_DISALLOW_GRAPHICS = (1 << 7), + DRC_DISALLOW_HOLES = (1 << 8), + DRC_DISALLOW_FOOTPRINTS = (1 << 9) }; @@ -85,37 +95,47 @@ private: class DRC_CONSTRAINT { -public: - DRC_CONSTRAINT() : - m_Type( DRC_RULE_ID_UNKNOWN ), - m_DisallowFlags( 0 ) - {} + public: + DRC_CONSTRAINT( DRC_CONSTRAINT_TYPE_T aType = DRC_CONSTRAINT_TYPE_UNKNOWN ) : + m_Type( aType ), + m_DisallowFlags( 0 ), + m_parentRule( nullptr ) // fixme + { + } const MINOPTMAX& GetValue() const { return m_Value; } MINOPTMAX& Value() { return m_Value; } + void SetParentRule( DRC_RULE *aParentRule ) { m_parentRule = aParentRule; } + DRC_RULE* GetParentRule() const { return m_parentRule; } + public: DRC_CONSTRAINT_TYPE_T m_Type; MINOPTMAX m_Value; int m_DisallowFlags; + +private: + DRC_RULE* m_parentRule; }; class DRC_RULE_CONDITION { public: - DRC_RULE_CONDITION(); + DRC_RULE_CONDITION( const wxString& aExpression = "" ); ~DRC_RULE_CONDITION(); bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer, REPORTER* aReporter = nullptr ); - bool Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset ); -public: - wxString m_Expression; + bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 ); + + void SetExpression( const wxString& aExpression ) { m_expression = aExpression; } + wxString GetExpression() const { return m_expression; } private: - PCB_EXPR_UCODE* m_ucode; + wxString m_expression; + std::unique_ptr m_ucode; }; @@ -125,13 +145,40 @@ public: DRC_RULE(); virtual ~DRC_RULE(); + virtual bool IsImplicit() const + { + return false; + }; + + virtual bool AppliesTo( const BOARD_ITEM* a, const BOARD_ITEM* b = nullptr ) const + { + return true; + }; + + virtual bool HasSpecificItemSet() const + { + return false; + }; + + virtual void FillSpecificItemSet( std::set specificItems ) + { + }; + + void SetPriority( int aPriority ) { m_Priority = aPriority; } + int GetPriority() const { return m_Priority; } + + void AddConstraint( DRC_CONSTRAINT& aConstraint ); + public: + bool m_Unary; wxString m_Name; wxString m_LayerSource; LSET m_LayerCondition; - wxString m_TestProviderName; - DRC_RULE_CONDITION m_Condition; + DRC_RULE_CONDITION* m_Condition; std::vector m_Constraints; + + int m_Priority; // 0 indicates automatic priority generation fixme: use enum + SEVERITY m_Severity; }; @@ -141,4 +188,4 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* REPORTER* aReporter = nullptr ); -#endif // DRC_RULE_H +#endif // DRC_RULE_H diff --git a/pcbnew/drc/drc_rule_parser.cpp b/pcbnew/drc/drc_rule_parser.cpp index e46e9f9c11..3d7367c08f 100644 --- a/pcbnew/drc/drc_rule_parser.cpp +++ b/pcbnew/drc/drc_rule_parser.cpp @@ -92,7 +92,7 @@ void DRC_RULES_PARSER::Parse( std::vector& aRules, REPORTER* aReporte m_reporter = aReporter; - for( T token = NextTok(); token != T_EOF; token = NextTok() ) + for( T token = NextTok(); token != T_EOF; token = NextTok() ) { if( token != T_LEFT ) reportError( _( "Missing '('." ) ); @@ -172,7 +172,7 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE() rule->m_Name = FromUTF8(); - for( token = NextTok(); token != T_RIGHT && token != T_EOF; token = NextTok() ) + for( token = NextTok(); token != T_RIGHT && token != T_EOF; token = NextTok() ) { if( token != T_LEFT ) reportError( _( "Missing '('." ) ); @@ -196,8 +196,8 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE() if( IsSymbol( token ) ) { - rule->m_Condition.m_Expression = FromUTF8(); - rule->m_Condition.Compile( m_reporter, CurLineNumber(), CurOffset() ); + rule->m_Condition->SetExpression( FromUTF8() ); + rule->m_Condition->Compile( m_reporter, CurLineNumber(), CurOffset() ); } else { @@ -241,11 +241,10 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE() void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule ) { - aRule->m_Constraints.emplace_back( DRC_CONSTRAINT() ); + DRC_CONSTRAINT constraint; - DRC_CONSTRAINT& constraint = aRule->m_Constraints.back(); - int value; - wxString msg; + int value; + wxString msg; T token = NextTok(); @@ -259,11 +258,16 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule ) switch( token ) { - case T_clearance: constraint.m_Type = DRC_RULE_ID_CLEARANCE; break; - case T_track_width: constraint.m_Type = DRC_RULE_ID_TRACK; break; - case T_annulus_width: constraint.m_Type = DRC_RULE_ID_ANNULUS; break; - case T_hole: constraint.m_Type = DRC_RULE_ID_HOLE_SIZE; break; - case T_disallow: constraint.m_Type = DRC_RULE_ID_DISALLOW; break; + case T_clearance: constraint.m_Type = DRC_CONSTRAINT_TYPE_CLEARANCE; break; + case T_hole_clearance: constraint.m_Type = DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE; break; + case T_edge_clearance: constraint.m_Type = DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE; break; + case T_hole: constraint.m_Type = DRC_CONSTRAINT_TYPE_HOLE_SIZE; break; + case T_courtyard_clearance: constraint.m_Type = DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE; break; + case T_silk_to_pad: constraint.m_Type = DRC_CONSTRAINT_TYPE_SILK_TO_PAD; break; + case T_silk_to_silk: constraint.m_Type = DRC_CONSTRAINT_TYPE_SILK_TO_SILK; break; + case T_track_width: constraint.m_Type = DRC_CONSTRAINT_TYPE_TRACK_WIDTH; break; + case T_annulus_width: constraint.m_Type = DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH; break; + case T_disallow: constraint.m_Type = DRC_CONSTRAINT_TYPE_DISALLOW; break; default: msg.Printf( _( "Unrecognized item '%s'.| Expected %s." ), FromUTF8(), @@ -272,7 +276,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule ) reportError( msg ); } - if( constraint.m_Type == DRC_RULE_ID_DISALLOW ) + if( constraint.m_Type == DRC_CONSTRAINT_TYPE_DISALLOW ) { for( token = NextTok(); token != T_RIGHT; token = NextTok() ) { @@ -281,16 +285,16 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule ) switch( token ) { - case T_track: constraint.m_DisallowFlags |= DISALLOW_TRACKS; break; - case T_via: constraint.m_DisallowFlags |= DISALLOW_VIAS; break; - case T_micro_via: constraint.m_DisallowFlags |= DISALLOW_MICRO_VIAS; break; - case T_buried_via: constraint.m_DisallowFlags |= DISALLOW_BB_VIAS; break; - case T_pad: constraint.m_DisallowFlags |= DISALLOW_PADS; break; - case T_zone: constraint.m_DisallowFlags |= DISALLOW_ZONES; break; - case T_text: constraint.m_DisallowFlags |= DISALLOW_TEXTS; break; - case T_graphic: constraint.m_DisallowFlags |= DISALLOW_GRAPHICS; break; - case T_hole: constraint.m_DisallowFlags |= DISALLOW_HOLES; break; - case T_footprint: constraint.m_DisallowFlags |= DISALLOW_FOOTPRINTS; break; + case T_track: constraint.m_DisallowFlags |= DRC_DISALLOW_TRACKS; break; + case T_via: constraint.m_DisallowFlags |= DRC_DISALLOW_VIAS; break; + case T_micro_via: constraint.m_DisallowFlags |= DRC_DISALLOW_MICRO_VIAS; break; + case T_buried_via: constraint.m_DisallowFlags |= DRC_DISALLOW_BB_VIAS; break; + case T_pad: constraint.m_DisallowFlags |= DRC_DISALLOW_PADS; break; + case T_zone: constraint.m_DisallowFlags |= DRC_DISALLOW_ZONES; break; + case T_text: constraint.m_DisallowFlags |= DRC_DISALLOW_TEXTS; break; + case T_graphic: constraint.m_DisallowFlags |= DRC_DISALLOW_GRAPHICS; break; + case T_hole: constraint.m_DisallowFlags |= DRC_DISALLOW_HOLES; break; + case T_footprint: constraint.m_DisallowFlags |= DRC_DISALLOW_FOOTPRINTS; break; case T_EOF: reportError( _( "Missing ')'." ) ); @@ -313,7 +317,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule ) return; } - for( token = NextTok(); token != T_RIGHT && token != T_EOF; token = NextTok() ) + for( token = NextTok(); token != T_RIGHT && token != T_EOF; token = NextTok() ) { if( token != T_LEFT ) reportError( _( "Missing '('." ) ); @@ -396,6 +400,8 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule ) if( (int) CurTok() != DSN_RIGHT ) reportError( _( "Missing ')'." ) ); + + aRule->AddConstraint( constraint ); } @@ -416,7 +422,7 @@ void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult PCB_EXPR_EVALUATOR evaluator; evaluator.SetErrorCallback( errorHandler ); - + evaluator.Evaluate( aExpr ); aResult = evaluator.Result(); } diff --git a/pcbnew/drc/drc_rule_parser.h b/pcbnew/drc/drc_rule_parser.h index c4557dffde..e4bfa7e50b 100644 --- a/pcbnew/drc/drc_rule_parser.h +++ b/pcbnew/drc/drc_rule_parser.h @@ -34,7 +34,7 @@ class BOARD_ITEM; -#define DRC_RULE_FILE_VERSION 20200515 +#define DRC_RULE_FILE_VERSION 20200610 class DRC_RULES_PARSER : public DRC_RULES_LEXER diff --git a/pcbnew/drc/drc_test_provider.cpp b/pcbnew/drc/drc_test_provider.cpp index 62f2d2e822..61a46a2e7c 100644 --- a/pcbnew/drc/drc_test_provider.cpp +++ b/pcbnew/drc/drc_test_provider.cpp @@ -1,60 +1,60 @@ #include #include -#include +#include -test::DRC_TEST_PROVIDER::DRC_TEST_PROVIDER() : +DRC_TEST_PROVIDER::DRC_TEST_PROVIDER() : m_drcEngine( nullptr ), m_enable( false ) { } -void test::DRC_TEST_PROVIDER::Enable( bool enable ) +void DRC_TEST_PROVIDER::Enable( bool enable ) { m_enable = enable; } -bool test::DRC_TEST_PROVIDER::IsEnabled() const +bool DRC_TEST_PROVIDER::IsEnabled() const { return m_enable; } -const wxString test::DRC_TEST_PROVIDER::GetName() const { return ""; } -const wxString test::DRC_TEST_PROVIDER::GetDescription() const { return ""; } +const wxString DRC_TEST_PROVIDER::GetName() const { return ""; } +const wxString DRC_TEST_PROVIDER::GetDescription() const { return ""; } -void test::DRC_TEST_PROVIDER::Report( std::shared_ptr item ) +void DRC_TEST_PROVIDER::Report( std::shared_ptr item ) { item->SetViolatingTest( this ); m_drcEngine->Report( item, nullptr ); } -void test::DRC_TEST_PROVIDER::ReportWithMarker( std::shared_ptr item, VECTOR2I aMarkerPos ) +void DRC_TEST_PROVIDER::ReportWithMarker( std::shared_ptr item, VECTOR2I aMarkerPos ) { item->SetViolatingTest( this ); MARKER_PCB* marker = new MARKER_PCB( item, wxPoint( aMarkerPos.x, aMarkerPos.y) ); m_drcEngine->Report( item, marker ); } -void test::DRC_TEST_PROVIDER::ReportWithMarker( std::shared_ptr item, wxPoint aMarkerPos ) +void DRC_TEST_PROVIDER::ReportWithMarker( std::shared_ptr item, wxPoint aMarkerPos ) { item->SetViolatingTest( this ); MARKER_PCB* marker = new MARKER_PCB( item, wxPoint( aMarkerPos.x, aMarkerPos.y) ); m_drcEngine->Report( item, marker ); // fixme: create marker } -void test::DRC_TEST_PROVIDER::ReportProgress( double aProgress ) +void DRC_TEST_PROVIDER::ReportProgress( double aProgress ) { m_drcEngine->ReportProgress( aProgress ); } -void test::DRC_TEST_PROVIDER::ReportStage ( const wxString& aStageName, int index, int total ) +void DRC_TEST_PROVIDER::ReportStage ( const wxString& aStageName, int index, int total ) { m_drcEngine->ReportStage( aStageName, index, total ); ReportAux( aStageName ); } -void test::DRC_TEST_PROVIDER::ReportAux( const wxString fmt, ... ) +void DRC_TEST_PROVIDER::ReportAux( const wxString& fmt, ... ) { va_list vargs; va_start( vargs, fmt ); @@ -64,45 +64,50 @@ void test::DRC_TEST_PROVIDER::ReportAux( const wxString fmt, ... ) m_drcEngine->ReportAux( str ); } -bool test::DRC_TEST_PROVIDER::isErrorLimitExceeded( int error_code ) +bool DRC_TEST_PROVIDER::isErrorLimitExceeded( int error_code ) { // fixme: implement error limit (or timeout) return false; } -EDA_UNITS test::DRC_TEST_PROVIDER::userUnits() const +EDA_UNITS DRC_TEST_PROVIDER::userUnits() const { return m_drcEngine->UserUnits(); } -void test::DRC_TEST_PROVIDER::accountCheck( const test::DRC_RULE* ruleToTest ) +void DRC_TEST_PROVIDER::accountCheck( const DRC_RULE* ruleToTest ) { auto it = m_stats.find( ruleToTest ); + if( it == m_stats.end() ) m_stats[ ruleToTest ] = 1; else it->second++; } -void test::DRC_TEST_PROVIDER::accountCheck( const test::DRC_CONSTRAINT& constraintToTest ) +void DRC_TEST_PROVIDER::accountCheck( const DRC_CONSTRAINT& constraintToTest ) { accountCheck( constraintToTest.GetParentRule() ); } -void test::DRC_TEST_PROVIDER::reportRuleStatistics() +void DRC_TEST_PROVIDER::reportRuleStatistics() { if( !m_isRuleDriven ) return; m_drcEngine->ReportAux("Rule hit statistics: "); - for( auto stat : m_stats ) + + for( const std::pair& stat : m_stats ) { - m_drcEngine->ReportAux( wxString::Format( " - rule '%s': %d hits ", stat.first->GetName().c_str(), stat.second ) ); + m_drcEngine->ReportAux( wxString::Format( " - rule '%s': %d hits ", + stat.first->m_Name, + stat.second ) ); } } -int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTypes, const LSET aLayers, std::function aFunc ) +int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTypes, const LSET aLayers, + std::function aFunc ) { BOARD *brd = m_drcEngine->GetBoard(); std::bitset typeMask; @@ -126,7 +131,7 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTy /* case PCB_TRACE_T: case PCB_VIA_T: case PCB_ARC_T:*/ - for ( auto item : brd->Tracks() ) + for( TRACK* item : brd->Tracks() ) { if( (item->GetLayerSet() & aLayers).any() ) { @@ -153,7 +158,7 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTy case PCB_TEXT_T: case PCB_TARGET_T: */ - for( auto item : brd->Drawings() ) + for( BOARD_ITEM* item : brd->Drawings() ) { if( (item->GetLayerSet() & aLayers).any() ) { @@ -188,7 +193,7 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTy } } - for( auto item : brd->Zones() ) + for( ZONE_CONTAINER* item : brd->Zones() ) { if( (item->GetLayerSet() & aLayers).any() ) { @@ -202,7 +207,7 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTy } } - for( auto mod : brd->Modules() ) + for( MODULE* mod : brd->Modules() ) { if( typeMask[ PCB_MODULE_TEXT_T ] ) { @@ -223,7 +228,7 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTy } } - for( auto pad : mod->Pads() ) + for( D_PAD* pad : mod->Pads() ) { if( (pad->GetLayerSet() & aLayers).any() ) { @@ -237,7 +242,7 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTy } } - for( auto dwg : mod->GraphicalItems() ) + for( BOARD_ITEM* dwg : mod->GraphicalItems() ) { if( (dwg->GetLayerSet() & aLayers).any() ) { @@ -258,7 +263,7 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTy } } - for( auto zone : mod->Zones() ) + for( ZONE_CONTAINER* zone : mod->Zones() ) { if( (zone->GetLayerSet() & aLayers).any() ) { diff --git a/pcbnew/drc/drc_test_provider.h b/pcbnew/drc/drc_test_provider.h index 2780f9aa8a..6f72064222 100644 --- a/pcbnew/drc/drc_test_provider.h +++ b/pcbnew/drc/drc_test_provider.h @@ -22,8 +22,8 @@ */ -#ifndef DRC_PROVIDER__H -#define DRC_PROVIDER__H +#ifndef DRC_TEST_PROVIDER__H +#define DRC_TEST_PROVIDER__H #include #include @@ -31,38 +31,37 @@ #include #include -namespace test { - class DRC_ENGINE; +class DRC_TEST_PROVIDER; + class DRC_TEST_PROVIDER_REGISTRY { - public: - DRC_TEST_PROVIDER_REGISTRY() {}; - ~DRC_TEST_PROVIDER_REGISTRY() {}; +public: + DRC_TEST_PROVIDER_REGISTRY() {}; + ~DRC_TEST_PROVIDER_REGISTRY() {}; - static DRC_TEST_PROVIDER_REGISTRY& Instance() - { - static DRC_TEST_PROVIDER_REGISTRY self; - return self; - } + static DRC_TEST_PROVIDER_REGISTRY& Instance() + { + static DRC_TEST_PROVIDER_REGISTRY self; + return self; + } - void RegisterTestProvider(DRC_TEST_PROVIDER* provider) { m_providers.push_back(provider); } - std::vector GetTestProviders() const { return m_providers; } - - private: - std::vector m_providers; + void RegisterTestProvider( DRC_TEST_PROVIDER* provider ) { m_providers.push_back( provider ); } + std::vector GetTestProviders() const { return m_providers; } +private: + std::vector m_providers; }; template class DRC_REGISTER_TEST_PROVIDER { - public: - DRC_REGISTER_TEST_PROVIDER() - { - T* provider = new T; - DRC_TEST_PROVIDER_REGISTRY::Instance().RegisterTestProvider( provider ); - } +public: + DRC_REGISTER_TEST_PROVIDER() + { + T* provider = new T; + DRC_TEST_PROVIDER_REGISTRY::Instance().RegisterTestProvider( provider ); + } }; /** @@ -96,7 +95,7 @@ public: virtual const wxString GetName() const; virtual const wxString GetDescription() const; - virtual void ReportAux( const wxString fmt, ... ); + virtual void ReportAux( const wxString& fmt, ... ); virtual void Report( std::shared_ptr item ); virtual void ReportWithMarker( std::shared_ptr item, wxPoint aMarkerPos ); virtual void ReportWithMarker( std::shared_ptr item, VECTOR2I aMarkerPos ); @@ -112,7 +111,6 @@ public: } protected: - int forEachGeometryItem( const std::vector aTypes, const LSET aLayers, std::function aFunc ); @@ -128,7 +126,4 @@ protected: bool m_isRuleDriven = true; }; - -}; - -#endif // DRC_PROVIDER__H +#endif // DRC_TEST_PROVIDER__H diff --git a/pcbnew/drc/drc_textvar_tester.cpp b/pcbnew/drc/drc_textvar_tester.cpp index 8ebb48d7bf..bd916a4251 100644 --- a/pcbnew/drc/drc_textvar_tester.cpp +++ b/pcbnew/drc/drc_textvar_tester.cpp @@ -31,7 +31,7 @@ DRC_TEXTVAR_TESTER::DRC_TEXTVAR_TESTER( MARKER_HANDLER aMarkerHandler, KIGFX::WS_PROXY_VIEW_ITEM* aWorksheet ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), + LEGACY_DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), m_units( EDA_UNITS::MILLIMETRES ), m_board( nullptr ), m_worksheet( aWorksheet ) diff --git a/pcbnew/drc/drc_textvar_tester.h b/pcbnew/drc/drc_textvar_tester.h index 678d5b878f..b453560b35 100644 --- a/pcbnew/drc/drc_textvar_tester.h +++ b/pcbnew/drc/drc_textvar_tester.h @@ -25,13 +25,13 @@ #ifndef DRC_TEXTVAR_TESTER__H #define DRC_TEXTVAR_TESTER__H -#include +#include class BOARD; -class DRC_TEXTVAR_TESTER : public DRC_TEST_PROVIDER +class DRC_TEXTVAR_TESTER : public LEGACY_DRC_TEST_PROVIDER { public: DRC_TEXTVAR_TESTER( MARKER_HANDLER aMarkerHandler, KIGFX::WS_PROXY_VIEW_ITEM* aWorksheet ); diff --git a/qa/drc_proto/CMakeLists.txt b/qa/drc_proto/CMakeLists.txt index 93b841cf91..da36c0a2e7 100644 --- a/qa/drc_proto/CMakeLists.txt +++ b/qa/drc_proto/CMakeLists.txt @@ -36,9 +36,9 @@ endif() add_executable( drc_proto drc_rules_proto_keywords.cpp drc_proto_test.cpp - drc_rule.cpp - drc_rule_parser.cpp - drc_test_provider.cpp + ../../pcbnew/drc/drc_rule.cpp + ../../pcbnew/drc/drc_rule_parser.cpp + ../../pcbnew/drc/drc_test_provider.cpp drc_test_provider_clearance_base.cpp drc_test_provider_copper_clearance.cpp drc_test_provider_hole_clearance.cpp @@ -52,8 +52,8 @@ add_executable( drc_proto drc_test_provider_via_diameter.cpp drc_test_provider_lvs.cpp drc_test_provider_misc.cpp - drc_engine.cpp - drc_item.cpp + ../../pcbnew/drc/drc_engine.cpp + ../../pcbnew/drc/drc_item.cpp ../qa_utils/mocks.cpp ../pcbnew_utils/board_file_utils.cpp ../qa_utils/stdstream_line_reader.cpp diff --git a/qa/drc_proto/drc.cpp b/qa/drc_proto/drc.cpp deleted file mode 100644 index 870265797d..0000000000 --- a/qa/drc_proto/drc.cpp +++ /dev/null @@ -1,1439 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2004-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2017-2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for KiROUND -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DRC::DRC() : - PCB_TOOL_BASE( "pcbnew.DRCTool" ), - m_editFrame( nullptr ), - m_pcb( nullptr ), - m_board_outline_valid( false ), - m_drcDialog( nullptr ), - m_largestClearance( 0 ) -{ - // establish initial values for everything: - m_doUnconnectedTest = true; // enable unconnected tests - m_testTracksAgainstZones = false; // disable zone to items clearance tests - m_doKeepoutTest = true; // enable keepout areas to items clearance tests - m_refillZones = false; // Only fill zones if requested by user. - m_reportAllTrackErrors = false; - m_testFootprints = false; - - m_drcRun = false; - m_footprintsTested = false; -} - - -DRC::~DRC() -{ - for( DRC_ITEM* unconnectedItem : m_unconnected ) - delete unconnectedItem; - - for( DRC_ITEM* footprintItem : m_footprints ) - delete footprintItem; -} - - -void DRC::Reset( RESET_REASON aReason ) -{ - m_editFrame = getEditFrame(); - - if( m_pcb != m_editFrame->GetBoard() ) - { - if( m_drcDialog ) - DestroyDRCDialog( wxID_OK ); - - m_pcb = m_editFrame->GetBoard(); - } -} - - -void DRC::ShowDRCDialog( wxWindow* aParent ) -{ - bool show_dlg_modal = true; - - // the dialog needs a parent frame. if it is not specified, this is - // the PCB editor frame specified in DRC class. - if( !aParent ) - { - // if any parent is specified, the dialog is modal. - // if this is the default PCB editor frame, it is not modal - show_dlg_modal = false; - aParent = m_editFrame; - } - - Activate(); - m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); - - if( !m_drcDialog ) - { - m_drcDialog = new DIALOG_DRC( this, m_editFrame, aParent ); - updatePointers(); - - if( show_dlg_modal ) - m_drcDialog->ShowModal(); - else - m_drcDialog->Show( true ); - } - else // The dialog is just not visible (because the user has double clicked on an error item) - { - updatePointers(); - m_drcDialog->Show( true ); - } -} - - -int DRC::ShowDRCDialog( const TOOL_EVENT& aEvent ) -{ - ShowDRCDialog( nullptr ); - return 0; -} - - -bool DRC::IsDRCDialogShown() -{ - if( m_drcDialog ) - return m_drcDialog->IsShown(); - - return false; -} - - -void DRC::addMarkerToPcb( BOARD_COMMIT& aCommit, MARKER_PCB* aMarker ) -{ - if( m_pcb->GetDesignSettings().Ignore( aMarker->GetRCItem()->GetErrorCode() ) ) - { - delete aMarker; - return; - } - - aCommit.Add( aMarker ); -} - - -void DRC::DestroyDRCDialog( int aReason ) -{ - if( m_drcDialog ) - { - m_drcDialog->Destroy(); - m_drcDialog = nullptr; - } -} - - -bool DRC::LoadRules() -{ - wxString rulesFilepath = m_editFrame->Prj().AbsolutePath( "drc-rules" ); - wxFileName rulesFile( rulesFilepath ); - - if( rulesFile.FileExists() ) - { - m_rules.clear(); - - FILE* fp = wxFopen( rulesFilepath, wxT( "rt" ) ); - - if( fp ) - { - try - { - DRC_RULES_PARSER parser( m_pcb, fp, rulesFilepath ); - parser.Parse( m_rules ); - } - catch( PARSE_ERROR& pe ) - { - // Don't leave possibly malformed stuff around for us to trip over - m_rules.clear(); - - wxSafeYield( m_editFrame ); - m_editFrame->ShowBoardSetupDialog( _( "Rules" ), pe.What(), ID_RULES_EDITOR, - pe.lineNumber, pe.byteIndex ); - - return false; - } - } - } - - std::reverse( std::begin( m_ruleSelectors ), std::end( m_ruleSelectors ) ); - - BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings(); - bds.m_DRCRuleSelectors = m_ruleSelectors; - bds.m_DRCRules = m_rules; - - return true; -} - - -void DRC::RunTests( wxTextCtrl* aMessages ) -{ - // Make absolutely sure these are up-to-date - if( !LoadRules() ) - return; - - wxASSERT( m_pcb == m_editFrame->GetBoard() ); - - BOARD_COMMIT commit( m_editFrame ); - BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings(); - - m_largestClearance = bds.GetBiggestClearanceValue(); - - if( !bds.Ignore( DRCE_INVALID_OUTLINE ) - || !bds.Ignore( DRCE_TRACK_NEAR_EDGE ) - || !bds.Ignore( DRCE_VIA_NEAR_EDGE ) - || !bds.Ignore( DRCE_PAD_NEAR_EDGE ) ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Board Outline...\n" ) ); - wxSafeYield(); - } - - testOutline( commit ); - } - - if( aMessages ) - { - aMessages->AppendText( _( "Netclasses...\n" ) ); - wxSafeYield(); - } - - DRC_NETCLASS_TESTER netclassTester( [&]( MARKER_PCB* aMarker ) - { - addMarkerToPcb( commit, aMarker ); - } ); - - if( !netclassTester.RunDRC( userUnits(), *m_pcb ) ) - { - // testing the netclasses is a special case because if the netclasses - // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net - // class (a NET) will cause its items such as tracks, vias, and pads - // to also fail. So quit after *all* netclass errors have been reported. - if( aMessages ) - aMessages->AppendText( _( "NETCLASS VIOLATIONS: Aborting DRC\n" ) ); - - commit.Push( wxEmptyString, false, false ); - - // update the m_drcDialog listboxes - updatePointers(); - - return; - } - - // test pad to pad clearances, nothing to do with tracks, vias or zones. - if( !bds.Ignore( DRCE_PAD_NEAR_EDGE ) - || !bds.Ignore( DRCE_PAD_NEAR_PAD ) - || !bds.Ignore( DRCE_HOLE_NEAR_PAD ) ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Pad clearances...\n" ) ); - wxSafeYield(); - } - - testPadClearances( commit ); - } - - // test drilled holes - if( !bds.Ignore( DRCE_DRILLED_HOLES_TOO_CLOSE ) - || !bds.Ignore( DRCE_TOO_SMALL_PAD_DRILL ) - || !bds.Ignore( DRCE_TOO_SMALL_VIA_DRILL ) - || !bds.Ignore( DRCE_TOO_SMALL_MICROVIA_DRILL ) ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Drill sizes and clearances...\n" ) ); - wxSafeYield(); - } - - DRC_DRILLED_HOLE_TESTER tester( [&]( MARKER_PCB* aMarker ) - { - addMarkerToPcb( commit, aMarker ); - } ); - - tester.RunDRC( userUnits(), *m_pcb ); - } - - // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC: - wxWindow* caller = aMessages ? aMessages->GetParent() : m_editFrame; - - if( m_refillZones ) - { - if( aMessages ) - aMessages->AppendText( _( "Refilling all zones...\n" ) ); - - m_toolMgr->GetTool()->FillAllZones( caller ); - } - else - { - if( aMessages ) - aMessages->AppendText( _( "Checking zone fills...\n" ) ); - - m_toolMgr->GetTool()->CheckAllZones( caller ); - } - - // test track and via clearances to other tracks, pads, and vias - if( aMessages ) - { - aMessages->AppendText( _( "Track clearances...\n" ) ); - wxSafeYield(); - } - - testTracks( commit, aMessages ? aMessages->GetParent() : m_editFrame, true ); - - // test zone clearances to other zones - if( aMessages ) - { - aMessages->AppendText( _( "Zone to zone clearances...\n" ) ); - wxSafeYield(); - } - - testZones( commit ); - - // find and gather unconnected pads. - if( m_doUnconnectedTest - && !bds.Ignore( DRCE_UNCONNECTED_ITEMS ) ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Unconnected pads...\n" ) ); - aMessages->Refresh(); - } - - testUnconnected(); - } - - // find and gather vias, tracks, pads inside keepout areas. - if( m_doKeepoutTest ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Keepout areas ...\n" ) ); - aMessages->Refresh(); - } - - DRC_KEEPOUT_TESTER tester( [&]( MARKER_PCB* aMarker ) - { - addMarkerToPcb( commit, aMarker ); - } ); - - tester.RunDRC( userUnits(), *m_pcb ); - } - - // find and gather vias, tracks, pads inside text boxes. - if( !bds.Ignore( DRCE_VIA_NEAR_COPPER ) - || !bds.Ignore( DRCE_TRACK_NEAR_COPPER ) ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Text and graphic clearances...\n" ) ); - wxSafeYield(); - } - - testCopperTextAndGraphics( commit ); - } - - // test courtyards - if( !bds.Ignore( DRCE_OVERLAPPING_FOOTPRINTS ) - || !bds.Ignore( DRCE_MISSING_COURTYARD ) - || !bds.Ignore( DRCE_MALFORMED_COURTYARD ) - || !bds.Ignore( DRCE_PTH_IN_COURTYARD ) - || !bds.Ignore( DRCE_NPTH_IN_COURTYARD ) ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Courtyard areas...\n" ) ); - aMessages->Refresh(); - } - - DRC_COURTYARD_TESTER tester( [&]( MARKER_PCB* aMarker ) - { - addMarkerToPcb( commit, aMarker ); - } ); - - tester.RunDRC( userUnits(), *m_pcb ); - } - - for( DRC_ITEM* footprintItem : m_footprints ) - delete footprintItem; - - m_footprints.clear(); - m_footprintsTested = false; - - if( m_testFootprints && !Kiface().IsSingle() ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Checking footprints against schematic...\n" ) ); - aMessages->Refresh(); - } - - NETLIST netlist; - m_editFrame->FetchNetlistFromSchematic( netlist, PCB_EDIT_FRAME::ANNOTATION_DIALOG ); - - if( m_drcDialog ) - m_drcDialog->Raise(); - - TestFootprints( netlist, m_pcb, m_footprints ); - m_footprintsTested = true; - } - - // Check if there are items on disabled layers - if( !bds.Ignore( DRCE_DISABLED_LAYER_ITEM ) ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Items on disabled layers...\n" ) ); - aMessages->Refresh(); - } - - testDisabledLayers( commit ); - } - - if( !bds.Ignore( DRCE_UNRESOLVED_VARIABLE ) ) - { - if( aMessages ) - { - aMessages->AppendText( _( "Unresolved text variables...\n" ) ); - aMessages->Refresh(); - } - - DRC_TEXTVAR_TESTER tester( [&]( MARKER_PCB* aMarker ) - { - addMarkerToPcb( commit, aMarker ); - }, - m_editFrame->GetCanvas()->GetWorksheet() ); - - tester.RunDRC( userUnits(), *m_pcb ); - } - - commit.Push( wxEmptyString, false, false ); - m_drcRun = true; - - // update the m_drcDialog listboxes - updatePointers(); - - if( aMessages ) - { - // no newline on this one because it is last, don't want the window - // to unnecessarily scroll. - aMessages->AppendText( _( "Finished" ) ); - } -} - - -void DRC::updatePointers() -{ - // update my pointers, m_editFrame is the only unchangeable one - m_pcb = m_editFrame->GetBoard(); - - m_editFrame->ResolveDRCExclusions(); - - if( m_drcDialog ) // Use diag list boxes only in DRC dialog - { - m_drcDialog->SetMarkersProvider( new BOARD_DRC_ITEMS_PROVIDER( m_pcb ) ); - m_drcDialog->SetUnconnectedProvider( new RATSNEST_DRC_ITEMS_PROVIDER( m_editFrame, - &m_unconnected ) ); - m_drcDialog->SetFootprintsProvider( new VECTOR_DRC_ITEMS_PROVIDER( m_editFrame, - &m_footprints ) ); - } -} - - -void DRC::testPadClearances( BOARD_COMMIT& aCommit ) -{ - BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings(); - std::vector sortedPads; - - m_pcb->GetSortedPadListByXthenYCoord( sortedPads ); - - if( sortedPads.empty() ) - return; - - // find the max size of the pads (used to stop the pad-to-pad tests) - int max_size = 0; - - for( D_PAD* pad : sortedPads ) - { - // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad - int radius = pad->GetBoundingRadius(); - - if( radius > max_size ) - max_size = radius; - } - - // Better to be fast than accurate; this keeps us from having to look up / calculate the - // actual clearances - max_size += m_largestClearance; - - // Upper limit of pad list (limit not included) - D_PAD** listEnd = &sortedPads[0] + sortedPads.size(); - - // Test the pads - for( auto& pad : sortedPads ) - { - if( !bds.Ignore( DRCE_PAD_NEAR_EDGE ) && m_board_outline_valid ) - { - int minClearance = bds.m_CopperEdgeClearance; - m_clearanceSource = _( "board edge" ); - - static DRAWSEGMENT dummyEdge; - dummyEdge.SetLayer( Edge_Cuts ); - - pad->GetRuleClearance( &dummyEdge, pad->GetLayer(), &minClearance, &m_clearanceSource ); - - for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ ) - { - int actual; - - if( !checkClearanceSegmToPad( *it, 0, pad, minClearance, &actual ) ) - { - actual = std::max( 0, actual ); - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_EDGE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( pad ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - - break; - } - } - } - - if( !bds.Ignore( DRCE_PAD_NEAR_PAD ) || !bds.Ignore( DRCE_HOLE_NEAR_PAD ) ) - { - int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size; - - doPadToPadsDrc( aCommit, pad, &pad, listEnd, x_limit ); - } - } -} - - -void DRC::testTracks( BOARD_COMMIT& aCommit, wxWindow *aActiveWindow, bool aShowProgressBar ) -{ - APP_PROGRESS_DIALOG* progressDialog = NULL; - const int delta = 500; // This is the number of tests between 2 calls to the - // progress bar - int count = m_pcb->Tracks().size(); - int deltamax = count/delta; - - if( aShowProgressBar && deltamax > 3 ) - { - // Do not use wxPD_APP_MODAL style here: it is not necessary and create issues - // on OSX - progressDialog = new APP_PROGRESS_DIALOG( _( "Track clearances" ), wxEmptyString, - deltamax, aActiveWindow, false, - wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME ); - progressDialog->Update( 0, wxEmptyString ); - } - - std::shared_ptr connectivity = m_pcb->GetConnectivity(); - BOARD_DESIGN_SETTINGS& settings = m_pcb->GetDesignSettings(); - - - if( !m_pcb->GetDesignSettings().Ignore( DRCE_DANGLING_TRACK ) - || !m_pcb->GetDesignSettings().Ignore( DRCE_DANGLING_VIA ) ) - { - connectivity->Clear(); - connectivity->Build( m_pcb ); // just in case. This really needs to be reliable. - } - - int ii = 0; - count = 0; - - for( auto seg_it = m_pcb->Tracks().begin(); seg_it != m_pcb->Tracks().end(); seg_it++ ) - { - if( ii++ > delta ) - { - ii = 0; - count++; - - if( progressDialog ) - { - if( !progressDialog->Update( count, wxEmptyString ) ) - break; // Aborted by user -#ifdef __WXMAC__ - // Work around a dialog z-order issue on OS X - if( count == deltamax ) - aActiveWindow->Raise(); -#endif - } - } - - // Test new segment against tracks and pads, optionally against copper zones - LSEQ layer_seq = ( *seg_it )->GetLayerSet().Seq(); - - if( ( *seg_it )->Type() == PCB_VIA_T ) - doSingleViaDRC( aCommit, static_cast( *seg_it ) ); - else - doSingleTrackDRC( aCommit, *seg_it ); - - for( PCB_LAYER_ID layer : layer_seq ) - doTrackDrc( aCommit, *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_testTracksAgainstZones, layer ); - - - // Test for dangling items - int code = (*seg_it)->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK; - wxPoint pos; - - if( !settings.Ignore( code ) && connectivity->TestTrackEndpointDangling( *seg_it, &pos ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( code ); - drcItem->SetItems( *seg_it ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, pos ); - addMarkerToPcb( aCommit, marker ); - } - } - - if( progressDialog ) - progressDialog->Destroy(); -} - - -void DRC::testUnconnected() -{ - for( DRC_ITEM* unconnectedItem : m_unconnected ) - delete unconnectedItem; - - m_unconnected.clear(); - - auto connectivity = m_pcb->GetConnectivity(); - - connectivity->Clear(); - connectivity->Build( m_pcb ); // just in case. This really needs to be reliable. - connectivity->RecalculateRatsnest(); - - std::vector edges; - connectivity->GetUnconnectedEdges( edges ); - - for( const CN_EDGE& edge : edges ) - { - DRC_ITEM* item = new DRC_ITEM( DRCE_UNCONNECTED_ITEMS ); - item->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() ); - m_unconnected.push_back( item ); - } -} - - -void DRC::testZones( BOARD_COMMIT& aCommit ) -{ - BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings(); - - // Test copper areas for valid netcodes - // if a netcode is < 0 the netname was not found when reading a netlist - // if a netcode is == 0 the netname is void, and the zone is not connected. - // This is allowed, but i am not sure this is a good idea - // - // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name - // is stored, and initialized from the file or the zone properties editor. - // if it differs from the net name from net code, there is a DRC issue - - std::vector smoothed_polys; - smoothed_polys.resize( m_pcb->GetAreaCount() ); - - for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ ) - { - ZONE_CONTAINER* zone = m_pcb->GetArea( ii ); - - if( !bds.Ignore( DRCE_ZONE_HAS_EMPTY_NET ) && zone->IsOnCopperLayer() ) - { - int netcode = zone->GetNetCode(); - // a netcode < 0 or > 0 and no pad in net is a error or strange - // perhaps a "dead" net, which happens when all pads in this net were removed - // Remark: a netcode < 0 should not happen (this is more a bug somewhere) - int pads_in_net = ( netcode > 0 ) ? m_pcb->GetConnectivity()->GetPadCount( netcode ) : 1; - - if( ( netcode < 0 ) || pads_in_net == 0 ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONE_HAS_EMPTY_NET ); - drcItem->SetItems( zone ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, zone->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } - - ZONE_CONTAINER* zoneRef = m_pcb->GetArea( ii ); - std::set colinearCorners; - zoneRef->GetColinearCorners( m_pcb, colinearCorners ); - - zoneRef->BuildSmoothedPoly( smoothed_polys[ii], &colinearCorners ); - } - - // iterate through all areas - for( int ia = 0; ia < m_pcb->GetAreaCount(); ia++ ) - { - ZONE_CONTAINER* zoneRef = m_pcb->GetArea( ia ); - - if( !zoneRef->IsOnCopperLayer() ) - continue; - - // If we are testing a single zone, then iterate through all other zones - // Otherwise, we have already tested the zone combination - for( int ia2 = ia + 1; ia2 < m_pcb->GetAreaCount(); ia2++ ) - { - ZONE_CONTAINER* zoneToTest = m_pcb->GetArea( ia2 ); - - if( zoneRef == zoneToTest ) - continue; - - // test for same layer - if( zoneRef->GetLayer() != zoneToTest->GetLayer() ) - continue; - - // Test for same net - if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 ) - continue; - - // test for different priorities - if( zoneRef->GetPriority() != zoneToTest->GetPriority() ) - continue; - - // test for different types - if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() ) - continue; - - // Examine a candidate zone: compare zoneToTest to zoneRef - - // Get clearance used in zone to zone test. The policy used to - // obtain that value is now part of the zone object itself by way of - // ZONE_CONTAINER::GetClearance(). - int zone2zoneClearance = zoneRef->GetClearance( zoneToTest, &m_clearanceSource ); - - // Keepout areas have no clearance, so set zone2zoneClearance to 1 - // ( zone2zoneClearance = 0 can create problems in test functions) - if( zoneRef->GetIsKeepout() ) - zone2zoneClearance = 1; - - // test for some corners of zoneRef inside zoneToTest - for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ ) - { - VECTOR2I currentVertex = *iterator; - wxPoint pt( currentVertex.x, currentVertex.y ); - - if( smoothed_polys[ia2].Contains( currentVertex ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT ); - drcItem->SetItems( zoneRef, zoneToTest ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, pt ); - addMarkerToPcb( aCommit, marker ); - } - } - - // test for some corners of zoneToTest inside zoneRef - for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ ) - { - VECTOR2I currentVertex = *iterator; - wxPoint pt( currentVertex.x, currentVertex.y ); - - if( smoothed_polys[ia].Contains( currentVertex ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT ); - drcItem->SetItems( zoneToTest, zoneRef ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, pt ); - addMarkerToPcb( aCommit, marker ); - } - } - - // Iterate through all the segments of refSmoothedPoly - std::map conflictPoints; - - for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ ) - { - // Build ref segment - SEG refSegment = *refIt; - - // Iterate through all the segments in smoothed_polys[ia2] - for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ ) - { - // Build test segment - SEG testSegment = *testIt; - wxPoint pt; - - int ax1, ay1, ax2, ay2; - ax1 = refSegment.A.x; - ay1 = refSegment.A.y; - ax2 = refSegment.B.x; - ay2 = refSegment.B.y; - - int bx1, by1, bx2, by2; - bx1 = testSegment.A.x; - by1 = testSegment.A.y; - bx2 = testSegment.B.x; - by2 = testSegment.B.y; - - int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, - 0, - ax1, ay1, ax2, ay2, - 0, - zone2zoneClearance, - &pt.x, &pt.y ); - - if( d < zone2zoneClearance ) - { - if( conflictPoints.count( pt ) ) - conflictPoints[ pt ] = std::min( conflictPoints[ pt ], d ); - else - conflictPoints[ pt ] = d; - } - } - } - - for( const std::pair& conflict : conflictPoints ) - { - int actual = conflict.second; - DRC_ITEM* drcItem; - - if( actual <= 0 ) - { - drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT ); - } - else - { - drcItem = new DRC_ITEM( DRCE_ZONES_TOO_CLOSE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), zone2zoneClearance, true ), - MessageTextFromValue( userUnits(), conflict.second, true ) ); - - drcItem->SetErrorMessage( m_msg ); - } - - drcItem->SetItems( zoneRef, zoneToTest ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, conflict.first ); - addMarkerToPcb( aCommit, marker ); - } - } - } -} - - -void DRC::testCopperTextAndGraphics( BOARD_COMMIT& aCommit ) -{ - // Test copper items for clearance violations with vias, tracks and pads - - for( BOARD_ITEM* brdItem : m_pcb->Drawings() ) - { - if( IsCopperLayer( brdItem->GetLayer() ) ) - testCopperDrawItem( aCommit, brdItem ); - } - - for( MODULE* module : m_pcb->Modules() ) - { - TEXTE_MODULE& ref = module->Reference(); - TEXTE_MODULE& val = module->Value(); - - if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) ) - testCopperDrawItem( aCommit, &ref ); - - if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) ) - testCopperDrawItem( aCommit, &val ); - - if( module->IsNetTie() ) - continue; - - for( BOARD_ITEM* item : module->GraphicalItems() ) - { - if( IsCopperLayer( item->GetLayer() ) ) - { - if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() ) - testCopperDrawItem( aCommit, item ); - else if( item->Type() == PCB_MODULE_EDGE_T ) - testCopperDrawItem( aCommit, item ); - } - } - } -} - - -void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem ) -{ - EDA_RECT bbox; - std::vector itemShape; - int itemWidth; - DRAWSEGMENT* drawItem = dynamic_cast( aItem ); - EDA_TEXT* textItem = dynamic_cast( aItem ); - - if( drawItem ) - { - bbox = drawItem->GetBoundingBox(); - itemWidth = drawItem->GetWidth(); - - switch( drawItem->GetShape() ) - { - case S_ARC: - { - SHAPE_ARC arc( drawItem->GetCenter(), drawItem->GetArcStart(), - (double) drawItem->GetAngle() / 10.0 ); - - SHAPE_LINE_CHAIN l = arc.ConvertToPolyline(); - - for( int i = 0; i < l.SegmentCount(); i++ ) - itemShape.push_back( l.Segment( i ) ); - - break; - } - - case S_SEGMENT: - itemShape.emplace_back( SEG( drawItem->GetStart(), drawItem->GetEnd() ) ); - break; - - case S_CIRCLE: - { - // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC - SHAPE_ARC circle( drawItem->GetCenter(), drawItem->GetEnd(), 360.0 ); - - SHAPE_LINE_CHAIN l = circle.ConvertToPolyline(); - - for( int i = 0; i < l.SegmentCount(); i++ ) - itemShape.push_back( l.Segment( i ) ); - - break; - } - - case S_CURVE: - { - drawItem->RebuildBezierToSegmentsPointsList( drawItem->GetWidth() ); - wxPoint start_pt = drawItem->GetBezierPoints()[0]; - - for( unsigned int jj = 1; jj < drawItem->GetBezierPoints().size(); jj++ ) - { - wxPoint end_pt = drawItem->GetBezierPoints()[jj]; - itemShape.emplace_back( SEG( start_pt, end_pt ) ); - start_pt = end_pt; - } - - break; - } - - case S_POLYGON: - { - SHAPE_LINE_CHAIN l = drawItem->GetPolyShape().Outline( 0 ); - - for( int i = 0; i < l.SegmentCount(); i++ ) - itemShape.push_back( l.Segment( i ) ); - } - break; - - default: - wxFAIL_MSG( "unknown shape type" ); - break; - } - } - else if( textItem ) - { - bbox = textItem->GetTextBox(); - itemWidth = textItem->GetEffectiveTextPenWidth(); - - std::vector textShape; - textItem->TransformTextShapeToSegmentList( textShape ); - - for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) - itemShape.emplace_back( SEG( textShape[jj], textShape[jj+1] ) ); - } - else - { - wxFAIL_MSG( "unknown item type in testCopperDrawItem()" ); - return; - } - - SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() ); - - if( itemShape.empty() ) - return; - - // Test tracks and vias - for( auto track : m_pcb->Tracks() ) - { - if( !track->IsOnLayer( aItem->GetLayer() ) ) - continue; - - int minClearance = track->GetClearance( aItem, &m_clearanceSource ); - int widths = ( track->GetWidth() + itemWidth ) / 2; - int center2centerAllowed = minClearance + widths; - - SEG trackSeg( track->GetStart(), track->GetEnd() ); - - // Fast test to detect a track segment candidate inside the text bounding box - if( !rect_area.Collide( trackSeg, center2centerAllowed ) ) - continue; - - OPT minSeg; - SEG::ecoord center2center_squared = 0; - - for( const SEG& itemSeg : itemShape ) - { - SEG::ecoord thisDist_squared = trackSeg.SquaredDistance( itemSeg ); - - if( !minSeg || thisDist_squared < center2center_squared ) - { - minSeg = itemSeg; - center2center_squared = thisDist_squared; - } - } - - if( center2center_squared < SEG::Square( center2centerAllowed ) ) - { - int actual = std::max( 0.0, sqrt( center2center_squared ) - widths ); - int errorCode = ( track->Type() == PCB_VIA_T ) ? DRCE_VIA_NEAR_COPPER - : DRCE_TRACK_NEAR_COPPER; - DRC_ITEM* drcItem = new DRC_ITEM( errorCode ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( track, aItem ); - - wxPoint pos = GetLocation( track, minSeg.get() ); - MARKER_PCB* marker = new MARKER_PCB( drcItem, pos ); - addMarkerToPcb( aCommit, marker ); - } - } - - // Test pads - for( auto pad : m_pcb->GetPads() ) - { - if( !pad->IsOnLayer( aItem->GetLayer() ) ) - continue; - - // Graphic items are allowed to act as net-ties within their own footprint - if( drawItem && pad->GetParent() == drawItem->GetParent() ) - continue; - - int minClearance = pad->GetClearance( aItem, &m_clearanceSource ); - int widths = itemWidth / 2; - int center2centerAllowed = minClearance + widths; - - // Fast test to detect a pad candidate inside the text bounding box - // Finer test (time consumming) is made only for pads near the text. - int bb_radius = pad->GetBoundingRadius() + minClearance; - VECTOR2I shape_pos( pad->ShapePos() ); - - if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) ) - continue; - - SHAPE_POLY_SET padOutline; - pad->TransformShapeWithClearanceToPolygon( padOutline, 0 ); - - OPT minSeg; - SEG::ecoord center2center_squared = 0; - - for( const SEG& itemSeg : itemShape ) - { - SEG::ecoord thisCenter2center_squared = padOutline.SquaredDistance( itemSeg ); - - if( !minSeg || thisCenter2center_squared < center2center_squared ) - { - minSeg = itemSeg; - center2center_squared = thisCenter2center_squared; - } - } - - if( center2center_squared < SEG::Square( center2centerAllowed ) ) - { - int actual = std::max( 0.0, sqrt( center2center_squared ) - widths ); - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_COPPER ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( pad, aItem ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } -} - - -void DRC::testOutline( BOARD_COMMIT& aCommit ) -{ - wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() ); - - m_board_outlines.RemoveAllContours(); - m_board_outline_valid = false; - - if( m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) ) - { - m_board_outline_valid = true; - } - else - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_INVALID_OUTLINE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( m_pcb ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, error_loc ); - addMarkerToPcb( aCommit, marker ); - } -} - - -void DRC::testDisabledLayers( BOARD_COMMIT& aCommit ) -{ - LSET disabledLayers = m_pcb->GetEnabledLayers().flip(); - - // Perform the test only for copper layers - disabledLayers &= LSET::AllCuMask(); - - for( TRACK* track : m_pcb->Tracks() ) - { - if( disabledLayers.test( track->GetLayer() ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_DISABLED_LAYER_ITEM ); - - m_msg.Printf( drcItem->GetErrorText() + _( "layer %s" ), - track->GetLayerName() ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( track ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, track->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } - - for( MODULE* module : m_pcb->Modules() ) - { - module->RunOnChildren( - [&]( BOARD_ITEM* child ) - { - if( disabledLayers.test( child->GetLayer() ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_DISABLED_LAYER_ITEM ); - - m_msg.Printf( drcItem->GetErrorText() + _( "layer %s" ), - child->GetLayerName() ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( child ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, child->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } ); - } - - for( ZONE_CONTAINER* zone : m_pcb->Zones() ) - { - if( disabledLayers.test( zone->GetLayer() ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_DISABLED_LAYER_ITEM ); - - m_msg.Printf( drcItem->GetErrorText() + _( "layer %s" ), - zone->GetLayerName() ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( zone ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, zone->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } -} - - -bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, - int x_limit ) -{ - const static LSET all_cu = LSET::AllCuMask(); - - LSET layerMask = aRefPad->GetLayerSet() & all_cu; - - // For hole testing we use a dummy pad which is given the shape of the hole. Note that - // this pad must have a parent because some functions expect a non-null parent to find - // the pad's board. - MODULE dummymodule( m_pcb ); // Creates a dummy parent - D_PAD dummypad( &dummymodule ); - - // Ensure the hole is on all copper layers - dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() ); - - for( D_PAD** pad_list = aStart; pad_listGetPosition().x > x_limit - // because the list is sorted by X values - if( pad->GetPosition().x > x_limit ) - break; - - // No problem if pads which are on copper layers are on different copper layers, - // (pads can be only on a technical layer, to build complex pads) - // but their hole (if any ) can create DRC error because they are on all - // copper layers, so we test them - if( ( pad->GetLayerSet() & layerMask ) == 0 && - ( pad->GetLayerSet() & all_cu ) != 0 && - ( aRefPad->GetLayerSet() & all_cu ) != 0 ) - { - // if holes are in the same location and have the same size and shape, - // this can be accepted - if( pad->GetPosition() == aRefPad->GetPosition() - && pad->GetDrillSize() == aRefPad->GetDrillSize() - && pad->GetDrillShape() == aRefPad->GetDrillShape() ) - { - if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE ) - continue; - - // for oval holes: must also have the same orientation - if( pad->GetOrientation() == aRefPad->GetOrientation() ) - continue; - } - - /* Here, we must test clearance between holes and pads - * dummy pad size and shape is adjusted to pad drill size and shape - */ - if( pad->GetDrillSize().x ) - { - // pad under testing has a hole, test this hole against pad reference - dummypad.SetPosition( pad->GetPosition() ); - dummypad.SetSize( pad->GetDrillSize() ); - dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ? - PAD_SHAPE_OVAL : PAD_SHAPE_CIRCLE ); - dummypad.SetOrientation( pad->GetOrientation() ); - - int minClearance = aRefPad->GetClearance( nullptr, &m_clearanceSource ); - int actual; - - if( !checkClearancePadToPad( aRefPad, &dummypad, minClearance, &actual ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_HOLE_NEAR_PAD ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( pad, aRefPad ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - return false; - } - } - - if( aRefPad->GetDrillSize().x ) // pad reference has a hole - { - dummypad.SetPosition( aRefPad->GetPosition() ); - dummypad.SetSize( aRefPad->GetDrillSize() ); - dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ? - PAD_SHAPE_OVAL : PAD_SHAPE_CIRCLE ); - dummypad.SetOrientation( aRefPad->GetOrientation() ); - - int minClearance = pad->GetClearance( nullptr, &m_clearanceSource ); - int actual; - - if( !checkClearancePadToPad( pad, &dummypad, minClearance, &actual ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_HOLE_NEAR_PAD ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefPad, pad ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - return false; - } - } - - continue; - } - - // The pad must be in a net (i.e pt_pad->GetNet() != 0 ), - // But no problem if pads have the same netcode (same net) - if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) ) - continue; - - // if pads are from the same footprint - if( pad->GetParent() == aRefPad->GetParent() ) - { - // and have the same pad number ( equivalent pads ) - - // one can argue that this 2nd test is not necessary, that any - // two pads from a single module are acceptable. This 2nd test - // should eventually be a configuration option. - if( pad->PadNameEqual( aRefPad ) ) - continue; - } - - // if either pad has no drill and is only on technical layers, not a clearance violation - if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) || - ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) ) - { - continue; - } - - int minClearance = aRefPad->GetClearance( pad, &m_clearanceSource ); - int clearanceAllowed = minClearance - m_pcb->GetDesignSettings().GetDRCEpsilon(); - int actual; - - if( !checkClearancePadToPad( aRefPad, pad, clearanceAllowed, &actual ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_PAD ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefPad, pad ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - return false; - } - } - - return true; -} - - -void DRC::setTransitions() -{ - Go( &DRC::ShowDRCDialog, PCB_ACTIONS::runDRC.MakeEvent() ); -} - - -const int UI_EPSILON = Mils2iu( 5 ); - - -wxPoint DRC::GetLocation( TRACK* aTrack, ZONE_CONTAINER* aConflictZone ) -{ - SHAPE_POLY_SET* conflictOutline; - - if( aConflictZone->IsFilled() ) - conflictOutline = const_cast( &aConflictZone->GetFilledPolysList() ); - else - conflictOutline = aConflictZone->Outline(); - - wxPoint pt1 = aTrack->GetPosition(); - wxPoint pt2 = aTrack->GetEnd(); - - // If the mid-point is in the zone, then that's a fine place for the marker - if( conflictOutline->SquaredDistance( ( pt1 + pt2 ) / 2 ) == 0 ) - return ( pt1 + pt2 ) / 2; - - // Otherwise do a binary search for a "good enough" marker location - else - { - while( GetLineLength( pt1, pt2 ) > UI_EPSILON ) - { - if( conflictOutline->SquaredDistance( pt1 ) < conflictOutline->SquaredDistance( pt2 ) ) - pt2 = ( pt1 + pt2 ) / 2; - else - pt1 = ( pt1 + pt2 ) / 2; - } - - // Once we're within UI_EPSILON pt1 and pt2 are "equivalent" - return pt1; - } -} - - -wxPoint DRC::GetLocation( TRACK* aTrack, const SEG& aConflictSeg ) -{ - wxPoint pt1 = aTrack->GetPosition(); - wxPoint pt2 = aTrack->GetEnd(); - - // Do a binary search along the track for a "good enough" marker location - while( GetLineLength( pt1, pt2 ) > UI_EPSILON ) - { - if( aConflictSeg.SquaredDistance( pt1 ) < aConflictSeg.SquaredDistance( pt2 ) ) - pt2 = ( pt1 + pt2 ) / 2; - else - pt1 = ( pt1 + pt2 ) / 2; - } - - // Once we're within UI_EPSILON pt1 and pt2 are "equivalent" - return pt1; -} - - diff --git a/qa/drc_proto/drc.h b/qa/drc_proto/drc.h deleted file mode 100644 index 6f6f17959d..0000000000 --- a/qa/drc_proto/drc.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2007-2016 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2017-2019 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef DRC_H -#define DRC_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/// DRC error codes: -enum PCB_DRC_CODE { - DRCE_FIRST = 1, - DRCE_UNCONNECTED_ITEMS = DRCE_FIRST, ///< items are unconnected - DRCE_TRACK_NEAR_HOLE, ///< thru hole is too close to track - DRCE_TRACK_NEAR_PAD, ///< pad too close to track - DRCE_TRACK_NEAR_VIA, ///< track too close to via - DRCE_TRACK_NEAR_ZONE, ///< track & zone collide or are too close together - DRCE_TRACK_NEAR_COPPER, ///< track & copper graphic collide or are too close - DRCE_VIA_NEAR_VIA, ///< via too close to via - DRCE_VIA_NEAR_TRACK, ///< via too close to track - DRCE_VIA_NEAR_COPPER, ///< via and copper graphic collide or are too close - DRCE_TRACK_ENDS, ///< track ends are too close - DRCE_TRACK_SEGMENTS_TOO_CLOSE, ///< 2 parallel track segments too close: segm ends between segref ends - DRCE_TRACKS_CROSSING, ///< tracks are crossing - DRCE_TRACK_NEAR_EDGE, ///< track too close to board edge - DRCE_VIA_NEAR_EDGE, ///< via too close to board edge - DRCE_PAD_NEAR_EDGE, ///< pad too close to board edge - DRCE_PAD_NEAR_PAD, ///< pad too close to pad - DRCE_PAD_NEAR_COPPER, ///< pad and copper graphic collide or are too close - DRCE_ZONES_INTERSECT, ///< copper area outlines intersect - DRCE_ZONES_TOO_CLOSE, ///< copper area outlines are too close - DRCE_ZONE_HAS_EMPTY_NET, ///< copper area has a net but no pads in nets, which is suspicious - DRCE_DANGLING_VIA, ///< via which isn't connected to anything - DRCE_DANGLING_TRACK, ///< track with at least one end not connected to anything - DRCE_HOLE_NEAR_PAD, ///< hole too close to pad - DRCE_HOLE_NEAR_TRACK, ///< hole too close to track - DRCE_DRILLED_HOLES_TOO_CLOSE, ///< overlapping drilled holes break drill bits - DRCE_TOO_SMALL_TRACK_WIDTH, ///< Too small track width - DRCE_TOO_LARGE_TRACK_WIDTH, ///< Too small track width - DRCE_TOO_SMALL_VIA, ///< Too small via size - DRCE_TOO_SMALL_VIA_ANNULUS, ///< Via size and drill leave annulus too small - DRCE_TOO_SMALL_VIA_DRILL, ///< Too small via drill - DRCE_TOO_SMALL_PAD_DRILL, ///< Too small via drill - DRCE_VIA_HOLE_BIGGER, ///< via's hole is bigger than its diameter - DRCE_MICROVIA_NOT_ALLOWED, ///< micro vias are not allowed - DRCE_MICROVIA_TOO_MANY_LAYERS, ///< micro via's layer pair incorrect (layers must be adjacent) - DRCE_TOO_SMALL_MICROVIA, ///< Too small micro via size - DRCE_TOO_SMALL_MICROVIA_DRILL, ///< Too small micro via drill - DRCE_BURIED_VIA_NOT_ALLOWED, ///< buried vias are not allowed - DRCE_NETCLASS_TRACKWIDTH, ///< netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth - DRCE_NETCLASS_CLEARANCE, ///< netclass has Clearance < board.m_designSettings->m_TrackClearance - DRCE_NETCLASS_VIAANNULUS, ///< netclass ViaSize & ViaDrill leave annulus < board.m_designSettings->m_ViasMinAnnulus - DRCE_NETCLASS_VIASIZE, ///< netclass has ViaSize < board.m_designSettings->m_ViasMinSize - DRCE_NETCLASS_VIADRILLSIZE, ///< netclass has ViaDrillSize < board.m_designSettings->m_MinThroughDrill - DRCE_NETCLASS_uVIASIZE, ///< netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize - DRCE_NETCLASS_uVIADRILLSIZE, ///< netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill - DRCE_VIA_INSIDE_KEEPOUT, - DRCE_MICROVIA_INSIDE_KEEPOUT, - DRCE_BBVIA_INSIDE_KEEPOUT, - DRCE_TRACK_INSIDE_KEEPOUT, - DRCE_PAD_INSIDE_KEEPOUT, - DRCE_FOOTPRINT_INSIDE_KEEPOUT, - DRCE_HOLE_INSIDE_KEEPOUT, - DRCE_TEXT_INSIDE_KEEPOUT, - DRCE_GRAPHICS_INSIDE_KEEPOUT, - DRCE_OVERLAPPING_FOOTPRINTS, ///< footprint courtyards overlap - DRCE_MISSING_COURTYARD, ///< footprint has no courtyard defined - DRCE_MALFORMED_COURTYARD, ///< footprint has a courtyard but malformed - ///< (not convertible to a closed polygon with holes) - DRCE_PTH_IN_COURTYARD, - DRCE_NPTH_IN_COURTYARD, - DRCE_DISABLED_LAYER_ITEM, ///< item on a disabled layer - DRCE_INVALID_OUTLINE, ///< invalid board outline - DRCE_MISSING_FOOTPRINT, ///< footprint not found for netlist item - DRCE_DUPLICATE_FOOTPRINT, ///< more than one footprints found for netlist item - DRCE_EXTRA_FOOTPRINT, ///< netlist item not found for footprint - - DRCE_UNRESOLVED_VARIABLE, - - DRCE_LAST = DRCE_UNRESOLVED_VARIABLE, - - // These are actually Cleanup Tracks and Vias actions, not DRCE errors - CLEANUP_SHORT, - CLEANUP_REDUNDANT_VIA, - CLEANUP_DUPLICATE_TRACK, - CLEANUP_MERGE_TRACKS, - CLEANUP_DANGLING_TRACK, - CLEANUP_DANGLING_VIA, - CLEANUP_ZERO_LENGTH_TRACK, - CLEANUP_TRACK_IN_PAD -}; - - -class PCB_EDIT_FRAME; -class DIALOG_DRC; -class BOARD_ITEM; -class BOARD; -class D_PAD; -class ZONE_CONTAINER; -class TRACK; -class MARKER_PCB; -class DRC_ITEM; -class NETCLASS; -class EDA_TEXT; -class DRAWSEGMENT; -class NETLIST; -class wxWindow; -class wxString; -class wxTextCtrl; - - -class DRC_ENGINE -{ - -} - -/** - * Design Rule Checker object that performs all the DRC tests. The output of - * the checking goes to the BOARD file in the form of two MARKER lists. Those - * two lists are displayable in the drc dialog box. And they can optionally - * be sent to a text file on disk. - * This class is given access to the windows and the BOARD - * that it needs via its constructor or public access functions. - */ -class DRC : public PCB_TOOL_BASE -{ - friend class DIALOG_DRC; - -public: - DRC(); - ~DRC(); - - /// @copydoc TOOL_INTERACTIVE::Reset() - void Reset( RESET_REASON aReason ) override; - -private: - bool m_doUnconnectedTest; // enable unconnected tests - bool m_testTracksAgainstZones; // enable zone to items clearance tests - bool m_doKeepoutTest; // enable keepout areas to items clearance tests - bool m_refillZones; // refill zones if requested (by user). - bool m_reportAllTrackErrors; // Report all tracks errors (or only 4 first errors) - bool m_testFootprints; // Test footprints against schematic - - PCB_EDIT_FRAME* m_editFrame; // The pcb frame editor which owns the board - BOARD* m_pcb; - SHAPE_POLY_SET m_board_outlines; // The board outline including cutouts - bool m_board_outline_valid; - DIALOG_DRC* m_drcDialog; - - std::vector m_unconnected; // list of unconnected pads - std::vector m_footprints; // list of footprint warnings - bool m_drcRun; // indicates DRC has been run at least once - bool m_footprintsTested; // indicates footprints were tested in last run - - std::vector m_ruleSelectors; - std::vector m_rules; - - // Temp variables for performance during a single DRC run - // - // wxString's c'tor is surprisingly expensive, and in the world of DRC everything matters - // - wxString m_msg; - wxString m_clearanceSource; - int m_largestClearance; - -private: - ///> Sets up handlers for various events. - void setTransitions() override; - - /** - * Update needed pointers from the one pointer which is known not to change. - */ - void updatePointers(); - - EDA_UNITS userUnits() const { return m_editFrame->GetUserUnits(); } - - /** - * Adds a DRC marker to the PCB through the COMMIT mechanism. - */ - void addMarkerToPcb( BOARD_COMMIT& aCommit, MARKER_PCB* aMarker ); - - //---------------------------------------------- - - /** - * Perform the DRC on all tracks. - * - * This test can take a while, a progress bar can be displayed - * @param aActiveWindow = the active window ued as parent for the progress bar - * @param aShowProgressBar = true to show a progress bar - * (Note: it is shown only if there are many tracks) - */ - void testTracks( BOARD_COMMIT& aCommit, wxWindow * aActiveWindow, bool aShowProgressBar ); - - void testPadClearances( BOARD_COMMIT& aCommit ); - - void testUnconnected(); - - void testZones( BOARD_COMMIT& aCommit ); - - void testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aDrawing ); - - void testCopperTextAndGraphics( BOARD_COMMIT& aCommit ); - - // Tests for items placed on disabled layers (causing false connections). - void testDisabledLayers( BOARD_COMMIT& aCommit ); - - /** - * Test that the board outline is contiguous and composed of valid elements - */ - void testOutline( BOARD_COMMIT& aCommit ); - - //---------------------------------------------- - - /** - * Test the clearance between aRefPad and other pads. - * - * The pad list must be sorted by x coordinate. - * - * @param aRefPad is the pad to test - * @param aStart is the first pad of the list to test against aRefPad - * @param aEnd is the end of the list and is not included - * @param x_limit is used to stop the test - * (i.e. when the current pad pos X in list exceeds this limit, because the list - * is sorted by X coordinate) - */ - bool doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, - int x_limit ); - - /** - * Test the current segment. - * - * @param aRefSeg The segment to test - * @param aStartIt the iterator to the first track to test - * @param aEndIt the marker for the iterator end - * @param aTestZones true if should do copper zones test. This can be very time consumming - * @param aLayer sets the layer to test against - * @return bool - true if no problems, else false and m_currentMarker is - * filled in with the problem information. - */ - void doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt, - TRACKS::iterator aEndIt, bool aTestZones, PCB_LAYER_ID aLayer ); - - /** - * Test a single via for DRC errors - * - * @param aCommit The board commit to add DRC errors - * @param aRefVia The via to test against design settings - */ - void doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia ); - - /** - * Test a single track segment for DRC errors - * - * @param aCommit The board commit to add DRC errors - * @param aRefSeg The track to test against design settings - */ - void doSingleTrackDRC( BOARD_COMMIT& aCommit, TRACK* aRefSeg ); - - //--------------------------------------------------- - - /** - * @param aRefPad The reference pad to check - * @param aPad Another pad to check against - * @param aMinClearance is the minimum allowed distance between the pads - * @param aActual [out] it the actual distance (only guaranteed to be set for violations) - * @return bool - true if clearance between aRefPad and aPad is >= aMinClearance, else false - */ - bool checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance, int* aActual ); - - - /** - * Check the distance from a pad to segment. This function uses several - * instance variable not passed in: - * @param aPad Is the pad involved in the check - * @param aSegmentWidth width of the segment to test - * @param aMinDist Is the minimum clearance needed - * @param aActualDist [out] Is the actual clearance (only guarantted to be set on violations) - * - * @return true distance >= dist_min, - * false if distance < dist_min - */ - bool checkClearanceSegmToPad( const SEG& seg, int segWidth, const D_PAD* pad, - int minClearance, int* aActualDist ); - - - - //-------------------------------------------------- - -public: - /** - * Load the DRC rules. Must be called after the netclasses have been read. - */ - bool LoadRules(); - - /** - * Fetches a reasonable point for marking a violoation between two non-point objects. - */ - static wxPoint GetLocation( TRACK* aTrack, ZONE_CONTAINER* aConflictZone ); - static wxPoint GetLocation( TRACK* aTrack, const SEG& aConflictSeg ); - - /** - * Open a dialog and prompts the user, then if a test run button is - * clicked, runs the test(s) and creates the MARKERS. The dialog is only - * created if it is not already in existence. - * - * @param aParent is the parent window for wxWidgets. Usually the PCB editor frame - * but can be another dialog - * if aParent == NULL (default), the parent will be the PCB editor frame - * and the dialog will be not modal (just float on parent - * if aParent is specified, the dialog will be modal. - * The modal mode is mandatory if the dialog is created from another dialog, not - * from the PCB editor frame - */ - void ShowDRCDialog( wxWindow* aParent ); - - int ShowDRCDialog( const TOOL_EVENT& aEvent ); - - /** - * Check to see if the DRC dialog is currently shown - * - * @return true if the dialog is shown - */ - bool IsDRCDialogShown(); - - /** - * Deletes this ui dialog box and zeros out its pointer to remember - * the state of the dialog's existence. - * - * @param aReason Indication of which button was clicked to cause the destruction. - * if aReason == wxID_OK, design parameters values which can be entered from the dialog - * will bbe saved in design parameters list - */ - void DestroyDRCDialog( int aReason ); - - /** - * Run all the tests specified with a previous call to - * SetSettings() - * @param aMessages = a wxTextControl where to display some activity messages. Can be NULL - */ - void RunTests( wxTextCtrl* aMessages = NULL ); -}; - - -#endif // DRC_H diff --git a/qa/drc_proto/drc_clearance_test_functions.cpp b/qa/drc_proto/drc_clearance_test_functions.cpp deleted file mode 100644 index 591a8b3a5e..0000000000 --- a/qa/drc_proto/drc_clearance_test_functions.cpp +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2004-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for KiROUND -#include -#include - - -/** - * compare 2 convex polygons and return true if distance > aDist (if no error DRC) - * i.e if for each edge of the first polygon distance from each edge of the other polygon - * is >= aDist - */ -bool poly2polyDRC( wxPoint* aTref, int aTrefCount, wxPoint* aTtest, int aTtestCount, - int aAllowedDist, int* actualDist ) -{ - /* Test if one polygon is contained in the other and thus the polygon overlap. - * This case is not covered by the following check if one polygone is - * completely contained in the other (because edges don't intersect)! - */ - if( TestPointInsidePolygon( aTref, aTrefCount, aTtest[0] ) ) - { - *actualDist = 0; - return false; - } - - if( TestPointInsidePolygon( aTtest, aTtestCount, aTref[0] ) ) - { - *actualDist = 0; - return false; - } - - for( int ii = 0, jj = aTrefCount - 1; ii < aTrefCount; jj = ii, ii++ ) - { - // for all edges in aTref - for( int kk = 0, ll = aTtestCount - 1; kk < aTtestCount; ll = kk, kk++ ) - { - // for all edges in aTtest - double d; - int intersect = TestForIntersectionOfStraightLineSegments( - aTref[ii].x, aTref[ii].y, aTref[jj].x, aTref[jj].y, - aTtest[kk].x, aTtest[kk].y, aTtest[ll].x, aTtest[ll].y, - nullptr, nullptr, &d ); - - if( intersect ) - { - *actualDist = 0; - return false; - } - - if( d < aAllowedDist ) - { - *actualDist = KiROUND( d ); - return false; - } - } - } - - return true; -} - - -/* - * compare a trapezoid (can be rectangle) and a segment and return true if distance > aDist - */ -bool poly2segmentDRC( wxPoint* aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd, - int aDist, int* aActual ) -{ - /* Test if the segment is contained in the polygon. - * This case is not covered by the following check if the segment is - * completely contained in the polygon (because edges don't intersect)! - */ - if( TestPointInsidePolygon( aTref, aTrefCount, aSegStart ) ) - { - *aActual = 0; - return false; - } - - for( int ii = 0, jj = aTrefCount-1; ii < aTrefCount; jj = ii, ii++ ) - { // for all edges in polygon - double d; - - if( TestForIntersectionOfStraightLineSegments( aTref[ii].x, aTref[ii].y, aTref[jj].x, - aTref[jj].y, aSegStart.x, aSegStart.y, - aSegEnd.x, aSegEnd.y, NULL, NULL, &d ) ) - { - *aActual = 0; - return false; - } - - if( d < aDist ) - { - *aActual = KiROUND( d ); - return false; - } - } - - return true; -} - - -void DRC::doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia ) -{ - BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings(); - - // test if the via size is smaller than minimum - if( aRefVia->GetViaType() == VIATYPE::MICROVIA ) - { - if( aRefVia->GetWidth() < bds.m_MicroViasMinSize ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_MICROVIA ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ), - MessageTextFromValue( userUnits(), bds.m_MicroViasMinSize, true ), - MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefVia ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } - else - { - if( aRefVia->GetWidth() < bds.m_ViasMinSize ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_VIA ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ), - MessageTextFromValue( userUnits(), bds.m_ViasMinSize, true ), - MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefVia ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } - - // test if via's hole is bigger than its diameter - // This test is necessary since the via hole size and width can be modified - // and a default via hole can be bigger than some vias sizes - if( aRefVia->GetDrillValue() > aRefVia->GetWidth() ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_HOLE_BIGGER ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (diameter %s; drill %s)" ), - MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ), - MessageTextFromValue( userUnits(), aRefVia->GetDrillValue(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefVia ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - - // test if the type of via is allowed due to design rules - if( aRefVia->GetViaType() == VIATYPE::MICROVIA && !bds.m_MicroViasAllowed ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); - - m_msg.Printf( _( "Microvia not allowed (board design rule constraints)" ) ); - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefVia ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - - // test if the type of via is allowed due to design rules - if( aRefVia->GetViaType() == VIATYPE::BLIND_BURIED && !bds.m_BlindBuriedViaAllowed ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); - - m_msg.Printf( _( "Blind/buried via not allowed (board design rule constraints)" ) ); - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefVia ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - - // For microvias: test if they are blind vias and only between 2 layers - // because they are used for very small drill size and are drill by laser - // and **only one layer** can be drilled - if( aRefVia->GetViaType() == VIATYPE::MICROVIA ) - { - PCB_LAYER_ID layer1, layer2; - bool err = true; - - aRefVia->LayerPair( &layer1, &layer2 ); - - if( layer1 > layer2 ) - std::swap( layer1, layer2 ); - - if( layer2 == B_Cu && layer1 == bds.GetCopperLayerCount() - 2 ) - err = false; - else if( layer1 == F_Cu && layer2 == In1_Cu ) - err = false; - - if( err ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_PADSTACK ); - - m_msg.Printf( _( "Microvia through too many layers (%s and %s not adjacent)" ), - m_pcb->GetLayerName( layer1 ), - m_pcb->GetLayerName( layer2 ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefVia ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } -} - - -void DRC::doSingleTrackDRC( BOARD_COMMIT& aCommit, TRACK* aRefSeg ) -{ - SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() ); - EDA_RECT refSegBB = aRefSeg->GetBoundingBox(); - int refSegWidth = aRefSeg->GetWidth(); - - int minWidth, maxWidth; - aRefSeg->GetWidthConstraints( &minWidth, &maxWidth, &m_clearanceSource ); - - int errorCode = 0; - int constraintWidth; - - if( refSegWidth < minWidth ) - { - errorCode = DRCE_TRACK_WIDTH; - constraintWidth = minWidth; - } - else if( refSegWidth > maxWidth ) - { - errorCode = DRCE_TRACK_WIDTH; - constraintWidth = maxWidth; - } - - if( errorCode ) - { - wxPoint refsegMiddle = ( aRefSeg->GetStart() + aRefSeg->GetEnd() ) / 2; - - DRC_ITEM* drcItem = DRC_ITEM::Create( errorCode ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), constraintWidth, true ), - MessageTextFromValue( userUnits(), refSegWidth, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefSeg ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, refsegMiddle ); - addMarkerToPcb( aCommit, marker ); - } -} - - -void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt, - TRACKS::iterator aEndIt, bool aTestZones, PCB_LAYER_ID aLayer ) -{ - BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings(); - SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() ); - - EDA_RECT refSegBB = aRefSeg->GetBoundingBox(); - SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() ); - int halfWidth = ( aRefSeg->GetWidth() + 1 ) / 2; - - /******************************************/ - /* Phase 0 : via DRC tests : */ - /******************************************/ - - if( aRefSeg->Type() == PCB_VIA_T ) - { - VIA* refvia = static_cast( aRefSeg ); - int viaAnnulus = ( refvia->GetWidth() - refvia->GetDrill() ) / 2; - int minAnnulus = refvia->GetMinAnnulus( aLayer, &m_clearanceSource ); - - if( !refvia->IsPadOnLayer( aLayer ) ) - { - halfWidth = ( refvia->GetDrillValue() + 1 ) / 2; - refSegBB = EDA_RECT( refvia->GetStart(), - wxSize( refvia->GetDrillValue(), refvia->GetDrillValue() ) ); - } - - // test if the via size is smaller than minimum - if( refvia->GetViaType() == VIATYPE::MICROVIA ) - { - if( viaAnnulus < minAnnulus ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS ); - - m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minAnnulus, true ), - MessageTextFromValue( userUnits(), viaAnnulus, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( refvia ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } - else - { - if( bds.m_ViasMinAnnulus > minAnnulus ) - { - minAnnulus = bds.m_ViasMinAnnulus; - m_clearanceSource = _( "board minimum" ); - } - - if( viaAnnulus < minAnnulus ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS ); - - m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minAnnulus, true ), - MessageTextFromValue( userUnits(), viaAnnulus, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( refvia ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() ); - addMarkerToPcb( aCommit, marker ); - } - } - - } - - - /******************************************/ - /* Phase 1 : test DRC track to pads : */ - /******************************************/ - - // Compute the min distance to pads - for( MODULE* mod : m_pcb->Modules() ) - { - // Don't preflight at the module level. Getting a module's bounding box goes - // through all its pads anyway (so it's no faster), and also all its drawings - // (so it's in fact slower). - - for( D_PAD* pad : mod->Pads() ) - { - // Preflight based on bounding boxes. - EDA_RECT inflatedBB = refSegBB; - inflatedBB.Inflate( pad->GetBoundingRadius() + m_largestClearance ); - - if( !inflatedBB.Contains( pad->GetPosition() ) ) - continue; - - if( !pad->IsOnLayer( aLayer ) ) - continue; - - // No need to check pads with the same net as the refSeg. - if( pad->GetNetCode() && aRefSeg->GetNetCode() == pad->GetNetCode() ) - continue; - - if( pad->GetDrillSize().x > 0 ) - { - // For hole testing we use a dummy pad which is a copy of the current pad - // shrunk down to nothing but its hole. - D_PAD dummypad( *pad ); - dummypad.SetSize( pad->GetDrillSize() ); - dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ? - PAD_SHAPE_OVAL : PAD_SHAPE_CIRCLE ); - // Ensure the hole is on all copper layers - const static LSET all_cu = LSET::AllCuMask(); - dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() ); - - int minClearance; - DRC_RULE* rule = GetRule( aRefSeg, &dummypad, DRC_CONSTRAINT_TYPE_CLEARANCE ); - - if( rule ) - { - m_clearanceSource = wxString::Format( _( "'%s' rule" ), rule->m_Name ); - minClearance = rule->m_Clearance.Min; - } - else - { - minClearance = aRefSeg->GetClearance( nullptr, &m_clearanceSource ); - } - - /* Treat an oval hole as a line segment along the hole's major axis, - * shortened by half its minor axis. - * A circular hole is just a degenerate case of an oval hole. - */ - wxPoint slotStart, slotEnd; - int slotWidth; - - pad->GetOblongGeometry( pad->GetDrillSize(), &slotStart, &slotEnd, &slotWidth ); - slotStart += pad->GetPosition(); - slotEnd += pad->GetPosition(); - - SEG slotSeg( slotStart, slotEnd ); - int center2centerAllowed = minClearance + halfWidth + bds.GetDRCEpsilon(); - - // Avoid square-roots if possible (for performance) - SEG::ecoord center2center_squared = refSeg.SquaredDistance( slotSeg ); - - if( center2center_squared < SEG::Square( center2centerAllowed ) ) - { - int actual = std::max( 0.0, sqrt( center2center_squared ) - halfWidth ); - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_HOLE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefSeg, pad ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, GetLocation( aRefSeg, slotSeg ) ); - addMarkerToPcb( aCommit, marker ); - - if( !m_reportAllTrackErrors ) - return; - } - } - - int minClearance = aRefSeg->GetClearance( aLayer, pad, &m_clearanceSource ); - int clearanceAllowed = minClearance - bds.GetDRCEpsilon(); - int actual; - - if( !checkClearanceSegmToPad( refSeg, refSeg.GetWidth(), pad, clearanceAllowed, &actual ) ) - { - actual = std::max( 0, actual ); - SEG padSeg( pad->GetPosition(), pad->GetPosition() ); - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_PAD ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefSeg, pad ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, GetLocation( aRefSeg, padSeg ) ); - addMarkerToPcb( aCommit, marker ); - - if( !m_reportAllTrackErrors ) - return; - } - } - } - - /***********************************************/ - /* Phase 2: test DRC with other track segments */ - /***********************************************/ - - // Test the reference segment with other track segments - for( auto it = aStartIt; it != aEndIt; it++ ) - { - TRACK* track = *it; - - // No problem if segments have the same net code: - if( aRefSeg->GetNetCode() == track->GetNetCode() ) - continue; - - if( !track->GetLayerSet().test( aLayer ) ) - continue; - - // Preflight based on worst-case inflated bounding boxes: - EDA_RECT trackBB = track->GetBoundingBox(); - trackBB.Inflate( m_largestClearance ); - - if( !trackBB.Intersects( refSegBB ) ) - continue; - - int minClearance = aRefSeg->GetClearance( aLayer, track, &m_clearanceSource ); - SEG trackSeg( track->GetStart(), track->GetEnd() ); - int widths = ( track->GetWidth() / 2 ) + halfWidth; - - /// Check to see if the via has a pad on this layer - if( track->Type() == PCB_VIA_T ) - { - VIA* via = static_cast( track ); - - if( !via->IsPadOnLayer( aLayer ) ) - widths = ( via->GetDrillValue() / 2 ) + halfWidth; - } - - int center2centerAllowed = minClearance + widths; - - // Avoid square-roots if possible (for performance) - SEG::ecoord center2center_squared = refSeg.SquaredDistance( trackSeg ); - OPT_VECTOR2I intersection = refSeg.Intersect( trackSeg ); - - // Check two tracks crossing first as it reports a DRCE without distances - if( intersection ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACKS_CROSSING ); - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefSeg, track ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, (wxPoint) intersection.get() ); - addMarkerToPcb( aCommit, marker ); - - if( !m_reportAllTrackErrors ) - return; - } - else if( center2center_squared < SEG::Square( center2centerAllowed ) ) - { - int errorCode = DRCE_TRACK_ENDS; - - if( aRefSeg->Type() == PCB_VIA_T && track->Type() == PCB_VIA_T ) - errorCode = DRCE_VIA_NEAR_VIA; - else if( aRefSeg->Type() == PCB_VIA_T || track->Type() == PCB_VIA_T ) - errorCode = DRCE_VIA_NEAR_TRACK; - else if( refSeg.ApproxParallel( trackSeg ) ) - errorCode = DRCE_TRACK_SEGMENTS_TOO_CLOSE; - - int actual = std::max( 0.0, sqrt( center2center_squared ) - widths ); - DRC_ITEM* drcItem = new DRC_ITEM( errorCode ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefSeg, track ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, GetLocation( aRefSeg, trackSeg ) ); - addMarkerToPcb( aCommit, marker ); - - if( !m_reportAllTrackErrors ) - return; - } - } - - /***************************************/ - /* Phase 3: test DRC with copper zones */ - /***************************************/ - // Can be *very* time consumming. - if( aTestZones ) - { - SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() ); - - for( ZONE_CONTAINER* zone : m_pcb->Zones() ) - { - if( !zone->GetLayerSet().test( aLayer ) || zone->GetFilledPolysList( aLayer ).IsEmpty() - || zone->GetIsKeepout() ) - continue; - - if( zone->GetNetCode() && zone->GetNetCode() == aRefSeg->GetNetCode() ) - continue; - - int minClearance = aRefSeg->GetClearance( aLayer, zone, &m_clearanceSource ); - int center2centerAllowed = minClearance + halfWidth; - SHAPE_POLY_SET* outline = const_cast( &zone->GetFilledPolysList( aLayer ) ); - - SEG::ecoord center2center_squared = outline->SquaredDistance( testSeg ); - - // 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 ) - - if( center2center_squared + THRESHOLD_DIST < SEG::Square( center2centerAllowed ) ) - { - int actual = std::max( 0.0, sqrt( center2center_squared ) - halfWidth ); - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_ZONE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefSeg, zone ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, GetLocation( aRefSeg, zone ) ); - addMarkerToPcb( aCommit, marker ); - } - } - } - - /***********************************************/ - /* Phase 4: test DRC with to board edge */ - /***********************************************/ - if( m_board_outline_valid ) - { - int minClearance = bds.m_CopperEdgeClearance; - m_clearanceSource = _( "board edge" ); - - static DRAWSEGMENT dummyEdge; - dummyEdge.SetLayer( Edge_Cuts ); - - if( aRefSeg->GetRuleClearance( &dummyEdge, aLayer, &minClearance, &m_clearanceSource ) ) - /* minClearance and m_clearanceSource set in GetRuleClearance() */; - - SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() ); - int center2centerAllowed = minClearance + halfWidth; - - for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ ) - { - SEG::ecoord center2center_squared = testSeg.SquaredDistance( *it ); - - if( center2center_squared < SEG::Square( center2centerAllowed ) ) - { - VECTOR2I pt = testSeg.NearestPoint( *it ); - - KICAD_T types[] = { PCB_LINE_T, EOT }; - DRAWSEGMENT* edge = nullptr; - INSPECTOR_FUNC inspector = - [&] ( EDA_ITEM* item, void* testData ) - { - DRAWSEGMENT* test_edge = dynamic_cast( item ); - - if( !test_edge || test_edge->GetLayer() != Edge_Cuts ) - return SEARCH_RESULT::CONTINUE; - - if( test_edge->HitTest( (wxPoint) pt, minClearance + halfWidth ) ) - { - edge = test_edge; - return SEARCH_RESULT::QUIT; - } - - return SEARCH_RESULT::CONTINUE; - }; - - // 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 errorCode = ( aRefSeg->Type() == PCB_VIA_T ) ? DRCE_VIA_NEAR_EDGE - : DRCE_TRACK_NEAR_EDGE; - DRC_ITEM* drcItem = new DRC_ITEM( errorCode ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - m_clearanceSource, - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aRefSeg, edge ); - - MARKER_PCB* marker = new MARKER_PCB( drcItem, (wxPoint) pt ); - addMarkerToPcb( aCommit, marker ); - } - } - } -} - - -bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance, int* aActual ) -{ - // relativePadPos is the aPad shape position relative to the aRefPad shape position - wxPoint relativePadPos = aPad->ShapePos() - aRefPad->ShapePos(); - - int center2center = KiROUND( EuclideanNorm( relativePadPos ) ); - - // Quick test: Clearance is OK if the bounding circles are further away than aMinClearance - if( center2center - aRefPad->GetBoundingRadius() - aPad->GetBoundingRadius() >= aMinClearance ) - return true; - - /* Here, pads are near and DRC depends on the pad shapes. We must compare distance using - * a fine shape analysis. - * Because a circle or oval shape is the easier shape to test, swap pads to have aRefPad be - * a PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL. If aRefPad = TRAPEZOID and aPad = RECT, also swap. - */ - bool swap_pads; - swap_pads = false; - - // swap pads to make comparisons easier - // Note also a ROUNDRECT pad with a corner radius = r can be considered as - // a smaller RECT (size - 2*r) with a clearance increased by r - // priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other - if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE ) - { - // pad ref shape is here oval, rect, roundrect, chamfered rect, trapezoid or custom - switch( aPad->GetShape() ) - { - case PAD_SHAPE_CIRCLE: - swap_pads = true; - break; - - case PAD_SHAPE_OVAL: - swap_pads = true; - break; - - case PAD_SHAPE_RECT: - case PAD_SHAPE_ROUNDRECT: - if( aRefPad->GetShape() != PAD_SHAPE_OVAL ) - swap_pads = true; - break; - - case PAD_SHAPE_TRAPEZOID: - case PAD_SHAPE_CHAMFERED_RECT: - case PAD_SHAPE_CUSTOM: - break; - } - } - - if( swap_pads ) - { - std::swap( aRefPad, aPad ); - relativePadPos = -relativePadPos; - } - - bool diag = true; - - if( ( aRefPad->GetShape() == PAD_SHAPE_CIRCLE || aRefPad->GetShape() == PAD_SHAPE_OVAL ) ) - { - /* Treat an oval pad as a line segment along the hole's major axis, - * shortened by half its minor axis. - * A circular pad is just a degenerate case of an oval hole. - */ - wxPoint refPadStart, refPadEnd; - int refPadWidth; - - aRefPad->GetOblongGeometry( aRefPad->GetSize(), &refPadStart, &refPadEnd, &refPadWidth ); - refPadStart += aRefPad->ShapePos(); - refPadEnd += aRefPad->ShapePos(); - - SEG refPadSeg( refPadStart, refPadEnd ); - diag = checkClearanceSegmToPad( refPadSeg, refPadWidth, aPad, aMinClearance, aActual ); - } - else - { - int dist_extra = 0; - - // corners of aRefPad (used only for rect/roundrect/trap pad) - wxPoint polyref[4]; - // corners of aRefPad (used only for custom pad) - SHAPE_POLY_SET polysetref; - - if( aRefPad->GetShape() == PAD_SHAPE_ROUNDRECT ) - { - int padRadius = aRefPad->GetRoundRectCornerRadius(); - dist_extra = padRadius; - GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ), aRefPad->GetSize(), - aRefPad->GetOrientation() ); - } - else if( aRefPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT ) - { - BOARD* board = aRefPad->GetBoard(); - int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF; - - // The reference pad can be rotated. Calculate the rotated coordinates. - // (note, the ref pad position is the origin of coordinates for this drc test) - int padRadius = aRefPad->GetRoundRectCornerRadius(); - - TransformRoundChamferedRectToPolygon( polysetref, wxPoint( 0, 0 ), aRefPad->GetSize(), - aRefPad->GetOrientation(), - padRadius, aRefPad->GetChamferRectRatio(), - aRefPad->GetChamferPositions(), maxError ); - } - else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM ) - { - polysetref.Append( aRefPad->GetCustomShapeAsPolygon() ); - - // The reference pad can be rotated. Calculate the rotated coordinates. - // (note, the ref pad position is the origin of coordinates for this drc test) - aRefPad->CustomShapeAsPolygonToBoardPosition( &polysetref, wxPoint( 0, 0 ), - aRefPad->GetOrientation() ); - } - else - { - // BuildPadPolygon has meaning for rect a trapeziod shapes and returns the 4 corners. - aRefPad->BuildPadPolygon( polyref, wxSize( 0, 0 ), aRefPad->GetOrientation() ); - } - - // corners of aPad (used only for rect/roundrect/trap pad) - wxPoint polycompare[4]; - // corners of aPad (used only custom pad) - SHAPE_POLY_SET polysetcompare; - - switch( aPad->GetShape() ) - { - case PAD_SHAPE_ROUNDRECT: - case PAD_SHAPE_RECT: - case PAD_SHAPE_CHAMFERED_RECT: - case PAD_SHAPE_TRAPEZOID: - case PAD_SHAPE_CUSTOM: - if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT ) - { - int padRadius = aPad->GetRoundRectCornerRadius(); - dist_extra = padRadius; - GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos, aPad->GetSize(), - aPad->GetOrientation() ); - } - else if( aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT ) - { - BOARD* board = aRefPad->GetBoard(); - int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF; - - // The pad to compare can be rotated. Calculate the rotated coordinates. - // ( note, the pad to compare position is the relativePadPos for this drc test) - int padRadius = aPad->GetRoundRectCornerRadius(); - - TransformRoundChamferedRectToPolygon( polysetcompare, relativePadPos, - aPad->GetSize(), aPad->GetOrientation(), - padRadius, aPad->GetChamferRectRatio(), - aPad->GetChamferPositions(), maxError ); - } - else if( aPad->GetShape() == PAD_SHAPE_CUSTOM ) - { - polysetcompare.Append( aPad->GetCustomShapeAsPolygon() ); - - // The pad to compare can be rotated. Calculate the rotated coordinates. - // ( note, the pad to compare position is the relativePadPos for this drc test) - aPad->CustomShapeAsPolygonToBoardPosition( &polysetcompare, relativePadPos, - aPad->GetOrientation() ); - } - else - { - aPad->BuildPadPolygon( polycompare, wxSize( 0, 0 ), aPad->GetOrientation() ); - - // Move aPad shape to relativePadPos - for( int ii = 0; ii < 4; ii++ ) - polycompare[ii] += relativePadPos; - } - - // And now test polygons: We have 3 cases: - // one poly is complex and the other is basic (has only 4 corners) - // both polys are complex - // both polys are basic (have only 4 corners) the most usual case - if( polysetref.OutlineCount() && polysetcompare.OutlineCount() == 0) - { - const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 ); - // And now test polygons: - if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(), - polycompare, 4, aMinClearance + dist_extra, aActual ) ) - { - *aActual = std::max( 0, *aActual - dist_extra ); - diag = false; - } - } - else if( polysetref.OutlineCount() == 0 && polysetcompare.OutlineCount()) - { - const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 ); - // And now test polygons: - if( !poly2polyDRC((wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(), - polyref, 4, aMinClearance + dist_extra, aActual ) ) - { - *aActual = std::max( 0, *aActual - dist_extra ); - diag = false; - } - } - else if( polysetref.OutlineCount() && polysetcompare.OutlineCount() ) - { - const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 ); - const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 ); - - // And now test polygons: - if( !poly2polyDRC((wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(), - (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(), - aMinClearance + dist_extra, aActual ) ) - { - *aActual = std::max( 0, *aActual - dist_extra ); - diag = false; - } - } - else - { - if( !poly2polyDRC( polyref, 4, polycompare, 4, aMinClearance + dist_extra, aActual ) ) - { - *aActual = std::max( 0, *aActual - dist_extra ); - diag = false; - } - } - break; - - default: - break; - } - } - - return diag; -} - - -/* - * Test if distance between a segment and a pad is > minClearance. Return the actual - * distance if it is less. - */ -bool DRC::checkClearanceSegmToPad( const SEG& refSeg, int refSegWidth, const D_PAD* pad, - int minClearance, int* aActualDist ) -{ - if( ( pad->GetShape() == PAD_SHAPE_CIRCLE || pad->GetShape() == PAD_SHAPE_OVAL ) ) - { - /* Treat an oval pad as a line segment along the hole's major axis, - * shortened by half its minor axis. - * A circular pad is just a degenerate case of an oval hole. - */ - wxPoint padStart, padEnd; - int padWidth; - - pad->GetOblongGeometry( pad->GetSize(), &padStart, &padEnd, &padWidth ); - padStart += pad->ShapePos(); - padEnd += pad->ShapePos(); - - SEG padSeg( padStart, padEnd ); - int widths = ( padWidth + refSegWidth ) / 2; - int center2centerAllowed = minClearance + widths; - - // Avoid square-roots if possible (for performance) - SEG::ecoord center2center_squared = refSeg.SquaredDistance( padSeg ); - - if( center2center_squared < SEG::Square( center2centerAllowed ) ) - { - *aActualDist = std::max( 0.0, sqrt( center2center_squared ) - widths ); - return false; - } - } - else if( ( pad->GetShape() == PAD_SHAPE_RECT || pad->GetShape() == PAD_SHAPE_ROUNDRECT ) - && ( (int) pad->GetOrientation() % 900 == 0 ) ) - { - EDA_RECT padBBox = pad->GetBoundingBox(); - int widths = refSegWidth / 2; - - // Note a ROUNDRECT pad with a corner radius = r can be treated as a smaller - // RECT (size - 2*r) with a clearance increased by r - if( pad->GetShape() == PAD_SHAPE_ROUNDRECT ) - { - padBBox.Inflate( - pad->GetRoundRectCornerRadius() ); - widths += pad->GetRoundRectCornerRadius(); - } - - SHAPE_RECT padShape( padBBox.GetPosition(), padBBox.GetWidth(), padBBox.GetHeight() ); - int actual; - - if( padShape.DoCollide( refSeg, minClearance + widths, &actual ) ) - { - *aActualDist = std::max( 0, actual - widths ); - return false; - } - } - else // Convert the rest to polygons - { - SHAPE_POLY_SET polyset; - - BOARD* board = pad->GetBoard(); - int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF; - - pad->TransformShapeWithClearanceToPolygon( polyset, 0, maxError ); - - const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 ); - int widths = refSegWidth / 2; - int actual; - - if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(), - (wxPoint) refSeg.A, (wxPoint) refSeg.B, - minClearance + widths, &actual ) ) - { - *aActualDist = std::max( 0, actual - widths ); - return false; - } - } - - return true; -} - diff --git a/qa/drc_proto/drc_courtyard_tester.cpp b/qa/drc_proto/drc_courtyard_tester.cpp deleted file mode 100644 index 36f148d492..0000000000 --- a/qa/drc_proto/drc_courtyard_tester.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2010 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#include - -#include -#include - -#include - -#include - - -DRC_COURTYARD_TESTER::DRC_COURTYARD_TESTER( MARKER_HANDLER aMarkerHandler ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ) -{ -} - - -bool DRC_COURTYARD_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) -{ - // Detects missing (or malformed) footprint courtyards and courtyard incursions (for those - // with a courtyard). - wxString msg; - bool success = true; - - // Update courtyard polygons, and test for missing courtyard definition: - for( MODULE* footprint : aBoard.Modules() ) - { - if( footprint->BuildPolyCourtyard() ) - { - if( !aBoard.GetDesignSettings().Ignore( DRCE_MISSING_COURTYARD ) - && footprint->GetPolyCourtyardFront().OutlineCount() == 0 - && footprint->GetPolyCourtyardBack().OutlineCount() == 0 ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_MISSING_COURTYARD ); - drcItem->SetItems( footprint ); - HandleMarker( new MARKER_PCB( drcItem, footprint->GetPosition() ) ); - success = false; - } - else - { - footprint->GetPolyCourtyardFront().BuildBBoxCaches(); - footprint->GetPolyCourtyardBack().BuildBBoxCaches(); - } - } - else - { - if( !aBoard.GetDesignSettings().Ignore( DRCE_MALFORMED_COURTYARD ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_MALFORMED_COURTYARD ); - - msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) ); - - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( footprint ); - HandleMarker( new MARKER_PCB( drcItem, footprint->GetPosition() ) ); - success = false; - } - } - } - - if( !aBoard.GetDesignSettings().Ignore( DRCE_OVERLAPPING_FOOTPRINTS ) ) - { - for( auto it1 = aBoard.Modules().begin(); it1 != aBoard.Modules().end(); it1++ ) - { - MODULE* footprint = *it1; - SHAPE_POLY_SET& footprintFront = footprint->GetPolyCourtyardFront(); - SHAPE_POLY_SET& footprintBack = footprint->GetPolyCourtyardBack(); - - if( footprintFront.OutlineCount() == 0 && footprintBack.OutlineCount() == 0 ) - continue; // No courtyards defined - - for( auto it2 = it1 + 1; it2 != aBoard.Modules().end(); it2++ ) - { - MODULE* test = *it2; - SHAPE_POLY_SET& testFront = test->GetPolyCourtyardFront(); - SHAPE_POLY_SET& testBack = test->GetPolyCourtyardBack(); - SHAPE_POLY_SET intersection; - bool overlap = false; - wxPoint pos; - - if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0 - && footprintFront.BBoxFromCaches().Intersects( testFront.BBoxFromCaches() ) ) - { - intersection.RemoveAllContours(); - intersection.Append( footprintFront ); - - // Build the common area between footprint and the test: - intersection.BooleanIntersection( testFront, SHAPE_POLY_SET::PM_FAST ); - - // If the intersection exists then they overlap - if( intersection.OutlineCount() > 0 ) - { - overlap = true; - pos = (wxPoint) intersection.CVertex( 0, 0, -1 ); - } - } - - if( footprintBack.OutlineCount() > 0 && testBack.OutlineCount() > 0 - && footprintBack.BBoxFromCaches().Intersects( testBack.BBoxFromCaches() ) ) - { - intersection.RemoveAllContours(); - intersection.Append( footprintBack ); - - intersection.BooleanIntersection( testBack, SHAPE_POLY_SET::PM_FAST ); - - if( intersection.OutlineCount() > 0 ) - { - overlap = true; - pos = (wxPoint) intersection.CVertex( 0, 0, -1 ); - } - } - - if( overlap ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_OVERLAPPING_FOOTPRINTS ); - drcItem->SetItems( footprint, test ); - HandleMarker( new MARKER_PCB( drcItem, pos ) ); - success = false; - } - } - } - } - - if( !aBoard.GetDesignSettings().Ignore( DRCE_PTH_IN_COURTYARD ) - || !aBoard.GetDesignSettings().Ignore( DRCE_NPTH_IN_COURTYARD ) ) - { - for( MODULE* footprint : aBoard.Modules() ) - { - SHAPE_POLY_SET& footprintFront = footprint->GetPolyCourtyardFront(); - SHAPE_POLY_SET& footprintBack = footprint->GetPolyCourtyardBack(); - - if( footprintFront.OutlineCount() == 0 && footprintBack.OutlineCount() == 0 ) - continue; // No courtyards defined - - for( MODULE* candidate : aBoard.Modules() ) - { - if( footprint == candidate ) - continue; - - for( D_PAD* pad : candidate->Pads() ) - { - if( pad->GetDrillSize().x == 0 || pad->GetDrillSize().y == 0 ) - continue; - - wxPoint pos = pad->GetPosition(); - - if( footprintFront.Contains( pos, -1, 0, true /* use bbox caches */ ) - || footprintBack.Contains( pos, -1, 0, true /* use bbox caches */ ) ) - { - int code = pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ? - DRCE_NPTH_IN_COURTYARD : - DRCE_PTH_IN_COURTYARD; - DRC_ITEM* drcItem = new DRC_ITEM( code ); - drcItem->SetItems( footprint, pad ); - HandleMarker( new MARKER_PCB( drcItem, pos ) ); - success = false; - } - } - } - } - } - - return success; -} diff --git a/qa/drc_proto/drc_courtyard_tester.h b/qa/drc_proto/drc_courtyard_tester.h deleted file mode 100644 index 4ba70b09d3..0000000000 --- a/qa/drc_proto/drc_courtyard_tester.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2018 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#ifndef DRC_COURTYARD_OVERLAP__H -#define DRC_COURTYARD_OVERLAP__H - -#include - - -class BOARD; - -class DRC_COURTYARD_TESTER : public DRC_TEST_PROVIDER -{ -public: - DRC_COURTYARD_TESTER( MARKER_HANDLER aMarkerHandler ); - - virtual ~DRC_COURTYARD_TESTER() {}; - - bool RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) override; -}; - -#endif // DRC_COURTYARD_OVERLAP__H diff --git a/qa/drc_proto/drc_drilled_hole_tester.cpp b/qa/drc_proto/drc_drilled_hole_tester.cpp deleted file mode 100644 index fb829e3ba4..0000000000 --- a/qa/drc_proto/drc_drilled_hole_tester.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#include - -#include -#include - -#include - - -DRC_DRILLED_HOLE_TESTER::DRC_DRILLED_HOLE_TESTER( MARKER_HANDLER aMarkerHandler ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), - m_units( EDA_UNITS::MILLIMETRES ), - m_board( nullptr ), - m_largestRadius( 0 ) -{ -} - - -bool DRC_DRILLED_HOLE_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) -{ - bool success = true; - - // Test drilled holes to minimize drill bit breakage. - // - // Check pad & std. via circular holes for hole-to-hole-min (non-circular holes are milled) - // Check pad & std. via holes for via-min-drill (minimum hole classification) - // Check uvia holes for uvia-min-drill (laser drill classification) - - m_units = aUnits; - m_board = &aBoard; - m_holes.clear(); - m_largestRadius = 0; - - for( MODULE* mod : aBoard.Modules() ) - { - for( D_PAD* pad : mod->Pads( ) ) - success &= checkPad( pad ); - } - - for( TRACK* track : aBoard.Tracks() ) - { - VIA* via = dynamic_cast( track ); - - if( via ) - { - if( via->GetViaType() == VIATYPE::MICROVIA ) - success &= checkMicroVia( via ); - else - success &= checkVia( via ); - } - } - - success &= checkHoles(); - - return success; -} - - -bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad ) -{ - bool success = true; - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - - int holeSize = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y ); - - if( holeSize == 0 ) - return true; - - if( !bds.Ignore( DRCE_TOO_SMALL_PAD_DRILL ) ) - { - int minHole = bds.m_MinThroughDrill; - wxString minHoleSource = _( "board minimum" ); - DRC_RULE* rule = GetRule( aPad, nullptr, DRC_CONSTRAINT_TYPE_HOLE_SIZE ); - - if( rule ) - { - minHole = rule->m_MinHole; - minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name ); - } - - if( holeSize < minHole ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_PAD_DRILL ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ), - minHoleSource, - MessageTextFromValue( m_units, minHole, true ), - MessageTextFromValue( m_units, holeSize, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( aPad ); - - HandleMarker( new MARKER_PCB( drcItem, aPad->GetPosition() ) ); - success = false; - } - } - - if( !bds.Ignore( DRCE_DRILLED_HOLES_TOO_CLOSE ) && bds.m_HoleToHoleMin != 0 ) - { - if( aPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE ) - addHole( aPad->GetPosition(), aPad->GetDrillSize().x / 2, aPad ); - } - - return success; -} - -bool DRC_DRILLED_HOLE_TESTER::checkVia( VIA* via ) -{ - bool success = true; - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - - if( !bds.Ignore( DRCE_TOO_SMALL_VIA_DRILL ) ) - { - int minHole = bds.m_MinThroughDrill; - wxString minHoleSource = _( "board minimum" ); - DRC_RULE* rule = GetRule( via, nullptr, DRC_CONSTRAINT_TYPE_HOLE_SIZE ); - - if( rule ) - { - minHole = rule->m_MinHole; - minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name ); - } - - if( via->GetDrillValue() < minHole ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_VIA_DRILL ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ), - minHoleSource, - MessageTextFromValue( m_units, minHole, true ), - MessageTextFromValue( m_units, via->GetDrillValue(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( via ); - - HandleMarker( new MARKER_PCB( drcItem, via->GetPosition() ) ); - success = false; - } - } - - if( !bds.Ignore( DRCE_DRILLED_HOLES_TOO_CLOSE ) && bds.m_HoleToHoleMin != 0 ) - { - addHole( via->GetPosition(), via->GetDrillValue() / 2, via ); - } - - return success; -} - - -bool DRC_DRILLED_HOLE_TESTER::checkMicroVia( VIA* via ) -{ - bool success = true; - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - - if( !bds.Ignore( DRCE_TOO_SMALL_MICROVIA_DRILL ) ) - { - int minHole = bds.m_MicroViasMinDrill; - wxString minHoleSource = _( "board minimum" ); - DRC_RULE* rule = GetRule( via, nullptr, DRC_CONSTRAINT_TYPE_HOLE_SIZE ); - - if( rule ) - { - minHole = rule->m_MinHole; - minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name ); - } - - if( via->GetDrillValue() < minHole ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_MICROVIA_DRILL ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ), - minHoleSource, - MessageTextFromValue( m_units, minHole, true ), - MessageTextFromValue( m_units, via->GetDrillValue(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( via ); - - HandleMarker( new MARKER_PCB( drcItem, via->GetPosition() ) ); - success = false; - } - } - - return success; -} - - -void DRC_DRILLED_HOLE_TESTER::addHole( const wxPoint& aLocation, int aRadius, BOARD_ITEM* aOwner ) -{ - DRILLED_HOLE hole; - - hole.m_location = aLocation; - hole.m_drillRadius = aRadius; - hole.m_owner = aOwner; - - m_largestRadius = std::max( m_largestRadius, aRadius ); - - m_holes.push_back( hole ); -} - - -bool DRC_DRILLED_HOLE_TESTER::checkHoles() -{ - bool success = true; - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - - // No need to check if we're ignoring DRCE_DRILLED_HOLES_TOO_CLOSE; if we are then we - // won't have collected any holes to test. - - // Sort holes by X for performance. In the nested iteration we then need to look at - // following holes only while they are within the refHole's neighborhood as defined by - // the refHole radius + the minimum hole-to-hole clearance + the largest radius any of - // the following holes can have. - std::sort( m_holes.begin(), m_holes.end(), - []( const DRILLED_HOLE& a, const DRILLED_HOLE& b ) - { - if( a.m_location.x == b.m_location.x ) - return a.m_location.y < b.m_location.y; - else - return a.m_location.x < b.m_location.x; - } ); - - for( size_t ii = 0; ii < m_holes.size(); ++ii ) - { - const DRILLED_HOLE& refHole = m_holes[ ii ]; - int neighborhood = refHole.m_drillRadius + bds.m_HoleToHoleMin + m_largestRadius; - - for( size_t jj = ii + 1; jj < m_holes.size(); ++jj ) - { - const DRILLED_HOLE& checkHole = m_holes[ jj ]; - - if( refHole.m_location.x + neighborhood < checkHole.m_location.x ) - break; - - // Holes with identical locations are allowable - if( checkHole.m_location == refHole.m_location ) - continue; - - int actual = KiROUND( GetLineLength( checkHole.m_location, refHole.m_location ) ); - actual = std::max( 0, actual - checkHole.m_drillRadius - refHole.m_drillRadius ); - - if( actual < bds.m_HoleToHoleMin ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_DRILLED_HOLES_TOO_CLOSE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ), - MessageTextFromValue( m_units, bds.m_HoleToHoleMin, true ), - MessageTextFromValue( m_units, actual, true ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( refHole.m_owner, checkHole.m_owner ); - - HandleMarker( new MARKER_PCB( drcItem, refHole.m_location ) ); - success = false; - } - } - } - - return success; -} diff --git a/qa/drc_proto/drc_drilled_hole_tester.h b/qa/drc_proto/drc_drilled_hole_tester.h deleted file mode 100644 index a23e6843eb..0000000000 --- a/qa/drc_proto/drc_drilled_hole_tester.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#ifndef DRC_DRILLED_HOLE_TESTER__H -#define DRC_DRILLED_HOLE_TESTER__H - -#include - - -class BOARD; -class BOARD_ITEM; - - -class DRC_DRILLED_HOLE_TESTER : public DRC_TEST_PROVIDER -{ -public: - DRC_DRILLED_HOLE_TESTER( MARKER_HANDLER aMarkerHandler ); - - virtual ~DRC_DRILLED_HOLE_TESTER() {}; - - bool RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) override; - -private: - bool checkPad( D_PAD* aPad ); - bool checkVia( VIA* aVia ); - bool checkMicroVia( VIA* aVia ); - - void addHole( const wxPoint& aLocation, int aRadius, BOARD_ITEM* aOwner ); - bool checkHoles(); - -private: - struct DRILLED_HOLE - { - wxPoint m_location; - int m_drillRadius = 0; - BOARD_ITEM* m_owner = nullptr; - }; - - EDA_UNITS m_units; - BOARD* m_board; - std::vector m_holes; - int m_largestRadius; - - wxString m_msg; // Construct only once for performance -}; - -#endif // DRC_DRILLED_HOLE_TESTER__H diff --git a/qa/drc_proto/drc_item.cpp b/qa/drc_proto/drc_item.cpp deleted file mode 100644 index 0c89763098..0000000000 --- a/qa/drc_proto/drc_item.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2015-2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include -#include - - -// These, being statically-defined, require specialized I18N handling. We continue to -// use the _() macro so that string harvesting by the I18N framework doesn't have to be -// specialized, but we don't translate on initialization and instead do it in the getters. - -#undef _ -#define _(s) s - -test::DRC_ITEM test::DRC_ITEM::unconnectedItems( DRCE_UNCONNECTED_ITEMS, - _( "Unconnected items" ), - wxT( "unconnected_items" ) ); - -test::DRC_ITEM test::DRC_ITEM::shortingItems( DRCE_SHORTING_ITEMS, - _( "Items shorting two nets" ), - wxT( "shorting_items" ) ); - -test::DRC_ITEM test::DRC_ITEM::itemsNotAllowed( DRCE_ALLOWED_ITEMS, - _( "Items not allowed" ), - wxT( "items_not_allowed" ) ); - -test::DRC_ITEM test::DRC_ITEM::clearance( DRCE_CLEARANCE, - _( "Clearance violation" ), - wxT( "clearance" ) ); - -test::DRC_ITEM test::DRC_ITEM::tracksCrossing( DRCE_TRACKS_CROSSING, - _( "Tracks crossing" ), - wxT( "tracks_crossing" ) ); - -test::DRC_ITEM test::DRC_ITEM::copperEdgeClearance( DRCE_COPPER_EDGE_CLEARANCE, - _( "Board edge clearance violation" ), - wxT( "copper_edge_clearance" ) ); - -test::DRC_ITEM test::DRC_ITEM::zonesIntersect( DRCE_ZONES_INTERSECT, - _( "Copper areas intersect" ), - wxT( "zones_intersect" ) ); - -test::DRC_ITEM test::DRC_ITEM::zoneHasEmptyNet( DRCE_ZONE_HAS_EMPTY_NET, - _( "Copper zone net has no pads" ), - wxT( "zone_has_empty_net" ) ); - -test::DRC_ITEM test::DRC_ITEM::viaDangling( DRCE_DANGLING_VIA, - _( "Via is not connected" ), - wxT( "via_dangling" ) ); - -test::DRC_ITEM test::DRC_ITEM::trackDangling( DRCE_DANGLING_TRACK, - _( "Track has unconnected end" ), - wxT( "track_dangling" ) ); - -test::DRC_ITEM test::DRC_ITEM::holeClearance( DRCE_HOLE_CLEARANCE, - _( "Drilled hole clearance violation" ), - wxT( "hole_clearance" ) ); - -test::DRC_ITEM test::DRC_ITEM::trackWidth( DRCE_TRACK_WIDTH, - _( "Track width outside allowed limits" ), - wxT( "track_width" ) ); - -test::DRC_ITEM test::DRC_ITEM::viaTooSmall( DRCE_TOO_SMALL_VIA, - _( "Via size too small" ), - wxT( "via_too_small" ) ); - -test::DRC_ITEM test::DRC_ITEM::annulus( DRCE_ANNULUS, - _( "annulus" ), - wxT( "annulus" ) ); - -test::DRC_ITEM test::DRC_ITEM::drillTooSmall( DRCE_TOO_SMALL_DRILL, - _( "Drill too small" ), - wxT( "drill_too_small" ) ); - -test::DRC_ITEM test::DRC_ITEM::viaHoleLargerThanPad( DRCE_VIA_HOLE_BIGGER, - _( "Via hole larger than diameter" ), - wxT( "via_hole_larger_than_pad" ) ); - -test::DRC_ITEM test::DRC_ITEM::padstack( DRCE_PADSTACK, - _( "Padstack is not valid" ), - wxT( "padstack" ) ); - -test::DRC_ITEM test::DRC_ITEM::microviaTooSmall( DRCE_TOO_SMALL_MICROVIA, - _( "Micro via size too small" ), - wxT( "microvia_too_small" ) ); - -test::DRC_ITEM test::DRC_ITEM::microviaDrillTooSmall( DRCE_TOO_SMALL_MICROVIA_DRILL, - _( "Micro via drill too small" ), - wxT( "microvia_drill_too_small" ) ); - -test::DRC_ITEM test::DRC_ITEM::keepout( DRCE_KEEPOUT, - _( "Keepout violation" ), - wxT( "keepout" ) ); - -test::DRC_ITEM test::DRC_ITEM::courtyardsOverlap( DRCE_OVERLAPPING_FOOTPRINTS, - _( "Courtyards overlap" ), - wxT( "courtyards_overlap" ) ); - -test::DRC_ITEM test::DRC_ITEM::missingCourtyard( DRCE_MISSING_COURTYARD, - _( "Footprint has no courtyard defined" ), - wxT( "missing_courtyard" ) ); - -test::DRC_ITEM test::DRC_ITEM::malformedCourtyard( DRCE_MALFORMED_COURTYARD, - _( "Footprint has malformed courtyard" ), - wxT( "malformed_courtyard" ) ); - -test::DRC_ITEM test::DRC_ITEM::pthInsideCourtyard( DRCE_PTH_IN_COURTYARD, - _( "PTH inside courtyard" ), - wxT( "pth_inside_courtyard" ) ); - -test::DRC_ITEM test::DRC_ITEM::npthInsideCourtyard( DRCE_NPTH_IN_COURTYARD, - _( "NPTH inside courtyard" ), - wxT( "npth_inside_courtyard" ) ); - -test::DRC_ITEM test::DRC_ITEM::itemOnDisabledLayer( DRCE_DISABLED_LAYER_ITEM, - _( "Item on a disabled layer" ), - wxT( "item_on_disabled_layer" ) ); - -test::DRC_ITEM test::DRC_ITEM::invalidOutline( DRCE_INVALID_OUTLINE, - _( "Board has malformed outline" ), - wxT( "invalid_outline" ) ); - -test::DRC_ITEM test::DRC_ITEM::duplicateFootprints( DRCE_DUPLICATE_FOOTPRINT, - _( "Duplicate footprints" ), - wxT( "duplicate_footprints" ) ); - -test::DRC_ITEM test::DRC_ITEM::missingFootprint( DRCE_MISSING_FOOTPRINT, - _( "Missing footprint" ), - wxT( "missing_footprint" ) ); - -test::DRC_ITEM test::DRC_ITEM::extraFootprint( DRCE_EXTRA_FOOTPRINT, - _( "Extra footprint" ), - wxT( "extra_footprint" ) ); - -test::DRC_ITEM test::DRC_ITEM::unresolvedVariable( DRCE_UNRESOLVED_VARIABLE, - _( "Unresolved text variable" ), - wxT( "unresolved_variable" ) ); - - -std::vector> test::DRC_ITEM::allItemTypes( { - DRC_ITEM::unconnectedItems, - DRC_ITEM::shortingItems, - DRC_ITEM::itemsNotAllowed, - DRC_ITEM::clearance, - DRC_ITEM::tracksCrossing, - DRC_ITEM::copperEdgeClearance, - DRC_ITEM::zonesIntersect, - DRC_ITEM::zoneHasEmptyNet, - DRC_ITEM::viaDangling, - DRC_ITEM::trackDangling, - DRC_ITEM::holeClearance, - DRC_ITEM::trackWidth, - DRC_ITEM::viaTooSmall, - DRC_ITEM::annulus, - DRC_ITEM::drillTooSmall, - DRC_ITEM::viaHoleLargerThanPad, - DRC_ITEM::padstack, - DRC_ITEM::microviaTooSmall, - DRC_ITEM::microviaDrillTooSmall, - DRC_ITEM::keepout, - DRC_ITEM::courtyardsOverlap, - DRC_ITEM::missingCourtyard, - DRC_ITEM::malformedCourtyard, - DRC_ITEM::pthInsideCourtyard, - DRC_ITEM::npthInsideCourtyard, - DRC_ITEM::itemOnDisabledLayer, - DRC_ITEM::invalidOutline, - DRC_ITEM::duplicateFootprints, - DRC_ITEM::missingFootprint, - DRC_ITEM::extraFootprint, - DRC_ITEM::unresolvedVariable - } ); - - -std::shared_ptr test::DRC_ITEM::Create( int aErrorCode ) -{ - DRC_ITEM *item; - - switch( aErrorCode ) - { - case DRCE_UNCONNECTED_ITEMS: item = new DRC_ITEM( unconnectedItems ); break; - case DRCE_SHORTING_ITEMS: item = new DRC_ITEM( shortingItems ); break; - case DRCE_ALLOWED_ITEMS: item = new DRC_ITEM( itemsNotAllowed ); break; - case DRCE_CLEARANCE: item = new DRC_ITEM( clearance ); break; - case DRCE_TRACKS_CROSSING: item = new DRC_ITEM( tracksCrossing ); break; - case DRCE_COPPER_EDGE_CLEARANCE: item = new DRC_ITEM( copperEdgeClearance ); break; - case DRCE_ZONES_INTERSECT: item = new DRC_ITEM( zonesIntersect ); break; - case DRCE_ZONE_HAS_EMPTY_NET: item = new DRC_ITEM( zoneHasEmptyNet ); break; - case DRCE_DANGLING_VIA: item = new DRC_ITEM( viaDangling ); break; - case DRCE_DANGLING_TRACK: item = new DRC_ITEM( trackDangling ); break; - case DRCE_HOLE_CLEARANCE: item = new DRC_ITEM( holeClearance ); break; - case DRCE_TRACK_WIDTH: item = new DRC_ITEM( trackWidth ); break; - case DRCE_TOO_SMALL_VIA: item = new DRC_ITEM( viaTooSmall ); break; - case DRCE_ANNULUS: item = new DRC_ITEM( annulus ); break; - case DRCE_TOO_SMALL_DRILL: item = new DRC_ITEM( drillTooSmall ); break; - case DRCE_VIA_HOLE_BIGGER: item = new DRC_ITEM( viaHoleLargerThanPad ); break; - case DRCE_PADSTACK: item = new DRC_ITEM( padstack ); break; - case DRCE_TOO_SMALL_MICROVIA: item = new DRC_ITEM( microviaTooSmall ); break; - case DRCE_TOO_SMALL_MICROVIA_DRILL: item = new DRC_ITEM( microviaDrillTooSmall ); break; - case DRCE_KEEPOUT: item = new DRC_ITEM( keepout ); break; - case DRCE_OVERLAPPING_FOOTPRINTS: item = new DRC_ITEM( courtyardsOverlap ); break; - case DRCE_MISSING_COURTYARD: item = new DRC_ITEM( missingCourtyard ); break; - case DRCE_MALFORMED_COURTYARD: item = new DRC_ITEM( malformedCourtyard ); break; - case DRCE_PTH_IN_COURTYARD: item = new DRC_ITEM( pthInsideCourtyard ); break; - case DRCE_NPTH_IN_COURTYARD: item = new DRC_ITEM( npthInsideCourtyard ); break; - case DRCE_DISABLED_LAYER_ITEM: item = new DRC_ITEM( itemOnDisabledLayer ); break; - case DRCE_INVALID_OUTLINE: item = new DRC_ITEM( invalidOutline ); break; - case DRCE_MISSING_FOOTPRINT: item = new DRC_ITEM( duplicateFootprints ); break; - case DRCE_DUPLICATE_FOOTPRINT: item = new DRC_ITEM( missingFootprint ); break; - case DRCE_EXTRA_FOOTPRINT: item = new DRC_ITEM( extraFootprint ); break; - case DRCE_UNRESOLVED_VARIABLE: item = new DRC_ITEM( unresolvedVariable ); break; - - default: - wxFAIL_MSG( wxString::Format( "Unknown DRC error code %d", aErrorCode ) ); - return nullptr; - } - return std::shared_ptr( item ); -} - - -std::shared_ptr test::DRC_ITEM::Create( const wxString& aErrorKey ) -{ - for( const RC_ITEM& item : allItemTypes ) - { - if( aErrorKey == item.GetSettingsKey() ) - return std::shared_ptr( new DRC_ITEM( static_cast( item ) ) ); - } - - // This can happen if a project has old-format exclusions. Just drop these items. - return nullptr; -} diff --git a/qa/drc_proto/drc_keepout_tester.cpp b/qa/drc_proto/drc_keepout_tester.cpp deleted file mode 100644 index fb36df85d0..0000000000 --- a/qa/drc_proto/drc_keepout_tester.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#include - -#include -#include - - -DRC_KEEPOUT_TESTER::DRC_KEEPOUT_TESTER( MARKER_HANDLER aMarkerHandler ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), - m_units( EDA_UNITS::MILLIMETRES ), - m_board( nullptr ), - m_zone( nullptr ), - m_keepoutFlags( 0 ) -{ -} - - -bool DRC_KEEPOUT_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) -{ - bool success = true; - - m_units = aUnits; - m_board = &aBoard; - - // Get a list of all zones to inspect, from both board and footprints - std::list areasToInspect = m_board->GetZoneList( true ); - - // Test keepout areas for vias, tracks and pads inside keepout areas - for( ZONE_CONTAINER* area : areasToInspect ) - { - m_keepoutFlags = area->GetKeepouts( &m_sources ); - - if( m_keepoutFlags > 0 ) - { - m_zone = area; - m_zoneBBox = area->GetBoundingBox(); - - success &= checkTracksAndVias(); - success &= checkFootprints(); - success &= checkDrawings(); - } - } - - return success; -} - - -bool DRC_KEEPOUT_TESTER::checkTracksAndVias() -{ - constexpr int VIA_MASK = DISALLOW_VIAS | DISALLOW_MICRO_VIAS | DISALLOW_BB_VIAS; - constexpr int CHECK_VIAS_MASK = VIA_MASK | DISALLOW_HOLES; - constexpr int CHECK_TRACKS_AND_VIAS_MASK = CHECK_VIAS_MASK | DISALLOW_TRACKS; - - if(( m_keepoutFlags & CHECK_TRACKS_AND_VIAS_MASK ) == 0 ) - return true; - - bool success = true; - - for( TRACK* segm : m_board->Tracks() ) - { - if( !m_zoneBBox.Intersects( segm->GetBoundingBox() ) ) - continue; - - if( segm->Type() == PCB_TRACE_T && ( m_keepoutFlags & DISALLOW_TRACKS ) != 0 ) - { - // Ignore if the keepout zone is not on the same layer - if( !m_zone->IsOnLayer( segm->GetLayer() ) ) - continue; - - int widths = segm->GetWidth() / 2; - SEG trackSeg( segm->GetStart(), segm->GetEnd() ); - SEG::ecoord center2center_squared = m_zone->Outline()->SquaredDistance( trackSeg ); - - if( center2center_squared <= SEG::Square( widths) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_INSIDE_KEEPOUT ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), - m_sources.at(DISALLOW_TRACKS ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( segm, m_zone ); - - HandleMarker( new MARKER_PCB( drcItem, DRC::GetLocation( segm, m_zone ) ) ); - success = false; - } - } - else if( segm->Type() == PCB_VIA_T && ( m_keepoutFlags & CHECK_VIAS_MASK ) != 0 ) - { - VIA* via = static_cast( segm ); - int errorCode = 0; - int sourceId = 0; - - if( ( m_keepoutFlags & DISALLOW_VIAS ) > 0 ) - { - errorCode = DRCE_VIA_INSIDE_KEEPOUT; - sourceId = DISALLOW_VIAS; - } - else if( via->GetViaType() == VIATYPE::MICROVIA - && ( m_keepoutFlags & DISALLOW_MICRO_VIAS ) > 0 ) - { - errorCode = DRCE_MICROVIA_INSIDE_KEEPOUT; - sourceId = DISALLOW_MICRO_VIAS; - } - else if( via->GetViaType() == VIATYPE::BLIND_BURIED - && ( m_keepoutFlags & DISALLOW_BB_VIAS ) > 0 ) - { - errorCode = DRCE_BBVIA_INSIDE_KEEPOUT; - sourceId = DISALLOW_BB_VIAS; - } - else if( ( m_keepoutFlags & DISALLOW_HOLES ) > 0 ) - { - errorCode = DRCE_HOLE_INSIDE_KEEPOUT; - sourceId = DISALLOW_HOLES; - } - else - continue; - - int widths = via->GetWidth() / 2; - wxPoint viaPos = via->GetPosition(); - - if( errorCode == DRCE_HOLE_INSIDE_KEEPOUT ) - widths = via->GetDrillValue() / 2; - - SEG::ecoord center2center_squared = m_zone->Outline()->SquaredDistance( viaPos ); - - if( center2center_squared <= SEG::Square( widths ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( errorCode ); - m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), m_sources.at( sourceId ) ); - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( segm, m_zone ); - - HandleMarker( new MARKER_PCB( drcItem, DRC::GetLocation( segm, m_zone ) ) ); - success = false; - } - } - } - - return success; -} - - -bool DRC_KEEPOUT_TESTER::checkFootprints() -{ - constexpr int CHECK_PADS_MASK = DISALLOW_PADS | DISALLOW_HOLES; - constexpr int CHECK_FOOTPRINTS_MASK = CHECK_PADS_MASK | DISALLOW_FOOTPRINTS; - - if(( m_keepoutFlags & CHECK_FOOTPRINTS_MASK ) == 0 ) - return true; - - bool success = true; - - for( MODULE* fp : m_board->Modules() ) - { - if( !m_zoneBBox.Intersects( fp->GetBoundingBox() ) ) - continue; - - if( ( m_keepoutFlags & DISALLOW_FOOTPRINTS ) > 0 - && ( fp->IsFlipped() ? m_zone->CommonLayerExists( LSET::BackMask() ) - : m_zone->CommonLayerExists( LSET::FrontMask() ) ) ) - { - SHAPE_POLY_SET poly; - - if( fp->BuildPolyCourtyard() ) - poly = fp->IsFlipped() ? fp->GetPolyCourtyardBack() : fp->GetPolyCourtyardFront(); - - if( poly.OutlineCount() == 0 ) - poly = fp->GetBoundingPoly(); - - // Build the common area between footprint and the keepout area: - poly.BooleanIntersection( *m_zone->Outline(), SHAPE_POLY_SET::PM_FAST ); - - // If it's not empty then we have a violation - if( poly.OutlineCount() ) - { - const VECTOR2I& pt = poly.CVertex( 0, 0, -1 ); - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_FOOTPRINT_INSIDE_KEEPOUT ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), - m_sources.at( DISALLOW_FOOTPRINTS ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( fp, m_zone ); - - HandleMarker( new MARKER_PCB( drcItem, (wxPoint) pt ) ); - success = false; - } - } - - if( ( m_keepoutFlags & CHECK_PADS_MASK ) > 0 ) - { - success &= checkPads( fp ); - } - } - - return success; -} - - -bool DRC_KEEPOUT_TESTER::checkPads( MODULE* aModule ) -{ - bool success = true; - - for( D_PAD* pad : aModule->Pads() ) - { - if( !m_zone->CommonLayerExists( pad->GetLayerSet() ) ) - continue; - - // Fast test to detect a pad inside the keepout area bounding box. - EDA_RECT padBBox( pad->ShapePos(), wxSize() ); - padBBox.Inflate( pad->GetBoundingRadius() ); - - if( !m_zoneBBox.Intersects( padBBox ) ) - continue; - - if( ( m_keepoutFlags & DISALLOW_PADS ) > 0 ) - { - SHAPE_POLY_SET outline; - pad->TransformShapeWithClearanceToPolygon( outline, 0 ); - - // Build the common area between pad and the keepout area: - outline.BooleanIntersection( *m_zone->Outline(), SHAPE_POLY_SET::PM_FAST ); - - // If it's not empty then we have a violation - if( outline.OutlineCount() ) - { - const VECTOR2I& pt = outline.CVertex( 0, 0, -1 ); - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_INSIDE_KEEPOUT ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), - m_sources.at( DISALLOW_PADS ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( pad, m_zone ); - - HandleMarker( new MARKER_PCB( drcItem, (wxPoint) pt ) ); - success = false; - } - } - else if( ( m_keepoutFlags & DISALLOW_HOLES ) > 0 ) - { - wxPoint slotStart, slotEnd; - int slotWidth; - - pad->GetOblongGeometry( pad->GetDrillSize(), &slotStart, &slotEnd, &slotWidth ); - slotStart += pad->GetPosition(); - slotEnd += pad->GetPosition(); - - SEG slotSeg( slotStart, slotEnd ); - SHAPE_POLY_SET* outline = const_cast( &m_zone->GetFilledPolysList() ); - SEG::ecoord center2center_sq = outline->SquaredDistance( slotSeg ); - - if( center2center_sq <= SEG::Square( slotWidth) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_HOLE_INSIDE_KEEPOUT ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), - m_sources.at( DISALLOW_HOLES ) ); - - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( pad, m_zone ); - - HandleMarker( new MARKER_PCB( drcItem, pad->GetPosition() ) ); - success = false; - } - } - } - - return success; -} - - -bool DRC_KEEPOUT_TESTER::checkDrawings() -{ - constexpr int CHECK_DRAWINGS_MASK = DISALLOW_TEXTS | DISALLOW_GRAPHICS; - constexpr KICAD_T graphicTypes[] = { PCB_LINE_T, PCB_DIMENSION_T, PCB_TARGET_T, EOT }; - - if(( m_keepoutFlags & CHECK_DRAWINGS_MASK ) == 0 ) - return true; - - bool success = true; - - for( BOARD_ITEM* drawing : m_board->Drawings() ) - { - if( !m_zoneBBox.Intersects( drawing->GetBoundingBox() ) ) - continue; - - int errorCode = 0; - int sourceId = 0; - - if( drawing->IsType( graphicTypes ) && ( m_keepoutFlags & DISALLOW_GRAPHICS ) > 0 ) - { - errorCode = DRCE_GRAPHICS_INSIDE_KEEPOUT; - sourceId = DISALLOW_GRAPHICS; - } - else if( drawing->Type() == PCB_TEXT_T && ( m_keepoutFlags & DISALLOW_TEXTS ) > 0 ) - { - errorCode = DRCE_TEXT_INSIDE_KEEPOUT; - sourceId = DISALLOW_TEXTS; - } - else - continue; - - SHAPE_POLY_SET poly; - drawing->TransformShapeWithClearanceToPolygon( poly, 0 ); - - // Build the common area between footprint and the keepout area: - poly.BooleanIntersection( *m_zone->Outline(), SHAPE_POLY_SET::PM_FAST ); - - // If it's not empty then we have a violation - if( poly.OutlineCount() ) - { - const VECTOR2I& pt = poly.CVertex( 0, 0, -1 ); - DRC_ITEM* drcItem = new DRC_ITEM( errorCode ); - m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), m_sources.at( sourceId ) ); - drcItem->SetErrorMessage( m_msg ); - drcItem->SetItems( drawing, m_zone ); - - HandleMarker( new MARKER_PCB( drcItem, (wxPoint) pt ) ); - success = false; - } - } - - return success; -} - - diff --git a/qa/drc_proto/drc_keepout_tester.h b/qa/drc_proto/drc_keepout_tester.h deleted file mode 100644 index c7cdf93019..0000000000 --- a/qa/drc_proto/drc_keepout_tester.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#ifndef DRC_KEEPOUT_TESTER__H -#define DRC_KEEPOUT_TESTER__H - -#include - - -class BOARD; - - -class DRC_KEEPOUT_TESTER : public DRC_TEST_PROVIDER -{ -public: - DRC_KEEPOUT_TESTER( MARKER_HANDLER aMarkerHandler ); - - virtual ~DRC_KEEPOUT_TESTER() {}; - - bool RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) override; - -private: - bool checkTracksAndVias(); - bool checkFootprints(); - bool checkPads( MODULE* aModule ); - bool checkDrawings(); - -private: - EDA_UNITS m_units; - BOARD* m_board; - - // Temp variables for use while testing: - ZONE_CONTAINER* m_zone; - EDA_RECT m_zoneBBox; - int m_keepoutFlags; // bitset of DISALLOW_* flags - std::map m_sources; // map of DISALLOW_* flag to source - wxString m_msg; // avoid lots of calls to wxString's c'tor. -}; - -#endif // DRC_KEEPOUT_TESTER__H diff --git a/qa/drc_proto/drc_marker_pcb.h b/qa/drc_proto/drc_marker_pcb.h deleted file mode 100644 index 1616bc5e42..0000000000 --- a/qa/drc_proto/drc_marker_pcb.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2009-2018 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr - * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/** - * @file class_marker_pcb.h - * @brief Markers used to show a drc problem on boards. - */ - -#ifndef CLASS_MARKER_PCB_H -#define CLASS_MARKER_PCB_H - - -#include -#include - -class DRC_ITEM; - -// Coordinates count for the basic shape marker -#define MARKER_SHAPE_POINT_COUNT 9 - -class MSG_PANEL_ITEM; - - -class MARKER_PCB : public BOARD_ITEM, public MARKER_BASE -{ -public: - MARKER_PCB( DRC_ITEM* aItem, const wxPoint& aPosition ); - - ~MARKER_PCB(); - - static inline bool ClassOf( const EDA_ITEM* aItem ) - { - return aItem && PCB_MARKER_T == aItem->Type(); - } - - const KIID GetUUID() const override { return m_Uuid; } - - wxString Serialize() const; - - static MARKER_PCB* Deserialize( const wxString& data ); - - void Move(const wxPoint& aMoveVector) override - { - m_Pos += aMoveVector; - } - - void Rotate( const wxPoint& aRotCentre, double aAngle ) override; - - void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override; - - wxPoint GetPosition() const override { return m_Pos; } - void SetPosition( const wxPoint& aPos ) override { m_Pos = aPos; } - - bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override - { - return HitTestMarker( aPosition, aAccuracy ); - } - - GAL_LAYER_ID GetColorLayer() const; - - void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) override; - - bool Matches( wxFindReplaceData& aSearchData, void* aAuxData ) override - { - return BOARD_ITEM::Matches( m_rcItem->GetErrorMessage(), aSearchData ); - } - - wxString GetSelectMenuText( EDA_UNITS aUnits ) const override; - - BITMAP_DEF GetMenuImage() const override; - - const BOX2I ViewBBox() const override; - - const EDA_RECT GetBoundingBox() const override; - - void ViewGetLayers( int aLayers[], int& aCount ) const override; - -#if defined(DEBUG) - void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } -#endif - - /** Get class name - * @return string "MARKER_PCB" - */ - virtual wxString GetClass() const override - { - return wxT( "MARKER_PCB" ); - } - -protected: - KIGFX::COLOR4D getColor() const override; -}; - -#endif // CLASS_MARKER_PCB_H diff --git a/qa/drc_proto/drc_netclass_tester.cpp b/qa/drc_proto/drc_netclass_tester.cpp deleted file mode 100644 index 6d2ad68078..0000000000 --- a/qa/drc_proto/drc_netclass_tester.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#include - - -DRC_NETCLASS_TESTER::DRC_NETCLASS_TESTER( MARKER_HANDLER aMarkerHandler ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), - m_units( EDA_UNITS::MILLIMETRES ), - m_board( nullptr ) -{ -} - - -bool DRC_NETCLASS_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) -{ - m_units = aUnits; - m_board = &aBoard; - - bool success = true; - NETCLASSES& netclasses = m_board->GetDesignSettings().m_NetClasses; - - success &= checkNetClass( netclasses.GetDefault() ); - - for( NETCLASSES::const_iterator i = netclasses.begin(); i != netclasses.end(); ++i ) - success &= checkNetClass( i->second ); - - return success; -} - - -bool DRC_NETCLASS_TESTER::checkNetClass( const NETCLASSPTR& nc ) -{ - bool ret = true; - - const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - - if( nc->GetClearance() < bds.m_MinClearance ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_CLEARANCE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; %s netclass %s)" ), - MessageTextFromValue( m_units, bds.m_MinClearance, true ), - nc->GetName(), - MessageTextFromValue( m_units, nc->GetClearance(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - HandleMarker( new MARKER_PCB( drcItem, wxPoint() ) ); - ret = false; - } - - if( nc->GetTrackWidth() < bds.m_TrackMinWidth ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_TRACKWIDTH ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; %s netclass %s)" ), - MessageTextFromValue( m_units, bds.m_TrackMinWidth, true ), - nc->GetName(), - MessageTextFromValue( m_units, nc->GetTrackWidth(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - HandleMarker( new MARKER_PCB( drcItem, wxPoint() ) ); - ret = false; - } - - if( nc->GetViaDiameter() < bds.m_ViasMinSize ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_VIASIZE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; %s netclass %s)" ), - MessageTextFromValue( m_units, bds.m_ViasMinSize, true ), - nc->GetName(), - MessageTextFromValue( m_units, nc->GetViaDiameter(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - HandleMarker( new MARKER_PCB( drcItem, wxPoint() ) ); - ret = false; - } - - if( nc->GetViaDrill() < bds.m_MinThroughDrill ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_VIADRILLSIZE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board min through hole %s; %s netclass %s)" ), - MessageTextFromValue( m_units, bds.m_MinThroughDrill, true ), - nc->GetName(), - MessageTextFromValue( m_units, nc->GetViaDrill(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - HandleMarker( new MARKER_PCB( drcItem, wxPoint() ) ); - ret = false; - } - - int ncViaAnnulus = ( nc->GetViaDiameter() - nc->GetViaDrill() ) / 2; - - if( ncViaAnnulus < bds.m_ViasMinAnnulus ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_VIAANNULUS ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; %s netclass %s)" ), - MessageTextFromValue( m_units, bds.m_ViasMinAnnulus, true ), - nc->GetName(), - MessageTextFromValue( m_units, ncViaAnnulus, true ) ); - - drcItem->SetErrorMessage( m_msg ); - HandleMarker( new MARKER_PCB( drcItem, wxPoint() ) ); - ret = false; - } - - if( nc->GetuViaDiameter() < bds.m_MicroViasMinSize ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_uVIASIZE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; %s netclass %s)" ), - MessageTextFromValue( m_units, bds.m_MicroViasMinSize, true ), - nc->GetName(), - MessageTextFromValue( m_units, nc->GetuViaDiameter(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - HandleMarker( new MARKER_PCB( drcItem, wxPoint() ) ); - ret = false; - } - - if( nc->GetuViaDrill() < bds.m_MicroViasMinDrill ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_uVIADRILLSIZE ); - - m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; %s netclass %s)" ), - MessageTextFromValue( m_units, bds.m_MicroViasMinDrill, true ), - nc->GetName(), - MessageTextFromValue( m_units, nc->GetuViaDrill(), true ) ); - - drcItem->SetErrorMessage( m_msg ); - HandleMarker( new MARKER_PCB( drcItem, wxPoint() ) ); - ret = false; - } - - return ret; -} - - diff --git a/qa/drc_proto/drc_netclass_tester.h b/qa/drc_proto/drc_netclass_tester.h deleted file mode 100644 index ed345df6cc..0000000000 --- a/qa/drc_proto/drc_netclass_tester.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#ifndef DRC_NETCLASS_TESTER__H -#define DRC_NETCLASS_TESTER__H - -#include - - -class BOARD; -class BOARD_ITEM; - - -class DRC_NETCLASS_TESTER : public DRC_TEST_PROVIDER -{ -public: - DRC_NETCLASS_TESTER( MARKER_HANDLER aMarkerHandler ); - - virtual ~DRC_NETCLASS_TESTER() {}; - - bool RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) override; - -private: - bool checkNetClass( const NETCLASSPTR& nc ); - -private: - EDA_UNITS m_units; - BOARD* m_board; - - wxString m_msg; // Construct only once for performance -}; - -#endif // DRC_NETCLASS_TESTER__H diff --git a/qa/drc_proto/drc_proto_test.cpp b/qa/drc_proto/drc_proto_test.cpp index 744974d4dc..c3f02898a8 100644 --- a/qa/drc_proto/drc_proto_test.cpp +++ b/qa/drc_proto/drc_proto_test.cpp @@ -29,8 +29,8 @@ #include #include -#include - +#include +#include #include #include @@ -184,6 +184,51 @@ PROJECT_CONTEXT loadKicadProject( wxString filename ) } +class TEST_DRC_ENGINE : public DRC_ENGINE +{ +public: + TEST_DRC_ENGINE( BOARD* aBoard, BOARD_DESIGN_SETTINGS* aSettings ) : + DRC_ENGINE( aBoard, aSettings ) + { } + + bool LoadRules( wxFileName aPath ) + { + if( aPath.FileExists() ) + { + m_ruleConditions.clear(); + m_rules.clear(); + + FILE* fp = wxFopen( aPath.GetFullPath(), wxT( "rt" ) ); + + if( fp ) + { + try + { + DRC_RULES_PARSER parser( m_board, fp, aPath.GetFullPath() ); + parser.Parse( m_rules, nullptr ); + } + catch( PARSE_ERROR& pe ) + { + // Don't leave possibly malformed stuff around for us to trip over + m_ruleConditions.clear(); + m_rules.clear(); + + //wxSafeYield( m_editFrame ); + //m_editFrame->ShowBoardSetupDialog( _( "Rules" ), pe.What(), ID_RULES_EDITOR, + // pe.lineNumber, pe.byteIndex ); + + throw; + + return false; + } + } + } + + return true; + } +}; + + int main( int argc, char *argv[] ) { PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); @@ -200,7 +245,7 @@ int main( int argc, char *argv[] ) - test::DRC_ENGINE drcEngine( project.board.get(), &project.board->GetDesignSettings() ); + TEST_DRC_ENGINE drcEngine( project.board.get(), &project.board->GetDesignSettings() ); CONSOLE_LOG consoleLog; diff --git a/qa/drc_proto/drc_rule_parser.cpp b/qa/drc_proto/drc_rule_parser.cpp deleted file mode 100644 index 5a5ec36764..0000000000 --- a/qa/drc_proto/drc_rule_parser.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#include -#include -#include - -#include -#include -#include -#include // drc_dbg -#include -#include - -using namespace DRCRULE_T; - -test::DRC_RULES_PARSER::DRC_RULES_PARSER( BOARD* aBoard, const wxString& aSource, - const wxString& aSourceDescr ) : - DRC_RULES_LEXER( aSource.ToStdString(), aSourceDescr ), - m_board( aBoard ), - m_requiredVersion( 0 ), - m_tooRecent( false ), - m_reporter( nullptr ) -{ -} - - -test::DRC_RULES_PARSER::DRC_RULES_PARSER( BOARD* aBoard, FILE* aFile, const wxString& aFilename ) : - DRC_RULES_LEXER( aFile, aFilename ), - m_board( aBoard ), - m_requiredVersion( 0 ), - m_tooRecent( false ), - m_reporter( nullptr ) -{ -} - - -void test::DRC_RULES_PARSER::reportError( const wxString& aMessage ) -{ - wxString rest; - wxString first = aMessage.BeforeFirst( '|', &rest ); - wxString msg = wxString::Format( _( "ERROR: %s%s" ), - CurLineNumber(), - CurOffset(), - first, - rest ); - - m_reporter->Report( msg, RPT_SEVERITY_ERROR ); -} - - -void test::DRC_RULES_PARSER::parseUnknown() -{ - int depth = 1; - - for( T token = NextTok(); token != T_EOF; token = NextTok() ) - { - if( token == T_LEFT ) - depth++; - - if( token == T_RIGHT ) - { - if( --depth == 0 ) - break; - } - } -} - - -void test::DRC_RULES_PARSER::Parse( std::vector& aRules, REPORTER* aReporter ) -{ - bool haveVersion = false; - wxString msg; - - m_reporter = aReporter; - - for( T token = NextTok(); token != T_EOF; token = NextTok() ) - { - if( token != T_LEFT ) - reportError( _( "Missing '('." ) ); - - token = NextTok(); - - if( !haveVersion && token != T_version ) - { - reportError( _( "Missing version statement." ) ); - haveVersion = true; // don't keep on reporting it - } - - switch( token ) - { - case T_version: - haveVersion = true; - token = NextTok(); - - if( (int) token == DSN_RIGHT ) - { - reportError( _( "Missing version number." ) ); - break; - } - - if( (int) token == DSN_NUMBER ) - { - m_requiredVersion = (int)strtol( CurText(), NULL, 10 ); - m_tooRecent = ( m_requiredVersion > DRC_RULE_FILE_VERSION ); - token = NextTok(); - } - else - { - msg.Printf( _( "Unrecognized item '%s'.| Expected version number" ), FromUTF8() ); - reportError( msg ); - } - - if( (int) token != DSN_RIGHT ) - { - msg.Printf( _( "Unrecognized item '%s'." ), FromUTF8() ); - reportError( msg ); - parseUnknown(); - } - - break; - - case T_rule: - aRules.push_back( parseDRC_RULE() ); - break; - - default: - msg.Printf( _( "Unrecognized item '%s'.| Expected %s." ), - FromUTF8(), "'rule', 'version'" ); - reportError( msg ); - parseUnknown(); - } - } - - if( !m_reporter->HasMessage() ) - m_reporter->Report( _( "No errors found." ), RPT_SEVERITY_INFO ); - - m_reporter = nullptr; -} - - -test::DRC_RULE* test::DRC_RULES_PARSER::parseDRC_RULE() -{ - DRC_RULE* rule = new DRC_RULE(); - T token = NextTok(); - wxString msg; - - if( !IsSymbol( token ) ) - reportError( _( "Missing rule name." ) ); - - rule->SetName( FromUTF8() ); - - for( token = NextTok(); token != T_RIGHT; token = NextTok() ) - { - if( token != T_LEFT ) - reportError( _( "Missing '('." ) ); - - token = NextTok(); - - switch( token ) - { - case T_constraint: - parseConstraint( rule ); - break; - - case T_condition: - token = NextTok(); - - if( (int) token == DSN_RIGHT ) - { - reportError( _( "Missing condition expression." ) ); - break; - } - - if( IsSymbol( token ) ) - { - auto condition = new DRC_RULE_CONDITION; - - condition->SetExpression( FromUTF8() ); - rule->SetCondition( condition ); - } - else - { - msg.Printf( _( "Unrecognized item '%s'.| Expected quoted expression." ), - FromUTF8() ); - reportError( msg ); - } - - if( (int) NextTok() != DSN_RIGHT ) - { - reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) ); - parseUnknown(); - } - - break; - - case T_layer: - rule->SetLayerCondition( parseLayer() ); - break; - - default: - msg.Printf( _( "Unrecognized item '%s'.| Expected %s." ), - FromUTF8(), - "'constraint', 'condition', 'disallow'" ); - reportError( msg ); - parseUnknown(); - } - } - - return rule; -} - - -void test::DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule ) -{ - DRC_CONSTRAINT constraint; - - int value; - wxString msg; - - T token = NextTok(); - - if( (int) token == DSN_RIGHT ) - { - msg.Printf( _( "Missing constraint type.| Expected %s." ), - "'clearance', 'track_width', 'annulus_width', 'hole', 'disallow'" ); - reportError( msg ); - return; - } - - switch( token ) - { - case T_clearance: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_CLEARANCE; break; - case T_hole_clearance: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE; break; - case T_edge_clearance: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE; break; - case T_hole: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_HOLE_SIZE; break; - case T_courtyard_clearance: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE; break; - case T_silk_to_pad: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_SILK_TO_PAD; break; - case T_silk_to_silk: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_SILK_TO_SILK; break; - case T_track_width: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_TRACK_WIDTH; break; - case T_annulus_width: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH; break; - case T_disallow: constraint.m_Type = test::DRC_CONSTRAINT_TYPE_DISALLOW; break; - default: - msg.Printf( _( "Unrecognized item '%s'.| Expected %s." ), - FromUTF8(), - "'clearance', 'track_width', 'annulus_width', 'hole', 'disallow'." - ); - reportError( msg ); - } - - if( constraint.m_Type == DRC_CONSTRAINT_TYPE_DISALLOW ) - { - for( token = NextTok(); token != T_RIGHT; token = NextTok() ) - { - if( (int) token == DSN_STRING ) - token = GetCurStrAsToken(); - - switch( token ) - { - case T_track: constraint.m_DisallowFlags |= DISALLOW_TRACKS; break; - case T_via: constraint.m_DisallowFlags |= DISALLOW_VIAS; break; - case T_micro_via: constraint.m_DisallowFlags |= DISALLOW_MICRO_VIAS; break; - case T_buried_via: constraint.m_DisallowFlags |= DISALLOW_BB_VIAS; break; - case T_pad: constraint.m_DisallowFlags |= DISALLOW_PADS; break; - case T_zone: constraint.m_DisallowFlags |= DISALLOW_ZONES; break; - case T_text: constraint.m_DisallowFlags |= DISALLOW_TEXTS; break; - case T_graphic: constraint.m_DisallowFlags |= DISALLOW_GRAPHICS; break; - case T_hole: constraint.m_DisallowFlags |= DISALLOW_HOLES; break; - case T_footprint: constraint.m_DisallowFlags |= DISALLOW_FOOTPRINTS; break; - default: - msg.Printf( _( "Unrecognized item '%s'.| Expected %s." ), - FromUTF8(), - "'track', 'via', 'micro_via', " - "'blind_via', 'pad', 'zone', 'text', 'graphic', 'hole'." - ); - reportError( msg ); - parseUnknown(); - } - } - - return; - } - - for( token = NextTok(); token != T_RIGHT; token = NextTok() ) - { - if( token != T_LEFT ) - reportError( _( "Missing '('." ) ); - - token = NextTok(); - - switch( token ) - { - case T_min: - token = NextTok(); - - if( (int) token == DSN_RIGHT ) - { - reportError( _( "Missing min value." ) ); - break; - } - - parseValueWithUnits( FromUTF8(), value ); - constraint.Value().SetMin( value ); - - if( (int) NextTok() != DSN_RIGHT ) - { - reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) ); - parseUnknown(); - } - - break; - - case T_max: - token = NextTok(); - - if( (int) token == DSN_RIGHT ) - { - reportError( _( "Missing max value." ) ); - break; - } - - parseValueWithUnits( FromUTF8(), value ); - constraint.Value().SetMax( value ); - - if( (int) NextTok() != DSN_RIGHT ) - { - reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) ); - parseUnknown(); - } - - break; - - case T_opt: - token = NextTok(); - - if( (int) token == DSN_RIGHT ) - { - reportError( _( "Missing opt value." ) ); - break; - } - - parseValueWithUnits( FromUTF8(), value ); - constraint.Value().SetOpt( value ); - - if( (int) NextTok() != DSN_RIGHT ) - { - reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) ); - parseUnknown(); - } - - break; - - /* fixme: bring these back? - - case T_enable: - rule->m_Enabled = parseInt("enabled"); - NeedRIGHT(); - break; - - case T_severity: - token = NextTok(); - switch( token ) - { - case T_error: - case T_warning: - case T_ignore: break; // fixme - default: - Expecting( "error, warning or ignore" ); - break; - } - NeedRIGHT(); - - - break; - */ - default: - msg.Printf( _( "Unrecognized item '%s'.| Expected %s." ), - FromUTF8(), "'min', 'max', 'opt'" ); - reportError( msg ); - parseUnknown(); - } - } - - aRule->AddConstraint( constraint ); -} - - - -void test::DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult ) -{ - PCB_EXPR_EVALUATOR evaluator; - - evaluator.Evaluate( aExpr ); - - if( evaluator.IsErrorPending() ) - { - auto err = evaluator.GetError(); - wxString str; - str.Printf( "Error: %s (line %d, offset %d)", err.message, CurLineNumber(), err.srcPos + CurOffset() ); - - m_reporter->Report( str, RPT_SEVERITY_ERROR ); - return; - } - - aResult = evaluator.Result(); -}; - - -LSET test::DRC_RULES_PARSER::parseLayer() -{ - LSET retVal; - int token = NextTok(); - - if( (int) token == DSN_RIGHT ) - { - reportError( _( "Missing layer name or type." ) ); - return LSET::AllCuMask(); - } - else if( token == T_outer ) - { - retVal = LSET::ExternalCuMask(); - } - else if( token == T_inner ) - { - retVal = LSET::InternalCuMask(); - } - else - { - wxString layerName = FromUTF8(); - PCB_LAYER_ID layer = ENUM_MAP::Instance().ToEnum( layerName ); - - if( layer == UNDEFINED_LAYER ) - reportError( wxString::Format( _( "Unrecognized layer '%s' " ), layerName ) ); - - retVal.set( layer ); - } - - if( (int) NextTok() != DSN_RIGHT ) - { - reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) ); - parseUnknown(); - } - - return retVal; -} diff --git a/qa/drc_proto/drc_rule_parser.h b/qa/drc_proto/drc_rule_parser.h deleted file mode 100644 index b5b9e6f825..0000000000 --- a/qa/drc_proto/drc_rule_parser.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef DRC_RULE_PARSER_H -#define DRC_RULE_PARSER_H - -#include -#include -#include -#include -#include - - -class BOARD_ITEM; - -namespace test { - -class DRC_RULE_CONDITION; -class DRC_RULE; - - -#define DRC_RULE_FILE_VERSION 20200610 - -class DRC_RULES_PARSER : public DRC_RULES_LEXER -{ -public: - DRC_RULES_PARSER( BOARD* aBoard, const wxString& aSource, const wxString& aSourceDescr ); - DRC_RULES_PARSER( BOARD* aBoard, FILE* aFile, const wxString& aFilename ); - - void Parse( std::vector& aRules, REPORTER* aReporter ); - -private: - DRC_RULE* parseDRC_RULE(); - - void parseConstraint( DRC_RULE* aRule ); - void parseValueWithUnits( const wxString& aExpr, int& aResult ); - LSET parseLayer(); - void parseUnknown(); - - void reportError( const wxString& aMessage ); - -private: - BOARD* m_board; - int m_requiredVersion; - bool m_tooRecent; - REPORTER* m_reporter; -}; - -}; - -#endif // DRC_RULE_PARSER_H diff --git a/qa/drc_proto/drc_test_provider_annulus.cpp b/qa/drc_proto/drc_test_provider_annulus.cpp index 66ae98a326..2186d3a188 100644 --- a/qa/drc_proto/drc_test_provider_annulus.cpp +++ b/qa/drc_proto/drc_test_provider_annulus.cpp @@ -27,10 +27,11 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* @@ -69,7 +70,7 @@ public: return "Tests pad/via annular rings"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; }; }; // namespace test @@ -77,8 +78,7 @@ public: bool test::DRC_TEST_PROVIDER_ANNULUS::Run() { - if( !m_drcEngine->HasCorrectRulesForId( - test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH ) ) + if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH ) ) { ReportAux( "No annulus constraints found. Skipping check." ); return false; @@ -96,8 +96,7 @@ bool test::DRC_TEST_PROVIDER_ANNULUS::Run() if( !via ) return true; - test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( - test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, via ); + DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, via ); accountCheck( constraint ); @@ -121,7 +120,7 @@ bool test::DRC_TEST_PROVIDER_ANNULUS::Run() wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s; actual annulus %s, constraint %s %s)" ), - constraint.GetParentRule()->GetName(), + constraint.GetParentRule()->m_Name, MessageTextFromValue( userUnits(), annulus, true ), fail_min ? _( "minimum" ) : _( "maximum" ), MessageTextFromValue( userUnits(), fail_min ? v_min : v_max, true ) ); @@ -148,8 +147,7 @@ bool test::DRC_TEST_PROVIDER_ANNULUS::Run() } -std::set -test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH }; } @@ -157,5 +155,5 @@ test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const namespace detail { -static test::DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_clearance_base.cpp b/qa/drc_proto/drc_test_provider_clearance_base.cpp index aa21e35487..a43a14deac 100644 --- a/qa/drc_proto/drc_test_provider_clearance_base.cpp +++ b/qa/drc_proto/drc_test_provider_clearance_base.cpp @@ -29,15 +29,15 @@ #include #include - #include #include #include -#include +#include #include -#include -#include +#include +#include +#include const int UI_EPSILON = Mils2iu( 5 ); diff --git a/qa/drc_proto/drc_test_provider_clearance_base.h b/qa/drc_proto/drc_test_provider_clearance_base.h index 359c642a79..3cf2371ba9 100644 --- a/qa/drc_proto/drc_test_provider_clearance_base.h +++ b/qa/drc_proto/drc_test_provider_clearance_base.h @@ -29,7 +29,7 @@ #include -#include +#include namespace test { @@ -37,10 +37,10 @@ class DRC_TEST_PROVIDER_CLEARANCE_BASE : public DRC_TEST_PROVIDER { public: DRC_TEST_PROVIDER_CLEARANCE_BASE () : - DRC_TEST_PROVIDER(), - m_board( nullptr ), - m_largestClearance( 0 ), - m_boardOutlineValid( false ) + DRC_TEST_PROVIDER(), + m_board( nullptr ), + m_largestClearance( 0 ), + m_boardOutlineValid( false ) { } diff --git a/qa/drc_proto/drc_test_provider_connectivity.cpp b/qa/drc_proto/drc_test_provider_connectivity.cpp index 7f8a83246d..76885178a7 100644 --- a/qa/drc_proto/drc_test_provider_connectivity.cpp +++ b/qa/drc_proto/drc_test_provider_connectivity.cpp @@ -27,10 +27,11 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* @@ -67,7 +68,7 @@ public: return "Tests board connectivity"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; }; }; // namespace test @@ -164,8 +165,7 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run() } -std::set -test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const { return {}; } @@ -173,5 +173,5 @@ test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const namespace detail { -static test::DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/drc_test_provider_copper_clearance.cpp b/qa/drc_proto/drc_test_provider_copper_clearance.cpp index b89a06303f..05de193279 100644 --- a/qa/drc_proto/drc_test_provider_copper_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_copper_clearance.cpp @@ -26,18 +26,17 @@ #include #include -#include #include - #include #include #include #include -#include -#include +#include +#include +#include #include -#include +#include #include /* @@ -77,7 +76,7 @@ public: return "Tests copper item clearance"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: void testPadClearances(); @@ -99,7 +98,8 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run() m_board = m_drcEngine->GetBoard(); DRC_CONSTRAINT worstClearanceConstraint; - if( m_drcEngine->QueryWorstConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) + if( m_drcEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, + worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) { m_largestClearance = worstClearanceConstraint.GetValue().Min(); } @@ -199,7 +199,8 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a if( !track->IsOnLayer( aItem->GetLayer() ) ) continue; - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, aItem, track, aItem->GetLayer() ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, + aItem, track, aItem->GetLayer() ); auto minClearance = constraint.GetValue().Min(); int actual = INT_MAX; wxPoint pos; @@ -224,7 +225,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - constraint.GetParentRule()->GetName(), + constraint.GetParentRule()->m_Name, MessageTextFromValue( userUnits(), minClearance, true ), MessageTextFromValue( userUnits(), actual, true ) ); @@ -246,7 +247,8 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a if( drawItem && pad->GetParent() == drawItem->GetParent() ) continue; - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, aItem, pad ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, + aItem, pad ); auto minClearance = constraint.GetValue().Min(); accountCheck( constraint ); @@ -270,7 +272,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - constraint.GetParentRule()->GetName(), + constraint.GetParentRule()->m_Name, MessageTextFromValue( userUnits(), minClearance, true ), MessageTextFromValue( userUnits(), actual, true ) ); @@ -358,7 +360,8 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK // fixme: hole to hole clearance moved elsewhere - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, aRefSeg, pad ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, + aRefSeg, pad ); auto minClearance = constraint.GetValue().Min(); int clearanceAllowed = minClearance - bds.GetDRCEpsilon(); int actual; @@ -432,7 +435,8 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK if( !trackBB.Intersects( refSegBB ) ) continue; - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, aRefSeg, track ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, + aRefSeg, track ); auto minClearance = constraint.GetValue().Min(); accountCheck( constraint ); @@ -500,7 +504,8 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK // fixme: per-layer onLayer() property - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, aRefSeg, zone ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, + aRefSeg, zone ); auto minClearance = constraint.GetValue().Min(); int widths = refSegWidth / 2; @@ -521,7 +526,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - constraint.GetParentRule()->GetName(), + constraint.GetParentRule()->m_Name, MessageTextFromValue( userUnits(), minClearance, true ), MessageTextFromValue( userUnits(), actual, true ) ); @@ -637,7 +642,8 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D continue; } - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, aRefPad, pad ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, + aRefPad, pad ); auto minClearance = constraint.GetValue().Min(); accountCheck( constraint ); @@ -721,8 +727,9 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones() // Examine a candidate zone: compare zoneToTest to zoneRef // Get clearance used in zone to zone test. - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, zoneRef, zoneToTest ); - auto zone2zoneClearance = constraint.GetValue().Min(); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE, + zoneRef, zoneToTest ); + int zone2zoneClearance = constraint.GetValue().Min(); accountCheck( constraint ); @@ -840,7 +847,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones() } -std::set test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_CLEARANCE }; } @@ -848,5 +855,5 @@ std::set test::DRC_TEST_PROVIDER_COPPER_CLEARANCE:: namespace detail { - static test::DRC_REGISTER_TEST_PROVIDER dummy; + static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_courtyard_clearance.cpp b/qa/drc_proto/drc_test_provider_courtyard_clearance.cpp index fb2fa481a7..8733053066 100644 --- a/qa/drc_proto/drc_test_provider_courtyard_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_courtyard_clearance.cpp @@ -28,15 +28,15 @@ #include #include - #include #include #include #include -#include -#include -#include +#include +#include +#include +#include #include /* @@ -76,7 +76,7 @@ public: return "Tests components' courtyard clearance"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: @@ -217,7 +217,7 @@ bool test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::Run() } -std::set test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE }; } @@ -225,5 +225,5 @@ std::set test::DRC_TEST_PROVIDER_COURTYARD_CLEARANC namespace detail { - static test::DRC_REGISTER_TEST_PROVIDER dummy; + static DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/drc_test_provider_disallow.cpp b/qa/drc_proto/drc_test_provider_disallow.cpp index 34cfbe444c..2d06edcee3 100644 --- a/qa/drc_proto/drc_test_provider_disallow.cpp +++ b/qa/drc_proto/drc_test_provider_disallow.cpp @@ -26,10 +26,11 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* "Disallow" test. Goes through all items, matching types/conditions drop errors. @@ -63,7 +64,7 @@ public: return "Tests for disallowed items (e.g. keepouts)"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: }; @@ -73,7 +74,7 @@ private: bool test::DRC_TEST_PROVIDER_DISALLOW::Run() { - if( !m_drcEngine->HasCorrectRulesForId( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW ) ) + if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW ) ) { ReportAux( "No disallow constraints found. Skipping check." ); return false; @@ -83,29 +84,23 @@ bool test::DRC_TEST_PROVIDER_DISALLOW::Run() auto checkItem = [&] ( BOARD_ITEM *item ) -> bool { - test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( - test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW, item ); + DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW, + item ); - if( constraint.Allowed() ) - return true; + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); + wxString msg; - if( ( constraint.GetAllowedLayers() & item->GetLayerSet() ).any() ) - { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); - wxString msg; + msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), constraint.GetParentRule()->m_Name ); - msg.Printf( - drcItem->GetErrorText() + _( " (%s)" ), constraint.GetParentRule()->GetName() ); + drcItem->SetErrorMessage( msg ); + drcItem->SetItems( item ); + drcItem->SetViolatingRule( constraint.GetParentRule() ); - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( item ); - drcItem->SetViolatingRule( constraint.GetParentRule() ); + ReportWithMarker( drcItem, item->GetPosition() ); - ReportWithMarker( drcItem, item->GetPosition() ); + if( isErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) ) + return false; - if( isErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) ) - return false; - } return true; }; @@ -117,8 +112,7 @@ bool test::DRC_TEST_PROVIDER_DISALLOW::Run() } -std::set -test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW }; } @@ -126,5 +120,5 @@ test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const namespace detail { -static test::DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_edge_clearance.cpp b/qa/drc_proto/drc_test_provider_edge_clearance.cpp index 6a4abea116..d00dd36e2d 100644 --- a/qa/drc_proto/drc_test_provider_edge_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_edge_clearance.cpp @@ -22,21 +22,17 @@ */ #include -#include #include -#include - -#include #include #include -#include #include #include -#include -#include -#include +#include +#include +#include +#include #include /* @@ -75,7 +71,7 @@ public: return "Tests items vs board edge clearance"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: }; @@ -88,7 +84,9 @@ bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() m_board = m_drcEngine->GetBoard(); DRC_CONSTRAINT worstClearanceConstraint; - if( m_drcEngine->QueryWorstConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) + + if( m_drcEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, + worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) { m_largestClearance = worstClearanceConstraint.GetValue().Min(); } @@ -132,12 +130,15 @@ bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() for( auto boardItem : boardItems ) { - drc_dbg(10, "RefT %d %p %s %d\n", outlineItem->Type(), outlineItem, outlineItem->GetClass(), outlineItem->GetLayer() ); - drc_dbg(10, "BoardT %d %p %s %d\n", boardItem->Type(), boardItem, boardItem->GetClass(), boardItem->GetLayer() ); + drc_dbg( 10, "RefT %d %p %s %d\n", outlineItem->Type(), outlineItem, + outlineItem->GetClass(), outlineItem->GetLayer() ); + drc_dbg( 10, "BoardT %d %p %s %d\n", boardItem->Type(), boardItem, + boardItem->GetClass(), boardItem->GetLayer() ); auto shape = boardItem->GetEffectiveShape(); - test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, outlineItem, boardItem ); + DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, + outlineItem, boardItem ); int minClearance = constraint.GetValue().Min(); int actual; @@ -149,7 +150,7 @@ bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - constraint.GetParentRule()->GetName(), + constraint.GetParentRule()->m_Name, MessageTextFromValue( userUnits(), minClearance, true ), MessageTextFromValue( userUnits(), actual, true ) ); @@ -177,7 +178,7 @@ bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() } -std::set test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE }; } @@ -185,5 +186,5 @@ std::set test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Ge namespace detail { - static test::DRC_REGISTER_TEST_PROVIDER dummy; + static DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/drc_test_provider_hole_clearance.cpp b/qa/drc_proto/drc_test_provider_hole_clearance.cpp index 4a210b5d60..08c5c6d8da 100644 --- a/qa/drc_proto/drc_test_provider_hole_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_hole_clearance.cpp @@ -26,17 +26,15 @@ #include #include -#include #include - #include -#include #include #include -#include -#include -#include +#include +#include +#include +#include #include /* @@ -75,7 +73,7 @@ public: return "Tests clearance of holes (via/pad drills)"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: void addHole( const VECTOR2I& aLocation, int aRadius, BOARD_ITEM* aOwner ); @@ -112,7 +110,8 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run() DRC_CONSTRAINT worstClearanceConstraint; - if( m_drcEngine->QueryWorstConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) + if( m_drcEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, + worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) { m_largestClearance = worstClearanceConstraint.GetValue().Min(); } @@ -271,11 +270,13 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, { // pad under testing has a hole, test this hole against pad reference - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, aRefPad, pad ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, + aRefPad, pad ); auto minClearance = constraint.GetValue().Min(); int actual; - drc_dbg(10,"check pad %p rule '%s' cl %d\n", pad, constraint.GetParentRule()->GetName(), minClearance ); + drc_dbg( 10, "check pad %p rule '%s' cl %d\n", + pad, constraint.GetParentRule()->m_Name, minClearance ); accountCheck( constraint.GetParentRule() ); @@ -304,13 +305,15 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, if( aRefPad->GetDrillSize().x ) // pad reference has a hole { - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, aRefPad, pad ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, + aRefPad, pad ); auto minClearance = constraint.GetValue().Min(); int actual; accountCheck( constraint.GetParentRule() ); - drc_dbg(10,"check pad %p rule '%s' cl %d\n", aRefPad, constraint.GetParentRule()->GetName(), minClearance ); + drc_dbg( 10,"check pad %p rule '%s' cl %d\n", aRefPad, + constraint.GetParentRule()->m_Name, minClearance ); auto padShape = pad->GetEffectiveShape(); if( padShape->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) ) @@ -389,7 +392,8 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::testHoles2Holes() int actual = ( checkHole.m_location - refHole.m_location ).EuclideanNorm(); actual = std::max( 0, actual - checkHole.m_drillRadius - refHole.m_drillRadius ); - DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, refHole.m_owner, checkHole.m_owner ); + DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE, + refHole.m_owner, checkHole.m_owner ); int minClearance = constraint.GetValue().Min(); accountCheck( constraint.GetParentRule() ); @@ -417,7 +421,7 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::testHoles2Holes() } -std::set test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE }; } @@ -425,5 +429,5 @@ std::set test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::Ge namespace detail { - static test::DRC_REGISTER_TEST_PROVIDER dummy; + static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_hole_size.cpp b/qa/drc_proto/drc_test_provider_hole_size.cpp index e08b250757..2caefa4f92 100644 --- a/qa/drc_proto/drc_test_provider_hole_size.cpp +++ b/qa/drc_proto/drc_test_provider_hole_size.cpp @@ -28,15 +28,15 @@ #include #include - #include #include #include #include -#include -#include -#include +#include +#include +#include +#include #include @@ -76,7 +76,7 @@ public: return "Tests sizes of drilled holes (via/pad drills)"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: bool checkVia( VIA* via ); @@ -135,7 +135,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( D_PAD* aPad ) if( holeSize == 0 ) return true; - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, aPad ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, aPad ); auto minHole = constraint.GetValue().Min(); accountCheck( constraint ); @@ -164,7 +164,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( D_PAD* aPad ) bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( VIA* via ) { - auto constraint = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, via ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, via ); auto minHole = constraint.GetValue().Min(); accountCheck( constraint ); @@ -194,7 +194,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( VIA* via ) } -std::set test::DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE }; } @@ -202,5 +202,5 @@ std::set test::DRC_TEST_PROVIDER_HOLE_SIZE::GetMatc namespace detail { -static test::DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_lvs.cpp b/qa/drc_proto/drc_test_provider_lvs.cpp index 8397a95df2..a0ec864981 100644 --- a/qa/drc_proto/drc_test_provider_lvs.cpp +++ b/qa/drc_proto/drc_test_provider_lvs.cpp @@ -25,10 +25,11 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -73,7 +74,7 @@ public: return "Performs layout-vs-schematics integity check"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: @@ -202,7 +203,7 @@ bool test::DRC_TEST_PROVIDER_LVS::Run() } -std::set test::DRC_TEST_PROVIDER_LVS::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_LVS::GetMatchingConstraintIds() const { return {}; } @@ -210,5 +211,5 @@ std::set test::DRC_TEST_PROVIDER_LVS::GetMatchingCo namespace detail { -static test::DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_misc.cpp b/qa/drc_proto/drc_test_provider_misc.cpp index 6788d9cae1..73768f663c 100644 --- a/qa/drc_proto/drc_test_provider_misc.cpp +++ b/qa/drc_proto/drc_test_provider_misc.cpp @@ -28,10 +28,11 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -74,7 +75,7 @@ public: return "Misc checks (board outline, missing textvars)"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: void testOutline(); @@ -206,7 +207,7 @@ bool test::DRC_TEST_PROVIDER_MISC::Run() } -std::set test::DRC_TEST_PROVIDER_MISC::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_MISC::GetMatchingConstraintIds() const { return {}; } @@ -214,5 +215,5 @@ std::set test::DRC_TEST_PROVIDER_MISC::GetMatchingC namespace detail { -static test::DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_silk_to_pad.cpp b/qa/drc_proto/drc_test_provider_silk_to_pad.cpp index 9bb5f069c4..92eb412de4 100644 --- a/qa/drc_proto/drc_test_provider_silk_to_pad.cpp +++ b/qa/drc_proto/drc_test_provider_silk_to_pad.cpp @@ -28,15 +28,15 @@ #include #include - #include #include #include #include -#include -#include -#include +#include +#include +#include +#include #include /* @@ -73,7 +73,7 @@ public: return "Tests for silkscreen covering components pads"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; private: }; @@ -88,7 +88,8 @@ bool test::DRC_TEST_PROVIDER_SILK_TO_PAD::Run() DRC_CONSTRAINT worstClearanceConstraint; m_largestClearance = 0; - if( m_drcEngine->QueryWorstConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_SILK_TO_PAD, worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) + if( m_drcEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_SILK_TO_PAD, + worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) { m_largestClearance = worstClearanceConstraint.m_Value.Min(); } @@ -96,21 +97,20 @@ bool test::DRC_TEST_PROVIDER_SILK_TO_PAD::Run() ReportAux( "Worst clearance : %d nm", m_largestClearance ); ReportStage( ("Testing pads vs silkscreen clearance"), 0, 2 ); - std::vector boardOutline; std::vector boardItems; - auto queryBoardOutlineItems = [&] ( BOARD_ITEM *item ) -> int - { - boardOutline.push_back( dyn_cast( item ) ); - }; + auto queryBoardOutlineItems = + [&]( BOARD_ITEM *item ) -> int + { + boardOutline.push_back( dyn_cast( item ) ); + }; - auto queryBoardGeometryItems = [&] ( BOARD_ITEM *item ) -> int - { - boardItems.push_back( item ); - }; - - + auto queryBoardGeometryItems = + [&]( BOARD_ITEM *item ) -> int + { + boardItems.push_back( item ); + }; forEachGeometryItem( { PCB_LINE_T }, LSET( Edge_Cuts ), queryBoardOutlineItems ); forEachGeometryItem( {}, LSET::AllTechMask() | LSET::AllCuMask(), queryBoardGeometryItems ); @@ -156,7 +156,7 @@ bool test::DRC_TEST_PROVIDER_SILK_TO_PAD::Run() } -std::set test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE }; } @@ -164,5 +164,5 @@ std::set test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Ge namespace detail { - static test::DRC_REGISTER_TEST_PROVIDER dummy; + static DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/drc_test_provider_track_width.cpp b/qa/drc_proto/drc_test_provider_track_width.cpp index fe9c4de0be..8049aa4aa4 100644 --- a/qa/drc_proto/drc_test_provider_track_width.cpp +++ b/qa/drc_proto/drc_test_provider_track_width.cpp @@ -25,10 +25,11 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* @@ -63,7 +64,7 @@ public: return "Tests track widths"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; }; }; // namespace test @@ -71,8 +72,7 @@ public: bool test::DRC_TEST_PROVIDER_TRACK_WIDTH::Run() { - if( !m_drcEngine->HasCorrectRulesForId( - test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH ) ) + if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH ) ) { ReportAux( "No track width constraints found. Skipping check." ); return false; @@ -95,8 +95,8 @@ bool test::DRC_TEST_PROVIDER_TRACK_WIDTH::Run() p0 = ( trk->GetStart() + trk->GetEnd() ) / 2; } - test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( - test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH, item ); + DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH, + item ); bool fail_min = false, fail_max = false; int constraintWidth; @@ -119,7 +119,7 @@ bool test::DRC_TEST_PROVIDER_TRACK_WIDTH::Run() wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s; width %s, constraint %s %s)" ), - constraint.GetParentRule()->GetName(), + constraint.GetParentRule()->m_Name, MessageTextFromValue( userUnits(), width, true ), fail_min ? _( "minimum" ) : _( "maximum" ), MessageTextFromValue( userUnits(), constraintWidth, true ) ); @@ -146,8 +146,7 @@ bool test::DRC_TEST_PROVIDER_TRACK_WIDTH::Run() } -std::set -test::DRC_TEST_PROVIDER_TRACK_WIDTH::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_TRACK_WIDTH::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH }; } @@ -155,5 +154,5 @@ test::DRC_TEST_PROVIDER_TRACK_WIDTH::GetMatchingConstraintIds() const namespace detail { -static test::DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/drc_test_provider_via_diameter.cpp b/qa/drc_proto/drc_test_provider_via_diameter.cpp index d3a1376bb4..edd2384334 100644 --- a/qa/drc_proto/drc_test_provider_via_diameter.cpp +++ b/qa/drc_proto/drc_test_provider_via_diameter.cpp @@ -25,10 +25,11 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* @@ -65,7 +66,7 @@ public: return "Tests via diameters"; } - virtual std::set GetMatchingConstraintIds() const override; + virtual std::set GetMatchingConstraintIds() const override; }; }; // namespace test @@ -73,8 +74,7 @@ public: bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run() { - if( !m_drcEngine->HasCorrectRulesForId( - test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ) ) + if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ) ) { ReportAux( "No diameter constraints found. Skipping check." ); return false; @@ -89,8 +89,7 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run() if( !via ) return true; - test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( - test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER, item ); + DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER, item ); bool fail_min = false, fail_max = false; int constraintDiameter; @@ -114,7 +113,7 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run() wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s; diameter %s, constraint %s %s)" ), - constraint.GetParentRule()->GetName(), + constraint.GetParentRule()->m_Name, MessageTextFromValue( userUnits(), diameter, true ), fail_min ? _( "minimum" ) : _( "maximum" ), MessageTextFromValue( userUnits(), constraintDiameter, true ) ); @@ -141,8 +140,7 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run() } -std::set -test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const +std::set test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER }; } @@ -150,5 +148,5 @@ test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const namespace detail { -static test::DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/drc_textvar_tester.h b/qa/drc_proto/drc_textvar_tester.h index 678d5b878f..820043e827 100644 --- a/qa/drc_proto/drc_textvar_tester.h +++ b/qa/drc_proto/drc_textvar_tester.h @@ -25,7 +25,7 @@ #ifndef DRC_TEXTVAR_TESTER__H #define DRC_TEXTVAR_TESTER__H -#include +#include class BOARD; diff --git a/qa/drc_proto/footprint_tester.cpp b/qa/drc_proto/footprint_tester.cpp deleted file mode 100644 index cbbf1377bf..0000000000 --- a/qa/drc_proto/footprint_tester.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include - -void TestFootprints( NETLIST& aNetlist, BOARD* aBoard, std::vector >& aDRCList ) -{ - wxString msg; - - auto comp = []( const MODULE* x, const MODULE* y ) - { - return x->GetReference().CmpNoCase( y->GetReference() ) < 0; - }; - auto mods = std::set( comp ); - - if( !aBoard->GetDesignSettings().Ignore( DRCE_DUPLICATE_FOOTPRINT ) ) - { - // Search for duplicate footprints on the board - for( MODULE* mod : aBoard->Modules() ) - { - auto ins = mods.insert( mod ); - - if( !ins.second ) - { - DRC_ITEM* item = new DRC_ITEM( DRCE_DUPLICATE_FOOTPRINT ); - item->SetItems( mod, *ins.first ); - aDRCList.push_back( item ); - } - } - } - - if( !aBoard->GetDesignSettings().Ignore( DRCE_MISSING_FOOTPRINT ) ) - { - // Search for component footprints in the netlist but not on the board. - for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ ) - { - COMPONENT* component = aNetlist.GetComponent( ii ); - MODULE* module = aBoard->FindModuleByReference( component->GetReference() ); - - if( module == NULL ) - { - msg.Printf( _( "Missing footprint %s (%s)" ), - component->GetReference(), - component->GetValue() ); - - DRC_ITEM* item = new DRC_ITEM( DRCE_MISSING_FOOTPRINT ); - item->SetErrorMessage( msg ); - aDRCList.push_back( item ); - } - } - } - - if( !aBoard->GetDesignSettings().Ignore( DRCE_EXTRA_FOOTPRINT ) ) - { - // Search for component footprints found on board but not in netlist. - for( auto module : mods ) - { - COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() ); - - if( component == NULL ) - { - DRC_ITEM* item = new DRC_ITEM( DRCE_EXTRA_FOOTPRINT ); - item->SetItems( module ); - aDRCList.push_back( item ); - } - } - } -} diff --git a/qa/drc_proto/footprint_tester.h b/qa/drc_proto/footprint_tester.h deleted file mode 100644 index bff20988a2..0000000000 --- a/qa/drc_proto/footprint_tester.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef FOOTPRINT_TESTER_H -#define FOOTPRINT_TESTER_H - -#include - -class BOARD; - - -void TestFootprints( NETLIST& aNetlist, BOARD* aBoard, std::vector& aDRCList ); - -#endif // FOOTPRINT_TESTER_H diff --git a/qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp b/qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp index 1ec499f537..a24a741b53 100644 --- a/qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp +++ b/qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp @@ -78,7 +78,7 @@ public: markers.push_back( std::unique_ptr( aMarker ) ); }; - std::unique_ptr drc_prov = createDrcProvider( aBoard, marker_handler ); + std::unique_ptr drc_prov = createDrcProvider( aBoard, marker_handler ); DRC_DURATION duration; { @@ -106,8 +106,8 @@ private: */ virtual void setDesignSettings( BOARD_DESIGN_SETTINGS& aSettings ) const = 0; - virtual std::unique_ptr createDrcProvider( - BOARD& aBoard, DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) = 0; + virtual std::unique_ptr createDrcProvider( + BOARD& aBoard, LEGACY_DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) = 0; void reportDuration( const DRC_DURATION& aDuration ) const { @@ -164,8 +164,8 @@ private: aSettings.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_ERROR; } - std::unique_ptr createDrcProvider( - BOARD& aBoard, DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) override + std::unique_ptr createDrcProvider( + BOARD& aBoard, LEGACY_DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) override { return std::make_unique( aHandler ); } @@ -198,8 +198,8 @@ private: aSettings.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_IGNORE; } - std::unique_ptr createDrcProvider( - BOARD& aBoard, DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) override + std::unique_ptr createDrcProvider( + BOARD& aBoard, LEGACY_DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) override { return std::make_unique( aHandler ); }