diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 8f9c64e936..734991f1cd 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -240,10 +240,17 @@ set( PCBNEW_DRC_SRCS drc/drc_engine.cpp drc/drc_rule_parser.cpp drc/drc_test_provider.cpp + drc/drc_test_provider_annulus.cpp drc/drc_test_provider_clearance_base.cpp + drc/drc_test_provider_disallow.cpp + drc/drc_test_provider_connectivity.cpp drc/drc_test_provider_copper_clearance.cpp drc/drc_test_provider_edge_clearance.cpp drc/drc_test_provider_hole_clearance.cpp + drc/drc_test_provider_hole_size.cpp + drc/drc_test_provider_misc.cpp + drc/drc_test_provider_track_width.cpp + drc/drc_test_provider_via_diameter.cpp ) set( PCBNEW_NETLIST_SRCS diff --git a/pcbnew/drc/drc_test_provider.cpp b/pcbnew/drc/drc_test_provider.cpp index 2201375b95..bd12d103cc 100644 --- a/pcbnew/drc/drc_test_provider.cpp +++ b/pcbnew/drc/drc_test_provider.cpp @@ -3,20 +3,8 @@ #include DRC_TEST_PROVIDER::DRC_TEST_PROVIDER() : - m_drcEngine( nullptr ), - m_enable( false ) + m_drcEngine( nullptr ) { - -} - -void DRC_TEST_PROVIDER::Enable( bool enable ) -{ - m_enable = enable; -} - -bool DRC_TEST_PROVIDER::IsEnabled() const -{ - return m_enable; } const wxString DRC_TEST_PROVIDER::GetName() const { return ""; } @@ -54,7 +42,7 @@ void DRC_TEST_PROVIDER::ReportStage ( const wxString& aStageName, int index, int ReportAux( aStageName ); } -void DRC_TEST_PROVIDER::ReportAux( const wxString& fmt, ... ) +void DRC_TEST_PROVIDER::ReportAux( wxString fmt, ... ) { va_list vargs; va_start( vargs, fmt ); diff --git a/pcbnew/drc/drc_test_provider.h b/pcbnew/drc/drc_test_provider.h index 6f72064222..c806c3c942 100644 --- a/pcbnew/drc/drc_test_provider.h +++ b/pcbnew/drc/drc_test_provider.h @@ -89,13 +89,10 @@ public: virtual bool Run() = 0; - virtual void Enable( bool enable ); - virtual bool IsEnabled() const; - virtual const wxString GetName() const; virtual const wxString GetDescription() const; - virtual void ReportAux( const wxString& fmt, ... ); + virtual void ReportAux( 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 ); @@ -119,11 +116,12 @@ protected: virtual void accountCheck( const DRC_CONSTRAINT& constraintToTest ); virtual bool isErrorLimitExceeded( int error_code ); - EDA_UNITS userUnits() const; - DRC_ENGINE *m_drcEngine; + EDA_UNITS userUnits() const; + DRC_ENGINE* m_drcEngine; std::unordered_map m_stats; - bool m_enable; - bool m_isRuleDriven = true; + bool m_isRuleDriven = true; + + wxString m_msg; // Allocating strings gets expensive enough to want to avoid it }; #endif // DRC_TEST_PROVIDER__H diff --git a/qa/drc_proto/drc_test_provider_annulus.cpp b/pcbnew/drc/drc_test_provider_annulus.cpp similarity index 50% rename from qa/drc_proto/drc_test_provider_annulus.cpp rename to pcbnew/drc/drc_test_provider_annulus.cpp index 2186d3a188..c1ac215ae6 100644 --- a/qa/drc_proto/drc_test_provider_annulus.cpp +++ b/pcbnew/drc/drc_test_provider_annulus.cpp @@ -21,19 +21,14 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include -#include - #include - +#include #include #include #include #include #include - /* Via/pad annular ring width test. Checks if there's sufficient copper ring around PTH/NPTH holes (vias/pads) Errors generated: @@ -44,9 +39,6 @@ - pad stack support (different IAR/OAR values depending on layer) */ -namespace test -{ - class DRC_TEST_PROVIDER_ANNULUS : public DRC_TEST_PROVIDER { public: @@ -73,71 +65,72 @@ public: virtual std::set GetMatchingConstraintIds() const override; }; -}; // namespace test - -bool test::DRC_TEST_PROVIDER_ANNULUS::Run() +bool DRC_TEST_PROVIDER_ANNULUS::Run() { - if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH ) ) + if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH ) ) { ReportAux( "No annulus constraints found. Skipping check." ); return false; } - ReportStage( ( "Testing via annular rings" ), 0, 2 ); + ReportStage( _( "Testing via annular rings" ), 0, 2 ); - auto checkAnnulus = [&]( BOARD_ITEM* item ) -> bool - { - bool fail_min = false, fail_max = false; - int v_min, v_max; - auto via = dyn_cast( item ); + auto checkAnnulus = + [&]( BOARD_ITEM* item ) -> bool + { + int v_min; + int v_max; + VIA* via = dyn_cast( item ); - // fixme: check minimum IAR/OAR ring for THT pads too - if( !via ) - return true; + // fixme: check minimum IAR/OAR ring for THT pads too + if( !via ) + return true; - DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, via ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, + via ); + int annulus = ( via->GetWidth() - via->GetDrillValue() ) / 2; + bool fail_min = false; + bool fail_max = false; - accountCheck( constraint ); + accountCheck( constraint ); - int annulus = ( via->GetWidth() - via->GetDrillValue() ) / 2; + if( constraint.Value().HasMin() ) + { + v_min = constraint.Value().Min(); + fail_min = annulus < v_min; + } - if( constraint.Value().HasMin() ) - { - v_min = constraint.Value().Min(); - fail_min = annulus < v_min; - } + if( constraint.Value().HasMax() ) + { + v_max = constraint.Value().Max(); + fail_max = annulus > v_max; + } - if( constraint.Value().HasMax() ) - { - v_max = constraint.Value().Max(); - fail_max = annulus > v_max; - } + if( fail_min || fail_max ) + { + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ANNULUS ); + wxString msg; - if( fail_min || fail_max ) - { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ANNULUS ); - wxString msg; + m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s annulus %s; actual %s)" ), + constraint.GetName(), + fail_min ? _( "minimum" ) : _( "maximum" ), + MessageTextFromValue( userUnits(), annulus, true ), + MessageTextFromValue( userUnits(), fail_min ? v_min : v_max, true ) ); - msg.Printf( drcItem->GetErrorText() + _( " (%s; actual annulus %s, constraint %s %s)" ), - constraint.GetParentRule()->m_Name, - MessageTextFromValue( userUnits(), annulus, true ), - fail_min ? _( "minimum" ) : _( "maximum" ), - MessageTextFromValue( userUnits(), fail_min ? v_min : v_max, true ) ); + drcItem->SetErrorMessage( msg ); + drcItem->SetItems( item ); + drcItem->SetViolatingRule( constraint.GetParentRule() ); - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( item ); - drcItem->SetViolatingRule( constraint.GetParentRule() ); + ReportWithMarker( drcItem, via->GetPosition() ); - ReportWithMarker( drcItem, via->GetPosition() ); + if( isErrorLimitExceeded( DRCE_ANNULUS ) ) + return false; - if( isErrorLimitExceeded( DRCE_ANNULUS ) ) - return false; + } - } - - return true; - }; + return true; + }; forEachGeometryItem( { PCB_VIA_T }, LSET::AllCuMask(), checkAnnulus ); @@ -147,7 +140,7 @@ bool test::DRC_TEST_PROVIDER_ANNULUS::Run() } -std::set test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const +std::set DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH }; } @@ -155,5 +148,5 @@ std::set test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingCons namespace detail { -static DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/pcbnew/drc/drc_test_provider_clearance_base.h b/pcbnew/drc/drc_test_provider_clearance_base.h index 00f1539732..047221db05 100644 --- a/pcbnew/drc/drc_test_provider_clearance_base.h +++ b/pcbnew/drc/drc_test_provider_clearance_base.h @@ -55,8 +55,6 @@ protected: BOARD* m_board; int m_largestClearance; bool m_boardOutlineValid; - - wxString m_msg; // Allocating strings gets expensive enough to want to avoid it }; diff --git a/qa/drc_proto/drc_test_provider_connectivity.cpp b/pcbnew/drc/drc_test_provider_connectivity.cpp similarity index 69% rename from qa/drc_proto/drc_test_provider_connectivity.cpp rename to pcbnew/drc/drc_test_provider_connectivity.cpp index 76885178a7..2e5c43a2b7 100644 --- a/qa/drc_proto/drc_test_provider_connectivity.cpp +++ b/pcbnew/drc/drc_test_provider_connectivity.cpp @@ -42,9 +42,6 @@ - DRCE_ZONE_HAS_EMPTY_NET */ -namespace test -{ - class DRC_TEST_PROVIDER_CONNECTIVITY : public DRC_TEST_PROVIDER { public: @@ -71,12 +68,10 @@ public: virtual std::set GetMatchingConstraintIds() const override; }; -}; // namespace test - -bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run() +bool DRC_TEST_PROVIDER_CONNECTIVITY::Run() { - ReportStage( ( "Testing dangling pads/vias" ), 0, 2 ); + ReportStage( _( "Testing dangling pads/vias" ), 0, 2 ); BOARD* board = m_drcEngine->GetBoard(); @@ -84,11 +79,11 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run() connectivity->Clear(); connectivity->Build( board ); // just in case. This really needs to be reliable. - - for( auto track : board->Tracks() ) + for( TRACK* track : board->Tracks() ) { bool exceedT = isErrorLimitExceeded( DRCE_DANGLING_TRACK ); bool exceedV = isErrorLimitExceeded( DRCE_DANGLING_VIA ); + // Test for dangling items int code = track->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK; wxPoint pos; @@ -101,10 +96,6 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run() if( connectivity->TestTrackEndpointDangling( track, &pos ) ) { std::shared_ptr drcItem = DRC_ITEM::Create( code ); - wxString msg; - - msg.Printf( drcItem->GetErrorText() ); - drcItem->SetErrorMessage( msg ); drcItem->SetItems( track ); ReportWithMarker( drcItem, pos ); } @@ -113,36 +104,32 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run() break; } - ReportStage( ( "Testing starved zones" ), 0, 2 ); + ReportStage( _( "Testing starved zones" ), 0, 2 ); /* test starved zones */ - for( auto zone : board->Zones() ) + for( ZONE_CONTAINER* zone : board->Zones() ) { if( !zone->IsOnCopperLayer() ) continue; - 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 ) ? connectivity->GetPadCount( netcode ) : 1; + 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 ) ? connectivity->GetPadCount( netcode ) : 1; - if( ( netcode < 0 ) || pads_in_net == 0 ) - { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ZONE_HAS_EMPTY_NET ); - wxString msg; + if( ( netcode < 0 ) || pads_in_net == 0 ) + { + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ZONE_HAS_EMPTY_NET ); + drcItem->SetItems( zone ); + ReportWithMarker( drcItem, zone->GetPosition() ); - msg.Printf( drcItem->GetErrorText() ); - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( zone ); - ReportWithMarker( drcItem, zone->GetPosition() ); - - if( isErrorLimitExceeded( DRCE_ZONE_HAS_EMPTY_NET ) ) - break; - } + if( isErrorLimitExceeded( DRCE_ZONE_HAS_EMPTY_NET ) ) + break; } + } - ReportStage( ( "Testing unconnected ratlines" ), 0, 2 ); + ReportStage( _( "Testing unconnected nets" ), 0, 2 ); connectivity->RecalculateRatsnest(); std::vector edges; @@ -151,7 +138,6 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run() for( const CN_EDGE& edge : edges ) { std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS ); - drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() ); ReportWithMarker( drcItem, edge.GetSourceNode()->Pos() ); @@ -165,7 +151,7 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run() } -std::set test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const +std::set DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const { return {}; } @@ -173,5 +159,5 @@ std::set test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchin namespace detail { -static DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp b/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp index f6e0fd54a6..0de1fd26ca 100644 --- a/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp @@ -21,18 +21,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include -//#include -//#include - -#include -//#include -//#include #include -//#include -//#include - #include #include #include @@ -85,6 +74,7 @@ private: void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions() { + // Detects missing (or malformed) footprint courtyards ReportStage( _( "Testing component courtyard definitions" ), 0, 2 ); for( MODULE* footprint : m_board->Modules() ) @@ -98,7 +88,6 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions() continue; std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_MISSING_COURTYARD ); - drcItem->SetItems( footprint ); ReportWithMarker( drcItem, footprint->GetPosition() ); } @@ -130,66 +119,66 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testOverlappingComponentCourtyards() ReportStage( _( "Testing component courtyard overlap" ), 0, 2 ); for( auto it1 = m_board->Modules().begin(); it1 != m_board->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 != m_board->Modules().end(); it2++ ) { - MODULE* footprint = *it1; - SHAPE_POLY_SET& footprintFront = footprint->GetPolyCourtyardFront(); - SHAPE_POLY_SET& footprintBack = footprint->GetPolyCourtyardBack(); + 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 && footprintBack.OutlineCount() == 0 ) - continue; // No courtyards defined - - for( auto it2 = it1 + 1; it2 != m_board->Modules().end(); it2++ ) + if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0 + && footprintFront.BBoxFromCaches().Intersects( testFront.BBoxFromCaches() ) ) { - MODULE* test = *it2; - SHAPE_POLY_SET& testFront = test->GetPolyCourtyardFront(); - SHAPE_POLY_SET& testBack = test->GetPolyCourtyardBack(); - SHAPE_POLY_SET intersection; - bool overlap = false; - wxPoint pos; + intersection.RemoveAllContours(); + intersection.Append( footprintFront ); - if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0 - && footprintFront.BBoxFromCaches().Intersects( testFront.BBoxFromCaches() ) ) + // 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 ) { - 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 ) - { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS ); - drcItem->SetItems( footprint, test ); - ReportWithMarker ( drcItem, pos ); - - if( isErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS ) ) - return; + 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 ) + { + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS ); + drcItem->SetItems( footprint, test ); + ReportWithMarker ( drcItem, pos ); + + if( isErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS ) ) + return; + } } + } } diff --git a/qa/drc_proto/drc_test_provider_disallow.cpp b/pcbnew/drc/drc_test_provider_disallow.cpp similarity index 66% rename from qa/drc_proto/drc_test_provider_disallow.cpp rename to pcbnew/drc/drc_test_provider_disallow.cpp index 2d06edcee3..7ee40fdcb6 100644 --- a/qa/drc_proto/drc_test_provider_disallow.cpp +++ b/pcbnew/drc/drc_test_provider_disallow.cpp @@ -21,10 +21,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include -#include +//#include #include #include @@ -38,9 +38,6 @@ - DRCE_ALLOWED_ITEMS */ -namespace test -{ - class DRC_TEST_PROVIDER_DISALLOW : public DRC_TEST_PROVIDER { public: @@ -65,14 +62,10 @@ public: } virtual std::set GetMatchingConstraintIds() const override; - -private: }; -}; // namespace test - -bool test::DRC_TEST_PROVIDER_DISALLOW::Run() +bool DRC_TEST_PROVIDER_DISALLOW::Run() { if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW ) ) { @@ -80,26 +73,28 @@ bool test::DRC_TEST_PROVIDER_DISALLOW::Run() return false; } - ReportStage( ("Testing for disallow constraints"), 0, 2 ); + ReportStage( _( "Testing disallow constraints" ), 0, 2 ); - auto checkItem = [&] ( BOARD_ITEM *item ) -> bool + auto checkItem = [&]( BOARD_ITEM *item ) -> bool { - DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW, - item ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_DISALLOW, item ); - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); - wxString msg; + if( constraint.m_DisallowFlags ) + { + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); - msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), constraint.GetParentRule()->m_Name ); + m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), + constraint.GetName() ); - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( item ); - drcItem->SetViolatingRule( constraint.GetParentRule() ); + drcItem->SetErrorMessage( m_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; }; @@ -112,7 +107,7 @@ bool test::DRC_TEST_PROVIDER_DISALLOW::Run() } -std::set test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const +std::set DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW }; } @@ -120,5 +115,5 @@ std::set test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingCon namespace detail { -static DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/pcbnew/drc/drc_test_provider_hole_clearance.cpp b/pcbnew/drc/drc_test_provider_hole_clearance.cpp index 9680814a49..109d66037b 100644 --- a/pcbnew/drc/drc_test_provider_hole_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_hole_clearance.cpp @@ -39,8 +39,6 @@ TODO: vias-in-smd-pads check */ -namespace test { - class DRC_TEST_PROVIDER_HOLE_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE { public: @@ -80,7 +78,7 @@ private: struct DRILLED_HOLE { - VECTOR2I m_location; + VECTOR2I m_location; int m_drillRadius = 0; BOARD_ITEM* m_owner = nullptr; }; @@ -91,10 +89,8 @@ private: }; -}; - -bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run() +bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run() { m_board = m_drcEngine->GetBoard(); @@ -130,11 +126,8 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run() } -void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::buildDrilledHoleList() +void DRC_TEST_PROVIDER_HOLE_CLEARANCE::buildDrilledHoleList() { - bool success = true; - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - m_drilledHoles.clear(); for( MODULE* module : m_board->Modules() ) @@ -155,7 +148,7 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::buildDrilledHoleList() for( TRACK* track : m_board->Tracks() ) { - if ( track->Type() == PCB_VIA_T ) + if( track->Type() == PCB_VIA_T ) { VIA* via = static_cast( track ); addHole( via->GetPosition(), via->GetDrillValue() / 2, via ); @@ -163,10 +156,9 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::buildDrilledHoleList() } ReportAux( "Total drilled holes : %d", m_drilledHoles.size() ); - } -void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::testPads2Holes() +void DRC_TEST_PROVIDER_HOLE_CLEARANCE::testPads2Holes() { std::vector sortedPads; @@ -206,7 +198,7 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::testPads2Holes() } -bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD** aStart, +bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit ) { const static LSET all_cu = LSET::AllCuMask(); @@ -329,7 +321,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, } -void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::addHole( const VECTOR2I& aLocation, int aRadius, +void DRC_TEST_PROVIDER_HOLE_CLEARANCE::addHole( const VECTOR2I& aLocation, int aRadius, BOARD_ITEM* aOwner ) { DRILLED_HOLE hole; @@ -344,7 +336,7 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::addHole( const VECTOR2I& aLocation, } -void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::testHoles2Holes() +void DRC_TEST_PROVIDER_HOLE_CLEARANCE::testHoles2Holes() { // 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 @@ -407,7 +399,7 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::testHoles2Holes() } -std::set test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetMatchingConstraintIds() const +std::set DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE }; } @@ -415,5 +407,5 @@ std::set test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetMatch namespace detail { - static DRC_REGISTER_TEST_PROVIDER dummy; + static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_hole_size.cpp b/pcbnew/drc/drc_test_provider_hole_size.cpp similarity index 67% rename from qa/drc_proto/drc_test_provider_hole_size.cpp rename to pcbnew/drc/drc_test_provider_hole_size.cpp index b19ec68a79..621d762225 100644 --- a/qa/drc_proto/drc_test_provider_hole_size.cpp +++ b/pcbnew/drc/drc_test_provider_hole_size.cpp @@ -21,23 +21,12 @@ * 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 /* @@ -49,9 +38,6 @@ TODO: max drill size check */ -namespace test -{ - class DRC_TEST_PROVIDER_HOLE_SIZE : public DRC_TEST_PROVIDER { public: @@ -85,38 +71,34 @@ private: BOARD* m_board; }; -}; // namespace test - -bool test::DRC_TEST_PROVIDER_HOLE_SIZE::Run() +bool DRC_TEST_PROVIDER_HOLE_SIZE::Run() { - ReportStage( ( "Testing pad holes" ), 0, 2 ); + ReportStage( _( "Testing pad holes" ), 0, 2 ); m_board = m_drcEngine->GetBoard(); - for( auto module : m_board->Modules() ) + for( MODULE* module : m_board->Modules() ) { - for( auto pad : module->Pads() ) + for( D_PAD* pad : module->Pads() ) { if( checkPad( pad ) ) break; } } - ReportStage( ( "Testing via/microvia holes" ), 0, 2 ); + ReportStage( _( "Testing via/microvia holes" ), 0, 2 ); std::vector vias; - for( auto track : m_board->Tracks() ) + for( TRACK* track : m_board->Tracks() ) { if( track->Type() == PCB_VIA_T ) - { vias.push_back( static_cast( track ) ); - } } - for( auto via : vias ) + for( VIA* via : vias ) { if( checkVia( via ) ) break; @@ -128,30 +110,30 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::Run() } -bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( D_PAD* aPad ) +bool DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( D_PAD* aPad ) { int holeSize = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y ); if( holeSize == 0 ) return true; - auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, aPad ); - auto minHole = constraint.GetValue().Min(); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_HOLE_SIZE, aPad ); + int minHole = constraint.GetValue().Min(); accountCheck( constraint ); if( holeSize < minHole ) { - wxString msg; std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL ); - msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ), - MessageTextFromValue( userUnits(), minHole, true ), - MessageTextFromValue( userUnits(), holeSize, true ) ); + m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ), + constraint.GetName(), + MessageTextFromValue( userUnits(), minHole, true ), + MessageTextFromValue( userUnits(), holeSize, true ) ); - drcItem->SetViolatingRule( constraint.GetParentRule() ); - drcItem->SetErrorMessage( msg ); + drcItem->SetErrorMessage( m_msg ); drcItem->SetItems( aPad ); + drcItem->SetViolatingRule( constraint.GetParentRule() ); ReportWithMarker( drcItem, aPad->GetPosition() ); @@ -162,28 +144,28 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( D_PAD* aPad ) } -bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( VIA* via ) +bool DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( VIA* via ) { - auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, via ); - auto minHole = constraint.GetValue().Min(); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_HOLE_SIZE, via ); + int minHole = constraint.GetValue().Min(); accountCheck( constraint ); if( via->GetDrillValue() < minHole ) { - wxString msg; int errorCode = via->GetViaType() == VIATYPE::MICROVIA ? DRCE_TOO_SMALL_MICROVIA_DRILL : DRCE_TOO_SMALL_DRILL; std::shared_ptr drcItem = DRC_ITEM::Create( errorCode ); - msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ), - MessageTextFromValue( userUnits(), minHole, true ), - MessageTextFromValue( userUnits(), via->GetDrillValue(), true ) ); + m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ), + constraint.GetName(), + MessageTextFromValue( userUnits(), minHole, true ), + MessageTextFromValue( userUnits(), via->GetDrillValue(), true ) ); - drcItem->SetViolatingRule( constraint.GetParentRule() ); - drcItem->SetErrorMessage( msg ); + drcItem->SetErrorMessage( m_msg ); drcItem->SetItems( via ); + drcItem->SetViolatingRule( constraint.GetParentRule() ); ReportWithMarker( drcItem, via->GetPosition() ); @@ -194,7 +176,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( VIA* via ) } -std::set test::DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingConstraintIds() const +std::set DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE }; } @@ -202,5 +184,5 @@ std::set test::DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingCo namespace detail { -static DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_lvs.cpp b/pcbnew/drc/drc_test_provider_lvs.cpp similarity index 57% rename from qa/drc_proto/drc_test_provider_lvs.cpp rename to pcbnew/drc/drc_test_provider_lvs.cpp index a0ec864981..03101eb4c4 100644 --- a/qa/drc_proto/drc_test_provider_lvs.cpp +++ b/pcbnew/drc/drc_test_provider_lvs.cpp @@ -22,10 +22,7 @@ */ #include -#include -#include - -#include +#include #include #include #include @@ -47,9 +44,6 @@ - cross-check PCB fields against SCH fields */ -namespace test -{ - class DRC_TEST_PROVIDER_LVS : public DRC_TEST_PROVIDER { public: @@ -82,20 +76,19 @@ private: void testFootprints( NETLIST& aNetlist ); }; -}; // namespace test - -void test::DRC_TEST_PROVIDER_LVS::testFootprints( NETLIST& aNetlist ) +void DRC_TEST_PROVIDER_LVS::testFootprints( NETLIST& aNetlist ) { - wxString msg; - BOARD* board = m_drcEngine->GetBoard(); + BOARD* board = m_drcEngine->GetBoard(); - auto comp = []( const MODULE* x, const MODULE* y ) { - return x->GetReference().CmpNoCase( y->GetReference() ) < 0; - }; + auto comp = []( const MODULE* x, const MODULE* y ) + { + return x->GetReference().CmpNoCase( y->GetReference() ) < 0; + }; auto mods = std::set( comp ); + // Search for duplicate footprints on the board for( MODULE* mod : board->Modules() ) { auto ins = mods.insert( mod ); @@ -120,21 +113,82 @@ void test::DRC_TEST_PROVIDER_LVS::testFootprints( NETLIST& aNetlist ) if( module == nullptr ) { - msg.Printf( _( "Missing footprint %s (%s)" ), component->GetReference(), + m_msg.Printf( _( "Missing footprint %s (%s)" ), component->GetReference(), component->GetValue() ); std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_MISSING_FOOTPRINT ); - drcItem->SetErrorMessage( msg ); + drcItem->SetErrorMessage( m_msg ); Report( drcItem ); if( isErrorLimitExceeded( DRCE_MISSING_FOOTPRINT ) ) break; } + else + { + for( D_PAD* pad : module->Pads() ) + { + const COMPONENT_NET& sch_net = component->GetNet( pad->GetName() ); + const wxString& pcb_netname = pad->GetNetname(); + + if( !pcb_netname.IsEmpty() && sch_net.GetPinName().IsEmpty() ) + { + m_msg.Printf( _( "No corresponding pin found in schematic." ) ); + + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT ); + drcItem->SetErrorMessage( m_msg ); + drcItem->SetItems( pad ); + ReportWithMarker( drcItem, module->GetPosition() ); + } + else if( pcb_netname.IsEmpty() && !sch_net.GetNetName().IsEmpty() ) + { + m_msg.Printf( _( "Pad missing net given by schematic (%s)." ), + sch_net.GetNetName() ); + + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT ); + drcItem->SetErrorMessage( m_msg ); + drcItem->SetItems( pad ); + ReportWithMarker( drcItem, module->GetPosition() ); + } + else if( pcb_netname != sch_net.GetNetName() ) + { + m_msg.Printf( _( "Pad net (%s) doesn't match net given by schematic (%s)." ), + pcb_netname, + sch_net.GetNetName() ); + + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT ); + drcItem->SetErrorMessage( m_msg ); + drcItem->SetItems( pad ); + ReportWithMarker( drcItem, module->GetPosition() ); + } + + if( isErrorLimitExceeded( DRCE_NET_CONFLICT ) ) + break; + } + + for( unsigned jj = 0; jj < component->GetNetCount(); ++jj ) + { + const COMPONENT_NET& sch_net = component->GetNet( jj ); + + if( !module->FindPadByName( sch_net.GetPinName() ) ) + { + m_msg.Printf( _( "No pad found for pin %s in schematic." ), + sch_net.GetPinName() ); + + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT ); + drcItem->SetErrorMessage( m_msg ); + drcItem->SetItems( module ); + ReportWithMarker( drcItem, module->GetPosition() ); + } + + if( isErrorLimitExceeded( DRCE_NET_CONFLICT ) ) + break; + } + } } - - for( auto module : mods ) + // Search for component footprints found on board but not in netlist. + for( MODULE* module : board->Modules() ) { COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() ); @@ -152,7 +206,7 @@ void test::DRC_TEST_PROVIDER_LVS::testFootprints( NETLIST& aNetlist ) } -bool test::DRC_TEST_PROVIDER_LVS::fetchNetlistFromSchematic( NETLIST& aNetlist ) +bool DRC_TEST_PROVIDER_LVS::fetchNetlistFromSchematic( NETLIST& aNetlist ) { // fixme: make it work without dependency on EDIT_FRAME/kiway #if 0 @@ -177,7 +231,7 @@ bool test::DRC_TEST_PROVIDER_LVS::fetchNetlistFromSchematic( NETLIST& aNetlist ) return false; } -bool test::DRC_TEST_PROVIDER_LVS::Run() +bool DRC_TEST_PROVIDER_LVS::Run() { ReportStage( _( "Layout-vs-Schematic checks..." ), 0, 2 ); @@ -203,7 +257,7 @@ bool test::DRC_TEST_PROVIDER_LVS::Run() } -std::set test::DRC_TEST_PROVIDER_LVS::GetMatchingConstraintIds() const +std::set DRC_TEST_PROVIDER_LVS::GetMatchingConstraintIds() const { return {}; } @@ -211,5 +265,5 @@ std::set test::DRC_TEST_PROVIDER_LVS::GetMatchingConstrai namespace detail { -static DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/qa/drc_proto/drc_test_provider_misc.cpp b/pcbnew/drc/drc_test_provider_misc.cpp similarity index 57% rename from qa/drc_proto/drc_test_provider_misc.cpp rename to pcbnew/drc/drc_test_provider_misc.cpp index 73768f663c..e418779254 100644 --- a/qa/drc_proto/drc_test_provider_misc.cpp +++ b/pcbnew/drc/drc_test_provider_misc.cpp @@ -21,18 +21,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include -#include - -#include #include - -#include +#include #include #include #include -#include +#include #include #include @@ -48,9 +42,6 @@ - if grows too big, split into separate providers */ -namespace test -{ - class DRC_TEST_PROVIDER_MISC : public DRC_TEST_PROVIDER { public: @@ -85,10 +76,8 @@ private: BOARD* m_board; }; -}; // namespace test - -void test::DRC_TEST_PROVIDER_MISC::testOutline() +void DRC_TEST_PROVIDER_MISC::testOutline() { wxPoint error_loc( m_board->GetBoardEdgesBoundingBox().GetPosition() ); @@ -98,80 +87,86 @@ void test::DRC_TEST_PROVIDER_MISC::testOutline() return; std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE ); - wxString msg; - msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) ); + m_msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) ); - drcItem->SetErrorMessage( msg ); + drcItem->SetErrorMessage( m_msg ); drcItem->SetItems( m_board ); ReportWithMarker( drcItem, error_loc ); } -void test::DRC_TEST_PROVIDER_MISC::testDisabledLayers() +void DRC_TEST_PROVIDER_MISC::testDisabledLayers() { LSET disabledLayers = m_board->GetEnabledLayers().flip(); - // Perform the test only for copper layers disabledLayers &= LSET::AllCuMask(); - auto checkDisabledLayers = [&]( BOARD_ITEM* item ) -> bool { - LSET refLayers ( item->GetLayer() ); + auto checkDisabledLayers = + [&]( BOARD_ITEM* item ) -> bool + { + LSET refLayers ( item->GetLayer() ); - if( ( disabledLayers & refLayers ).any() ) - { - wxString msg; - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_DISABLED_LAYER_ITEM ); + if( ( disabledLayers & refLayers ).any() ) + { + std::shared_ptrdrcItem = DRC_ITEM::Create( DRCE_DISABLED_LAYER_ITEM ); - msg.Printf( drcItem->GetErrorText() + _( " (layer %s)" ), item->GetLayerName() ); + m_msg.Printf( drcItem->GetErrorText() + _( " (layer %s)" ), + item->GetLayerName() ); - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( item ); + drcItem->SetErrorMessage( m_msg ); + drcItem->SetItems( item ); - ReportWithMarker( drcItem, item->GetPosition() ); - } - return true; - }; + ReportWithMarker( drcItem, item->GetPosition() ); + } + return true; + }; // fixme: what about graphical items? forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_PAD_T }, - LSET::AllLayersMask(), checkDisabledLayers ); + LSET::AllLayersMask(), checkDisabledLayers ); } -void test::DRC_TEST_PROVIDER_MISC::testTextVars() +void DRC_TEST_PROVIDER_MISC::testTextVars() { - auto checkUnresolvedTextVar = [&]( EDA_ITEM* item ) -> bool { - EDA_TEXT* text = dynamic_cast( item ); + auto checkUnresolvedTextVar = + [&]( EDA_ITEM* item ) -> bool + { + EDA_TEXT* text = dynamic_cast( item ); - assert( text ); + wxASSERT( text ); + if( text->GetShownText().Matches( wxT( "*${*}*" ) ) ) + { + if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) ) + return false; - if( text->GetShownText().Matches( wxT( "*${*}*" ) ) ) - { - if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) ) - return false; + std::shared_ptrdrcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE ); + drcItem->SetItems( item ); - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE ); - drcItem->SetItems( item ); + ReportWithMarker( drcItem, item->GetPosition() ); + } + return true; + }; - ReportWithMarker( drcItem, item->GetPosition() ); - } - return true; - }; + forEachGeometryItem( { PCB_MODULE_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(), + checkUnresolvedTextVar ); - forEachGeometryItem( - { PCB_MODULE_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(), checkUnresolvedTextVar ); - - WS_DRAW_ITEM_LIST wsItems; - - auto worksheet = m_drcEngine->GetWorksheet(); + KIGFX::WS_PROXY_VIEW_ITEM* worksheet = m_drcEngine->GetWorksheet(); + WS_DRAW_ITEM_LIST wsItems; if( !worksheet ) return; wsItems.SetMilsToIUfactor( IU_PER_MILS ); + wsItems.SetSheetNumber( 1 ); + wsItems.SetSheetCount( 1 ); + wsItems.SetFileName( "dummyFilename" ); + wsItems.SetSheetName( "dummySheet" ); + wsItems.SetSheetLayer( "dummyLayer" ); + wsItems.SetProject( m_board->GetProject() ); wsItems.BuildWorkSheetGraphicList( worksheet->GetPageInfo(), worksheet->GetTitleBlock() ); for( WS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() ) @@ -181,16 +176,19 @@ void test::DRC_TEST_PROVIDER_MISC::testTextVars() if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) ) return; - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE ); - drcItem->SetItems( text ); + if( text->GetShownText().Matches( wxT( "*${*}*" ) ) ) + { + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE ); + drcItem->SetItems( text ); - ReportWithMarker( drcItem, text->GetPosition() ); + ReportWithMarker( drcItem, text->GetPosition() ); + } } } } -bool test::DRC_TEST_PROVIDER_MISC::Run() +bool DRC_TEST_PROVIDER_MISC::Run() { m_board = m_drcEngine->GetBoard(); @@ -207,7 +205,7 @@ bool test::DRC_TEST_PROVIDER_MISC::Run() } -std::set test::DRC_TEST_PROVIDER_MISC::GetMatchingConstraintIds() const +std::set DRC_TEST_PROVIDER_MISC::GetMatchingConstraintIds() const { return {}; } @@ -215,5 +213,5 @@ std::set test::DRC_TEST_PROVIDER_MISC::GetMatchingConstra namespace detail { -static DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } diff --git a/pcbnew/drc/drc_test_provider_track_width.cpp b/pcbnew/drc/drc_test_provider_track_width.cpp new file mode 100644 index 0000000000..e2a16a89d3 --- /dev/null +++ b/pcbnew/drc/drc_test_provider_track_width.cpp @@ -0,0 +1,152 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2020 KiCad Developers. + * + * 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 + + +/* + Track width test. As the name says, checks width of the tracks (including segments and arcs) + Errors generated: + - DRCE_TRACK_WIDTH +*/ + +class DRC_TEST_PROVIDER_TRACK_WIDTH : public DRC_TEST_PROVIDER +{ +public: + DRC_TEST_PROVIDER_TRACK_WIDTH() + { + } + + virtual ~DRC_TEST_PROVIDER_TRACK_WIDTH() + { + } + + virtual bool Run() override; + + virtual const wxString GetName() const override + { + return "width"; + }; + + virtual const wxString GetDescription() const override + { + return "Tests track widths"; + } + + virtual std::set GetMatchingConstraintIds() const override; +}; + + +bool DRC_TEST_PROVIDER_TRACK_WIDTH::Run() +{ + if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH ) ) + { + ReportAux( "No track width constraints found. Skipping check." ); + return false; + } + + ReportStage( _( "Testing track widths" ), 0, 2 ); + + auto checkTrackWidth = + [&]( BOARD_ITEM* item ) -> bool + { + int actual; + VECTOR2I p0; + + if( ARC* arc = dyn_cast( item ) ) + { + actual = arc->GetWidth(); + p0 = arc->GetStart(); + } + else if( TRACK* trk = dyn_cast( item ) ) + { + actual = trk->GetWidth(); + p0 = ( trk->GetStart() + trk->GetEnd() ) / 2; + } + + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_TRACK_WIDTH, + item ); + bool fail_min = false; + bool fail_max = false; + int constraintWidth; + + if( constraint.Value().HasMin() && actual < constraint.Value().Min() ) + { + fail_min = true; + constraintWidth = constraint.Value().Min(); + } + + if( constraint.Value().HasMax() && actual > constraint.Value().Max() ) + { + fail_max = true; + constraintWidth = constraint.Value().Max(); + } + + if( fail_min || fail_max ) + { + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_TRACK_WIDTH ); + + m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s width %s; actual %s)" ), + constraint.GetName(), + fail_min ? _( "minimum" ) : _( "maximum" ), + MessageTextFromValue( userUnits(), constraintWidth, true ) ); + MessageTextFromValue( userUnits(), actual, true ), + + drcItem->SetErrorMessage( m_msg ); + drcItem->SetItems( item ); + drcItem->SetViolatingRule( constraint.GetParentRule() ); + + ReportWithMarker( drcItem, p0 ); + + if( isErrorLimitExceeded( DRCE_TRACK_WIDTH ) ) + return false; + + } + + return true; + }; + + forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T }, LSET::AllCuMask(), checkTrackWidth ); + + reportRuleStatistics(); + + return true; +} + + +std::set DRC_TEST_PROVIDER_TRACK_WIDTH::GetMatchingConstraintIds() const +{ + return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH }; +} + + +namespace detail +{ +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/pcbnew/drc/drc_test_provider_via_diameter.cpp similarity index 50% rename from qa/drc_proto/drc_test_provider_via_diameter.cpp rename to pcbnew/drc/drc_test_provider_via_diameter.cpp index edd2384334..2297686461 100644 --- a/qa/drc_proto/drc_test_provider_via_diameter.cpp +++ b/pcbnew/drc/drc_test_provider_via_diameter.cpp @@ -21,10 +21,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include -#include - #include #include #include @@ -40,9 +38,6 @@ - DRCE_TOO_SMALL_MICROVIA */ -namespace test -{ - class DRC_TEST_PROVIDER_VIA_DIAMETER : public DRC_TEST_PROVIDER { public: @@ -69,12 +64,10 @@ public: virtual std::set GetMatchingConstraintIds() const override; }; -}; // namespace test - -bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run() +bool DRC_TEST_PROVIDER_VIA_DIAMETER::Run() { - if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ) ) + if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_VIA_DIAMETER ) ) { ReportAux( "No diameter constraints found. Skipping check." ); return false; @@ -82,55 +75,57 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run() ReportStage( ( "Testing via diameters" ), 0, 2 ); - auto checkViaDiameter = [&]( BOARD_ITEM* item ) -> bool { - auto via = dyn_cast( item ); + auto checkViaDiameter = + [&]( BOARD_ITEM* item ) -> bool + { + auto via = dyn_cast( item ); - // fixme: move to pad stack check? - if( !via ) - return true; + // fixme: move to pad stack check? + if( !via ) + return true; - DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER, item ); + auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_VIA_DIAMETER, + item ); + bool fail_min = false; + bool fail_max = false; + int constraintDiameter; + int actual = via->GetWidth(); - bool fail_min = false, fail_max = false; - int constraintDiameter; - int diameter = via->GetWidth(); + if( constraint.Value().HasMin() && actual < constraint.Value().Min() ) + { + fail_min = true; + constraintDiameter = constraint.Value().Min(); + } - if( constraint.Value().HasMin() && diameter < constraint.Value().Min() ) - { - fail_min = true; - constraintDiameter = constraint.Value().Min(); - } + if( constraint.Value().HasMax() && actual > constraint.Value().Max() ) + { + fail_max = true; + constraintDiameter = constraint.Value().Max(); + } - if( constraint.Value().HasMax() && diameter > constraint.Value().Max() ) - { - fail_max = true; - constraintDiameter = constraint.Value().Max(); - } + if( fail_min || fail_max ) + { + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_VIA_DIAMETER ); - if( fail_min || fail_max ) - { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_VIA_DIAMETER ); - wxString msg; + m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s diameter %s; actual %s)" ), + constraint.GetName(), + fail_min ? _( "minimum" ) : _( "maximum" ), + MessageTextFromValue( userUnits(), constraintDiameter, true ) ); + MessageTextFromValue( userUnits(), actual, true ), - msg.Printf( drcItem->GetErrorText() + _( " (%s; diameter %s, constraint %s %s)" ), - constraint.GetParentRule()->m_Name, - MessageTextFromValue( userUnits(), diameter, true ), - fail_min ? _( "minimum" ) : _( "maximum" ), - MessageTextFromValue( userUnits(), constraintDiameter, true ) ); + drcItem->SetErrorMessage( m_msg ); + drcItem->SetItems( item ); + drcItem->SetViolatingRule( constraint.GetParentRule() ); - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( item ); - drcItem->SetViolatingRule( constraint.GetParentRule() ); + ReportWithMarker( drcItem, via->GetPosition() ); - ReportWithMarker( drcItem, via->GetPosition() ); + if( isErrorLimitExceeded( DRCE_VIA_DIAMETER ) ) + return false; - if( isErrorLimitExceeded( DRCE_VIA_DIAMETER ) ) - return false; + } - } - - return true; - }; + return true; + }; forEachGeometryItem( { PCB_VIA_T }, LSET::AllCuMask(), checkViaDiameter ); @@ -140,7 +135,7 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run() } -std::set test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const +std::set DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const { return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER }; } @@ -148,5 +143,5 @@ std::set test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchin namespace detail { -static DRC_REGISTER_TEST_PROVIDER dummy; +static DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/CMakeLists.txt b/qa/drc_proto/CMakeLists.txt index e19a294080..04cc7e2d07 100644 --- a/qa/drc_proto/CMakeLists.txt +++ b/qa/drc_proto/CMakeLists.txt @@ -34,7 +34,6 @@ endif() add_executable( drc_proto - drc_rules_proto_keywords.cpp drc_proto_test.cpp ../../pcbnew/drc/drc_rule.cpp ../../pcbnew/drc/drc_rule_parser.cpp @@ -43,15 +42,15 @@ add_executable( drc_proto ../../pcbnew/drc/drc_test_provider_copper_clearance.cpp ../../pcbnew/drc/drc_test_provider_hole_clearance.cpp ../../pcbnew/drc/drc_test_provider_edge_clearance.cpp - drc_test_provider_hole_size.cpp - drc_test_provider_disallow.cpp - drc_test_provider_track_width.cpp - drc_test_provider_annulus.cpp - drc_test_provider_connectivity.cpp + ../../pcbnew/drc/drc_test_provider_hole_size.cpp + ../../pcbnew/drc/drc_test_provider_disallow.cpp + ../../pcbnew/drc/drc_test_provider_track_width.cpp + ../../pcbnew/drc/drc_test_provider_annulus.cpp + ../../pcbnew/drc/drc_test_provider_connectivity.cpp ../../pcbnew/drc/drc_test_provider_courtyard_clearance.cpp - drc_test_provider_via_diameter.cpp - drc_test_provider_lvs.cpp - drc_test_provider_misc.cpp + ../../pcbnew/drc/drc_test_provider_via_diameter.cpp + ../../pcbnew/drc/drc_test_provider_lvs.cpp + ../../pcbnew/drc/drc_test_provider_misc.cpp ../../pcbnew/drc/drc_engine.cpp ../../pcbnew/drc/drc_item.cpp ../qa_utils/mocks.cpp @@ -114,12 +113,3 @@ target_link_libraries( drc_proto ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${wxWidgets_LIBRARIES} ) - -# auto-generate drc_rules_lexer.h and drc_rules_keywords.cpp -make_lexer( - drc_proto - drc_rules_proto.keywords - drc_rules_proto_lexer.h - drc_rules_proto_keywords.cpp - DRCRULEPROTO_T -) diff --git a/qa/drc_proto/drc_provider.h b/qa/drc_proto/drc_provider.h deleted file mode 100644 index c7887988aa..0000000000 --- a/qa/drc_proto/drc_provider.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * 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 - */ - -#ifndef DRC_PROVIDER__H -#define DRC_PROVIDER__H - -#include -#include - -#include - -namespace test { - -class DRC_ENGINE; - -/** - * 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. - */ -class DRC_TEST_PROVIDER -{ -public: - DRC_TEST_PROVIDER ( DRC_ENGINE *aDrc ); - virtual ~DRC_TEST_PROVIDER() {} - - /** - * Runs this provider against the given PCB with configured options (if any). - * - * Note: Board is non-const, as some DRC functions modify the board (e.g. zone fill - * or polygon coalescing) - */ - virtual bool Run() = 0; - - virtual void Enable( bool enable ); - virtual bool IsEnabled() const; - - virtual const wxString GetName() const; - virtual const wxString GetDescription() const; - - virtual std::set GetMatchingConstraintIds() const; - - /** - * Pass a given marker to the marker handler - */ - virtual void HandleMarker( MARKER_PCB* aMarker ) const; - -private: - - DRC_ENGINE *m_drcEngine; - -}; - - -#if 0 -/** - * BOARD_DRC_ITEMS_PROVIDER - * is an implementation of the RC_ITEMS_PROVIDER interface which uses a BOARD instance - * to fulfill the interface. - */ -class BOARD_DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER -{ -private: - BOARD* m_board; - - int m_severities; - std::vector m_filteredMarkers; - -public: - BOARD_DRC_ITEMS_PROVIDER( BOARD* aBoard ) : - m_board( aBoard ), - m_severities( 0 ) - { - } - - void SetSeverities( int aSeverities ) override - { - m_severities = aSeverities; - - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - - m_filteredMarkers.clear(); - - for( MARKER_PCB* marker : m_board->Markers() ) - { - int markerSeverity; - - if( marker->IsExcluded() ) - markerSeverity = RPT_SEVERITY_EXCLUSION; - else - markerSeverity = bds.GetSeverity( marker->GetRCItem()->GetErrorCode() ); - - if( markerSeverity & m_severities ) - m_filteredMarkers.push_back( marker ); - } - } - - int GetCount( int aSeverity = -1 ) override - { - if( aSeverity < 0 ) - return m_filteredMarkers.size(); - - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - - int count = 0; - - for( MARKER_PCB* marker : m_board->Markers() ) - { - int markerSeverity; - - if( marker->IsExcluded() ) - markerSeverity = RPT_SEVERITY_EXCLUSION; - else - markerSeverity = bds.GetSeverity( marker->GetRCItem()->GetErrorCode() ); - - if( markerSeverity == aSeverity ) - count++; - } - - return count; - } - - DRC_ITEM* GetItem( int aIndex ) override - { - MARKER_PCB* marker = m_filteredMarkers[ aIndex ]; - - return marker ? static_cast( marker->GetRCItem() ) : nullptr; - } - - void DeleteItem( int aIndex, bool aDeep ) override - { - MARKER_PCB* marker = m_filteredMarkers[ aIndex ]; - m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex ); - - if( aDeep ) - m_board->Delete( marker ); - } - - void DeleteAllItems() override - { - m_board->DeleteMARKERs(); - m_filteredMarkers.clear(); - } -}; - - -/** - * VECTOR_DRC_ITEMS_PROVIDER - * is an implementation of the interface named DRC_ITEMS_PROVIDER which uses a vector - * of pointers to DRC_ITEMs to fulfill the interface. No ownership is taken of the - * vector. - */ -class VECTOR_DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER -{ - PCB_BASE_FRAME* m_frame; - std::vector* m_sourceVector; // owns its DRC_ITEMs - - int m_severities; - std::vector m_filteredVector; // does not own its DRC_ITEMs - -public: - - VECTOR_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector* aList ) : - m_frame( aFrame ), - m_sourceVector( aList ), - m_severities( 0 ) - { - } - - void SetSeverities( int aSeverities ) override - { - m_severities = aSeverities; - - BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings(); - - m_filteredVector.clear(); - - if( m_sourceVector ) - { - for( DRC_ITEM* item : *m_sourceVector ) - { - if( bds.GetSeverity( item->GetErrorCode() ) & aSeverities ) - m_filteredVector.push_back( item ); - } - } - } - - int GetCount( int aSeverity = -1 ) override - { - if( aSeverity < 0 ) - return m_filteredVector.size(); - - int count = 0; - BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings(); - - if( m_sourceVector ) - { - for( DRC_ITEM* item : *m_sourceVector ) - { - if( bds.GetSeverity( item->GetErrorCode() ) == aSeverity ) - count++; - } - } - - return count; - } - - DRC_ITEM* GetItem( int aIndex ) override - { - return (m_filteredVector)[aIndex]; - } - - void DeleteItem( int aIndex, bool aDeep ) override - { - DRC_ITEM* item = m_filteredVector[aIndex]; - m_filteredVector.erase( m_filteredVector.begin() + aIndex ); - - if( aDeep ) - { - for( size_t i = 0; i < m_sourceVector->size(); ++i ) - { - if( m_sourceVector->at( i ) == item ) - { - delete item; - m_sourceVector->erase( m_sourceVector->begin() + i ); - break; - } - } - } - } - - void DeleteAllItems() override - { - if( m_sourceVector ) - { - for( DRC_ITEM* item : *m_sourceVector ) - delete item; - - m_sourceVector->clear(); - } - - m_filteredVector.clear(); // no ownership of DRC_ITEM pointers - } -}; - - -/** - * RATSNEST_DRC_ITEMS_PROVIDER - */ -class RATSNEST_DRC_ITEMS_PROVIDER : public VECTOR_DRC_ITEMS_PROVIDER -{ - // TODO: for now this is just a vector, but we need to map it to some board-level - // data-structure so that deleting/excluding things can do a deep delete/exclusion - // which will be reflected in the ratsnest.... -public: - RATSNEST_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector* aList ) : - VECTOR_DRC_ITEMS_PROVIDER( aFrame, aList ) - { } -}; - -#endif - -}; - -#endif // DRC_PROVIDER__H diff --git a/qa/drc_proto/drc_rtree.h b/qa/drc_proto/drc_rtree.h deleted file mode 100644 index 5e81ddbc32..0000000000 --- a/qa/drc_proto/drc_rtree.h +++ /dev/null @@ -1,358 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors. - * Copyright (C) 2020 CERN - * - * 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 3 - * 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-3.0.html - * or you may search the http://www.gnu.org website for the version 3 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef DRC_RTREE_H_ -#define DRC_RTREE_H_ - -#include -#include -#include -#include - -#include -#include - -/** - * DRC_RTREE - - * Implements an R-tree for fast spatial and layer indexing of connectable items. - * Non-owning. - */ -class DRC_RTREE -{ -private: - using drc_rtree = RTree; - -public: - DRC_RTREE() - { - for( int layer : LSET::AllLayersMask().Seq() ) - m_tree[layer] = new drc_rtree(); - - m_count = 0; - } - - ~DRC_RTREE() - { - for( auto tree : m_tree ) - delete tree; - } - - /** - * Function Insert() - * Inserts an item into the tree. Item's bounding box is taken via its GetBoundingBox() method. - */ - void insert( BOARD_ITEM* aItem ) - { - if( ZONE_CONTAINER* zone = dyn_cast( aItem ) ) - { - for( int layer : zone->GetLayerSet().Seq() ) - { - const SHAPE_POLY_SET& polyset = zone->GetFilledPolysList( PCB_LAYER_ID( layer ) ); - - for( int ii = 0; ii < polyset.TriangulatedPolyCount(); ++ii ) - { - const auto poly = polyset.TriangulatedPolygon( ii ); - - for( int jj = 0; jj < poly->GetTriangleCount(); ++jj ) - { - VECTOR2I a; - VECTOR2I b; - VECTOR2I c; - poly->GetTriangle( jj, a, b, c ); - - const int mmin2[2] = { std::min( a.x, std::min( b.x, c.x ) ), - std::min( a.y, std::min( b.y, c.y ) ) }; - const int mmax2[2] = { std::max( a.x, std::max( b.x, c.x ) ), - std::max( a.y, std::max( b.y, c.y ) ) }; - - m_tree[layer]->Insert( mmin2, mmax2, aItem ); - } - } - } - } - else - { - const EDA_RECT& bbox = aItem->GetBoundingBox(); - const int mmin[2] = { bbox.GetX(), bbox.GetY() }; - const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() }; - - for( int layer : aItem->GetLayerSet().Seq() ) - { - m_tree[layer]->Insert( mmin, mmax, aItem ); - } - } - - m_count++; - } - - /** - * Function Remove() - * Removes an item from the tree. Removal is done by comparing pointers, attempting - * to remove a copy of the item will fail. - */ - bool remove( BOARD_ITEM* aItem ) - { - // First, attempt to remove the item using its given BBox - const EDA_RECT& bbox = aItem->GetBoundingBox(); - const int mmin[2] = { bbox.GetX(), bbox.GetY() }; - const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() }; - bool removed = false; - - for( auto layer : aItem->GetLayerSet().Seq() ) - { - if( ZONE_CONTAINER* zone = dyn_cast( aItem ) ) - { - // Continue removing the zone elements from the tree until they cannot be found - while( !m_tree[int( layer )]->Remove( mmin, mmax, aItem ) ) - ; - - const int mmin2[2] = { INT_MIN, INT_MIN }; - const int mmax2[2] = { INT_MAX, INT_MAX }; - - // If we are not successful ( true == not found ), then we expand - // the search to the full tree - while( !m_tree[int( layer )]->Remove( mmin2, mmax2, aItem ) ) - ; - - // Loop to the next layer - continue; - } - - // The non-zone search expects only a single element in the tree with the same - // pointer aItem - if( m_tree[int( layer )]->Remove( mmin, mmax, aItem ) ) - { - // N.B. We must search the whole tree for the pointer to remove - // because the item may have been moved before we have the chance to - // delete it from the tree - const int mmin2[2] = { INT_MIN, INT_MIN }; - const int mmax2[2] = { INT_MAX, INT_MAX }; - - if( m_tree[int( layer )]->Remove( mmin2, mmax2, aItem ) ) - continue; - } - - removed = true; - } - - m_count -= int( removed ); - - return removed; - } - - /** - * Function RemoveAll() - * Removes all items from the RTree - */ - void clear() - { - for( auto tree : m_tree ) - tree->RemoveAll(); - - m_count = 0; - } - - /** - * Determine if a given item exists in the tree. Note that this does not search the full tree - * so if the item has been moved, this will return false when it should be true. - * - * @param aItem Item that may potentially exist in the tree - * @param aRobust If true, search the whole tree, not just the bounding box - * @return true if the item definitely exists, false if it does not exist within bbox - */ - bool contains( BOARD_ITEM* aItem, bool aRobust = false ) - { - const EDA_RECT& bbox = aItem->GetBoundingBox(); - const int mmin[2] = { bbox.GetX(), bbox.GetY() }; - const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() }; - bool found = false; - - auto search = [&found, &aItem]( const BOARD_ITEM* aSearchItem ) { - if( aSearchItem == aItem ) - { - found = true; - return false; - } - - return true; - }; - - for( int layer : aItem->GetLayerSet().Seq() ) - { - m_tree[layer]->Search( mmin, mmax, search ); - - if( found ) - break; - } - - if( !found && aRobust ) - { - for( int layer : LSET::AllCuMask().Seq() ) - { - // N.B. We must search the whole tree for the pointer to remove - // because the item may have been moved. We do not expand the item - // layer search as this should not change. - - const int mmin2[2] = { INT_MIN, INT_MIN }; - const int mmax2[2] = { INT_MAX, INT_MAX }; - - m_tree[layer]->Search( mmin2, mmax2, search ); - - if( found ) - break; - } - } - - return found; - } - - std::vector> GetNearest( const wxPoint &aPoint, - PCB_LAYER_ID aLayer, - int aLimit ) - { - - const int point[2] = { aPoint.x, aPoint.y }; - auto result = m_tree[int( aLayer )]->NearestNeighbors( point, - [aLimit]( std::size_t a_count, int a_maxDist ) -> bool - { - return a_count >= aLimit; - }, - []( BOARD_ITEM* aElement) -> bool - { - // Don't remove any elements from the list - return false; - }, - [aLayer]( const int* a_point, BOARD_ITEM* a_data ) -> int - { - switch( a_data->Type() ) - { - case PCB_TRACE_T: - { - TRACK* track = static_cast( a_data ); - SEG seg( track->GetStart(), track->GetEnd() ); - return seg.Distance( VECTOR2I( a_point[0], a_point[1] ) ) - - ( track->GetWidth() + 1 ) / 2; - } - case PCB_VIA_T: - { - VIA* via = static_cast( a_data ); - return ( VECTOR2I( via->GetPosition() ) - - VECTOR2I( a_point[0], a_point[1] ) ).EuclideanNorm() - - ( via->GetWidth() + 1 ) / 2; - - } - default: - { - VECTOR2I point( a_point[0], a_point[1] ); - int dist = 0; - auto shape = a_data->GetEffectiveShape( aLayer ); - - // Here we use a hack to get the distance by colliding with a large area - // However, we can't use just MAX_INT because we will overflow the collision calculations - shape->Collide( point, std::numeric_limits::max() / 2, &dist); - return dist; - } - } - return 0; - }); - - return result; - } - - /** - * Returns the number of items in the tree - * @return number of elements in the tree; - */ - size_t size() - { - return m_count; - } - - bool empty() - { - return m_count == 0; - } - - using iterator = typename drc_rtree::Iterator; - - /** - * The DRC_LAYER struct provides a layer-specific auto-range iterator to the RTree. Using - * this struct, one can write lines like: - * - * for( auto item : rtree.OnLayer( In1_Cu ) ) - * - * and iterate over only the RTree items that are on In1 - */ - struct DRC_LAYER - { - DRC_LAYER( drc_rtree* aTree ) : layer_tree( aTree ) - { - m_rect = { { INT_MIN, INT_MIN }, { INT_MAX, INT_MAX } }; - }; - - DRC_LAYER( drc_rtree* aTree, const EDA_RECT aRect ) : layer_tree( aTree ) - { - m_rect = { { aRect.GetX(), aRect.GetY() }, - { aRect.GetRight(), aRect.GetBottom() } }; - }; - - drc_rtree::Rect m_rect; - drc_rtree* layer_tree; - - iterator begin() - { - return layer_tree->begin( m_rect ); - } - - iterator end() - { - return layer_tree->end( m_rect ); - } - }; - - DRC_LAYER OnLayer( PCB_LAYER_ID aLayer ) - { - return DRC_LAYER( m_tree[int( aLayer )] ); - } - - DRC_LAYER Overlapping( PCB_LAYER_ID aLayer, const wxPoint& aPoint, int aAccuracy = 0 ) - { - EDA_RECT rect( aPoint, wxSize( 0, 0 ) ); - rect.Inflate( aAccuracy ); - return DRC_LAYER( m_tree[int( aLayer )], rect ); - } - - DRC_LAYER Overlapping( PCB_LAYER_ID aLayer, const EDA_RECT& aRect ) - { - return DRC_LAYER( m_tree[int( aLayer )], aRect ); - } - - -private: - drc_rtree* m_tree[MAX_CU_LAYERS]; - size_t m_count; -}; - - -#endif /* DRC_RTREE_H_ */ diff --git a/qa/drc_proto/drc_rules_keywords.cpp b/qa/drc_proto/drc_rules_keywords.cpp deleted file mode 100644 index 391dff5341..0000000000 --- a/qa/drc_proto/drc_rules_keywords.cpp +++ /dev/null @@ -1,50 +0,0 @@ - -/* Do not modify this file it was automatically generated by the - * TokenList2DsnLexer CMake script. - * - * Include this file in your lexer class to provide the keywords for - * your DSN lexer. - */ - -#include - -using namespace DRCRULE_T; - -#define TOKDEF(x) { #x, T_##x } - -const KEYWORD DRC_RULES_LEXER::keywords[] = { - TOKDEF( allow ), - TOKDEF( condition ), - TOKDEF( enable ), - TOKDEF( error ), - TOKDEF( expression ), - TOKDEF( ignore ), - TOKDEF( info ), - TOKDEF( max ), - TOKDEF( min ), - TOKDEF( name ), - TOKDEF( opt ), - TOKDEF( priority ), - TOKDEF( rule ), - TOKDEF( severity ), - TOKDEF( type ), - TOKDEF( version ), - TOKDEF( warning ) -}; - -const unsigned DRC_RULES_LEXER::keyword_count = unsigned( sizeof( DRC_RULES_LEXER::keywords )/sizeof( DRC_RULES_LEXER::keywords[0] ) ); - - -const char* DRC_RULES_LEXER::TokenName( T aTok ) -{ - const char* ret; - - if( aTok < 0 ) - ret = DSNLEXER::Syntax( aTok ); - else if( (unsigned) aTok < keyword_count ) - ret = keywords[aTok].name; - else - ret = "token too big"; - - return ret; -} diff --git a/qa/drc_proto/drc_rules_proto.keywords b/qa/drc_proto/drc_rules_proto.keywords deleted file mode 100644 index 3d672a8fab..0000000000 --- a/qa/drc_proto/drc_rules_proto.keywords +++ /dev/null @@ -1,22 +0,0 @@ -clearance -condition -constraint -inner -layer -max -min -name -opt -outer -allow -rule -version -priority -expression -enable -severity -type -error -warning -info -ignore \ 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 deleted file mode 100644 index 8049aa4aa4..0000000000 --- a/qa/drc_proto/drc_test_provider_track_width.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2004-2020 KiCad Developers. - * - * 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 - - -/* - Track width test. As the name says, checks width of the tracks (including segments and arcs) - Errors generated: - - DRCE_TRACK_WIDTH -*/ - -namespace test -{ - -class DRC_TEST_PROVIDER_TRACK_WIDTH : public DRC_TEST_PROVIDER -{ -public: - DRC_TEST_PROVIDER_TRACK_WIDTH() - { - } - - virtual ~DRC_TEST_PROVIDER_TRACK_WIDTH() - { - } - - virtual bool Run() override; - - virtual const wxString GetName() const override - { - return "width"; - }; - - virtual const wxString GetDescription() const override - { - return "Tests track widths"; - } - - virtual std::set GetMatchingConstraintIds() const override; -}; - -}; // namespace test - - -bool test::DRC_TEST_PROVIDER_TRACK_WIDTH::Run() -{ - if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH ) ) - { - ReportAux( "No track width constraints found. Skipping check." ); - return false; - } - - ReportStage( ( "Testing track widths" ), 0, 2 ); - - auto checkTrackWidth = [&]( BOARD_ITEM* item ) -> bool { - int width; - VECTOR2I p0; - - if( auto arc = dyn_cast( item ) ) - { - width = arc->GetWidth(); - p0 = arc->GetStart(); - } - else if( auto trk = dyn_cast( item ) ) - { - width = trk->GetWidth(); - p0 = ( trk->GetStart() + trk->GetEnd() ) / 2; - } - - 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; - - if( constraint.Value().HasMin() && width < constraint.Value().Min() ) - { - fail_min = true; - constraintWidth = constraint.Value().Min(); - } - - if( constraint.Value().HasMax() && width > constraint.Value().Max() ) - { - fail_max = true; - constraintWidth = constraint.Value().Max(); - } - - if( fail_min || fail_max ) - { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_TRACK_WIDTH ); - wxString msg; - - msg.Printf( drcItem->GetErrorText() + _( " (%s; width %s, constraint %s %s)" ), - constraint.GetParentRule()->m_Name, - MessageTextFromValue( userUnits(), width, true ), - fail_min ? _( "minimum" ) : _( "maximum" ), - MessageTextFromValue( userUnits(), constraintWidth, true ) ); - - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( item ); - drcItem->SetViolatingRule( constraint.GetParentRule() ); - - ReportWithMarker( drcItem, p0 ); - - if( isErrorLimitExceeded( DRCE_TRACK_WIDTH ) ) - return false; - - } - - return true; - }; - - forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T }, LSET::AllCuMask(), checkTrackWidth ); - - reportRuleStatistics(); - - return true; -} - - -std::set test::DRC_TEST_PROVIDER_TRACK_WIDTH::GetMatchingConstraintIds() const -{ - return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH }; -} - - -namespace detail -{ -static DRC_REGISTER_TEST_PROVIDER dummy; -} \ No newline at end of file diff --git a/qa/drc_proto/drc_textvar_tester.cpp b/qa/drc_proto/drc_textvar_tester.cpp deleted file mode 100644 index c845f299b8..0000000000 --- a/qa/drc_proto/drc_textvar_tester.cpp +++ /dev/null @@ -1,116 +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 -#include - -DRC_TEXTVAR_TESTER::DRC_TEXTVAR_TESTER( MARKER_HANDLER aMarkerHandler, - KIGFX::WS_PROXY_VIEW_ITEM* aWorksheet ) : - DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ), - m_units( EDA_UNITS::MILLIMETRES ), - m_board( nullptr ), - m_worksheet( aWorksheet ) -{ -} - - -bool DRC_TEXTVAR_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) -{ - bool success = true; - - m_units = aUnits; - m_board = &aBoard; - - for( MODULE* module : m_board->Modules() ) - { - module->RunOnChildren( - [&]( BOARD_ITEM* child ) - { - if( child->Type() == PCB_MODULE_TEXT_T ) - { - TEXTE_MODULE* text = static_cast( child ); - - if( text->GetShownText().Matches( wxT( "*${*}*" ) ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_UNRESOLVED_VARIABLE ); - drcItem->SetItems( text ); - - HandleMarker( new MARKER_PCB( drcItem, text->GetPosition() ) ); - success = false; - } - } - } ); - } - - for( BOARD_ITEM* drawing : m_board->Drawings() ) - { - if( drawing->Type() == PCB_TEXT_T ) - { - TEXTE_PCB* text = static_cast( drawing ); - - if( text->GetShownText().Matches( wxT( "*${*}*" ) ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_UNRESOLVED_VARIABLE ); - drcItem->SetItems( text ); - - HandleMarker( new MARKER_PCB( drcItem, text->GetPosition() ) ); - success = false; - } - } - } - - WS_DRAW_ITEM_LIST wsItems; - - if( m_worksheet ) - { - wsItems.SetMilsToIUfactor( IU_PER_MILS ); - wsItems.BuildWorkSheetGraphicList( m_worksheet->GetPageInfo(), - m_worksheet->GetTitleBlock() ); - - for( WS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() ) - { - if( WS_DRAW_ITEM_TEXT* text = dynamic_cast( item ) ) - { - if( text->GetShownText().Matches( wxT( "*${*}*" ) ) ) - { - DRC_ITEM* drcItem = new DRC_ITEM( DRCE_UNRESOLVED_VARIABLE ); - drcItem->SetErrorMessage( _( "Unresolved text variable in worksheet." ) ); - - HandleMarker( new MARKER_PCB( drcItem, text->GetPosition() ) ); - success = false; - } - } - } - } - - // JEY TODO: Test text vars in worksheet... - - return success; -} - - diff --git a/qa/drc_proto/drc_textvar_tester.h b/qa/drc_proto/drc_textvar_tester.h deleted file mode 100644 index 820043e827..0000000000 --- a/qa/drc_proto/drc_textvar_tester.h +++ /dev/null @@ -1,49 +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_TEXTVAR_TESTER__H -#define DRC_TEXTVAR_TESTER__H - -#include - - -class BOARD; - - -class DRC_TEXTVAR_TESTER : public DRC_TEST_PROVIDER -{ -public: - DRC_TEXTVAR_TESTER( MARKER_HANDLER aMarkerHandler, KIGFX::WS_PROXY_VIEW_ITEM* aWorksheet ); - - virtual ~DRC_TEXTVAR_TESTER() {}; - - bool RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) override; - -private: - EDA_UNITS m_units; - BOARD* m_board; - KIGFX::WS_PROXY_VIEW_ITEM* m_worksheet; -}; - -#endif // DRC_TEXTVAR_TESTER__H