Move rest of DRC tests to kicad.
This commit is contained in:
parent
d14c6ba71f
commit
ce2937a399
|
@ -240,10 +240,17 @@ set( PCBNEW_DRC_SRCS
|
||||||
drc/drc_engine.cpp
|
drc/drc_engine.cpp
|
||||||
drc/drc_rule_parser.cpp
|
drc/drc_rule_parser.cpp
|
||||||
drc/drc_test_provider.cpp
|
drc/drc_test_provider.cpp
|
||||||
|
drc/drc_test_provider_annulus.cpp
|
||||||
drc/drc_test_provider_clearance_base.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_copper_clearance.cpp
|
||||||
drc/drc_test_provider_edge_clearance.cpp
|
drc/drc_test_provider_edge_clearance.cpp
|
||||||
drc/drc_test_provider_hole_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
|
set( PCBNEW_NETLIST_SRCS
|
||||||
|
|
|
@ -3,20 +3,8 @@
|
||||||
#include <drc/drc_test_provider.h>
|
#include <drc/drc_test_provider.h>
|
||||||
|
|
||||||
DRC_TEST_PROVIDER::DRC_TEST_PROVIDER() :
|
DRC_TEST_PROVIDER::DRC_TEST_PROVIDER() :
|
||||||
m_drcEngine( nullptr ),
|
m_drcEngine( nullptr )
|
||||||
m_enable( false )
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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>"; }
|
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 );
|
ReportAux( aStageName );
|
||||||
}
|
}
|
||||||
|
|
||||||
void DRC_TEST_PROVIDER::ReportAux( const wxString& fmt, ... )
|
void DRC_TEST_PROVIDER::ReportAux( wxString fmt, ... )
|
||||||
{
|
{
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
va_start( vargs, fmt );
|
va_start( vargs, fmt );
|
||||||
|
|
|
@ -89,13 +89,10 @@ public:
|
||||||
|
|
||||||
virtual bool Run() = 0;
|
virtual bool Run() = 0;
|
||||||
|
|
||||||
virtual void Enable( bool enable );
|
|
||||||
virtual bool IsEnabled() const;
|
|
||||||
|
|
||||||
virtual const wxString GetName() const;
|
virtual const wxString GetName() const;
|
||||||
virtual const wxString GetDescription() 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 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, wxPoint aMarkerPos );
|
||||||
virtual void ReportWithMarker( std::shared_ptr<DRC_ITEM> item, VECTOR2I aMarkerPos );
|
virtual void ReportWithMarker( std::shared_ptr<DRC_ITEM> item, VECTOR2I aMarkerPos );
|
||||||
|
@ -119,11 +116,12 @@ protected:
|
||||||
virtual void accountCheck( const DRC_CONSTRAINT& constraintToTest );
|
virtual void accountCheck( const DRC_CONSTRAINT& constraintToTest );
|
||||||
virtual bool isErrorLimitExceeded( int error_code );
|
virtual bool isErrorLimitExceeded( int error_code );
|
||||||
|
|
||||||
EDA_UNITS userUnits() const;
|
EDA_UNITS userUnits() const;
|
||||||
DRC_ENGINE *m_drcEngine;
|
DRC_ENGINE* m_drcEngine;
|
||||||
std::unordered_map<const DRC_RULE*, int> m_stats;
|
std::unordered_map<const DRC_RULE*, int> 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
|
#endif // DRC_TEST_PROVIDER__H
|
||||||
|
|
|
@ -21,19 +21,14 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 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 <common.h>
|
||||||
|
#include <class_track.h>
|
||||||
#include <drc/drc_engine.h>
|
#include <drc/drc_engine.h>
|
||||||
#include <drc/drc.h>
|
#include <drc/drc.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
#include <drc/drc_rule.h>
|
#include <drc/drc_rule.h>
|
||||||
#include <drc/drc_test_provider.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)
|
Via/pad annular ring width test. Checks if there's sufficient copper ring around PTH/NPTH holes (vias/pads)
|
||||||
Errors generated:
|
Errors generated:
|
||||||
|
@ -44,9 +39,6 @@
|
||||||
- pad stack support (different IAR/OAR values depending on layer)
|
- pad stack support (different IAR/OAR values depending on layer)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace test
|
|
||||||
{
|
|
||||||
|
|
||||||
class DRC_TEST_PROVIDER_ANNULUS : public DRC_TEST_PROVIDER
|
class DRC_TEST_PROVIDER_ANNULUS : public DRC_TEST_PROVIDER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -73,71 +65,72 @@ public:
|
||||||
virtual std::set<DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
virtual std::set<DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace test
|
|
||||||
|
|
||||||
|
bool DRC_TEST_PROVIDER_ANNULUS::Run()
|
||||||
bool test::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." );
|
ReportAux( "No annulus constraints found. Skipping check." );
|
||||||
return false;
|
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;
|
int v_min;
|
||||||
auto via = dyn_cast<VIA*>( item );
|
int v_max;
|
||||||
|
VIA* via = dyn_cast<VIA*>( item );
|
||||||
|
|
||||||
// fixme: check minimum IAR/OAR ring for THT pads too
|
// fixme: check minimum IAR/OAR ring for THT pads too
|
||||||
if( !via )
|
if( !via )
|
||||||
return true;
|
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() )
|
if( constraint.Value().HasMax() )
|
||||||
{
|
{
|
||||||
v_min = constraint.Value().Min();
|
v_max = constraint.Value().Max();
|
||||||
fail_min = annulus < v_min;
|
fail_max = annulus > v_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( constraint.Value().HasMax() )
|
if( fail_min || fail_max )
|
||||||
{
|
{
|
||||||
v_max = constraint.Value().Max();
|
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ANNULUS );
|
||||||
fail_max = annulus > v_max;
|
wxString msg;
|
||||||
}
|
|
||||||
|
|
||||||
if( fail_min || fail_max )
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s annulus %s; actual %s)" ),
|
||||||
{
|
constraint.GetName(),
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ANNULUS );
|
fail_min ? _( "minimum" ) : _( "maximum" ),
|
||||||
wxString msg;
|
MessageTextFromValue( userUnits(), annulus, true ),
|
||||||
|
MessageTextFromValue( userUnits(), fail_min ? v_min : v_max, true ) );
|
||||||
|
|
||||||
msg.Printf( drcItem->GetErrorText() + _( " (%s; actual annulus %s, constraint %s %s)" ),
|
drcItem->SetErrorMessage( msg );
|
||||||
constraint.GetParentRule()->m_Name,
|
drcItem->SetItems( item );
|
||||||
MessageTextFromValue( userUnits(), annulus, true ),
|
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||||
fail_min ? _( "minimum" ) : _( "maximum" ),
|
|
||||||
MessageTextFromValue( userUnits(), fail_min ? v_min : v_max, true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( msg );
|
ReportWithMarker( drcItem, via->GetPosition() );
|
||||||
drcItem->SetItems( item );
|
|
||||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
|
||||||
|
|
||||||
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 );
|
forEachGeometryItem( { PCB_VIA_T }, LSET::AllCuMask(), checkAnnulus );
|
||||||
|
|
||||||
|
@ -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 };
|
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
|
namespace detail
|
||||||
{
|
{
|
||||||
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_ANNULUS> dummy;
|
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_ANNULUS> dummy;
|
||||||
}
|
}
|
|
@ -55,8 +55,6 @@ protected:
|
||||||
BOARD* m_board;
|
BOARD* m_board;
|
||||||
int m_largestClearance;
|
int m_largestClearance;
|
||||||
bool m_boardOutlineValid;
|
bool m_boardOutlineValid;
|
||||||
|
|
||||||
wxString m_msg; // Allocating strings gets expensive enough to want to avoid it
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,6 @@
|
||||||
- DRCE_ZONE_HAS_EMPTY_NET
|
- DRCE_ZONE_HAS_EMPTY_NET
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace test
|
|
||||||
{
|
|
||||||
|
|
||||||
class DRC_TEST_PROVIDER_CONNECTIVITY : public DRC_TEST_PROVIDER
|
class DRC_TEST_PROVIDER_CONNECTIVITY : public DRC_TEST_PROVIDER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -71,12 +68,10 @@ public:
|
||||||
virtual std::set<DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
virtual std::set<DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace test
|
|
||||||
|
|
||||||
|
bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
|
||||||
bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
|
|
||||||
{
|
{
|
||||||
ReportStage( ( "Testing dangling pads/vias" ), 0, 2 );
|
ReportStage( _( "Testing dangling pads/vias" ), 0, 2 );
|
||||||
|
|
||||||
BOARD* board = m_drcEngine->GetBoard();
|
BOARD* board = m_drcEngine->GetBoard();
|
||||||
|
|
||||||
|
@ -84,11 +79,11 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
|
||||||
connectivity->Clear();
|
connectivity->Clear();
|
||||||
connectivity->Build( board ); // just in case. This really needs to be reliable.
|
connectivity->Build( board ); // just in case. This really needs to be reliable.
|
||||||
|
|
||||||
|
for( TRACK* track : board->Tracks() )
|
||||||
for( auto track : board->Tracks() )
|
|
||||||
{
|
{
|
||||||
bool exceedT = isErrorLimitExceeded( DRCE_DANGLING_TRACK );
|
bool exceedT = isErrorLimitExceeded( DRCE_DANGLING_TRACK );
|
||||||
bool exceedV = isErrorLimitExceeded( DRCE_DANGLING_VIA );
|
bool exceedV = isErrorLimitExceeded( DRCE_DANGLING_VIA );
|
||||||
|
|
||||||
// Test for dangling items
|
// Test for dangling items
|
||||||
int code = track->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
int code = track->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
||||||
wxPoint pos;
|
wxPoint pos;
|
||||||
|
@ -101,10 +96,6 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
|
||||||
if( connectivity->TestTrackEndpointDangling( track, &pos ) )
|
if( connectivity->TestTrackEndpointDangling( track, &pos ) )
|
||||||
{
|
{
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( code );
|
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( code );
|
||||||
wxString msg;
|
|
||||||
|
|
||||||
msg.Printf( drcItem->GetErrorText() );
|
|
||||||
drcItem->SetErrorMessage( msg );
|
|
||||||
drcItem->SetItems( track );
|
drcItem->SetItems( track );
|
||||||
ReportWithMarker( drcItem, pos );
|
ReportWithMarker( drcItem, pos );
|
||||||
}
|
}
|
||||||
|
@ -113,36 +104,32 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportStage( ( "Testing starved zones" ), 0, 2 );
|
ReportStage( _( "Testing starved zones" ), 0, 2 );
|
||||||
|
|
||||||
/* test starved zones */
|
/* test starved zones */
|
||||||
for( auto zone : board->Zones() )
|
for( ZONE_CONTAINER* zone : board->Zones() )
|
||||||
{
|
{
|
||||||
if( !zone->IsOnCopperLayer() )
|
if( !zone->IsOnCopperLayer() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int netcode = zone->GetNetCode();
|
int netcode = zone->GetNetCode();
|
||||||
// a netcode < 0 or > 0 and no pad in net is a error or strange
|
// 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
|
// 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)
|
// Remark: a netcode < 0 should not happen (this is more a bug somewhere)
|
||||||
int pads_in_net = ( netcode > 0 ) ? connectivity->GetPadCount( netcode ) : 1;
|
int pads_in_net = ( netcode > 0 ) ? connectivity->GetPadCount( netcode ) : 1;
|
||||||
|
|
||||||
if( ( netcode < 0 ) || pads_in_net == 0 )
|
if( ( netcode < 0 ) || pads_in_net == 0 )
|
||||||
{
|
{
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ZONE_HAS_EMPTY_NET );
|
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ZONE_HAS_EMPTY_NET );
|
||||||
wxString msg;
|
drcItem->SetItems( zone );
|
||||||
|
ReportWithMarker( drcItem, zone->GetPosition() );
|
||||||
|
|
||||||
msg.Printf( drcItem->GetErrorText() );
|
if( isErrorLimitExceeded( DRCE_ZONE_HAS_EMPTY_NET ) )
|
||||||
drcItem->SetErrorMessage( msg );
|
break;
|
||||||
drcItem->SetItems( zone );
|
|
||||||
ReportWithMarker( drcItem, zone->GetPosition() );
|
|
||||||
|
|
||||||
if( isErrorLimitExceeded( DRCE_ZONE_HAS_EMPTY_NET ) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ReportStage( ( "Testing unconnected ratlines" ), 0, 2 );
|
ReportStage( _( "Testing unconnected nets" ), 0, 2 );
|
||||||
|
|
||||||
connectivity->RecalculateRatsnest();
|
connectivity->RecalculateRatsnest();
|
||||||
std::vector<CN_EDGE> edges;
|
std::vector<CN_EDGE> edges;
|
||||||
|
@ -151,7 +138,6 @@ bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
|
||||||
for( const CN_EDGE& edge : edges )
|
for( const CN_EDGE& edge : edges )
|
||||||
{
|
{
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );
|
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );
|
||||||
|
|
||||||
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
|
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
|
||||||
ReportWithMarker( drcItem, edge.GetSourceNode()->Pos() );
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -173,5 +159,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchin
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_CONNECTIVITY> dummy;
|
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_CONNECTIVITY> dummy;
|
||||||
}
|
}
|
|
@ -21,18 +21,7 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 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_poly_set.h>
|
||||||
//#include <geometry/shape_rect.h>
|
|
||||||
//#include <geometry/shape_segment.h>
|
|
||||||
|
|
||||||
#include <drc/drc_engine.h>
|
#include <drc/drc_engine.h>
|
||||||
#include <drc/drc.h>
|
#include <drc/drc.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
|
@ -85,6 +74,7 @@ private:
|
||||||
|
|
||||||
void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
|
void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
|
||||||
{
|
{
|
||||||
|
// Detects missing (or malformed) footprint courtyards
|
||||||
ReportStage( _( "Testing component courtyard definitions" ), 0, 2 );
|
ReportStage( _( "Testing component courtyard definitions" ), 0, 2 );
|
||||||
|
|
||||||
for( MODULE* footprint : m_board->Modules() )
|
for( MODULE* footprint : m_board->Modules() )
|
||||||
|
@ -98,7 +88,6 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_COURTYARD );
|
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_COURTYARD );
|
||||||
|
|
||||||
drcItem->SetItems( footprint );
|
drcItem->SetItems( footprint );
|
||||||
ReportWithMarker( drcItem, footprint->GetPosition() );
|
ReportWithMarker( drcItem, footprint->GetPosition() );
|
||||||
}
|
}
|
||||||
|
@ -130,66 +119,66 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testOverlappingComponentCourtyards()
|
||||||
ReportStage( _( "Testing component courtyard overlap" ), 0, 2 );
|
ReportStage( _( "Testing component courtyard overlap" ), 0, 2 );
|
||||||
|
|
||||||
for( auto it1 = m_board->Modules().begin(); it1 != m_board->Modules().end(); it1++ )
|
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;
|
MODULE* test = *it2;
|
||||||
SHAPE_POLY_SET& footprintFront = footprint->GetPolyCourtyardFront();
|
SHAPE_POLY_SET& testFront = test->GetPolyCourtyardFront();
|
||||||
SHAPE_POLY_SET& footprintBack = footprint->GetPolyCourtyardBack();
|
SHAPE_POLY_SET& testBack = test->GetPolyCourtyardBack();
|
||||||
|
SHAPE_POLY_SET intersection;
|
||||||
|
bool overlap = false;
|
||||||
|
wxPoint pos;
|
||||||
|
|
||||||
if( footprintFront.OutlineCount() == 0 && footprintBack.OutlineCount() == 0 )
|
if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0
|
||||||
continue; // No courtyards defined
|
&& footprintFront.BBoxFromCaches().Intersects( testFront.BBoxFromCaches() ) )
|
||||||
|
|
||||||
for( auto it2 = it1 + 1; it2 != m_board->Modules().end(); it2++ )
|
|
||||||
{
|
{
|
||||||
MODULE* test = *it2;
|
intersection.RemoveAllContours();
|
||||||
SHAPE_POLY_SET& testFront = test->GetPolyCourtyardFront();
|
intersection.Append( footprintFront );
|
||||||
SHAPE_POLY_SET& testBack = test->GetPolyCourtyardBack();
|
|
||||||
SHAPE_POLY_SET intersection;
|
|
||||||
bool overlap = false;
|
|
||||||
wxPoint pos;
|
|
||||||
|
|
||||||
if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0
|
// Build the common area between footprint and the test:
|
||||||
&& footprintFront.BBoxFromCaches().Intersects( testFront.BBoxFromCaches() ) )
|
intersection.BooleanIntersection( testFront, SHAPE_POLY_SET::PM_FAST );
|
||||||
|
|
||||||
|
// If the intersection exists then they overlap
|
||||||
|
if( intersection.OutlineCount() > 0 )
|
||||||
{
|
{
|
||||||
intersection.RemoveAllContours();
|
overlap = true;
|
||||||
intersection.Append( footprintFront );
|
pos = (wxPoint) intersection.CVertex( 0, 0, -1 );
|
||||||
|
|
||||||
// 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<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS );
|
|
||||||
drcItem->SetItems( footprint, test );
|
|
||||||
ReportWithMarker ( drcItem, pos );
|
|
||||||
|
|
||||||
if( isErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS ) )
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS );
|
||||||
|
drcItem->SetItems( footprint, test );
|
||||||
|
ReportWithMarker ( drcItem, pos );
|
||||||
|
|
||||||
|
if( isErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <class_board.h>
|
//#include <class_board.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
|
||||||
#include <geometry/shape.h>
|
//#include <geometry/shape.h>
|
||||||
|
|
||||||
#include <drc/drc_engine.h>
|
#include <drc/drc_engine.h>
|
||||||
#include <drc/drc.h>
|
#include <drc/drc.h>
|
||||||
|
@ -38,9 +38,6 @@
|
||||||
- DRCE_ALLOWED_ITEMS
|
- DRCE_ALLOWED_ITEMS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace test
|
|
||||||
{
|
|
||||||
|
|
||||||
class DRC_TEST_PROVIDER_DISALLOW : public DRC_TEST_PROVIDER
|
class DRC_TEST_PROVIDER_DISALLOW : public DRC_TEST_PROVIDER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -65,14 +62,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::set<DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
virtual std::set<DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace test
|
|
||||||
|
|
||||||
|
bool DRC_TEST_PROVIDER_DISALLOW::Run()
|
||||||
bool test::DRC_TEST_PROVIDER_DISALLOW::Run()
|
|
||||||
{
|
{
|
||||||
if( !m_drcEngine->HasCorrectRulesForId( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW ) )
|
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;
|
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,
|
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_DISALLOW, item );
|
||||||
item );
|
|
||||||
|
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
|
if( constraint.m_DisallowFlags )
|
||||||
wxString msg;
|
{
|
||||||
|
std::shared_ptr<DRC_ITEM> 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->SetErrorMessage( m_msg );
|
||||||
drcItem->SetItems( item );
|
drcItem->SetItems( item );
|
||||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||||
|
|
||||||
ReportWithMarker( drcItem, item->GetPosition() );
|
ReportWithMarker( drcItem, item->GetPosition() );
|
||||||
|
|
||||||
if( isErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) )
|
if( isErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) )
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
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 };
|
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
|
namespace detail
|
||||||
{
|
{
|
||||||
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_DISALLOW> dummy;
|
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_DISALLOW> dummy;
|
||||||
}
|
}
|
|
@ -39,8 +39,6 @@
|
||||||
TODO: vias-in-smd-pads check
|
TODO: vias-in-smd-pads check
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
class DRC_TEST_PROVIDER_HOLE_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
class DRC_TEST_PROVIDER_HOLE_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -80,7 +78,7 @@ private:
|
||||||
|
|
||||||
struct DRILLED_HOLE
|
struct DRILLED_HOLE
|
||||||
{
|
{
|
||||||
VECTOR2I m_location;
|
VECTOR2I m_location;
|
||||||
int m_drillRadius = 0;
|
int m_drillRadius = 0;
|
||||||
BOARD_ITEM* m_owner = nullptr;
|
BOARD_ITEM* m_owner = nullptr;
|
||||||
};
|
};
|
||||||
|
@ -91,10 +89,8 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run()
|
||||||
bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run()
|
|
||||||
{
|
{
|
||||||
m_board = m_drcEngine->GetBoard();
|
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();
|
m_drilledHoles.clear();
|
||||||
|
|
||||||
for( MODULE* module : m_board->Modules() )
|
for( MODULE* module : m_board->Modules() )
|
||||||
|
@ -155,7 +148,7 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::buildDrilledHoleList()
|
||||||
|
|
||||||
for( TRACK* track : m_board->Tracks() )
|
for( TRACK* track : m_board->Tracks() )
|
||||||
{
|
{
|
||||||
if ( track->Type() == PCB_VIA_T )
|
if( track->Type() == PCB_VIA_T )
|
||||||
{
|
{
|
||||||
VIA* via = static_cast<VIA*>( track );
|
VIA* via = static_cast<VIA*>( track );
|
||||||
addHole( via->GetPosition(), via->GetDrillValue() / 2, via );
|
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() );
|
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;
|
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 )
|
D_PAD** aEnd, int x_limit )
|
||||||
{
|
{
|
||||||
const static LSET all_cu = LSET::AllCuMask();
|
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 )
|
BOARD_ITEM* aOwner )
|
||||||
{
|
{
|
||||||
DRILLED_HOLE hole;
|
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
|
// 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
|
// 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 };
|
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
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,23 +21,12 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <class_board.h>
|
|
||||||
#include <class_drawsegment.h>
|
|
||||||
#include <class_pad.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_engine.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
#include <drc/drc_rule.h>
|
#include <drc/drc_rule.h>
|
||||||
#include <drc/drc.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
|
TODO: max drill size check
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace test
|
|
||||||
{
|
|
||||||
|
|
||||||
class DRC_TEST_PROVIDER_HOLE_SIZE : public DRC_TEST_PROVIDER
|
class DRC_TEST_PROVIDER_HOLE_SIZE : public DRC_TEST_PROVIDER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -85,38 +71,34 @@ private:
|
||||||
BOARD* m_board;
|
BOARD* m_board;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace test
|
|
||||||
|
|
||||||
|
bool DRC_TEST_PROVIDER_HOLE_SIZE::Run()
|
||||||
bool test::DRC_TEST_PROVIDER_HOLE_SIZE::Run()
|
|
||||||
{
|
{
|
||||||
ReportStage( ( "Testing pad holes" ), 0, 2 );
|
ReportStage( _( "Testing pad holes" ), 0, 2 );
|
||||||
|
|
||||||
m_board = m_drcEngine->GetBoard();
|
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 ) )
|
if( checkPad( pad ) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportStage( ( "Testing via/microvia holes" ), 0, 2 );
|
ReportStage( _( "Testing via/microvia holes" ), 0, 2 );
|
||||||
|
|
||||||
std::vector<VIA*> vias;
|
std::vector<VIA*> vias;
|
||||||
|
|
||||||
for( auto track : m_board->Tracks() )
|
for( TRACK* track : m_board->Tracks() )
|
||||||
{
|
{
|
||||||
if( track->Type() == PCB_VIA_T )
|
if( track->Type() == PCB_VIA_T )
|
||||||
{
|
|
||||||
vias.push_back( static_cast<VIA*>( track ) );
|
vias.push_back( static_cast<VIA*>( track ) );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for( auto via : vias )
|
for( VIA* via : vias )
|
||||||
{
|
{
|
||||||
if( checkVia( via ) )
|
if( checkVia( via ) )
|
||||||
break;
|
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 );
|
int holeSize = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
|
||||||
|
|
||||||
if( holeSize == 0 )
|
if( holeSize == 0 )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, aPad );
|
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_HOLE_SIZE, aPad );
|
||||||
auto minHole = constraint.GetValue().Min();
|
int minHole = constraint.GetValue().Min();
|
||||||
|
|
||||||
accountCheck( constraint );
|
accountCheck( constraint );
|
||||||
|
|
||||||
if( holeSize < minHole )
|
if( holeSize < minHole )
|
||||||
{
|
{
|
||||||
wxString msg;
|
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
|
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)" ),
|
||||||
MessageTextFromValue( userUnits(), minHole, true ),
|
constraint.GetName(),
|
||||||
MessageTextFromValue( userUnits(), holeSize, true ) );
|
MessageTextFromValue( userUnits(), minHole, true ),
|
||||||
|
MessageTextFromValue( userUnits(), holeSize, true ) );
|
||||||
|
|
||||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
drcItem->SetErrorMessage( msg );
|
|
||||||
drcItem->SetItems( aPad );
|
drcItem->SetItems( aPad );
|
||||||
|
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||||
|
|
||||||
ReportWithMarker( drcItem, aPad->GetPosition() );
|
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 constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_HOLE_SIZE, via );
|
||||||
auto minHole = constraint.GetValue().Min();
|
int minHole = constraint.GetValue().Min();
|
||||||
|
|
||||||
accountCheck( constraint );
|
accountCheck( constraint );
|
||||||
|
|
||||||
if( via->GetDrillValue() < minHole )
|
if( via->GetDrillValue() < minHole )
|
||||||
{
|
{
|
||||||
wxString msg;
|
|
||||||
int errorCode = via->GetViaType() == VIATYPE::MICROVIA ? DRCE_TOO_SMALL_MICROVIA_DRILL :
|
int errorCode = via->GetViaType() == VIATYPE::MICROVIA ? DRCE_TOO_SMALL_MICROVIA_DRILL :
|
||||||
DRCE_TOO_SMALL_DRILL;
|
DRCE_TOO_SMALL_DRILL;
|
||||||
|
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( errorCode );
|
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)" ),
|
||||||
MessageTextFromValue( userUnits(), minHole, true ),
|
constraint.GetName(),
|
||||||
MessageTextFromValue( userUnits(), via->GetDrillValue(), true ) );
|
MessageTextFromValue( userUnits(), minHole, true ),
|
||||||
|
MessageTextFromValue( userUnits(), via->GetDrillValue(), true ) );
|
||||||
|
|
||||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
drcItem->SetErrorMessage( msg );
|
|
||||||
drcItem->SetItems( via );
|
drcItem->SetItems( via );
|
||||||
|
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||||
|
|
||||||
ReportWithMarker( drcItem, via->GetPosition() );
|
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 };
|
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
|
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;
|
||||||
}
|
}
|
|
@ -22,10 +22,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
#include <class_track.h>
|
#include <drc/drc_engine.h>
|
||||||
#include <common.h>
|
|
||||||
|
|
||||||
#include <pcbnew/drc/drc_engine.h>
|
|
||||||
#include <drc/drc.h>
|
#include <drc/drc.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
#include <drc/drc_rule.h>
|
#include <drc/drc_rule.h>
|
||||||
|
@ -47,9 +44,6 @@
|
||||||
- cross-check PCB fields against SCH fields
|
- cross-check PCB fields against SCH fields
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace test
|
|
||||||
{
|
|
||||||
|
|
||||||
class DRC_TEST_PROVIDER_LVS : public DRC_TEST_PROVIDER
|
class DRC_TEST_PROVIDER_LVS : public DRC_TEST_PROVIDER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -82,20 +76,19 @@ private:
|
||||||
void testFootprints( NETLIST& aNetlist );
|
void testFootprints( NETLIST& aNetlist );
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace test
|
|
||||||
|
|
||||||
|
void DRC_TEST_PROVIDER_LVS::testFootprints( NETLIST& aNetlist )
|
||||||
void test::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 ) {
|
auto comp = []( const MODULE* x, const MODULE* y )
|
||||||
return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
|
{
|
||||||
};
|
return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
|
||||||
|
};
|
||||||
|
|
||||||
auto mods = std::set<MODULE*, decltype( comp )>( comp );
|
auto mods = std::set<MODULE*, decltype( comp )>( comp );
|
||||||
|
|
||||||
|
// Search for duplicate footprints on the board
|
||||||
for( MODULE* mod : board->Modules() )
|
for( MODULE* mod : board->Modules() )
|
||||||
{
|
{
|
||||||
auto ins = mods.insert( mod );
|
auto ins = mods.insert( mod );
|
||||||
|
@ -120,21 +113,82 @@ void test::DRC_TEST_PROVIDER_LVS::testFootprints( NETLIST& aNetlist )
|
||||||
|
|
||||||
if( module == nullptr )
|
if( module == nullptr )
|
||||||
{
|
{
|
||||||
msg.Printf( _( "Missing footprint %s (%s)" ), component->GetReference(),
|
m_msg.Printf( _( "Missing footprint %s (%s)" ), component->GetReference(),
|
||||||
component->GetValue() );
|
component->GetValue() );
|
||||||
|
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_FOOTPRINT );
|
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_FOOTPRINT );
|
||||||
|
|
||||||
drcItem->SetErrorMessage( msg );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
Report( drcItem );
|
Report( drcItem );
|
||||||
|
|
||||||
if( isErrorLimitExceeded( DRCE_MISSING_FOOTPRINT ) )
|
if( isErrorLimitExceeded( DRCE_MISSING_FOOTPRINT ) )
|
||||||
break;
|
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( 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( auto module : mods )
|
for( MODULE* module : board->Modules() )
|
||||||
{
|
{
|
||||||
COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
|
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
|
// fixme: make it work without dependency on EDIT_FRAME/kiway
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -177,7 +231,7 @@ bool test::DRC_TEST_PROVIDER_LVS::fetchNetlistFromSchematic( NETLIST& aNetlist )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test::DRC_TEST_PROVIDER_LVS::Run()
|
bool DRC_TEST_PROVIDER_LVS::Run()
|
||||||
{
|
{
|
||||||
ReportStage( _( "Layout-vs-Schematic checks..." ), 0, 2 );
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -211,5 +265,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_LVS::GetMatchingConstrai
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_LVS> dummy;
|
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_LVS> dummy;
|
||||||
}
|
}
|
|
@ -21,18 +21,12 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 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 <class_pcb_text.h>
|
||||||
|
#include <drc/drc_engine.h>
|
||||||
#include <pcbnew/drc/drc_engine.h>
|
|
||||||
#include <drc/drc.h>
|
#include <drc/drc.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
#include <drc/drc_rule.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_draw_item.h>
|
||||||
#include <ws_proxy_view_item.h>
|
#include <ws_proxy_view_item.h>
|
||||||
|
@ -48,9 +42,6 @@
|
||||||
- if grows too big, split into separate providers
|
- if grows too big, split into separate providers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace test
|
|
||||||
{
|
|
||||||
|
|
||||||
class DRC_TEST_PROVIDER_MISC : public DRC_TEST_PROVIDER
|
class DRC_TEST_PROVIDER_MISC : public DRC_TEST_PROVIDER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -85,10 +76,8 @@ private:
|
||||||
BOARD* m_board;
|
BOARD* m_board;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace test
|
|
||||||
|
|
||||||
|
void DRC_TEST_PROVIDER_MISC::testOutline()
|
||||||
void test::DRC_TEST_PROVIDER_MISC::testOutline()
|
|
||||||
{
|
{
|
||||||
wxPoint error_loc( m_board->GetBoardEdgesBoundingBox().GetPosition() );
|
wxPoint error_loc( m_board->GetBoardEdgesBoundingBox().GetPosition() );
|
||||||
|
|
||||||
|
@ -98,80 +87,86 @@ void test::DRC_TEST_PROVIDER_MISC::testOutline()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
|
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 );
|
drcItem->SetItems( m_board );
|
||||||
|
|
||||||
ReportWithMarker( drcItem, error_loc );
|
ReportWithMarker( drcItem, error_loc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test::DRC_TEST_PROVIDER_MISC::testDisabledLayers()
|
void DRC_TEST_PROVIDER_MISC::testDisabledLayers()
|
||||||
{
|
{
|
||||||
LSET disabledLayers = m_board->GetEnabledLayers().flip();
|
LSET disabledLayers = m_board->GetEnabledLayers().flip();
|
||||||
|
|
||||||
|
|
||||||
// Perform the test only for copper layers
|
// Perform the test only for copper layers
|
||||||
disabledLayers &= LSET::AllCuMask();
|
disabledLayers &= LSET::AllCuMask();
|
||||||
|
|
||||||
auto checkDisabledLayers = [&]( BOARD_ITEM* item ) -> bool {
|
auto checkDisabledLayers =
|
||||||
LSET refLayers ( item->GetLayer() );
|
[&]( BOARD_ITEM* item ) -> bool
|
||||||
|
{
|
||||||
|
LSET refLayers ( item->GetLayer() );
|
||||||
|
|
||||||
if( ( disabledLayers & refLayers ).any() )
|
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 );
|
drcItem->SetItems( item );
|
||||||
|
|
||||||
ReportWithMarker( drcItem, item->GetPosition() );
|
ReportWithMarker( drcItem, item->GetPosition() );
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// fixme: what about graphical items?
|
// fixme: what about graphical items?
|
||||||
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_PAD_T },
|
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 {
|
auto checkUnresolvedTextVar =
|
||||||
EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
|
[&]( 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;
|
||||||
|
|
||||||
if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
|
std::shared_ptr<DRC_ITEM>drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
|
||||||
{
|
drcItem->SetItems( item );
|
||||||
if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
|
ReportWithMarker( drcItem, item->GetPosition() );
|
||||||
drcItem->SetItems( item );
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
ReportWithMarker( drcItem, item->GetPosition() );
|
forEachGeometryItem( { PCB_MODULE_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(),
|
||||||
}
|
checkUnresolvedTextVar );
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
forEachGeometryItem(
|
KIGFX::WS_PROXY_VIEW_ITEM* worksheet = m_drcEngine->GetWorksheet();
|
||||||
{ PCB_MODULE_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(), checkUnresolvedTextVar );
|
WS_DRAW_ITEM_LIST wsItems;
|
||||||
|
|
||||||
WS_DRAW_ITEM_LIST wsItems;
|
|
||||||
|
|
||||||
auto worksheet = m_drcEngine->GetWorksheet();
|
|
||||||
|
|
||||||
if( !worksheet )
|
if( !worksheet )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wsItems.SetMilsToIUfactor( IU_PER_MILS );
|
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() );
|
wsItems.BuildWorkSheetGraphicList( worksheet->GetPageInfo(), worksheet->GetTitleBlock() );
|
||||||
|
|
||||||
for( WS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() )
|
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 ) )
|
if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
|
if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
|
||||||
drcItem->SetItems( text );
|
{
|
||||||
|
std::shared_ptr<DRC_ITEM> 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();
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -215,5 +213,5 @@ std::set<DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_MISC::GetMatchingConstra
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
static DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_MISC> dummy;
|
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_MISC> dummy;
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -21,10 +21,8 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <class_board.h>
|
//#include <common.h>
|
||||||
#include <class_track.h>
|
#include <class_track.h>
|
||||||
#include <common.h>
|
|
||||||
|
|
||||||
#include <drc/drc_engine.h>
|
#include <drc/drc_engine.h>
|
||||||
#include <drc/drc.h>
|
#include <drc/drc.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
|
@ -40,9 +38,6 @@
|
||||||
- DRCE_TOO_SMALL_MICROVIA
|
- DRCE_TOO_SMALL_MICROVIA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace test
|
|
||||||
{
|
|
||||||
|
|
||||||
class DRC_TEST_PROVIDER_VIA_DIAMETER : public DRC_TEST_PROVIDER
|
class DRC_TEST_PROVIDER_VIA_DIAMETER : public DRC_TEST_PROVIDER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -69,12 +64,10 @@ public:
|
||||||
virtual std::set<DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
virtual std::set<DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace test
|
|
||||||
|
|
||||||
|
bool DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
|
||||||
bool test::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." );
|
ReportAux( "No diameter constraints found. Skipping check." );
|
||||||
return false;
|
return false;
|
||||||
|
@ -82,55 +75,57 @@ bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
|
||||||
|
|
||||||
ReportStage( ( "Testing via diameters" ), 0, 2 );
|
ReportStage( ( "Testing via diameters" ), 0, 2 );
|
||||||
|
|
||||||
auto checkViaDiameter = [&]( BOARD_ITEM* item ) -> bool {
|
auto checkViaDiameter =
|
||||||
auto via = dyn_cast<VIA*>( item );
|
[&]( BOARD_ITEM* item ) -> bool
|
||||||
|
{
|
||||||
|
auto via = dyn_cast<VIA*>( item );
|
||||||
|
|
||||||
// fixme: move to pad stack check?
|
// fixme: move to pad stack check?
|
||||||
if( !via )
|
if( !via )
|
||||||
return true;
|
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;
|
if( constraint.Value().HasMin() && actual < constraint.Value().Min() )
|
||||||
int constraintDiameter;
|
{
|
||||||
int diameter = via->GetWidth();
|
fail_min = true;
|
||||||
|
constraintDiameter = constraint.Value().Min();
|
||||||
|
}
|
||||||
|
|
||||||
if( constraint.Value().HasMin() && diameter < constraint.Value().Min() )
|
if( constraint.Value().HasMax() && actual > constraint.Value().Max() )
|
||||||
{
|
{
|
||||||
fail_min = true;
|
fail_max = true;
|
||||||
constraintDiameter = constraint.Value().Min();
|
constraintDiameter = constraint.Value().Max();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( constraint.Value().HasMax() && diameter > constraint.Value().Max() )
|
if( fail_min || fail_max )
|
||||||
{
|
{
|
||||||
fail_max = true;
|
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_VIA_DIAMETER );
|
||||||
constraintDiameter = constraint.Value().Max();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( fail_min || fail_max )
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s diameter %s; actual %s)" ),
|
||||||
{
|
constraint.GetName(),
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_VIA_DIAMETER );
|
fail_min ? _( "minimum" ) : _( "maximum" ),
|
||||||
wxString msg;
|
MessageTextFromValue( userUnits(), constraintDiameter, true ) );
|
||||||
|
MessageTextFromValue( userUnits(), actual, true ),
|
||||||
|
|
||||||
msg.Printf( drcItem->GetErrorText() + _( " (%s; diameter %s, constraint %s %s)" ),
|
drcItem->SetErrorMessage( m_msg );
|
||||||
constraint.GetParentRule()->m_Name,
|
drcItem->SetItems( item );
|
||||||
MessageTextFromValue( userUnits(), diameter, true ),
|
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||||
fail_min ? _( "minimum" ) : _( "maximum" ),
|
|
||||||
MessageTextFromValue( userUnits(), constraintDiameter, true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( msg );
|
ReportWithMarker( drcItem, via->GetPosition() );
|
||||||
drcItem->SetItems( item );
|
|
||||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
|
||||||
|
|
||||||
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 );
|
forEachGeometryItem( { PCB_VIA_T }, LSET::AllCuMask(), checkViaDiameter );
|
||||||
|
|
||||||
|
@ -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 };
|
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
|
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;
|
||||||
}
|
}
|
|
@ -34,7 +34,6 @@ endif()
|
||||||
|
|
||||||
|
|
||||||
add_executable( drc_proto
|
add_executable( drc_proto
|
||||||
drc_rules_proto_keywords.cpp
|
|
||||||
drc_proto_test.cpp
|
drc_proto_test.cpp
|
||||||
../../pcbnew/drc/drc_rule.cpp
|
../../pcbnew/drc/drc_rule.cpp
|
||||||
../../pcbnew/drc/drc_rule_parser.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_copper_clearance.cpp
|
||||||
../../pcbnew/drc/drc_test_provider_hole_clearance.cpp
|
../../pcbnew/drc/drc_test_provider_hole_clearance.cpp
|
||||||
../../pcbnew/drc/drc_test_provider_edge_clearance.cpp
|
../../pcbnew/drc/drc_test_provider_edge_clearance.cpp
|
||||||
drc_test_provider_hole_size.cpp
|
../../pcbnew/drc/drc_test_provider_hole_size.cpp
|
||||||
drc_test_provider_disallow.cpp
|
../../pcbnew/drc/drc_test_provider_disallow.cpp
|
||||||
drc_test_provider_track_width.cpp
|
../../pcbnew/drc/drc_test_provider_track_width.cpp
|
||||||
drc_test_provider_annulus.cpp
|
../../pcbnew/drc/drc_test_provider_annulus.cpp
|
||||||
drc_test_provider_connectivity.cpp
|
../../pcbnew/drc/drc_test_provider_connectivity.cpp
|
||||||
../../pcbnew/drc/drc_test_provider_courtyard_clearance.cpp
|
../../pcbnew/drc/drc_test_provider_courtyard_clearance.cpp
|
||||||
drc_test_provider_via_diameter.cpp
|
../../pcbnew/drc/drc_test_provider_via_diameter.cpp
|
||||||
drc_test_provider_lvs.cpp
|
../../pcbnew/drc/drc_test_provider_lvs.cpp
|
||||||
drc_test_provider_misc.cpp
|
../../pcbnew/drc/drc_test_provider_misc.cpp
|
||||||
../../pcbnew/drc/drc_engine.cpp
|
../../pcbnew/drc/drc_engine.cpp
|
||||||
../../pcbnew/drc/drc_item.cpp
|
../../pcbnew/drc/drc_item.cpp
|
||||||
../qa_utils/mocks.cpp
|
../qa_utils/mocks.cpp
|
||||||
|
@ -114,12 +113,3 @@ target_link_libraries( drc_proto
|
||||||
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
|
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
|
||||||
${wxWidgets_LIBRARIES}
|
${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
|
|
||||||
)
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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_ */
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
Loading…
Reference in New Issue