Move rest of DRC tests to kicad.

This commit is contained in:
Jeff Young 2020-09-11 22:50:53 +01:00
parent d14c6ba71f
commit ce2937a399
22 changed files with 536 additions and 1457 deletions

View File

@ -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

View File

@ -3,20 +3,8 @@
#include <drc/drc_test_provider.h>
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 "<no name test>"; }
@ -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 );

View File

@ -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<DRC_ITEM> item );
virtual void ReportWithMarker( std::shared_ptr<DRC_ITEM> item, wxPoint aMarkerPos );
virtual void ReportWithMarker( std::shared_ptr<DRC_ITEM> item, VECTOR2I aMarkerPos );
@ -120,10 +117,11 @@ protected:
virtual bool isErrorLimitExceeded( int error_code );
EDA_UNITS userUnits() const;
DRC_ENGINE *m_drcEngine;
DRC_ENGINE* m_drcEngine;
std::unordered_map<const DRC_RULE*, int> m_stats;
bool m_enable;
bool m_isRuleDriven = true;
wxString m_msg; // Allocating strings gets expensive enough to want to avoid it
};
#endif // DRC_TEST_PROVIDER__H

View File

@ -21,19 +21,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <class_board.h>
#include <class_track.h>
#include <class_pad.h>
#include <common.h>
#include <class_track.h>
#include <drc/drc_engine.h>
#include <drc/drc.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <drc/drc_test_provider.h>
/*
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,35 +65,36 @@ public:
virtual std::set<DRC_CONSTRAINT_TYPE_T> 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
auto checkAnnulus =
[&]( BOARD_ITEM* item ) -> bool
{
bool fail_min = false, fail_max = false;
int v_min, v_max;
auto via = dyn_cast<VIA*>( item );
int v_min;
int v_max;
VIA* via = dyn_cast<VIA*>( item );
// 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 );
int annulus = ( via->GetWidth() - via->GetDrillValue() ) / 2;
if( constraint.Value().HasMin() )
{
v_min = constraint.Value().Min();
@ -119,10 +112,10 @@ bool test::DRC_TEST_PROVIDER_ANNULUS::Run()
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ANNULUS );
wxString msg;
msg.Printf( drcItem->GetErrorText() + _( " (%s; actual annulus %s, constraint %s %s)" ),
constraint.GetParentRule()->m_Name,
MessageTextFromValue( userUnits(), annulus, true ),
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 ) );
drcItem->SetErrorMessage( msg );
@ -147,7 +140,7 @@ bool test::DRC_TEST_PROVIDER_ANNULUS::Run()
}
std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const
{
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH };
}
@ -155,5 +148,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingCons
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_ANNULUS> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_ANNULUS> dummy;
}

View File

@ -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
};

View File

@ -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<DRC_CONSTRAINT_TYPE_T> 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<DRC_ITEM> drcItem = DRC_ITEM::Create( code );
wxString msg;
msg.Printf( drcItem->GetErrorText() );
drcItem->SetErrorMessage( msg );
drcItem->SetItems( track );
ReportWithMarker( drcItem, pos );
}
@ -113,10 +104,10 @@ 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;
@ -130,10 +121,6 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
if( ( netcode < 0 ) || pads_in_net == 0 )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ZONE_HAS_EMPTY_NET );
wxString msg;
msg.Printf( drcItem->GetErrorText() );
drcItem->SetErrorMessage( msg );
drcItem->SetItems( zone );
ReportWithMarker( drcItem, zone->GetPosition() );
@ -142,7 +129,7 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
}
}
ReportStage( ( "Testing unconnected ratlines" ), 0, 2 );
ReportStage( _( "Testing unconnected nets" ), 0, 2 );
connectivity->RecalculateRatsnest();
std::vector<CN_EDGE> edges;
@ -151,7 +138,6 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
for( const CN_EDGE& edge : edges )
{
std::shared_ptr<DRC_ITEM> 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<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const
{
return {};
}
@ -173,5 +159,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchin
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_CONNECTIVITY> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_CONNECTIVITY> dummy;
}

View File

@ -21,18 +21,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <common.h>
#include <class_board.h>
//#include <class_drawsegment.h>
//#include <class_pad.h>
#include <convert_basic_shapes_to_polygon.h>
//#include <geometry/polygon_test_point_inside.h>
//#include <geometry/seg.h>
#include <geometry/shape_poly_set.h>
//#include <geometry/shape_rect.h>
//#include <geometry/shape_segment.h>
#include <drc/drc_engine.h>
#include <drc/drc.h>
#include <drc/drc_item.h>
@ -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<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_COURTYARD );
drcItem->SetItems( footprint );
ReportWithMarker( drcItem, footprint->GetPosition() );
}

View File

@ -21,10 +21,10 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <class_board.h>
//#include <class_board.h>
#include <common.h>
#include <geometry/shape.h>
//#include <geometry/shape.h>
#include <drc/drc_engine.h>
#include <drc/drc.h>
@ -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<DRC_CONSTRAINT_TYPE_T> 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,19 +73,20 @@ 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 );
if( constraint.m_DisallowFlags )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
wxString msg;
msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), constraint.GetParentRule()->m_Name );
m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ),
constraint.GetName() );
drcItem->SetErrorMessage( msg );
drcItem->SetErrorMessage( m_msg );
drcItem->SetItems( item );
drcItem->SetViolatingRule( constraint.GetParentRule() );
@ -100,6 +94,7 @@ bool test::DRC_TEST_PROVIDER_DISALLOW::Run()
if( isErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) )
return false;
}
return true;
};
@ -112,7 +107,7 @@ bool test::DRC_TEST_PROVIDER_DISALLOW::Run()
}
std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const
{
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW };
}
@ -120,5 +115,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingCon
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_DISALLOW> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_DISALLOW> dummy;
}

View File

@ -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:
@ -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<VIA*>( 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<D_PAD*> 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<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetMatchingConstraintIds() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetMatchingConstraintIds() const
{
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE };
}
@ -415,5 +407,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetMatch
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_HOLE_CLEARANCE> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_HOLE_CLEARANCE> dummy;
}

View File

@ -21,23 +21,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <class_board.h>
#include <class_drawsegment.h>
#include <class_pad.h>
#include <common.h>
#include <convert_basic_shapes_to_polygon.h>
#include <geometry/polygon_test_point_inside.h>
#include <geometry/seg.h>
#include <geometry/shape_poly_set.h>
#include <geometry/shape_rect.h>
#include <geometry/shape_segment.h>
#include <drc/drc_engine.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <drc/drc.h>
#include <pcbnew/drc/drc_test_provider_clearance_base.h>
#include <drc/drc_test_provider_clearance_base.h>
/*
@ -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<VIA*> vias;
for( auto track : m_board->Tracks() )
for( TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_VIA_T )
{
vias.push_back( static_cast<VIA*>( 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<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ),
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<DRC_ITEM> drcItem = DRC_ITEM::Create( errorCode );
msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ),
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<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingConstraintIds() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingConstraintIds() const
{
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE };
}
@ -202,5 +184,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingCo
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_HOLE_SIZE> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_HOLE_SIZE> dummy;
}

View File

@ -22,10 +22,7 @@
*/
#include <class_board.h>
#include <class_track.h>
#include <common.h>
#include <pcbnew/drc/drc_engine.h>
#include <drc/drc_engine.h>
#include <drc/drc.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
@ -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();
auto comp = []( const MODULE* x, const MODULE* y ) {
auto comp = []( const MODULE* x, const MODULE* y )
{
return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
};
auto mods = std::set<MODULE*, decltype( comp )>( 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<DRC_ITEM> 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<DRC_ITEM> 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<DRC_ITEM> 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<DRC_ITEM> 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( auto module : mods )
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<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT );
drcItem->SetErrorMessage( m_msg );
drcItem->SetItems( module );
ReportWithMarker( drcItem, module->GetPosition() );
}
if( isErrorLimitExceeded( DRCE_NET_CONFLICT ) )
break;
}
}
}
// 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<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_LVS::GetMatchingConstraintIds() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_LVS::GetMatchingConstraintIds() const
{
return {};
}
@ -211,5 +265,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_LVS::GetMatchingConstrai
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_LVS> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_LVS> dummy;
}

View File

@ -21,18 +21,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <class_board.h>
#include <class_track.h>
#include <common.h>
#include <class_module.h>
#include <class_pcb_text.h>
#include <pcbnew/drc/drc_engine.h>
#include <drc/drc_engine.h>
#include <drc/drc.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <pcbnew/drc/drc_test_provider.h>
#include <drc/drc_test_provider.h>
#include <ws_draw_item.h>
#include <ws_proxy_view_item.h>
@ -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,36 +87,36 @@ void test::DRC_TEST_PROVIDER_MISC::testOutline()
return;
std::shared_ptr<DRC_ITEM> 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 {
auto checkDisabledLayers =
[&]( BOARD_ITEM* item ) -> bool
{
LSET refLayers ( item->GetLayer() );
if( ( disabledLayers & refLayers ).any() )
{
wxString msg;
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_DISABLED_LAYER_ITEM );
std::shared_ptr<DRC_ITEM>drcItem = 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->SetErrorMessage( m_msg );
drcItem->SetItems( item );
ReportWithMarker( drcItem, item->GetPosition() );
@ -140,20 +129,21 @@ void test::DRC_TEST_PROVIDER_MISC::testDisabledLayers()
LSET::AllLayersMask(), checkDisabledLayers );
}
void test::DRC_TEST_PROVIDER_MISC::testTextVars()
void DRC_TEST_PROVIDER_MISC::testTextVars()
{
auto checkUnresolvedTextVar = [&]( EDA_ITEM* item ) -> bool {
auto checkUnresolvedTextVar =
[&]( EDA_ITEM* item ) -> bool
{
EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
assert( text );
wxASSERT( text );
if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
{
if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
return false;
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
std::shared_ptr<DRC_ITEM>drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
drcItem->SetItems( item );
ReportWithMarker( drcItem, item->GetPosition() );
@ -161,17 +151,22 @@ void test::DRC_TEST_PROVIDER_MISC::testTextVars()
return true;
};
forEachGeometryItem(
{ PCB_MODULE_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(), checkUnresolvedTextVar );
forEachGeometryItem( { PCB_MODULE_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(),
checkUnresolvedTextVar );
KIGFX::WS_PROXY_VIEW_ITEM* worksheet = m_drcEngine->GetWorksheet();
WS_DRAW_ITEM_LIST wsItems;
auto worksheet = m_drcEngine->GetWorksheet();
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;
if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
drcItem->SetItems( text );
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<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_MISC::GetMatchingConstraintIds() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_MISC::GetMatchingConstraintIds() const
{
return {};
}
@ -215,5 +213,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_MISC::GetMatchingConstra
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_MISC> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_MISC> dummy;
}

View File

@ -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 <common.h>
#include <class_track.h>
#include <drc/drc_engine.h>
#include <drc/drc.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <drc/drc_test_provider.h>
/*
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<DRC_CONSTRAINT_TYPE_T> 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<ARC*>( item ) )
{
actual = arc->GetWidth();
p0 = arc->GetStart();
}
else if( TRACK* trk = dyn_cast<TRACK*>( 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<DRC_ITEM> 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_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_TRACK_WIDTH::GetMatchingConstraintIds() const
{
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH };
}
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_TRACK_WIDTH> dummy;
}

View File

@ -21,10 +21,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <class_board.h>
//#include <common.h>
#include <class_track.h>
#include <common.h>
#include <drc/drc_engine.h>
#include <drc/drc.h>
#include <drc/drc_item.h>
@ -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<DRC_CONSTRAINT_TYPE_T> 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,26 +75,29 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
ReportStage( ( "Testing via diameters" ), 0, 2 );
auto checkViaDiameter = [&]( BOARD_ITEM* item ) -> bool {
auto checkViaDiameter =
[&]( BOARD_ITEM* item ) -> bool
{
auto via = dyn_cast<VIA*>( item );
// 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 );
bool fail_min = false, fail_max = false;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_VIA_DIAMETER,
item );
bool fail_min = false;
bool fail_max = false;
int constraintDiameter;
int diameter = via->GetWidth();
int actual = via->GetWidth();
if( constraint.Value().HasMin() && diameter < constraint.Value().Min() )
if( constraint.Value().HasMin() && actual < constraint.Value().Min() )
{
fail_min = true;
constraintDiameter = constraint.Value().Min();
}
if( constraint.Value().HasMax() && diameter > constraint.Value().Max() )
if( constraint.Value().HasMax() && actual > constraint.Value().Max() )
{
fail_max = true;
constraintDiameter = constraint.Value().Max();
@ -110,15 +106,14 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
if( fail_min || fail_max )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_VIA_DIAMETER );
wxString msg;
msg.Printf( drcItem->GetErrorText() + _( " (%s; diameter %s, constraint %s %s)" ),
constraint.GetParentRule()->m_Name,
MessageTextFromValue( userUnits(), diameter, true ),
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 ),
drcItem->SetErrorMessage( msg );
drcItem->SetErrorMessage( m_msg );
drcItem->SetItems( item );
drcItem->SetViolatingRule( constraint.GetParentRule() );
@ -140,7 +135,7 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
}
std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const
{
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER };
}
@ -148,5 +143,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchin
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_VIA_DIAMETER> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_VIA_DIAMETER> dummy;
}

View File

@ -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
)

View File

@ -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 <class_board.h>
#include <class_marker_pcb.h>
#include <functional>
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<test::DRC_CONSTRAINT_TYPE_T> 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<MARKER_PCB*> 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<DRC_ITEM*>( 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<DRC_ITEM*>* m_sourceVector; // owns its DRC_ITEMs
int m_severities;
std::vector<DRC_ITEM*> m_filteredVector; // does not own its DRC_ITEMs
public:
VECTOR_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector<DRC_ITEM*>* 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<DRC_ITEM*>* aList ) :
VECTOR_DRC_ITEMS_PROVIDER( aFrame, aList )
{ }
};
#endif
};
#endif // DRC_PROVIDER__H

View File

@ -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 <eda_rect.h>
#include <class_board_item.h>
#include <set>
#include <vector>
#include <geometry/rtree.h>
#include <vector2d.h>
/**
* 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<BOARD_ITEM*, int, 2, double>;
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<ZONE_CONTAINER*>( 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<ZONE_CONTAINER*>( 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<std::pair<int, BOARD_ITEM*>> 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<TRACK*>( 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<VIA*>( 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<int>::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_ */

View File

@ -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 </home/twl/Kicad-dev/kicad-build/debug-dev/common/drc_rules_lexer.h>
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;
}

View File

@ -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

View File

@ -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 <class_board.h>
#include <class_track.h>
#include <common.h>
#include <drc/drc_engine.h>
#include <drc/drc.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <drc/drc_test_provider.h>
/*
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<DRC_CONSTRAINT_TYPE_T> 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<ARC*>( item ) )
{
width = arc->GetWidth();
p0 = arc->GetStart();
}
else if( auto trk = dyn_cast<TRACK*>( 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<DRC_ITEM> 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<DRC_CONSTRAINT_TYPE_T> 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<test::DRC_TEST_PROVIDER_TRACK_WIDTH> dummy;
}

View File

@ -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 <drc/drc_textvar_tester.h>
#include <class_module.h>
#include <class_pcb_text.h>
#include <ws_draw_item.h>
#include <ws_proxy_view_item.h>
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<TEXTE_MODULE*>( 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<TEXTE_PCB*>( 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<WS_DRAW_ITEM_TEXT*>( 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;
}

View File

@ -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 <drc/drc_results_provider.h>
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