Update DRC rules to new layer and disallow grammars.
Also adds support for hooking rules up to named zones. Fixes https://gitlab.com/kicad/code/kicad/issues/2041
This commit is contained in:
parent
406de56964
commit
e5b50d90a7
|
@ -360,9 +360,9 @@ void AR_AUTOPLACER::buildFpAreas( MODULE* aFootprint, int aFpClearance )
|
|||
addFpBody( fpBBox.GetOrigin(), fpBBox.GetEnd(), layerMask );
|
||||
|
||||
// Trace pads + clearance areas.
|
||||
for( auto pad : aFootprint->Pads() )
|
||||
for( D_PAD* pad : aFootprint->Pads() )
|
||||
{
|
||||
int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance();
|
||||
int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance( pad->GetLayer() );
|
||||
addPad( pad, margin );
|
||||
}
|
||||
}
|
||||
|
@ -414,9 +414,9 @@ void AR_AUTOPLACER::genModuleOnRoutingMatrix( MODULE* Module )
|
|||
CELL_IS_MODULE, AR_MATRIX::WRITE_OR_CELL );
|
||||
|
||||
// Trace pads + clearance areas.
|
||||
for( auto pad : Module->Pads() )
|
||||
for( D_PAD* pad : Module->Pads() )
|
||||
{
|
||||
int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance();
|
||||
int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance( pad->GetLayer() );
|
||||
m_matrix.PlacePad( pad, CELL_IS_MODULE, margin, AR_MATRIX::WRITE_OR_CELL );
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,8 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetEffectiveNetclass() const
|
|||
* LEVEL 2: Rules
|
||||
* LEVEL 3: Accumulated local settings, netclass settings, & board design settings
|
||||
*/
|
||||
int BOARD_CONNECTED_ITEM::GetClearance( BOARD_ITEM* aItem, wxString* aSource ) const
|
||||
int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem,
|
||||
wxString* aSource ) const
|
||||
{
|
||||
BOARD* board = GetBoard();
|
||||
int clearance = 0;
|
||||
|
@ -122,7 +123,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( BOARD_ITEM* aItem, wxString* aSource ) c
|
|||
|
||||
// LEVEL 2: Rules
|
||||
//
|
||||
if( GetRuleClearance( aItem, &clearance, aSource ) )
|
||||
if( GetRuleClearance( aItem, aLayer, &clearance, aSource ) )
|
||||
return clearance;
|
||||
|
||||
// LEVEL 3: Accumulated local settings, netclass settings, & board design settings
|
||||
|
@ -163,17 +164,18 @@ int BOARD_CONNECTED_ITEM::GetClearance( BOARD_ITEM* aItem, wxString* aSource ) c
|
|||
}
|
||||
|
||||
|
||||
bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, int* aClearance,
|
||||
wxString* aSource ) const
|
||||
bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer,
|
||||
int* aClearance, wxString* aSource ) const
|
||||
{
|
||||
DRC_RULE* rule = GetRule( this, aItem, CLEARANCE_CONSTRAINT );
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( this, aItem, DRC_RULE_ID_CLEARANCE, aLayer,
|
||||
aSource );
|
||||
|
||||
if( rule )
|
||||
if( constraint )
|
||||
{
|
||||
if( aSource )
|
||||
*aSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
||||
*aSource = wxString::Format( _( "'%s' rule" ), *aSource );
|
||||
|
||||
*aClearance = rule->m_Clearance.Min;
|
||||
*aClearance = constraint->m_Value.Min();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,20 +161,24 @@ public:
|
|||
* returned clearance is the greater of this object's NETCLASS clearance and
|
||||
* aItem's NETCLASS clearance. If \a aItem is NULL, then this objects clearance
|
||||
* is returned.
|
||||
* @param aLayer the layer in question
|
||||
* @param aItem is an optional BOARD_ITEM
|
||||
* @param aSource [out] optionally reports the source as a user-readable string
|
||||
* @return int - the clearance in internal units.
|
||||
*/
|
||||
virtual int GetClearance( BOARD_ITEM* aItem = nullptr, wxString* aSource = nullptr ) const;
|
||||
virtual int GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem = nullptr,
|
||||
wxString* aSource = nullptr ) const;
|
||||
|
||||
/**
|
||||
* Function GetRuleClearance
|
||||
* returns any rule-based clearance.
|
||||
* @param aLayer the current layer under test
|
||||
* @param aClearance [out] the clearance value in internal units
|
||||
* @param aSource [out] reports the source as a user-readable string
|
||||
* @return true if a rule was fired
|
||||
*/
|
||||
virtual bool GetRuleClearance( BOARD_ITEM* aItem, int* aClearance, wxString* aSource ) const;
|
||||
virtual bool GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int* aClearance,
|
||||
wxString* aSource ) const;
|
||||
|
||||
/**
|
||||
* Function GetLocalClearanceOverrides
|
||||
|
|
|
@ -822,7 +822,13 @@ int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue()
|
|||
clearance = std::max( clearance, netclass.second->GetClearance() );
|
||||
|
||||
for( const DRC_RULE* rule : m_DRCRules )
|
||||
clearance = std::max( clearance, rule->m_Clearance.Min );
|
||||
{
|
||||
for( const DRC_CONSTRAINT& constraint : rule->m_Constraints )
|
||||
{
|
||||
if( constraint.m_Type == DRC_RULE_ID_CLEARANCE )
|
||||
clearance = std::max( clearance, constraint.m_Value.Min() );
|
||||
}
|
||||
}
|
||||
|
||||
return clearance;
|
||||
}
|
||||
|
|
|
@ -825,7 +825,7 @@ void D_PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>
|
|||
}
|
||||
|
||||
wxString source;
|
||||
int clearance = GetClearance( nullptr, &source );
|
||||
int clearance = GetClearance( GetLayer(), nullptr, &source );
|
||||
|
||||
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
||||
msg2.Printf( _( "(from %s)" ), source );
|
||||
|
|
|
@ -133,15 +133,16 @@ void TRACK::GetWidthConstraints( int* aMin, int* aMax, wxString* aSource ) const
|
|||
// Not currently implemented
|
||||
|
||||
// LEVEL 2: Rules
|
||||
DRC_RULE* rule = GetRule( this, nullptr, TRACK_CONSTRAINT );
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_TRACK, m_Layer,
|
||||
aSource );
|
||||
|
||||
if( rule )
|
||||
if( constraint )
|
||||
{
|
||||
*aMin = rule->m_TrackConstraint.Min;
|
||||
*aMax = rule->m_TrackConstraint.Max;
|
||||
*aMin = constraint->m_Value.Min();
|
||||
*aMax = constraint->m_Value.Max();
|
||||
|
||||
if( aSource )
|
||||
*aSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
||||
*aSource = wxString::Format( _( "'%s' rule" ), *aSource );
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -160,16 +161,17 @@ void TRACK::GetWidthConstraints( int* aMin, int* aMax, wxString* aSource ) const
|
|||
}
|
||||
|
||||
|
||||
int VIA::GetMinAnnulus( wxString* aSource ) const
|
||||
int VIA::GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const
|
||||
{
|
||||
DRC_RULE* rule = GetRule( this, nullptr, ANNULUS_CONSTRAINT );
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_ANNULUS, aLayer,
|
||||
aSource );
|
||||
|
||||
if( rule )
|
||||
if( constraint )
|
||||
{
|
||||
if( aSource )
|
||||
*aSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
||||
*aSource = wxString::Format( _( "'%s' rule" ), *aSource );
|
||||
|
||||
return rule->m_MinAnnulusWidth;
|
||||
return constraint->m_Value.Min();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -493,7 +495,7 @@ unsigned int TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
|
|||
const BOX2I TRACK::ViewBBox() const
|
||||
{
|
||||
BOX2I bbox = GetBoundingBox();
|
||||
bbox.Inflate( 2 * GetClearance() );
|
||||
bbox.Inflate( 2 * GetClearance( GetLayer() ) );
|
||||
return bbox;
|
||||
}
|
||||
|
||||
|
@ -612,7 +614,7 @@ void TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>
|
|||
}
|
||||
}
|
||||
|
||||
int clearance = GetClearance( nullptr, &source );
|
||||
int clearance = GetClearance( GetLayer(), nullptr, &source );
|
||||
|
||||
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
||||
msg2.Printf( _( "(from %s)" ), source );
|
||||
|
@ -685,13 +687,13 @@ void VIA::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
|
|||
|
||||
aList.emplace_back( _( "Drill" ), msg, RED );
|
||||
|
||||
int clearance = GetClearance( nullptr, &source );
|
||||
int clearance = GetClearance( GetLayer(), nullptr, &source );
|
||||
|
||||
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
||||
msg2.Printf( _( "(from %s)" ), source );
|
||||
aList.emplace_back( msg, msg2, BLACK );
|
||||
|
||||
int minAnnulus = GetMinAnnulus( &source );
|
||||
int minAnnulus = GetMinAnnulus( GetLayer(), &source );
|
||||
|
||||
msg.Printf( _( "Min Annulus: %s" ), MessageTextFromValue( units, minAnnulus, true ) );
|
||||
msg2.Printf( _( "(from %s)" ), source );
|
||||
|
|
|
@ -442,7 +442,7 @@ public:
|
|||
void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
|
||||
int GetMinAnnulus( wxString* aSource ) const;
|
||||
int GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const;
|
||||
|
||||
/**
|
||||
* Function SetDrill
|
||||
|
|
|
@ -336,7 +336,7 @@ int ZONE_CONTAINER::GetThermalReliefCopperBridge( D_PAD* aPad ) const
|
|||
}
|
||||
|
||||
|
||||
int ZONE_CONTAINER::GetKeepouts( std::map<int, wxString>* aSources ) const
|
||||
int ZONE_CONTAINER::GetKeepouts( PCB_LAYER_ID aLayer, std::map<int, wxString>* aSources ) const
|
||||
{
|
||||
wxString source;
|
||||
int keepouts = 0;
|
||||
|
@ -370,41 +370,42 @@ int ZONE_CONTAINER::GetKeepouts( std::map<int, wxString>* aSources ) const
|
|||
setFlag( DISALLOW_ZONES );
|
||||
}
|
||||
|
||||
DRC_RULE* rule = GetRule( this, nullptr, DISALLOW_CONSTRAINT );
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_DISALLOW, aLayer,
|
||||
&source );
|
||||
|
||||
if( rule )
|
||||
if( constraint )
|
||||
{
|
||||
if( aSources )
|
||||
source = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
||||
source = wxString::Format( _( "'%s' rule" ), source );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_VIAS ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_VIAS ) > 0 )
|
||||
setFlag( DISALLOW_VIAS );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_MICRO_VIAS ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_MICRO_VIAS ) > 0 )
|
||||
setFlag( DISALLOW_MICRO_VIAS );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_BB_VIAS ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_BB_VIAS ) > 0 )
|
||||
setFlag( DISALLOW_BB_VIAS );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_TRACKS ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_TRACKS ) > 0 )
|
||||
setFlag( DISALLOW_TRACKS );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_PADS ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_PADS ) > 0 )
|
||||
setFlag( DISALLOW_PADS );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_ZONES ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_ZONES ) > 0 )
|
||||
setFlag( DISALLOW_ZONES );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_TEXTS ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_TEXTS ) > 0 )
|
||||
setFlag( DISALLOW_TEXTS );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_GRAPHICS ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_GRAPHICS ) > 0 )
|
||||
setFlag( DISALLOW_GRAPHICS );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_HOLES ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_HOLES ) > 0 )
|
||||
setFlag( DISALLOW_HOLES );
|
||||
|
||||
if( ( rule->m_DisallowFlags & DISALLOW_FOOTPRINTS ) > 0 )
|
||||
if( ( constraint->m_DisallowFlags & DISALLOW_FOOTPRINTS ) > 0 )
|
||||
setFlag( DISALLOW_FOOTPRINTS );
|
||||
}
|
||||
|
||||
|
@ -678,7 +679,7 @@ void ZONE_CONTAINER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
|
|||
aList.emplace_back( _( "Filled Area" ), msg, BLUE );
|
||||
|
||||
wxString source;
|
||||
int clearance = GetClearance( nullptr, &source );
|
||||
int clearance = GetClearance( GetLayer(), nullptr, &source );
|
||||
|
||||
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
||||
msg2.Printf( _( "(from %s)" ), source );
|
||||
|
@ -1374,6 +1375,8 @@ static struct ZONE_CONTAINER_DESC
|
|||
//&ZONE_CONTAINER::SetIsFilled, &ZONE_CONTAINER::IsFilled ) );
|
||||
propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _( "Min Thickness" ),
|
||||
&ZONE_CONTAINER::SetMinThickness, &ZONE_CONTAINER::GetMinThickness, PROPERTY_DISPLAY::DISTANCE ) );
|
||||
propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, wxString>( _( "Name" ),
|
||||
&ZONE_CONTAINER::SetZoneName, &ZONE_CONTAINER::GetZoneName ) );
|
||||
// TODO pad connection, thermal relief gap, thermal relief copper bridge
|
||||
}
|
||||
} _ZONE_CONTAINER_DESC;
|
||||
|
|
|
@ -723,7 +723,7 @@ public:
|
|||
* flag.
|
||||
* @return a bitset of DISALLOW_* flags.
|
||||
*/
|
||||
int GetKeepouts( std::map<int, wxString>* aSources = nullptr ) const;
|
||||
int GetKeepouts( PCB_LAYER_ID aLayer, std::map<int, wxString>* aSources = nullptr ) const;
|
||||
|
||||
void SetIsKeepout( bool aEnable ) { m_isKeepout = aEnable; }
|
||||
void SetDoNotAllowCopperPour( bool aEnable ) { m_doNotAllowCopperPour = aEnable; }
|
||||
|
|
|
@ -179,21 +179,38 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
|
|||
if( sexprs.empty() )
|
||||
tokens = "rule version";
|
||||
else if( sexprs.top() == "rule" )
|
||||
tokens = "condition constraint disallow layer";
|
||||
tokens = "condition constraint layer";
|
||||
else if( sexprs.top() == "constraint" )
|
||||
tokens = "max min opt";
|
||||
}
|
||||
else if( context == SEXPR_TOKEN )
|
||||
{
|
||||
if( sexprs.empty() )
|
||||
/* badly formed grammar */;
|
||||
{
|
||||
/* badly formed grammar */
|
||||
}
|
||||
else if( sexprs.top() == "constraint" )
|
||||
tokens = "annulus_width clearance hole track_width";
|
||||
else if( sexprs.top() == "disallow" )
|
||||
{
|
||||
tokens = "annulus_width clearance disallow hole track_width";
|
||||
}
|
||||
else if( sexprs.top() == "disallow"
|
||||
|| sexprs.top() == "buried_via"
|
||||
|| sexprs.top() == "graphic"
|
||||
|| sexprs.top() == "hole"
|
||||
|| sexprs.top() == "micro_via"
|
||||
|| sexprs.top() == "pad"
|
||||
|| sexprs.top() == "text"
|
||||
|| sexprs.top() == "track"
|
||||
|| sexprs.top() == "via"
|
||||
|| sexprs.top() == "zone" )
|
||||
{
|
||||
tokens = "buried_via graphic hole micro_via pad text track via zone";
|
||||
}
|
||||
else if( sexprs.top() == "layer" )
|
||||
{
|
||||
tokens = "inner outer \"x\"";
|
||||
}
|
||||
}
|
||||
else if( context == STRING && expr_context == STRUCT_REF )
|
||||
{
|
||||
if( !sexprs.empty() && sexprs.top() == "condition" )
|
||||
|
@ -327,11 +344,16 @@ void PANEL_SETUP_RULES::OnSyntaxHelp( wxHyperlinkEvent& aEvent )
|
|||
msg << _( "Rule Clauses" );
|
||||
msg << "</b>"
|
||||
"<pre>"
|
||||
"(disallow <item_type>)\r"
|
||||
"(constraint <constraint_type> ...)\r"
|
||||
"(condition \"<expression>\")\r"
|
||||
"\r</pre>"
|
||||
"<b>";
|
||||
msg << _( "Constraint Types" );
|
||||
msg << "</b>"
|
||||
"<pre>"
|
||||
"clearance annulus_width track_width hole dissallow\r"
|
||||
"\r</pre>"
|
||||
"<b>";
|
||||
msg << _( "Item Types" );
|
||||
msg << "</b>"
|
||||
"<pre>"
|
||||
|
@ -340,17 +362,11 @@ void PANEL_SETUP_RULES::OnSyntaxHelp( wxHyperlinkEvent& aEvent )
|
|||
"hole buried_via graphic\r"
|
||||
"\r</pre>"
|
||||
"<b>";
|
||||
msg << _( "Constraint Types" );
|
||||
msg << "</b>"
|
||||
"<pre>"
|
||||
"clearance annulus_width track_width hole\r"
|
||||
"\r</pre>"
|
||||
"<b>";
|
||||
msg << _( "Examples" );
|
||||
msg << "</b>"
|
||||
"<pre>"
|
||||
"(rule \"copper keepout\"\r"
|
||||
" (disallow track) (disallow via) (disallow zone)\r"
|
||||
" (constraint disallow track via zone)\r"
|
||||
" (condition \"A.name == 'no_copper'\"))\r"
|
||||
"\r"
|
||||
"(rule \"BGA neckdown\"\r"
|
||||
|
|
|
@ -502,10 +502,7 @@ void DRC::testPadClearances( BOARD_COMMIT& aCommit )
|
|||
static DRAWSEGMENT dummyEdge;
|
||||
dummyEdge.SetLayer( Edge_Cuts );
|
||||
|
||||
if( pad->GetRuleClearance( &dummyEdge, &minClearance, &m_clearanceSource ) )
|
||||
{
|
||||
/* minClearance and m_clearanceSource set in GetRuleClearance() */;
|
||||
}
|
||||
pad->GetRuleClearance( &dummyEdge, pad->GetLayer(), &minClearance, &m_clearanceSource );
|
||||
|
||||
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
||||
{
|
||||
|
@ -723,7 +720,8 @@ void DRC::testZones( BOARD_COMMIT& aCommit )
|
|||
// Get clearance used in zone to zone test. The policy used to
|
||||
// obtain that value is now part of the zone object itself by way of
|
||||
// ZONE_CONTAINER::GetClearance().
|
||||
int zone2zoneClearance = zoneRef->GetClearance( zoneToTest, &m_clearanceSource );
|
||||
int zone2zoneClearance = zoneRef->GetClearance( zoneRef->GetLayer(), zoneToTest,
|
||||
&m_clearanceSource );
|
||||
|
||||
// Keepout areas have no clearance, so set zone2zoneClearance to 1
|
||||
// ( zone2zoneClearance = 0 can create problems in test functions)
|
||||
|
@ -907,12 +905,12 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
|||
SHAPE_RECT bboxShape( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
|
||||
|
||||
// Test tracks and vias
|
||||
for( auto track : m_pcb->Tracks() )
|
||||
for( TRACK* track : m_pcb->Tracks() )
|
||||
{
|
||||
if( !track->IsOnLayer( aItem->GetLayer() ) )
|
||||
continue;
|
||||
|
||||
int minClearance = track->GetClearance( aItem, &m_clearanceSource );
|
||||
int minClearance = track->GetClearance( track->GetLayer(), aItem, &m_clearanceSource );
|
||||
int actual = INT_MAX;
|
||||
wxPoint pos;
|
||||
|
||||
|
@ -954,7 +952,7 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
|||
}
|
||||
|
||||
// Test pads
|
||||
for( auto pad : m_pcb->GetPads() )
|
||||
for( D_PAD* pad : m_pcb->GetPads() )
|
||||
{
|
||||
if( !pad->IsOnLayer( aItem->GetLayer() ) )
|
||||
continue;
|
||||
|
@ -963,7 +961,7 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
|||
if( drawItem && pad->GetParent() == drawItem->GetParent() )
|
||||
continue;
|
||||
|
||||
int minClearance = pad->GetClearance( aItem, &m_clearanceSource );
|
||||
int minClearance = pad->GetClearance( aItem->GetLayer(), aItem, &m_clearanceSource );
|
||||
int actual = INT_MAX;
|
||||
|
||||
// Fast test to detect a pad candidate inside the text bounding box
|
||||
|
@ -1136,7 +1134,8 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
|
||||
if( pad->GetDrillSize().x )
|
||||
{
|
||||
int minClearance = aRefPad->GetClearance( nullptr, &m_clearanceSource );
|
||||
int minClearance = aRefPad->GetClearance( aRefPad->GetLayer(), nullptr,
|
||||
&m_clearanceSource );
|
||||
int actual;
|
||||
|
||||
if( aRefPad->Collide( pad->GetEffectiveHoleShape(), minClearance, &actual ) )
|
||||
|
@ -1159,7 +1158,8 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
|
||||
if( aRefPad->GetDrillSize().x )
|
||||
{
|
||||
int minClearance = pad->GetClearance( nullptr, &m_clearanceSource );
|
||||
int minClearance = pad->GetClearance( pad->GetLayer(), nullptr,
|
||||
&m_clearanceSource );
|
||||
int actual;
|
||||
|
||||
if( pad->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) )
|
||||
|
@ -1216,7 +1216,9 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
continue;
|
||||
}
|
||||
|
||||
int minClearance = aRefPad->GetClearance( pad, &m_clearanceSource );
|
||||
for( PCB_LAYER_ID layer : aRefPad->GetLayerSet().Seq() )
|
||||
{
|
||||
int minClearance = aRefPad->GetClearance( layer, pad, &m_clearanceSource );
|
||||
int clearanceAllowed = minClearance - m_pcb->GetDesignSettings().GetDRCEpsilon();
|
||||
int actual;
|
||||
|
||||
|
@ -1237,6 +1239,7 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
{
|
||||
VIA *refvia = static_cast<VIA*>( aRefSeg );
|
||||
int viaAnnulus = ( refvia->GetWidth() - refvia->GetDrill() ) / 2;
|
||||
int minAnnulus = refvia->GetMinAnnulus( &m_clearanceSource );
|
||||
int minAnnulus = refvia->GetMinAnnulus( refvia->GetLayer(), &m_clearanceSource );
|
||||
|
||||
// test if the via size is smaller than minimum
|
||||
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
||||
|
@ -281,19 +281,21 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
if( pad->GetDrillSize().x > 0 )
|
||||
{
|
||||
const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape();
|
||||
DRC_RULE* rule = GetRule( aRefSeg, pad, CLEARANCE_CONSTRAINT );
|
||||
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( aRefSeg, pad,
|
||||
DRC_RULE_ID_CLEARANCE, refLayer,
|
||||
&m_clearanceSource );
|
||||
int minClearance;
|
||||
int actual;
|
||||
|
||||
if( rule )
|
||||
if( constraint )
|
||||
{
|
||||
m_clearanceSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
||||
minClearance = rule->m_Clearance.Min;
|
||||
m_clearanceSource = wxString::Format( _( "'%s' rule" ), m_clearanceSource );
|
||||
minClearance = constraint->m_Value.Min();
|
||||
}
|
||||
else
|
||||
{
|
||||
minClearance = aRefSeg->GetClearance( nullptr, &m_clearanceSource );
|
||||
minClearance = aRefSeg->GetClearance( refLayer, nullptr,
|
||||
&m_clearanceSource );
|
||||
}
|
||||
|
||||
if( slot->Collide( &refSeg, minClearance + bds.GetDRCEpsilon(), &actual ) )
|
||||
|
@ -316,7 +318,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
}
|
||||
}
|
||||
|
||||
int minClearance = aRefSeg->GetClearance( pad, &m_clearanceSource );
|
||||
int minClearance = aRefSeg->GetClearance( aRefSeg->GetLayer(), pad,
|
||||
&m_clearanceSource );
|
||||
int actual;
|
||||
|
||||
if( pad->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual ) )
|
||||
|
@ -383,7 +386,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
if( !trackBB.Intersects( refSegBB ) )
|
||||
continue;
|
||||
|
||||
int minClearance = aRefSeg->GetClearance( track, &m_clearanceSource );
|
||||
int minClearance = aRefSeg->GetClearance( aRefSeg->GetLayer(), track,
|
||||
&m_clearanceSource );
|
||||
int actual;
|
||||
SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
|
||||
|
||||
|
@ -447,7 +451,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
// (1 micron)
|
||||
#define THRESHOLD_DIST Millimeter2iu( 0.001 )
|
||||
|
||||
int minClearance = aRefSeg->GetClearance( zone, &m_clearanceSource );
|
||||
int minClearance = aRefSeg->GetClearance( aRefSeg->GetLayer(), zone,
|
||||
&m_clearanceSource );
|
||||
int widths = refSegWidth / 2;
|
||||
int allowedDist = minClearance + widths + THRESHOLD_DIST;
|
||||
int actual;
|
||||
|
@ -483,10 +488,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
static DRAWSEGMENT dummyEdge;
|
||||
dummyEdge.SetLayer( Edge_Cuts );
|
||||
|
||||
if( aRefSeg->GetRuleClearance( &dummyEdge, &minClearance, &m_clearanceSource ) )
|
||||
{
|
||||
/* minClearance and m_clearanceSource set in GetRuleClearance() */;
|
||||
}
|
||||
aRefSeg->GetRuleClearance( &dummyEdge, aRefSeg->GetLayer(), &minClearance,
|
||||
&m_clearanceSource );
|
||||
|
||||
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
||||
int halfWidth = refSegWidth / 2;
|
||||
|
|
|
@ -84,6 +84,8 @@ bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad )
|
|||
bool success = true;
|
||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||
|
||||
// drilled holes go all the way through, so which layer we use shouldn't matter
|
||||
PCB_LAYER_ID layer = F_Cu;
|
||||
int holeSize = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
|
||||
|
||||
if( holeSize == 0 )
|
||||
|
@ -91,14 +93,19 @@ bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad )
|
|||
|
||||
if( !bds.Ignore( DRCE_TOO_SMALL_DRILL ) )
|
||||
{
|
||||
int minHole = bds.m_MinThroughDrill;
|
||||
wxString minHoleSource = _( "board minimum" );
|
||||
DRC_RULE* rule = GetRule( aPad, nullptr, HOLE_CONSTRAINT );
|
||||
int minHole;
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( aPad, nullptr, DRC_RULE_ID_HOLE_SIZE,
|
||||
layer, &m_source );
|
||||
|
||||
if( rule )
|
||||
if( constraint )
|
||||
{
|
||||
minHole = rule->m_MinHole;
|
||||
minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
||||
minHole = constraint->m_Value.Min();
|
||||
m_source = wxString::Format( _( "'%s' rule" ), m_source );
|
||||
}
|
||||
else
|
||||
{
|
||||
minHole = bds.m_MinThroughDrill;
|
||||
m_source = _( "board minimum" );
|
||||
}
|
||||
|
||||
if( holeSize < minHole )
|
||||
|
@ -106,7 +113,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad )
|
|||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
||||
minHoleSource,
|
||||
m_source,
|
||||
MessageTextFromValue( m_units, minHole, true ),
|
||||
MessageTextFromValue( m_units, holeSize, true ) );
|
||||
|
||||
|
@ -132,16 +139,24 @@ bool DRC_DRILLED_HOLE_TESTER::checkVia( VIA* via )
|
|||
bool success = true;
|
||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||
|
||||
// drilled holes go all the way through, so which layer we use shouldn't matter
|
||||
PCB_LAYER_ID layer = F_Cu;
|
||||
|
||||
if( !bds.Ignore( DRCE_TOO_SMALL_DRILL ) )
|
||||
{
|
||||
int minHole = bds.m_MinThroughDrill;
|
||||
wxString minHoleSource = _( "board minimum" );
|
||||
DRC_RULE* rule = GetRule( via, nullptr, HOLE_CONSTRAINT );
|
||||
int minHole;
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( via, nullptr, DRC_RULE_ID_HOLE_SIZE,
|
||||
layer, &m_source );
|
||||
|
||||
if( rule )
|
||||
if( constraint )
|
||||
{
|
||||
minHole = rule->m_MinHole;
|
||||
minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
||||
minHole = constraint->m_Value.Min();
|
||||
m_source = wxString::Format( _( "'%s' rule" ), m_source );
|
||||
}
|
||||
else
|
||||
{
|
||||
minHole = bds.m_MinThroughDrill;
|
||||
m_source = _( "board minimum" );
|
||||
}
|
||||
|
||||
if( via->GetDrillValue() < minHole )
|
||||
|
@ -149,7 +164,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkVia( VIA* via )
|
|||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
||||
minHoleSource,
|
||||
m_source,
|
||||
MessageTextFromValue( m_units, minHole, true ),
|
||||
MessageTextFromValue( m_units, via->GetDrillValue(), true ) );
|
||||
|
||||
|
@ -175,16 +190,25 @@ bool DRC_DRILLED_HOLE_TESTER::checkMicroVia( VIA* via )
|
|||
bool success = true;
|
||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||
|
||||
// while microvia holes don't necessarily go all the way through, they can't be different
|
||||
// sizes on different layers so we should still be safe enough using a fixed layer.
|
||||
PCB_LAYER_ID layer = F_Cu;
|
||||
|
||||
if( !bds.Ignore( DRCE_TOO_SMALL_MICROVIA_DRILL ) )
|
||||
{
|
||||
int minHole = bds.m_MicroViasMinDrill;
|
||||
wxString minHoleSource = _( "board minimum" );
|
||||
DRC_RULE* rule = GetRule( via, nullptr, HOLE_CONSTRAINT );
|
||||
int minHole;
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( via, nullptr, DRC_RULE_ID_HOLE_SIZE,
|
||||
layer, &m_source );
|
||||
|
||||
if( rule )
|
||||
if( constraint )
|
||||
{
|
||||
minHole = rule->m_MinHole;
|
||||
minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
||||
minHole = constraint->m_Value.Min();
|
||||
m_source = wxString::Format( _( "'%s' rule" ), m_source );
|
||||
}
|
||||
else
|
||||
{
|
||||
minHole = bds.m_MicroViasMinDrill;
|
||||
m_source = _( "board minimum" );
|
||||
}
|
||||
|
||||
if( via->GetDrillValue() < minHole )
|
||||
|
@ -192,7 +216,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkMicroVia( VIA* via )
|
|||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_MICROVIA_DRILL );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
||||
minHoleSource,
|
||||
m_source,
|
||||
MessageTextFromValue( m_units, minHole, true ),
|
||||
MessageTextFromValue( m_units, via->GetDrillValue(), true ) );
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ private:
|
|||
std::vector<DRILLED_HOLE> m_holes;
|
||||
int m_largestRadius;
|
||||
|
||||
wxString m_source; // Construct only once for performance
|
||||
wxString m_msg; // Construct only once for performance
|
||||
};
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ bool DRC_KEEPOUT_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard )
|
|||
// Test keepout areas for vias, tracks and pads inside keepout areas
|
||||
for( ZONE_CONTAINER* area : areasToInspect )
|
||||
{
|
||||
m_keepoutFlags = area->GetKeepouts( &m_sources );
|
||||
// JEY TODO: our existing keepout strategy needs a work-over for rules....
|
||||
m_keepoutFlags = area->GetKeepouts( F_Cu, &m_sources );
|
||||
|
||||
if( m_keepoutFlags > 0 )
|
||||
{
|
||||
|
|
|
@ -23,13 +23,15 @@
|
|||
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <drc/drc_rule.h>
|
||||
#include <class_board.h>
|
||||
#include <class_board_item.h>
|
||||
|
||||
#include <drc/drc_rule.h>
|
||||
#include <pcb_expr_evaluator.h>
|
||||
|
||||
|
||||
DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint )
|
||||
const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
|
||||
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName )
|
||||
{
|
||||
BOARD* board = aItem->GetBoard();
|
||||
|
||||
|
@ -38,13 +40,32 @@ DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstr
|
|||
|
||||
for( DRC_RULE* rule : board->GetDesignSettings().m_DRCRules )
|
||||
{
|
||||
if( ( rule->m_ConstraintFlags & aConstraint ) > 0 )
|
||||
{
|
||||
if( rule->m_Condition.EvaluateFor( aItem, bItem ) )
|
||||
return rule;
|
||||
if( !rule->m_LayerCondition.test( aLayer ) )
|
||||
continue;
|
||||
|
||||
if( bItem && rule->m_Condition.EvaluateFor( bItem, aItem ) )
|
||||
return rule;
|
||||
for( const DRC_CONSTRAINT& constraint : rule->m_Constraints )
|
||||
{
|
||||
if( constraint.m_Type != aConstraint )
|
||||
continue;
|
||||
|
||||
if( !rule->m_LayerCondition.test( aLayer ) )
|
||||
continue;
|
||||
|
||||
if( rule->m_Condition.EvaluateFor( aItem, bItem, aLayer ) )
|
||||
{
|
||||
if( aRuleName )
|
||||
*aRuleName = rule->m_Name;
|
||||
|
||||
return &constraint;
|
||||
}
|
||||
|
||||
if( bItem && rule->m_Condition.EvaluateFor( bItem, aItem, aLayer ) )
|
||||
{
|
||||
if( aRuleName )
|
||||
*aRuleName = rule->m_Name;
|
||||
|
||||
return &constraint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +73,17 @@ DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstr
|
|||
}
|
||||
|
||||
|
||||
DRC_RULE::DRC_RULE() :
|
||||
m_LayerCondition( LSET::AllLayersMask() )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DRC_RULE::~DRC_RULE()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DRC_RULE_CONDITION::DRC_RULE_CONDITION()
|
||||
{
|
||||
m_ucode = nullptr;
|
||||
|
@ -64,7 +96,8 @@ DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
|
|||
}
|
||||
|
||||
|
||||
bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB )
|
||||
bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
|
||||
PCB_LAYER_ID aLayer )
|
||||
{
|
||||
// An unconditional rule is always true
|
||||
if( m_Expression.IsEmpty() )
|
||||
|
@ -77,7 +110,7 @@ bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM
|
|||
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
|
||||
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
|
||||
|
||||
PCB_EXPR_CONTEXT ctx;
|
||||
PCB_EXPR_CONTEXT ctx( aLayer );
|
||||
ctx.SetItems( a, b );
|
||||
|
||||
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
|
||||
|
@ -91,14 +124,10 @@ bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSou
|
|||
if (!m_ucode)
|
||||
m_ucode = new PCB_EXPR_UCODE;
|
||||
|
||||
PCB_EXPR_CONTEXT preflightContext;
|
||||
PCB_EXPR_CONTEXT preflightContext( F_Cu );
|
||||
|
||||
bool ok = compiler.Compile( m_Expression.ToUTF8().data(), m_ucode, &preflightContext );
|
||||
|
||||
if( ok )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#define DRC_RULE_H
|
||||
|
||||
#include <core/typeinfo.h>
|
||||
#include <netclass.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <netclass.h>
|
||||
#include <libeval_compiler/libeval_compiler.h>
|
||||
|
||||
|
||||
|
@ -34,12 +34,6 @@ class BOARD_ITEM;
|
|||
class PCB_EXPR_UCODE;
|
||||
|
||||
|
||||
#define CLEARANCE_CONSTRAINT (1 << 0)
|
||||
#define ANNULUS_CONSTRAINT (1 << 1)
|
||||
#define TRACK_CONSTRAINT (1 << 2)
|
||||
#define HOLE_CONSTRAINT (1 << 3)
|
||||
#define DISALLOW_CONSTRAINT (1 << 4)
|
||||
|
||||
#define DISALLOW_VIAS (1 << 0)
|
||||
#define DISALLOW_MICRO_VIAS (1 << 1)
|
||||
#define DISALLOW_BB_VIAS (1 << 2)
|
||||
|
@ -52,6 +46,17 @@ class PCB_EXPR_UCODE;
|
|||
#define DISALLOW_FOOTPRINTS (1 << 9)
|
||||
|
||||
|
||||
enum DRC_RULE_ID_T
|
||||
{
|
||||
DRC_RULE_ID_UNKNOWN = -1,
|
||||
DRC_RULE_ID_CLEARANCE = 0,
|
||||
DRC_RULE_ID_HOLE_SIZE,
|
||||
DRC_RULE_ID_ANNULUS,
|
||||
DRC_RULE_ID_TRACK,
|
||||
DRC_RULE_ID_DISALLOW
|
||||
};
|
||||
|
||||
|
||||
template<class T=int>
|
||||
class MINOPTMAX
|
||||
{
|
||||
|
@ -78,19 +83,36 @@ private:
|
|||
};
|
||||
|
||||
|
||||
class DRC_CONSTRAINT
|
||||
{
|
||||
public:
|
||||
DRC_CONSTRAINT() :
|
||||
m_Type( DRC_RULE_ID_UNKNOWN ),
|
||||
m_DisallowFlags( 0 ),
|
||||
m_LayerCondition( LSET::AllLayersMask() )
|
||||
{}
|
||||
|
||||
const MINOPTMAX<int>& GetValue() const { return m_Value; }
|
||||
|
||||
public:
|
||||
DRC_RULE_ID_T m_Type;
|
||||
MINOPTMAX<int> m_Value;
|
||||
int m_DisallowFlags;
|
||||
LSET m_LayerCondition;
|
||||
};
|
||||
|
||||
|
||||
class DRC_RULE_CONDITION
|
||||
{
|
||||
public:
|
||||
DRC_RULE_CONDITION();
|
||||
~DRC_RULE_CONDITION();
|
||||
|
||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
|
||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer );
|
||||
bool Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset );
|
||||
|
||||
public:
|
||||
LSET m_LayerCondition;
|
||||
wxString m_Expression;
|
||||
wxString m_TargetRuleName;
|
||||
|
||||
private:
|
||||
PCB_EXPR_UCODE* m_ucode;
|
||||
|
@ -100,40 +122,20 @@ private:
|
|||
class DRC_RULE
|
||||
{
|
||||
public:
|
||||
DRC_RULE() :
|
||||
m_ConstraintFlags( 0 ),
|
||||
m_DisallowFlags( 0 ),
|
||||
m_Clearance( { 0, 0, INT_MAX / 2 } ),
|
||||
m_MinAnnulusWidth( 0 ),
|
||||
m_TrackConstraint( { 0, 0, INT_MAX / 2 } ),
|
||||
m_MinHole( 0 )
|
||||
{ }
|
||||
|
||||
struct MINOPTMAX
|
||||
{
|
||||
int Min;
|
||||
int Opt;
|
||||
int Max;
|
||||
};
|
||||
DRC_RULE();
|
||||
virtual ~DRC_RULE();
|
||||
|
||||
public:
|
||||
wxString m_Name;
|
||||
int m_ConstraintFlags;
|
||||
int m_DisallowFlags;
|
||||
|
||||
// A 0 value means the property is not modified by this rule.
|
||||
// A positive value is a minimum.
|
||||
MINOPTMAX m_Clearance;
|
||||
int m_MinAnnulusWidth;
|
||||
MINOPTMAX m_TrackConstraint;
|
||||
int m_MinHole;
|
||||
|
||||
LSET m_LayerCondition;
|
||||
wxString m_TestProviderName;
|
||||
DRC_RULE_CONDITION m_Condition;
|
||||
std::vector<DRC_CONSTRAINT> m_Constraints;
|
||||
};
|
||||
|
||||
|
||||
DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint );
|
||||
const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
|
||||
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName );
|
||||
|
||||
|
||||
#endif // DRC_RULE_H
|
||||
|
|
|
@ -178,49 +178,6 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
|||
|
||||
switch( token )
|
||||
{
|
||||
case T_disallow:
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing disallowed type.| Expected 'track', 'via', 'micro_via', "
|
||||
"'blind_via', 'pad', 'zone', 'text', 'graphic' or 'hole'." ) );
|
||||
break;
|
||||
}
|
||||
else if( (int) token == DSN_STRING )
|
||||
{
|
||||
token = GetCurStrAsToken();
|
||||
}
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_track: rule->m_DisallowFlags |= DISALLOW_TRACKS; break;
|
||||
case T_via: rule->m_DisallowFlags |= DISALLOW_VIAS; break;
|
||||
case T_micro_via: rule->m_DisallowFlags |= DISALLOW_MICRO_VIAS; break;
|
||||
case T_buried_via: rule->m_DisallowFlags |= DISALLOW_BB_VIAS; break;
|
||||
case T_pad: rule->m_DisallowFlags |= DISALLOW_PADS; break;
|
||||
case T_zone: rule->m_DisallowFlags |= DISALLOW_ZONES; break;
|
||||
case T_text: rule->m_DisallowFlags |= DISALLOW_TEXTS; break;
|
||||
case T_graphic: rule->m_DisallowFlags |= DISALLOW_GRAPHICS; break;
|
||||
case T_hole: rule->m_DisallowFlags |= DISALLOW_HOLES; break;
|
||||
case T_footprint: rule->m_DisallowFlags |= DISALLOW_FOOTPRINTS; break;
|
||||
default:
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'track', 'via', 'micro_via', "
|
||||
"'blind_via', 'pad', 'zone', 'text', 'graphic' or 'hole'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
rule->m_ConstraintFlags = DISALLOW_CONSTRAINT;
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_constraint:
|
||||
parseConstraint( rule );
|
||||
break;
|
||||
|
@ -273,34 +230,65 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
|||
|
||||
void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||
{
|
||||
T token;
|
||||
int constraintType = 0;
|
||||
aRule->m_Constraints.emplace_back( DRC_CONSTRAINT() );
|
||||
|
||||
DRC_CONSTRAINT& constraint = aRule->m_Constraints.back();
|
||||
int value;
|
||||
wxString msg;
|
||||
|
||||
token = NextTok();
|
||||
T token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing constraint type.| Expected 'clearance', 'track_width', "
|
||||
"'annulus_width' or 'hole'." ) );
|
||||
"'annulus_width', 'hole' or 'disallow'." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_clearance: constraintType = CLEARANCE_CONSTRAINT; break;
|
||||
case T_track_width: constraintType = TRACK_CONSTRAINT; break;
|
||||
case T_annulus_width: constraintType = ANNULUS_CONSTRAINT; break;
|
||||
case T_hole: constraintType = HOLE_CONSTRAINT; break;
|
||||
case T_clearance: constraint.m_Type = DRC_RULE_ID_CLEARANCE; break;
|
||||
case T_track_width: constraint.m_Type = DRC_RULE_ID_TRACK; break;
|
||||
case T_annulus_width: constraint.m_Type = DRC_RULE_ID_ANNULUS; break;
|
||||
case T_hole: constraint.m_Type = DRC_RULE_ID_HOLE_SIZE; break;
|
||||
case T_disallow: constraint.m_Type = DRC_RULE_ID_DISALLOW; break;
|
||||
default:
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'clearance', 'track_width', "
|
||||
"'annulus_width' or 'hole'." ),
|
||||
"'annulus_width', 'hole' or 'disallow'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
aRule->m_ConstraintFlags |= constraintType;
|
||||
if( constraint.m_Type == DRC_RULE_ID_DISALLOW )
|
||||
{
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( (int) token == DSN_STRING )
|
||||
token = GetCurStrAsToken();
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_track: constraint.m_DisallowFlags |= DISALLOW_TRACKS; break;
|
||||
case T_via: constraint.m_DisallowFlags |= DISALLOW_VIAS; break;
|
||||
case T_micro_via: constraint.m_DisallowFlags |= DISALLOW_MICRO_VIAS; break;
|
||||
case T_buried_via: constraint.m_DisallowFlags |= DISALLOW_BB_VIAS; break;
|
||||
case T_pad: constraint.m_DisallowFlags |= DISALLOW_PADS; break;
|
||||
case T_zone: constraint.m_DisallowFlags |= DISALLOW_ZONES; break;
|
||||
case T_text: constraint.m_DisallowFlags |= DISALLOW_TEXTS; break;
|
||||
case T_graphic: constraint.m_DisallowFlags |= DISALLOW_GRAPHICS; break;
|
||||
case T_hole: constraint.m_DisallowFlags |= DISALLOW_HOLES; break;
|
||||
case T_footprint: constraint.m_DisallowFlags |= DISALLOW_FOOTPRINTS; break;
|
||||
default:
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'track', 'via', 'micro_via', "
|
||||
"'blind_via', 'pad', 'zone', 'text', 'graphic' or 'hole'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
|
@ -321,14 +309,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
|||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
|
||||
switch( constraintType )
|
||||
{
|
||||
case CLEARANCE_CONSTRAINT: aRule->m_Clearance.Min = value; break;
|
||||
case TRACK_CONSTRAINT: aRule->m_TrackConstraint.Min = value; break;
|
||||
case ANNULUS_CONSTRAINT: aRule->m_MinAnnulusWidth = value; break;
|
||||
case HOLE_CONSTRAINT: aRule->m_MinHole = value; break;
|
||||
}
|
||||
constraint.m_Value.SetMin( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
|
@ -348,12 +329,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
|||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
|
||||
switch( constraintType )
|
||||
{
|
||||
case CLEARANCE_CONSTRAINT: aRule->m_Clearance.Max = value; break;
|
||||
case TRACK_CONSTRAINT: aRule->m_TrackConstraint.Max = value; break;
|
||||
}
|
||||
constraint.m_Value.SetMax( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
|
@ -373,12 +349,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
|||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
|
||||
switch( constraintType )
|
||||
{
|
||||
case CLEARANCE_CONSTRAINT: aRule->m_Clearance.Opt = value; break;
|
||||
case TRACK_CONSTRAINT: aRule->m_TrackConstraint.Opt = value; break;
|
||||
}
|
||||
constraint.m_Value.SetOpt( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
|
|
|
@ -468,13 +468,17 @@ void GERBER_JOBFILE_WRITER::addJSONDesignRules()
|
|||
|
||||
for( MODULE* module : m_pcb->Modules() )
|
||||
{
|
||||
for( auto& pad : module->Pads() )
|
||||
for( D_PAD* pad : module->Pads() )
|
||||
{
|
||||
if( ( pad->GetLayerSet() & LSET::InternalCuMask() ).any() )
|
||||
minPadClearanceInner = std::min( minPadClearanceInner, pad->GetClearance() );
|
||||
for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() )
|
||||
{
|
||||
int padClearance = pad->GetClearance( layer );
|
||||
|
||||
if( ( pad->GetLayerSet() & LSET::ExternalCuMask() ).any() )
|
||||
minPadClearanceOuter = std::min( minPadClearanceOuter, pad->GetClearance() );
|
||||
if( layer == B_Cu || layer == F_Cu )
|
||||
minPadClearanceOuter = std::min( minPadClearanceOuter, padClearance );
|
||||
else
|
||||
minPadClearanceInner = std::min( minPadClearanceInner, padClearance );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,13 +523,16 @@ void GERBER_JOBFILE_WRITER::addJSONDesignRules()
|
|||
if( zone->GetIsKeepout() || !zone->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
int zclerance = zone->GetClearance();
|
||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||
{
|
||||
int zclerance = zone->GetClearance( layer );
|
||||
|
||||
if( zone->GetLayer() == B_Cu || zone->GetLayer() == F_Cu )
|
||||
if( layer == B_Cu || layer == F_Cu )
|
||||
minclearanceOuter = std::min( minclearanceOuter, zclerance );
|
||||
else
|
||||
minclearanceInner = std::min( minclearanceInner, zclerance );
|
||||
}
|
||||
}
|
||||
|
||||
if( minclearanceOuter != INT_MAX )
|
||||
m_json["DesignRules"][0]["TrackToRegion"] = mapValue( minclearanceOuter );
|
||||
|
|
|
@ -140,6 +140,63 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
}
|
||||
|
||||
|
||||
static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
||||
{
|
||||
PCB_EXPR_CONTEXT* context = static_cast<PCB_EXPR_CONTEXT*>( aCtx );
|
||||
LIBEVAL::VALUE* arg = aCtx->Pop();
|
||||
LIBEVAL::VALUE* result = aCtx->AllocValue();
|
||||
|
||||
result->Set( 0.0 );
|
||||
aCtx->Push( result );
|
||||
|
||||
if( !arg )
|
||||
{
|
||||
aCtx->ReportError( wxString::Format( _( "Missing argument to '%s'" ),
|
||||
wxT( "insideArea()" ) ) );
|
||||
return;
|
||||
}
|
||||
|
||||
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
|
||||
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||
ZONE_CONTAINER* zone = nullptr;
|
||||
|
||||
if( !item )
|
||||
return;
|
||||
|
||||
if( arg->AsString() == "A" )
|
||||
{
|
||||
zone = dynamic_cast<ZONE_CONTAINER*>( context->GetItem( 0 ) );
|
||||
}
|
||||
else if( arg->AsString() == "B" )
|
||||
{
|
||||
zone = dynamic_cast<ZONE_CONTAINER*>( context->GetItem( 1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ZONE_CONTAINER* candidate : item->GetBoard()->Zones() )
|
||||
{
|
||||
if( candidate->GetZoneName().Matches( arg->AsString() ) )
|
||||
{
|
||||
zone = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( zone )
|
||||
{
|
||||
SHAPE_POLY_SET zonePoly = zone->GetFilledPolysList( context->GetLayer() );
|
||||
SHAPE_POLY_SET testPoly;
|
||||
|
||||
item->TransformShapeWithClearanceToPolygon( testPoly, 0 );
|
||||
testPoly.BooleanIntersection( zonePoly, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
if( testPoly.OutlineCount() )
|
||||
result->Set( 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS()
|
||||
{
|
||||
auto registerFunc = [&]( const wxString& funcSignature, FPTR funcPtr )
|
||||
|
@ -152,6 +209,7 @@ PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS()
|
|||
registerFunc( "onLayer('x')", onLayer );
|
||||
registerFunc( "isPlated()", isPlated );
|
||||
registerFunc( "insideCourtyard('x')", insideCourtyard );
|
||||
registerFunc( "insideArea('x')", insideArea );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,8 @@ public:
|
|||
class PCB_EXPR_CONTEXT : public LIBEVAL::CONTEXT
|
||||
{
|
||||
public:
|
||||
PCB_EXPR_CONTEXT()
|
||||
PCB_EXPR_CONTEXT( PCB_LAYER_ID aLayer ) :
|
||||
m_layer( aLayer )
|
||||
{
|
||||
m_items[0] = nullptr;
|
||||
m_items[1] = nullptr;
|
||||
|
@ -69,8 +70,14 @@ public:
|
|||
return m_items[index];
|
||||
}
|
||||
|
||||
PCB_LAYER_ID GetLayer() const
|
||||
{
|
||||
return m_layer;
|
||||
}
|
||||
|
||||
private:
|
||||
BOARD_ITEM* m_items[2];
|
||||
PCB_LAYER_ID m_layer;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -508,7 +508,8 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer )
|
|||
m_gal->SetIsFill( false );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetStrokeColor( color );
|
||||
m_gal->DrawSegment( start, end, width + aTrack->GetClearance() * 2 );
|
||||
m_gal->DrawSegment( start, end,
|
||||
width + aTrack->GetClearance( ToLAYER_ID( aLayer ) ) * 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +548,7 @@ void PCB_PAINTER::draw( const ARC* aArc, int aLayer )
|
|||
m_gal->SetStrokeColor( color );
|
||||
|
||||
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
|
||||
width + aArc->GetClearance() * 2 );
|
||||
width + aArc->GetClearance( ToLAYER_ID( aLayer ) ) * 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -688,7 +689,7 @@ void PCB_PAINTER::draw( const VIA* aVia, int aLayer )
|
|||
m_gal->SetIsFill( false );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetStrokeColor( color );
|
||||
m_gal->DrawCircle( center, radius + aVia->GetClearance() );
|
||||
m_gal->DrawCircle( center, radius + aVia->GetClearance( aVia->GetLayer() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -894,7 +895,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
|
|||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetIsFill( false );
|
||||
m_gal->SetStrokeColor( color );
|
||||
int clearance = aPad->GetClearance();
|
||||
int clearance = aPad->GetClearance( aPad->GetLayer() );
|
||||
|
||||
const std::shared_ptr<SHAPE_COMPOUND> shapes =
|
||||
std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
|
||||
|
|
|
@ -1750,9 +1750,10 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
if( !(item->GetLayerSet() & lset ).any() )
|
||||
continue;
|
||||
|
||||
if( auto track = dyn_cast<TRACK*>( item ) )
|
||||
if( TRACK* track = dyn_cast<TRACK*>( item ) )
|
||||
{
|
||||
int max_clearance = std::max( clearance, track->GetClearance() );
|
||||
int max_clearance = std::max( clearance,
|
||||
track->GetClearance( track->GetLayer() ) );
|
||||
|
||||
if( TestSegmentHit( position, track->GetStart(), track->GetEnd(),
|
||||
( track->GetWidth() + aVia->GetWidth() ) / 2 + max_clearance ) )
|
||||
|
@ -1761,11 +1762,11 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
return true;
|
||||
|
||||
net = track->GetNetCode();
|
||||
clearance = track->GetClearance();
|
||||
clearance = track->GetClearance( track->GetLayer() );
|
||||
}
|
||||
}
|
||||
|
||||
if( auto via = dyn_cast<VIA*>( item ) )
|
||||
if( VIA* via = dyn_cast<VIA*>( item ) )
|
||||
{
|
||||
int dist = KiROUND( GetLineLength( position, via->GetPosition() ) );
|
||||
|
||||
|
@ -1773,11 +1774,13 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
return true;
|
||||
}
|
||||
|
||||
if( auto mod = dyn_cast<MODULE*>( item ) )
|
||||
if( MODULE* mod = dyn_cast<MODULE*>( item ) )
|
||||
{
|
||||
for( D_PAD* pad : mod->Pads() )
|
||||
{
|
||||
int max_clearance = std::max( clearance, pad->GetClearance() );
|
||||
for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() )
|
||||
{
|
||||
int max_clearance = std::max( clearance, pad->GetClearance( layer ) );
|
||||
|
||||
if( pad->HitTest( aVia->GetBoundingBox(), false, max_clearance ) )
|
||||
{
|
||||
|
@ -1785,7 +1788,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
return true;
|
||||
|
||||
net = pad->GetNetCode();
|
||||
clearance = pad->GetClearance();
|
||||
clearance = pad->GetClearance( layer );
|
||||
}
|
||||
|
||||
if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
|
@ -1798,6 +1801,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -656,7 +656,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
if( pad->GetNetCode() > 0 && pad->GetNetCode() == aZone->GetNetCode() )
|
||||
gap = std::max( zone_clearance, aZone->GetThermalReliefGap( pad ) );
|
||||
else
|
||||
gap = aZone->GetClearance( pad );
|
||||
gap = aZone->GetClearance( aLayer, pad );
|
||||
|
||||
addKnockout( pad, gap, aHoles );
|
||||
}
|
||||
|
@ -676,7 +676,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
|
||||
if( track->GetBoundingBox().Intersects( zone_boundingbox ) )
|
||||
{
|
||||
int gap = aZone->GetClearance( track ) + extra_margin;
|
||||
int gap = aZone->GetClearance( aLayer, track ) + extra_margin;
|
||||
|
||||
track->TransformShapeWithClearanceToPolygon( aHoles, gap, m_low_def );
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
|
||||
{
|
||||
bool ignoreLineWidth = aItem->IsOnLayer( Edge_Cuts );
|
||||
int gap = aZone->GetClearance( aItem );
|
||||
int gap = aZone->GetClearance( aLayer, aItem );
|
||||
|
||||
addKnockout( aItem, gap, ignoreLineWidth, aHoles );
|
||||
}
|
||||
|
@ -739,7 +739,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
int gap = 0;
|
||||
|
||||
if( !zone->GetIsKeepout() && aZone->GetNetCode() != zone->GetNetCode() )
|
||||
gap = aZone->GetClearance( zone );
|
||||
gap = aZone->GetClearance( aLayer, zone );
|
||||
|
||||
zone->TransformOutlinesShapeWithClearanceToPolygon( aHoles, gap );
|
||||
}
|
||||
|
|
|
@ -536,8 +536,7 @@ void DRC::testPadClearances( BOARD_COMMIT& aCommit )
|
|||
static DRAWSEGMENT dummyEdge;
|
||||
dummyEdge.SetLayer( Edge_Cuts );
|
||||
|
||||
if( pad->GetRuleClearance( &dummyEdge, &minClearance, &m_clearanceSource ) )
|
||||
/* minClearance and m_clearanceSource set in GetRuleClearance() */;
|
||||
pad->GetRuleClearance( &dummyEdge, pad->GetLayer(), &minClearance, &m_clearanceSource );
|
||||
|
||||
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
||||
{
|
||||
|
|
|
@ -391,7 +391,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
|
||||
|
||||
int minClearance;
|
||||
DRC_RULE* rule = GetRule( aRefSeg, &dummypad, CLEARANCE_CONSTRAINT );
|
||||
DRC_RULE* rule = GetRule( aRefSeg, &dummypad, DRC_RULE_ID_CLEARANCE );
|
||||
|
||||
if( rule )
|
||||
{
|
||||
|
|
|
@ -93,7 +93,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad )
|
|||
{
|
||||
int minHole = bds.m_MinThroughDrill;
|
||||
wxString minHoleSource = _( "board minimum" );
|
||||
DRC_RULE* rule = GetRule( aPad, nullptr, HOLE_CONSTRAINT );
|
||||
DRC_RULE* rule = GetRule( aPad, nullptr, DRC_RULE_ID_HOLE_SIZE );
|
||||
|
||||
if( rule )
|
||||
{
|
||||
|
@ -136,7 +136,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkVia( VIA* via )
|
|||
{
|
||||
int minHole = bds.m_MinThroughDrill;
|
||||
wxString minHoleSource = _( "board minimum" );
|
||||
DRC_RULE* rule = GetRule( via, nullptr, HOLE_CONSTRAINT );
|
||||
DRC_RULE* rule = GetRule( via, nullptr, DRC_RULE_ID_HOLE_SIZE );
|
||||
|
||||
if( rule )
|
||||
{
|
||||
|
@ -179,7 +179,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkMicroVia( VIA* via )
|
|||
{
|
||||
int minHole = bds.m_MicroViasMinDrill;
|
||||
wxString minHoleSource = _( "board minimum" );
|
||||
DRC_RULE* rule = GetRule( via, nullptr, HOLE_CONSTRAINT );
|
||||
DRC_RULE* rule = GetRule( via, nullptr, DRC_RULE_ID_HOLE_SIZE );
|
||||
|
||||
if( rule )
|
||||
{
|
||||
|
|
|
@ -245,7 +245,7 @@ test::DRC_RULE* test::DRC_ENGINE::EvalRulesForItems( test::DRC_RULE_ID_T ruleID,
|
|||
drc_dbg( 8, " -> check condition '%s'\n",
|
||||
(const char*) condition->m_Expression.c_str() );
|
||||
|
||||
bool result = condition->EvaluateFor( a, b );
|
||||
bool result = condition->EvaluateFor( a, b, F_Cu ); // FIXME: need the actual layer
|
||||
if( result )
|
||||
{
|
||||
drc_dbg( 8, " -> rule '%s' matches, triggered by condition '%s'\n",
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <class_board.h>
|
||||
#include <class_board_item.h>
|
||||
|
||||
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <pcb_expr_evaluator.h>
|
||||
|
||||
|
@ -37,14 +36,14 @@ test::DRC_RULE::DRC_RULE() :
|
|||
m_Conditional( false ),
|
||||
m_Priority( 0 )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
test::DRC_RULE::~DRC_RULE()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
test::DRC_RULE_CONDITION::DRC_RULE_CONDITION()
|
||||
{
|
||||
m_ucode = nullptr;
|
||||
|
@ -57,11 +56,20 @@ test::DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
|
|||
}
|
||||
|
||||
|
||||
bool test::DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB )
|
||||
bool test::DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
|
||||
PCB_LAYER_ID aLayer )
|
||||
{
|
||||
// An unconditional rule is always true
|
||||
if( m_Expression.IsEmpty() )
|
||||
return true;
|
||||
|
||||
// A rule which failed to compile is always false
|
||||
if( !m_ucode )
|
||||
return false;
|
||||
|
||||
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
|
||||
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
|
||||
PCB_EXPR_CONTEXT ctx;
|
||||
PCB_EXPR_CONTEXT ctx( aLayer );
|
||||
ctx.SetItems( a, b );
|
||||
|
||||
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
|
||||
|
@ -75,7 +83,7 @@ bool test::DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, in
|
|||
if (!m_ucode)
|
||||
m_ucode = new PCB_EXPR_UCODE;
|
||||
|
||||
LIBEVAL::CONTEXT preflightContext;
|
||||
PCB_EXPR_CONTEXT preflightContext( F_Cu );
|
||||
|
||||
bool ok = compiler.Compile( m_Expression.ToUTF8().data(), m_ucode, &preflightContext );
|
||||
return ok;
|
||||
|
|
|
@ -34,7 +34,6 @@ class BOARD_ITEM;
|
|||
namespace LIBEVAL
|
||||
{
|
||||
class UCODE;
|
||||
class ERROR_STATUS;
|
||||
};
|
||||
|
||||
class PCB_EXPR_UCODE;
|
||||
|
@ -42,14 +41,20 @@ class PCB_EXPR_UCODE;
|
|||
namespace test
|
||||
{
|
||||
|
||||
enum class DRC_RULE_ID_T {
|
||||
enum class DRC_RULE_ID_T
|
||||
{
|
||||
DRC_RULE_ID_UNKNOWN = -1,
|
||||
DRC_RULE_ID_CLEARANCE = 0,
|
||||
DRC_RULE_ID_HOLE_CLEARANCE,
|
||||
DRC_RULE_ID_EDGE_CLEARANCE,
|
||||
DRC_RULE_ID_HOLE_SIZE
|
||||
DRC_RULE_ID_HOLE_SIZE,
|
||||
DRC_RULE_ID_ANNULUS,
|
||||
DRC_RULE_ID_TRACK,
|
||||
DRC_RULE_ID_DISALLOW
|
||||
};
|
||||
|
||||
enum class DRC_RULE_SEVERITY_T {
|
||||
enum class DRC_RULE_SEVERITY_T
|
||||
{
|
||||
DRC_SEVERITY_IGNORE = 0,
|
||||
DRC_SEVERITY_WARNING,
|
||||
DRC_SEVERITY_ERROR
|
||||
|
@ -80,17 +85,48 @@ private:
|
|||
bool m_hasMax = false;
|
||||
};
|
||||
|
||||
|
||||
class DRC_CONSTRAINT
|
||||
{
|
||||
public:
|
||||
public:
|
||||
DRC_CONSTRAINT() :
|
||||
m_Type( DRC_RULE_ID_T::DRC_RULE_ID_UNKNOWN ),
|
||||
m_DisallowFlags( 0 ),
|
||||
m_LayerCondition( LSET::AllLayersMask() )
|
||||
{
|
||||
}
|
||||
|
||||
const MINOPTMAX<int>& GetValue() const { return m_Value; }
|
||||
bool Allowed() const { return m_Allow; }
|
||||
|
||||
public:
|
||||
public:
|
||||
DRC_RULE_ID_T m_Type;
|
||||
MINOPTMAX<int> m_Value;
|
||||
int m_DisallowFlags;
|
||||
LSET m_LayerCondition;
|
||||
|
||||
bool m_Allow;
|
||||
};
|
||||
|
||||
|
||||
class DRC_RULE_CONDITION
|
||||
{
|
||||
public:
|
||||
DRC_RULE_CONDITION();
|
||||
~DRC_RULE_CONDITION();
|
||||
|
||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer );
|
||||
bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
|
||||
|
||||
public:
|
||||
wxString m_Expression;
|
||||
wxString m_TargetRuleName;
|
||||
|
||||
private:
|
||||
PCB_EXPR_UCODE* m_ucode;
|
||||
};
|
||||
|
||||
|
||||
class DRC_RULE
|
||||
{
|
||||
public:
|
||||
|
@ -116,36 +152,22 @@ public:
|
|||
bool m_Unary;
|
||||
|
||||
wxString m_Name;
|
||||
LSET m_LayerCondition;
|
||||
wxString m_TestProviderName;
|
||||
DRC_RULE_CONDITION m_Condition;
|
||||
std::vector<DRC_CONSTRAINT> m_Constraints;
|
||||
|
||||
DRC_RULE_SEVERITY_T m_Severity;
|
||||
bool m_Enabled;
|
||||
bool m_Conditional;
|
||||
int m_Priority; // 0 indicates automatic priority generation
|
||||
|
||||
DRC_CONSTRAINT m_Constraint;
|
||||
DRC_CONSTRAINT m_Constraint; // FIXME: move to m_Constraints
|
||||
};
|
||||
|
||||
|
||||
class DRC_RULE_CONDITION
|
||||
{
|
||||
public:
|
||||
DRC_RULE_CONDITION();
|
||||
~DRC_RULE_CONDITION();
|
||||
|
||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
|
||||
bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
|
||||
|
||||
public:
|
||||
LSET m_LayerCondition;
|
||||
wxString m_Expression;
|
||||
wxString m_TargetRuleName;
|
||||
|
||||
private:
|
||||
PCB_EXPR_UCODE* m_ucode;
|
||||
};
|
||||
|
||||
|
||||
//DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint );
|
||||
//const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
|
||||
// int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName );
|
||||
|
||||
}; // namespace test
|
||||
|
||||
|
|
Loading…
Reference in New Issue