61#define ERROR_LIMIT 199
62#define EXTENDED_ERROR_LIMIT 499
79 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
81 int setLevel = wxAtoi( valueStr );
83 if( level <= setLevel )
84 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
127 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
154 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
157 rule->SetImplicitSource( aImplicitSource );
168 wxString expr, expr2, ncName;
172 std::shared_ptr<DRC_RULE> rule =
177 rule->AddConstraint( widthConstraint );
181 rule->AddConstraint( connectionConstraint );
185 rule->AddConstraint( drillConstraint );
189 rule->AddConstraint( annulusConstraint );
193 rule->AddConstraint( diameterConstraint );
197 rule->AddConstraint( holeToHoleConstraint );
203 rule->AddConstraint( thermalSpokeCountConstraint );
209 rule->AddConstraint( silkClearanceConstraint );
216 rule->AddConstraint( silkTextHeightConstraint );
223 rule->AddConstraint( silkTextThicknessConstraint );
228 rule->AddConstraint( holeClearanceConstraint );
233 rule->AddConstraint( edgeClearanceConstraint );
238 rule->AddConstraint( courtyardClearanceConstraint );
242 std::shared_ptr<DRC_RULE> uViaRule =
249 uViaRule->AddConstraint( uViaDrillConstraint );
253 uViaRule->AddConstraint( uViaDiameterConstraint );
257 std::shared_ptr<DRC_RULE> barcodeRule =
261 barcodeRule->AddConstraint( barcodeSeparationConstraint );
266 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
267 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
269 auto makeNetclassRules =
270 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
272 ncName = nc->GetName();
273 ncName.Replace(
"'",
"\\'" );
275 if( nc->HasClearance() )
277 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
278 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
279 nc->GetClearanceParent()->GetHumanReadableName() );
282 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
284 netclassClearanceRules.push_back( netclassRule );
288 netclassRule->AddConstraint( constraint );
296 if( nc->HasTrackWidth() )
298 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
299 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
300 nc->GetTrackWidthParent()->GetHumanReadableName() );
303 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
305 netclassClearanceRules.push_back( netclassRule );
310 netclassRule->AddConstraint( constraint );
313 if( nc->HasDiffPairWidth() )
315 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
316 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
317 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
320 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
322 netclassItemSpecificRules.push_back( netclassRule );
326 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
327 netclassRule->AddConstraint( constraint );
330 if( nc->HasDiffPairGap() )
332 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
333 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
334 nc->GetDiffPairGapParent()->GetHumanReadableName() );
337 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
339 netclassItemSpecificRules.push_back( netclassRule );
344 netclassRule->AddConstraint( constraint );
347 if( nc->GetDiffPairGap() < nc->GetClearance() )
349 netclassRule = std::make_shared<DRC_RULE>();
350 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
351 nc->GetDiffPairGapParent()->GetHumanReadableName() );
354 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
356 netclassItemSpecificRules.push_back( netclassRule );
359 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
360 netclassRule->AddConstraint( min_clearanceConstraint );
366 if( nc->HasViaDiameter() )
368 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
369 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
370 nc->GetViaDiameterParent()->GetHumanReadableName() );
373 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
375 netclassItemSpecificRules.push_back( netclassRule );
380 netclassRule->AddConstraint( constraint );
383 if( nc->HasViaDrill() )
385 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
386 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
387 nc->GetViaDrillParent()->GetHumanReadableName() );
390 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
392 netclassItemSpecificRules.push_back( netclassRule );
397 netclassRule->AddConstraint( constraint );
400 if( nc->HasuViaDiameter() )
402 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
403 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
404 nc->GetuViaDiameterParent()->GetHumanReadableName() );
407 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
409 netclassItemSpecificRules.push_back( netclassRule );
413 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
414 netclassRule->AddConstraint( constraint );
417 if( nc->HasuViaDrill() )
419 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
420 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
421 nc->GetuViaDrillParent()->GetHumanReadableName() );
424 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
426 netclassItemSpecificRules.push_back( netclassRule );
431 netclassRule->AddConstraint( constraint );
435 m_board->SynchronizeNetsAndNetClasses(
false );
439 makeNetclassRules( netclass,
false );
442 makeNetclassRules( netclass,
false );
449 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
450 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
452 return lhs->m_Constraints[0].m_Value.Min()
453 < rhs->m_Constraints[0].m_Value.Min();
456 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
459 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
463 auto addTuningSingleRule =
465 const wxString& aNetclassName )
470 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
472 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
475 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s'" ),
484 tuningRule->AddConstraint( constraint );
489 auto addTuningDifferentialRules =
496 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
498 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
501 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
502 aNetclass->GetName(),
510 tuningRule->AddConstraint( constraint );
514 std::shared_ptr<DRC_RULE> tuningRule2 = std::make_shared<DRC_RULE>();
516 tuningRule2->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
519 expr2 = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
520 aNetclass->GetName(),
528 tuningRule2->AddConstraint( constraint2 );
535 std::shared_ptr<DRC_RULE> diffPairClearanceRule = std::make_shared<DRC_RULE>();
537 diffPairClearanceRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
540 expr = wxString::Format(
541 wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && AB.isCoupledDiffPair()" ),
547 diffPairClearanceRule->AddConstraint( min_clearanceConstraint );
549 addRule( diffPairClearanceRule );
555 std::shared_ptr<TUNING_PROFILES> tuningParams =
project->GetProjectFile().TuningProfileParameters();
557 auto addNetclassTuningProfileRules =
558 [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules](
NETCLASS* aNetclass )
560 if( aNetclass->HasTuningProfile() )
562 const wxString delayProfileName = aNetclass->GetTuningProfile();
563 const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName );
571 addTuningSingleRule( entry, delayProfileName, aNetclass->GetName() );
573 addTuningDifferentialRules( entry, delayProfileName, aNetclass );
581 addNetclassTuningProfileRules( netclass.get() );
584 addNetclassTuningProfileRules( netclass.get() );
588 auto addKeepoutZoneRule =
598 wxString::Format(
_(
"keepout area of %s" ),
DescribeRef( parentFP->GetReference() ) ),
622 rule->m_ImplicitItemId = zone->
m_Uuid;
623 rule->m_ImplicitItem = zone;
625 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsArea('%s')" ),
630 int disallowFlags = 0;
649 rule->AddConstraint( disallowConstraint );
655 addKeepoutZoneRule( zone,
nullptr );
660 for(
ZONE* zone : footprint->Zones() )
663 addKeepoutZoneRule( zone, footprint );
671 if(
m_board && aPath.FileExists() )
673 std::vector<std::shared_ptr<DRC_RULE>> rules;
675 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
680 std::function<bool( wxString* )>
resolver =
681 [&]( wxString* token ) ->
bool
683 return m_board->ResolveTextVar( token, 0 );
686 while(
char* line = lineReader.
ReadLine() )
688 wxString str( line );
689 str =
m_board->ConvertCrossReferencesToKIIDs( str );
692 rulesText << str <<
'\n';
702 for( std::shared_ptr<DRC_RULE>& rule : rules )
715 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
719 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
721 condition = rule->m_Condition;
722 condition->
Compile( &error_semaphore );
727 TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
734 ruleVec =
new std::vector<DRC_ENGINE_CONSTRAINT*>();
738 engineConstraint->
layerTest = rule->m_LayerCondition;
746 const auto& cache =
m_board->GetItemByIdCache();
747 auto it = cache.find( rule->m_ImplicitItemId );
749 if( it != cache.end() && it->second->Type() ==
PCB_ZONE_T )
753 ruleVec->push_back( engineConstraint );
765 if( c->parentRule && !c->parentRule->IsImplicit() )
774 && c->condition->HasGeometryDependentFunctions() )
791 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
793 provider->SetDRCEngine(
this );
829 throw original_parse_error;
846 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
848 provider->SetDRCEngine(
this );
904 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
907 throw original_parse_error;
944 if( !cacheGenerator.
Run() )
948 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
950 int timestamp =
m_board->GetTimeStamp();
955 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
959 if( !provider->RunTests( aUnits ) )
962 providerTimer.
Stop();
964 provider->GetName(), providerTimer.
msecs() );
972 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
976#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
984 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
992 pad =
static_cast<const PAD*
>( a );
994 pad =
static_cast<const PAD*
>( b );
1002 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
1027 const PAD*
pad =
nullptr;
1028 const ZONE* zone =
nullptr;
1029 const FOOTPRINT* parentFootprint =
nullptr;
1039 pad =
static_cast<const PAD*
>( a );
1041 zone =
static_cast<const ZONE*
>( a );
1044 pad =
static_cast<const PAD*
>( b );
1046 zone =
static_cast<const ZONE*
>( b );
1049 parentFootprint =
pad->GetParentFootprint();
1053 constraint.
m_Type = aConstraintType;
1055 auto applyConstraint =
1058 if( c->constraint.m_Value.HasMin() )
1060 if( c->parentRule && c->parentRule->IsImplicit() )
1068 if( c->constraint.m_Value.HasOpt() )
1071 if( c->constraint.m_Value.HasMax() )
1074 switch( c->constraint.m_Type )
1109 && ( ( ( !ac ) ^ ( !bc ) )
1112 || ( ( footprints[0] == footprints[1] )
1113 && footprints[0] ) )
1115 && !b_is_non_copper )
1122 for(
int ii = 0; ii < 2; ++ii )
1125 if( !footprints[ii] || !alt_items[ii] )
1128 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
1130 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
1132 if( it != netcodes.end() )
1135 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
1136 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
1138 constraint.
SetName(
_(
"net tie" ) );
1148 int override_val = 0;
1149 std::optional<int> overrideA;
1150 std::optional<int> overrideB;
1152 if( ac && !b_is_non_copper )
1155 if( bc && !a_is_non_copper )
1158 if( overrideA.has_value() || overrideB.has_value() )
1162 if( overrideA.has_value() )
1165 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1172 if( overrideB.has_value() )
1175 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1179 if( overrideB > override_val )
1187 if( override_val < m_designSettings->m_MinClearance )
1190 msg =
_(
"board minimum" );
1193 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1199 if( override_val < m_designSettings->m_HoleClearance )
1202 msg =
_(
"board minimum hole" );
1205 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
1224 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
1235 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
1238 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
1241 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
1252 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
1255 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
1258 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
1267 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
1279 std::optional<int>
override;
1283 override =
pad->GetLocalSolderMaskMargin();
1285 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
1289 if( !
override.has_value() &&
pad )
1291 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1293 override = overrideFootprint->GetLocalSolderMaskMargin();
1294 overrideItem = overrideFootprint;
1301 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1311 std::optional<int>
override;
1315 override =
pad->GetLocalSolderPasteMargin();
1317 if( !
override.has_value() &&
pad )
1319 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1321 override = overrideFootprint->GetLocalSolderPasteMargin();
1322 overrideItem = overrideFootprint;
1329 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1339 std::optional<double> overrideRatio;
1343 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1345 if( !overrideRatio.has_value() &&
pad )
1347 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1349 overrideRatio = overrideFootprint->GetLocalSolderPasteMarginRatio();
1350 overrideItem = overrideFootprint;
1357 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1366 auto testAssertion =
1369 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1370 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1372 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1373 REPORT(
_(
"Assertion passed." ) )
1378 auto processConstraint =
1381 bool implicit = c->parentRule && c->parentRule->IsImplicit();
1385 switch( c->constraint.m_Type )
1394 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1399 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1404 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1410 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1416 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1422 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1428 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1434 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute clearance: %s." ),
1440 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1446 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1452 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1473 switch( c->constraint.m_Type )
1476 if( c->constraint.m_Value.HasOpt() )
1478 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1482 else if( c->constraint.m_Value.HasMin() )
1484 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1492 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1498 if( c->constraint.m_Value.HasOpt() )
1500 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1504 else if( c->constraint.m_Value.HasMin() )
1506 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1513 if( c->constraint.m_Value.HasOpt() )
1515 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1519 else if( c->constraint.m_Value.HasMin() )
1521 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1531 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1537 if( c->constraint.m_Value.HasOpt() )
1539 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1543 else if( c->constraint.m_Value.HasMin() )
1545 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1553 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1559 REPORT( wxString::Format(
_(
"Checking %s." ),
1565 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1567 c->constraint.m_Value.HasMin()
1569 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1570 c->constraint.m_Value.HasOpt()
1572 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1573 c->constraint.m_Value.HasMax()
1575 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ) ) )
1581 REPORT( wxString::Format(
_(
"Checking %s." ),
1587 if( a_is_non_copper || b_is_non_copper )
1591 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1593 else if( a_is_non_copper )
1595 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1598 else if( b_is_non_copper )
1600 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1619 if(
via->IsMicroVia() )
1621 else if(
via->IsBlindVia() )
1623 else if(
via->IsBuriedVia() )
1645 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1653 default: mask = 0;
break;
1657 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1660 REPORT(
_(
"Keepout constraint not met." ) )
1662 REPORT(
_(
"Disallow constraint not met." ) )
1680 if( !( c->layerTest & itemLayers ).any() )
1684 REPORT(
_(
"Keepout layer(s) not matched." ) )
1686 else if( c->parentRule )
1688 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1689 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1693 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1700 if( (
IsPcbLayer( aLayer ) && !c->layerTest.test( aLayer ) )
1701 || (
m_board->GetEnabledLayers() & c->layerTest ).count() == 0 )
1705 REPORT(
_(
"Constraint layer not matched." ) )
1707 else if( c->parentRule )
1709 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1710 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1714 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1721 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1724 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1730 REPORT(
_(
"Unconditional constraint applied." ) )
1734 REPORT(
_(
"Unconditional rule applied." ) )
1739 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1743 applyConstraint( c );
1751 if( c->implicitKeepoutZone && !aReporter )
1754 BOX2I zoneBBox = c->implicitKeepoutZone->GetBoundingBox();
1766 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1767 EscapeHTML( c->condition->GetExpression() ) ) )
1770 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1776 REPORT(
_(
"Constraint applied." ) )
1780 REPORT(
_(
"Rule applied." ) )
1785 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1789 applyConstraint( c );
1793 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1794 :
_(
"Condition not satisfied; rule ignored." ) )
1805 && ( !b || !b_is_non_copper ) )
1830 if( !ncNameA.empty() || !ncNameB.empty() )
1834 if( !ncNameA.empty() )
1842 if( !ncNameB.empty() )
1864 processConstraint( rule );
1882 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
1886 a = parentFootprint;
1888 b = parentFootprint;
1895 processConstraint( rule );
1905 constraint.
SetName(
_(
"board setup" ) );
1912 constraint.
SetName(
_(
"board setup" ) );
1919 constraint.
SetName(
_(
"board setup" ) );
1932 bool needBlankLine =
true;
1941 needBlankLine =
false;
1944 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1965 needBlankLine =
false;
1968 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1982 if( !a_is_non_copper && !b_is_non_copper )
1987 needBlankLine =
false;
1990 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1996 constraint.
SetName(
_(
"board minimum" ) );
2006 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
2012 constraint.
SetName(
_(
"board minimum" ) );
2020 if(
pad && parentFootprint )
2027 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
2032 constraint.
SetName(
_(
"footprint" ) );
2043 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
2060 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
2077 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
2142 auto testAssertion =
2145 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
2146 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
2148 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2151 REPORT(
_(
"Assertion passed." ) )
2156 aFailureHandler( &c->constraint );
2160 auto processConstraint =
2164 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
2168 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
2169 EscapeHTML( c->parentRule->m_LayerSource ) ) )
2172 if( !c->condition || c->condition->GetExpression().IsEmpty() )
2174 REPORT(
_(
"Unconditional rule applied." ) )
2179 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
2180 EscapeHTML( c->condition->GetExpression() ) ) )
2182 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2185 REPORT(
_(
"Rule applied." ) )
2190 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
2199 for(
int ii = 0; ii < (int) it->second->size(); ++ii )
2200 processConstraint( it->second->at( ii ) );
2210 assert( error_code >= 0 && error_code <=
DRCE_LAST );
2217 int aMarkerLayer,
const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
2226 static std::mutex handlerLock;
2227 std::lock_guard<std::mutex> guard( handlerLock );
2233 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
2234 aItem->GetViolatingTest()->GetName(),
2235 aItem->GetErrorMessage(
false ),
2236 aItem->GetErrorCode() );
2238 DRC_RULE* rule = aItem->GetViolatingRule();
2241 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
2245 wxString violatingItemsStr = wxT(
"Violating items: " );
2247 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
2311 bool aUnconditionalOnly )
2320 if( aUnconditionalOnly && c->
condition )
2325 if( current > worst )
2361 std::set<int> distinctMinimums;
2370 return distinctMinimums;
2376 wxString& aBaseDpName )
2381 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2385 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
2389 else if( ch ==
'+' )
2391 aComplementNet = wxT(
"-" );
2394 else if( ch ==
'-' )
2396 aComplementNet = wxT(
"+" );
2399 else if( ch ==
'N' )
2401 aComplementNet = wxT(
"P" );
2404 else if ( ch ==
'P' )
2406 aComplementNet = wxT(
"N" );
2415 if( rv != 0 && count >= 1 )
2417 aBaseDpName = aNetName.Left( aNetName.Length() - count );
2418 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
2428 wxString
dummy, coupledNetName;
2464 if( parentFootprint && parentFootprint->
IsNetTie() )
2471 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2473 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2485enum class SHOWMATCH_DOMAIN
2492 MASK_EXPANSION_ITEMS,
2505struct SHOWMATCH_DOMAIN_SPEC
2507 SHOWMATCH_DOMAIN primary;
2508 SHOWMATCH_DOMAIN secondary = SHOWMATCH_DOMAIN::ALL_ITEMS;
2509 bool hasSecondary =
false;
2510 bool secondaryUnary =
false;
2514bool isShowMatchSkippable(
const BOARD_ITEM* aItem )
2516 switch( aItem->
Type() )
2522 default:
return false;
2527bool matchesShowMatchDomain(
const BOARD_ITEM* aItem, SHOWMATCH_DOMAIN aDomain )
2529 if( !aItem || isShowMatchSkippable( aItem ) )
2534 case SHOWMATCH_DOMAIN::ALL_ITEMS:
return true;
2538 case SHOWMATCH_DOMAIN::EDGE_ITEMS:
2544 const PAD*
pad =
static_cast<const PAD*
>( aItem );
2552 case SHOWMATCH_DOMAIN::HOLE_ITEMS:
return aItem->
HasHole();
2554 case SHOWMATCH_DOMAIN::MASK_EXPANSION_ITEMS:
2555 switch( aItem->
Type() )
2564 default:
return false;
2569 case SHOWMATCH_DOMAIN::PADS:
return aItem->
Type() ==
PCB_PAD_T;
2575 case SHOWMATCH_DOMAIN::ROUTING_ITEMS:
2576 switch( aItem->
Type() )
2583 default:
return false;
2588 case SHOWMATCH_DOMAIN::SILK_TARGET_ITEMS:
2595 case SHOWMATCH_DOMAIN::TEXT_ITEMS:
2599 case SHOWMATCH_DOMAIN::VIAS:
return aItem->
Type() ==
PCB_VIA_T;
2606SHOWMATCH_DOMAIN_SPEC getShowMatchDomainSpec(
DRC_CONSTRAINT_T aConstraint )
2608 switch( aConstraint )
2625 return { SHOWMATCH_DOMAIN::SILK_ITEMS, SHOWMATCH_DOMAIN::SILK_TARGET_ITEMS,
true,
false };
2657 default:
return { SHOWMATCH_DOMAIN::ALL_ITEMS };
2662std::vector<BOARD_ITEM*> collectShowMatchCandidates(
BOARD* aBoard, SHOWMATCH_DOMAIN aDomain )
2664 std::vector<BOARD_ITEM*> items;
2671 if( matchesShowMatchDomain( item, aDomain ) )
2672 items.push_back( item );
2679std::vector<PCB_LAYER_ID> getShowMatchLayers(
const BOARD_ITEM* aItem )
2681 std::vector<PCB_LAYER_ID> layers;
2683 switch( aItem->
Type() )
2685 case PCB_PAD_T: layers =
static_cast<const PAD*
>( aItem )->Padstack().UniqueLayers();
break;
2687 case PCB_VIA_T: layers =
static_cast<const PCB_VIA*
>( aItem )->Padstack().UniqueLayers();
break;
2691 layers.push_back( layer );
2696 if( layers.empty() )
2706 bool testedLayer =
false;
2708 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItem ) )
2733std::vector<PCB_LAYER_ID> getShowMatchPairLayers(
const DRC_RULE& aRule,
const BOARD_ITEM* aItemA,
2736 std::vector<PCB_LAYER_ID> layers;
2737 std::set<int> seenLayers;
2744 if( seenLayers.insert(
static_cast<int>( aLayer ) ).second )
2745 layers.push_back( aLayer );
2748 switch( aConstraint )
2751 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemA ) )
2759 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemA ) )
2762 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemB ) )
2768 if( layers.empty() )
2778 for(
PCB_LAYER_ID layer : getShowMatchPairLayers( aRule, aItemA, aItemB, aConstraint ) )
2796 if(
name == prov->GetName() )
2808 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2809 wxS(
"[ShowMatches] engine enter: expr='%s', constraint=%d" ), aExpression, (
int) aConstraint );
2810 std::vector<BOARD_ITEM*> matches;
2819 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine: compile failed" ) );
2826 if(
auto connectivity =
m_board->GetConnectivity() )
2828 if(
auto ftCache = connectivity->GetFromToCache() )
2833 size_t totalItems = 0;
2834 size_t skippedItems = 0;
2835 size_t noLayerItems = 0;
2836 size_t checkedItems = 0;
2838 for(
auto& [kiid, item] :
m_board->GetItemByIdCache() )
2843 switch( item->Type() )
2855 LSET itemLayers = item->GetLayerSet();
2857 if( itemLayers.none() )
2864 bool matched =
false;
2868 if( condition.
EvaluateFor( item,
nullptr,
static_cast<int>( aConstraint ), layer,
2871 matches.push_back( item );
2872 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2873 wxS(
"[ShowMatches] engine: match type=%d kiid=%s layer=%d" ),
2874 (
int) item->Type(), kiid.AsString(), (
int) layer );
2881 if( !matched && matches.size() == 0 && checkedItems <= 5 )
2883 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2884 wxS(
"[ShowMatches] engine: no-match sample type=%d kiid=%s layers=%s" ),
2885 (
int) item->Type(), kiid.AsString(), itemLayers.
FmtHex() );
2889 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2890 wxS(
"[ShowMatches] engine stats: total=%zu skipped=%zu noLayer=%zu checked=%zu" ),
2891 totalItems, skippedItems, noLayerItems, checkedItems );
2893 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine exit: total=%zu" ), matches.size() );
2900 std::vector<BOARD_ITEM*> matches;
2905 const wxString condition = aRule->m_Condition ? aRule->m_Condition->GetExpression() : wxString();
2906 const bool requiresPairwise = condition.Contains( wxS(
"B." ) );
2907 std::set<BOARD_ITEM*> matchedItems;
2909 if(
auto connectivity =
m_board->GetConnectivity() )
2911 if(
auto ftCache = connectivity->GetFromToCache() )
2920 SHOWMATCH_DOMAIN_SPEC domainSpec = getShowMatchDomainSpec( constraint.
m_Type );
2921 std::vector<BOARD_ITEM*> primaryItems = collectShowMatchCandidates(
m_board, domainSpec.primary );
2922 std::vector<BOARD_ITEM*> secondaryItems;
2924 if( domainSpec.hasSecondary )
2925 secondaryItems = collectShowMatchCandidates(
m_board, domainSpec.secondary );
2927 if( requiresPairwise )
2929 if( secondaryItems.empty() )
2931 for(
size_t ii = 0; ii < primaryItems.size(); ++ii )
2935 for(
size_t jj = ii + 1; jj < primaryItems.size(); ++jj )
2939 if( ruleMatchesPair( *aRule, itemA, itemB, constraint.
m_Type,
2942 matchedItems.insert( itemA );
2943 matchedItems.insert( itemB );
2954 if( itemA == itemB )
2957 if( ruleMatchesPair( *aRule, itemA, itemB, constraint.
m_Type,
2960 matchedItems.insert( itemA );
2961 matchedItems.insert( itemB );
2971 if( ruleMatchesUnary( *aRule, item, constraint.
m_Type, aReporter ? aReporter :
m_logReporter ) )
2973 matchedItems.insert( item );
2977 if( domainSpec.hasSecondary && domainSpec.secondaryUnary )
2981 if( ruleMatchesUnary( *aRule, item, constraint.
m_Type, aReporter ? aReporter :
m_logReporter ) )
2983 matchedItems.insert( item );
2990 matches.assign( matchedItems.begin(), matchedItems.end() );
3020 const PAD*
pad =
static_cast<const PAD*
>( aItem );
3035 *aSource = constraint.
GetName();
3069 if( it->first.m_uuid == aUuid )
3095 using CLEARANCE_MAP = std::unordered_map<DRC_OWN_CLEARANCE_CACHE_KEY, int>;
3099 std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>> itemsToProcess;
3100 size_t estimatedPads = 0;
3103 estimatedPads += footprint->Pads().size();
3105 itemsToProcess.reserve(
m_board->Tracks().size() + estimatedPads * 2 );
3112 itemsToProcess.emplace_back( track, layer );
3116 itemsToProcess.emplace_back( track, track->GetLayer() );
3122 for(
PAD*
pad : footprint->Pads() )
3125 itemsToProcess.emplace_back(
pad, layer );
3129 if( itemsToProcess.empty() )
3139 auto processItems = [
this](
size_t aStart,
size_t aEnd,
3140 const std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>>& aItems )
3143 CLEARANCE_MAP localCache;
3145 for(
size_t i = aStart; i < aEnd; ++i )
3154 const PAD*
pad =
static_cast<const PAD*
>( item );
3173 auto results =
tp.submit_blocks( 0, itemsToProcess.size(),
3174 [&](
size_t aStart,
size_t aEnd ) -> CLEARANCE_MAP
3176 return processItems( aStart, aEnd, itemsToProcess );
3183 std::vector<CLEARANCE_MAP> collectedResults;
3184 collectedResults.reserve( results.size() );
3186 for(
size_t i = 0; i < results.size(); ++i )
3188 if( results[i].valid() )
3189 collectedResults.push_back( results[i].get() );
3196 for(
const auto& localCache : collectedResults )
constexpr EDA_IU_SCALE pcbIUScale
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
#define MAXIMUM_CLEARANCE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
std::string FmtHex() const
Return a hex string showing contents of this set.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual std::optional< int > GetClearanceOverrides(wxString *aSource) const
Return any clearance overrides set in the "classic" (ie: pre-rule) system.
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
virtual std::optional< int > GetLocalClearance() const
Return any local clearances set in the "classic" (ie: pre-rule) system.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
int m_CopperEdgeClearance
std::map< int, SEVERITY > m_DRCSeverities
int m_MinSilkTextThickness
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
int m_ViasMinAnnularWidth
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
virtual bool HasDrilledHole() const
virtual bool IsOnCopperLayer() const
virtual bool HasHole() const
Information pertinent to a Pcbnew printed circuit board.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
const std::unordered_map< KIID, BOARD_ITEM * > & GetItemByIdCache() const
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Represents a single line in a time domain profile track propagation setup.
int GetDiffPairGap() const
PCB_LAYER_ID GetSignalLayer() const
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
void SetParentRule(DRC_RULE *aParentRule)
MINOPTMAX< int > & Value()
const MINOPTMAX< int > & GetValue() const
ZONE_CONNECTION m_ZoneConnection
void SetName(const wxString &aName)
void SetOptionsFromOther(const DRC_CONSTRAINT &aOther)
DRC_RULE * GetParentRule() const
std::map< DRC_CONSTRAINT_T, std::vector< DRC_ENGINE_CONSTRAINT * > * > m_constraintMap
DRC_CLEARANCE_BATCH EvalClearanceBatch(const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer)
Evaluate all clearance-related constraints in a single batch call.
std::shared_ptr< DRC_RULE > createImplicitRule(const wxString &name, DRC_IMPLICIT_SOURCE aImplicitSource)
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
std::unordered_map< DRC_OWN_CLEARANCE_CACHE_KEY, int > m_ownClearanceCache
bool m_hasDiffPairClearanceOverrides
void addRule(std::shared_ptr< DRC_RULE > &rule)
PROGRESS_REPORTER * m_progressReporter
void ClearClearanceCache()
Clear the entire clearance cache.
void loadRules(const wxFileName &aPath)
Load and parse a rule set from an sexpr text file.
std::vector< DRC_TEST_PROVIDER * > m_testProviders
std::map< DRC_CONSTRAINT_T, std::vector< DRC_ENGINE_CONSTRAINT * > > m_explicitConstraints
std::set< int > QueryDistinctConstraints(DRC_CONSTRAINT_T aConstraintId)
bool m_hasGeometryDependentRules
DS_PROXY_VIEW_ITEM * m_drawingSheet
NETLIST * m_schematicNetlist
std::shared_mutex m_clearanceCacheMutex
bool KeepRefreshing(bool aWait=false)
std::vector< BOARD_ITEM * > GetItemsMatchingRule(const std::shared_ptr< DRC_RULE > &aRule, REPORTER *aReporter=nullptr)
int GetCachedOwnClearance(const BOARD_ITEM *aItem, PCB_LAYER_ID aLayer, wxString *aSource=nullptr)
Get the cached own clearance for an item on a specific layer.
bool m_reportAllTrackErrors
bool ReportProgress(double aProgress)
DRC_TEST_PROVIDER * GetTestProvider(const wxString &name) const
bool HasRulesForConstraintType(DRC_CONSTRAINT_T constraintID)
BOARD_DESIGN_SETTINGS * GetDesignSettings() const
void SetMaxProgress(int aSize)
DRC_ENGINE(BOARD *aBoard=nullptr, BOARD_DESIGN_SETTINGS *aSettings=nullptr)
bool m_hasExplicitClearanceRules
std::vector< int > m_errorLimits
bool IsErrorLimitExceeded(int error_code)
void ProcessAssertions(const BOARD_ITEM *a, std::function< void(const DRC_CONSTRAINT *)> aFailureHandler, REPORTER *aReporter=nullptr)
DRC_VIOLATION_HANDLER m_violationHandler
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
std::vector< std::shared_ptr< DRC_RULE > > m_rules
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint, bool aUnconditionalOnly=false)
std::unordered_map< wxString, int > m_netclassClearances
static bool IsNetADiffPair(BOARD *aBoard, NETINFO_ITEM *aNet, int &aNetP, int &aNetN)
bool IsNetTieExclusion(int aTrackNetCode, PCB_LAYER_ID aTrackLayer, const VECTOR2I &aCollisionPos, BOARD_ITEM *aCollidingItem)
Check if the given collision between a track and another item occurs during the track's entry into a ...
std::vector< BOARD_ITEM * > GetItemsMatchingCondition(const wxString &aExpression, DRC_CONSTRAINT_T aConstraint=ASSERTION_CONSTRAINT, REPORTER *aReporter=nullptr)
Evaluate a DRC condition against all board items and return matches.
void InitEngine(const wxFileName &aRulePath)
Initialize the DRC engine.
DRC_CONSTRAINT EvalZoneConnection(const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
static int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet, wxString &aBaseDpName)
Check if the given net is a diff pair, returning its polarity and complement if so.
bool ReportPhase(const wxString &aMessage)
void InitializeClearanceCache()
Initialize the clearance cache for all items on the board.
void InvalidateClearanceCache(const KIID &aUuid)
Invalidate the clearance cache for a specific item.
BOARD_DESIGN_SETTINGS * m_designSettings
bool HasUserDefinedPhysicalConstraint()
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator={})
std::mutex m_errorLimitsMutex
void SetViolatingRule(DRC_RULE *aRule)
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
bool EvaluateFor(const BOARD_ITEM *aItemA, const BOARD_ITEM *aItemB, int aConstraint, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
DRC_RULE_CONDITION * m_Condition
std::vector< DRC_TEST_PROVIDER * > GetShowMatchesProviders() const
static DRC_SHOWMATCHES_PROVIDER_REGISTRY & Instance()
std::vector< DRC_TEST_PROVIDER * > GetTestProviders() const
static DRC_TEST_PROVIDER_REGISTRY & Instance()
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out DRC_ITEM and posi...
void SetDRCEngine(DRC_ENGINE *engine)
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
KICAD_T Type() const
Returns the type of object.
EDA_ITEM_FLAGS GetFlags() const
A LINE_READER that reads from an open file.
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
wxString AsString() const
LSET is a set of PCB_LAYER_IDs.
static const LSET & FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
A collection of nets and the parameters used to route or test these nets.
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
Handle the data for a net.
const wxString & GetNetname() const
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetCompositeNetclasses() const
Gets all composite (multiple assignment / missing defaults) netclasses.
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetNetclasses() const
Gets all netclasses.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
std::optional< int > GetLocalSolderMaskMargin() const
A small class to help profiling.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
double msecs(bool aSinceLast=false)
Container for project specific data.
A pure virtual class used to derive REPORTER objects from.
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
const EDA_IU_SCALE & GetIuScale() const
wxString MessageTextFromUnscaledValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
UNITS_PROVIDER(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
Handle a list of polygons defining a copper zone.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
bool GetDoNotAllowVias() const
bool GetDoNotAllowPads() const
bool GetDoNotAllowTracks() const
const wxString & GetZoneName() const
int GetMinThickness() const
ZONE_CONNECTION GetPadConnection() const
int GetThermalReliefSpokeWidth() const
bool GetDoNotAllowFootprints() const
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
bool HasKeepoutParametersSet() const
Accessor to determine if any keepout parameters are set.
bool GetDoNotAllowZoneFills() const
int GetThermalReliefGap() const
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
wxString DescribeRef(const wxString &aRef)
Returns a user-visible HTML string describing a footprint reference designator.
void drcPrintDebugMessage(int level, const wxString &msg, const char *function, int line)
#define EXTENDED_ERROR_LIMIT
static bool isKeepoutZone(const BOARD_ITEM *aItem, bool aCheckFlags)
@ DRCE_TUNING_PROFILE_IMPLICIT_RULES
@ DRC_DISALLOW_BURIED_VIAS
@ DRC_DISALLOW_BLIND_VIAS
@ DRC_DISALLOW_THROUGH_VIAS
@ DRC_DISALLOW_FOOTPRINTS
@ DRC_DISALLOW_MICRO_VIAS
@ ANNULAR_WIDTH_CONSTRAINT
@ COURTYARD_CLEARANCE_CONSTRAINT
@ VIA_DIAMETER_CONSTRAINT
@ ZONE_CONNECTION_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
@ NET_CHAIN_LENGTH_CONSTRAINT
@ SOLDER_MASK_SLIVER_CONSTRAINT
@ NET_CHAIN_STUB_LENGTH_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ MIN_RESOLVED_SPOKES_CONSTRAINT
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
@ TEXT_THICKNESS_CONSTRAINT
@ NET_CHAIN_RETURN_PATH_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
@ CONNECTION_WIDTH_CONSTRAINT
@ THERMAL_RELIEF_GAP_CONSTRAINT
@ MAX_UNCOUPLED_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_ABS_MARGIN_CONSTRAINT
@ SOLDER_MASK_EXPANSION_CONSTRAINT
@ PHYSICAL_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_REL_MARGIN_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
constexpr int DRC_DISALLOW_VIAS
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
static FILENAME_RESOLVER * resolver
static const wxChar * traceDrcProfile
Flag to enable DRC profile timing logging.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
bool IsPcbLayer(int aLayer)
Test whether a layer is a valid layer for Pcbnew.
PCB_LAYER_ID
A quick note on layer IDs:
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ PTH
Plated through hole pad.
std::deque< FOOTPRINT * > FOOTPRINTS
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Batch result for clearance-related constraints to reduce per-query overhead during PNS routing.
ZONE * implicitKeepoutZone
std::shared_ptr< DRC_RULE > parentRule
DRC_RULE_CONDITION * condition
DRC_CONSTRAINT constraint
Cache key for own clearance lookups, combining item UUID and layer.
A filename or source description, a problem input line, a line number, a byte offset,...
Represents a single line in the tuning profile configuration grid.
std::vector< DELAY_PROFILE_TRACK_PROPAGATION_ENTRY > m_TrackPropagationEntries
static const long long MM
wxString result
Test unit parsing edge cases and error handling.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I
wxString PrintZoneConnection(ZONE_CONNECTION aConnection)
ZONE_CONNECTION
How pads are covered by copper in zone.
@ THERMAL
Use thermal relief for pads.
@ THT_THERMAL
Thermal relief only for THT pads.
@ FULL
pads are covered by copper