59#define ERROR_LIMIT 199
60#define EXTENDED_ERROR_LIMIT 499
77 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
79 int setLevel = wxAtoi( valueStr );
81 if( level <= setLevel )
82 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
125 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
152 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
155 rule->SetImplicitSource( aImplicitSource );
166 wxString expr, expr2, ncName;
170 std::shared_ptr<DRC_RULE> rule =
175 rule->AddConstraint( widthConstraint );
179 rule->AddConstraint( connectionConstraint );
183 rule->AddConstraint( drillConstraint );
187 rule->AddConstraint( annulusConstraint );
191 rule->AddConstraint( diameterConstraint );
195 rule->AddConstraint( holeToHoleConstraint );
201 rule->AddConstraint( thermalSpokeCountConstraint );
207 rule->AddConstraint( silkClearanceConstraint );
214 rule->AddConstraint( silkTextHeightConstraint );
221 rule->AddConstraint( silkTextThicknessConstraint );
226 rule->AddConstraint( holeClearanceConstraint );
231 rule->AddConstraint( edgeClearanceConstraint );
236 rule->AddConstraint( courtyardClearanceConstraint );
240 std::shared_ptr<DRC_RULE> uViaRule =
247 uViaRule->AddConstraint( uViaDrillConstraint );
251 uViaRule->AddConstraint( uViaDiameterConstraint );
255 std::shared_ptr<DRC_RULE> barcodeRule =
259 barcodeRule->AddConstraint( barcodeSeparationConstraint );
264 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
265 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
267 auto makeNetclassRules =
268 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
270 ncName = nc->GetName();
271 ncName.Replace(
"'",
"\\'" );
273 if( nc->HasClearance() )
275 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
276 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
277 nc->GetClearanceParent()->GetHumanReadableName() );
280 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
282 netclassClearanceRules.push_back( netclassRule );
286 netclassRule->AddConstraint( constraint );
294 if( nc->HasTrackWidth() )
296 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
297 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
298 nc->GetTrackWidthParent()->GetHumanReadableName() );
301 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
303 netclassClearanceRules.push_back( netclassRule );
308 netclassRule->AddConstraint( constraint );
311 if( nc->HasDiffPairWidth() )
313 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
314 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
315 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
318 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
320 netclassItemSpecificRules.push_back( netclassRule );
324 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
325 netclassRule->AddConstraint( constraint );
328 if( nc->HasDiffPairGap() )
330 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
331 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
332 nc->GetDiffPairGapParent()->GetHumanReadableName() );
335 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
337 netclassItemSpecificRules.push_back( netclassRule );
342 netclassRule->AddConstraint( constraint );
345 if( nc->GetDiffPairGap() < nc->GetClearance() )
347 netclassRule = std::make_shared<DRC_RULE>();
348 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
349 nc->GetDiffPairGapParent()->GetHumanReadableName() );
352 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
354 netclassItemSpecificRules.push_back( netclassRule );
357 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
358 netclassRule->AddConstraint( min_clearanceConstraint );
364 if( nc->HasViaDiameter() )
366 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
367 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
368 nc->GetViaDiameterParent()->GetHumanReadableName() );
371 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
373 netclassItemSpecificRules.push_back( netclassRule );
378 netclassRule->AddConstraint( constraint );
381 if( nc->HasViaDrill() )
383 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
384 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
385 nc->GetViaDrillParent()->GetHumanReadableName() );
388 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
390 netclassItemSpecificRules.push_back( netclassRule );
395 netclassRule->AddConstraint( constraint );
398 if( nc->HasuViaDiameter() )
400 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
401 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
402 nc->GetuViaDiameterParent()->GetHumanReadableName() );
405 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
407 netclassItemSpecificRules.push_back( netclassRule );
411 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
412 netclassRule->AddConstraint( constraint );
415 if( nc->HasuViaDrill() )
417 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
418 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
419 nc->GetuViaDrillParent()->GetHumanReadableName() );
422 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
424 netclassItemSpecificRules.push_back( netclassRule );
429 netclassRule->AddConstraint( constraint );
433 m_board->SynchronizeNetsAndNetClasses(
false );
437 makeNetclassRules( netclass,
false );
440 makeNetclassRules( netclass,
false );
447 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
448 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
450 return lhs->m_Constraints[0].m_Value.Min()
451 < rhs->m_Constraints[0].m_Value.Min();
454 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
457 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
461 auto addTuningSingleRule =
463 const wxString& aNetclassName )
468 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
470 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
473 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s'" ),
482 tuningRule->AddConstraint( constraint );
487 auto addTuningDifferentialRules =
494 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
496 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
499 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
500 aNetclass->GetName(),
508 tuningRule->AddConstraint( constraint );
512 std::shared_ptr<DRC_RULE> tuningRule2 = std::make_shared<DRC_RULE>();
514 tuningRule2->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
517 expr2 = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
518 aNetclass->GetName(),
526 tuningRule2->AddConstraint( constraint2 );
533 std::shared_ptr<DRC_RULE> diffPairClearanceRule = std::make_shared<DRC_RULE>();
535 diffPairClearanceRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
538 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
539 aNetclass->GetName(),
545 diffPairClearanceRule->AddConstraint( min_clearanceConstraint );
547 addRule( diffPairClearanceRule );
553 std::shared_ptr<TUNING_PROFILES> tuningParams =
project->GetProjectFile().TuningProfileParameters();
555 auto addNetclassTuningProfileRules =
556 [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules](
NETCLASS* aNetclass )
558 if( aNetclass->HasTuningProfile() )
560 const wxString delayProfileName = aNetclass->GetTuningProfile();
561 const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName );
569 addTuningSingleRule( entry, delayProfileName, aNetclass->GetName() );
571 addTuningDifferentialRules( entry, delayProfileName, aNetclass );
579 addNetclassTuningProfileRules( netclass.get() );
582 addNetclassTuningProfileRules( netclass.get() );
586 auto addKeepoutZoneRule =
596 wxString::Format(
_(
"keepout area of %s" ),
DescribeRef( parentFP->GetReference() ) ),
620 rule->m_ImplicitItemId = zone->
m_Uuid;
622 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsArea('%s')" ),
627 int disallowFlags = 0;
646 rule->AddConstraint( disallowConstraint );
652 addKeepoutZoneRule( zone,
nullptr );
657 for(
ZONE* zone : footprint->Zones() )
660 addKeepoutZoneRule( zone, footprint );
668 if(
m_board && aPath.FileExists() )
670 std::vector<std::shared_ptr<DRC_RULE>> rules;
672 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
677 std::function<bool( wxString* )>
resolver =
678 [&]( wxString* token ) ->
bool
680 return m_board->ResolveTextVar( token, 0 );
683 while(
char* line = lineReader.
ReadLine() )
685 wxString str( line );
686 str =
m_board->ConvertCrossReferencesToKIIDs( str );
689 rulesText << str <<
'\n';
699 for( std::shared_ptr<DRC_RULE>& rule : rules )
712 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
716 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
718 condition = rule->m_Condition;
719 condition->
Compile( &error_semaphore );
724 TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
731 ruleVec =
new std::vector<DRC_ENGINE_CONSTRAINT*>();
735 engineConstraint->
layerTest = rule->m_LayerCondition;
743 const auto& cache =
m_board->GetItemByIdCache();
744 auto it = cache.find( rule->m_ImplicitItemId );
746 if( it != cache.end() && it->second->Type() ==
PCB_ZONE_T )
750 ruleVec->push_back( engineConstraint );
762 if( c->parentRule && !c->parentRule->IsImplicit() )
771 && c->condition->HasGeometryDependentFunctions() )
788 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
790 provider->SetDRCEngine(
this );
815 throw original_parse_error;
832 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
834 provider->SetDRCEngine(
this );
879 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
882 throw original_parse_error;
919 if( !cacheGenerator.
Run() )
923 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
925 int timestamp =
m_board->GetTimeStamp();
930 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
934 if( !provider->RunTests( aUnits ) )
937 providerTimer.
Stop();
939 provider->GetName(), providerTimer.
msecs() );
947 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
951#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
959 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
967 pad =
static_cast<const PAD*
>( a );
969 pad =
static_cast<const PAD*
>( b );
977 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
1002 const PAD*
pad =
nullptr;
1003 const ZONE* zone =
nullptr;
1004 const FOOTPRINT* parentFootprint =
nullptr;
1014 pad =
static_cast<const PAD*
>( a );
1016 zone =
static_cast<const ZONE*
>( a );
1019 pad =
static_cast<const PAD*
>( b );
1021 zone =
static_cast<const ZONE*
>( b );
1024 parentFootprint =
pad->GetParentFootprint();
1028 constraint.
m_Type = aConstraintType;
1030 auto applyConstraint =
1033 if( c->constraint.m_Value.HasMin() )
1035 if( c->parentRule && c->parentRule->IsImplicit() )
1041 if( c->constraint.m_Value.HasOpt() )
1044 if( c->constraint.m_Value.HasMax() )
1047 switch( c->constraint.m_Type )
1082 && ( ( ( !ac ) ^ ( !bc ) )
1085 || ( ( footprints[0] == footprints[1] )
1086 && footprints[0] ) )
1088 && !b_is_non_copper )
1095 for(
int ii = 0; ii < 2; ++ii )
1098 if( !footprints[ii] || !alt_items[ii] )
1101 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
1103 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
1105 if( it != netcodes.end() )
1108 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
1109 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
1111 constraint.
SetName(
_(
"net tie" ) );
1121 int override_val = 0;
1122 std::optional<int> overrideA;
1123 std::optional<int> overrideB;
1125 if( ac && !b_is_non_copper )
1128 if( bc && !a_is_non_copper )
1131 if( overrideA.has_value() || overrideB.has_value() )
1135 if( overrideA.has_value() )
1138 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1145 if( overrideB.has_value() )
1148 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1152 if( overrideB > override_val )
1160 if( override_val < m_designSettings->m_MinClearance )
1163 msg =
_(
"board minimum" );
1166 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1172 if( override_val < m_designSettings->m_HoleClearance )
1175 msg =
_(
"board minimum hole" );
1178 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
1197 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
1208 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
1211 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
1214 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
1225 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
1228 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
1231 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
1240 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
1252 std::optional<int>
override;
1256 override =
pad->GetLocalSolderMaskMargin();
1258 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
1262 if( !
override.has_value() &&
pad )
1264 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1266 override = overrideFootprint->GetLocalSolderMaskMargin();
1267 overrideItem = overrideFootprint;
1274 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1284 std::optional<int>
override;
1288 override =
pad->GetLocalSolderPasteMargin();
1290 if( !
override.has_value() &&
pad )
1292 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1294 override = overrideFootprint->GetLocalSolderPasteMargin();
1295 overrideItem = overrideFootprint;
1302 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1312 std::optional<double> overrideRatio;
1316 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1318 if( !overrideRatio.has_value() &&
pad )
1320 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1322 overrideRatio = overrideFootprint->GetLocalSolderPasteMarginRatio();
1323 overrideItem = overrideFootprint;
1330 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1339 auto testAssertion =
1342 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1343 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1345 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1346 REPORT(
_(
"Assertion passed." ) )
1351 auto processConstraint =
1354 bool implicit = c->parentRule && c->parentRule->IsImplicit();
1358 switch( c->constraint.m_Type )
1367 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1372 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1377 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1383 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1389 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1395 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1401 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1407 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute clearance: %s." ),
1413 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1419 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1425 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1443 switch( c->constraint.m_Type )
1446 if( c->constraint.m_Value.HasOpt() )
1448 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1452 else if( c->constraint.m_Value.HasMin() )
1454 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1462 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1468 if( c->constraint.m_Value.HasOpt() )
1470 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1474 else if( c->constraint.m_Value.HasMin() )
1476 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1483 if( c->constraint.m_Value.HasOpt() )
1485 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1489 else if( c->constraint.m_Value.HasMin() )
1491 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1501 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1507 if( c->constraint.m_Value.HasOpt() )
1509 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1513 else if( c->constraint.m_Value.HasMin() )
1515 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1523 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1529 REPORT( wxString::Format(
_(
"Checking %s." ),
1535 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1537 c->constraint.m_Value.HasMin()
1539 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1540 c->constraint.m_Value.HasOpt()
1542 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1543 c->constraint.m_Value.HasMax()
1545 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ) ) )
1551 REPORT( wxString::Format(
_(
"Checking %s." ),
1557 if( a_is_non_copper || b_is_non_copper )
1561 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1563 else if( a_is_non_copper )
1565 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1568 else if( b_is_non_copper )
1570 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1589 if(
via->IsMicroVia() )
1591 else if(
via->IsBlindVia() )
1593 else if(
via->IsBuriedVia() )
1615 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1623 default: mask = 0;
break;
1627 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1630 REPORT(
_(
"Keepout constraint not met." ) )
1632 REPORT(
_(
"Disallow constraint not met." ) )
1650 if( !( c->layerTest & itemLayers ).any() )
1654 REPORT(
_(
"Keepout layer(s) not matched." ) )
1656 else if( c->parentRule )
1658 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1659 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1663 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1670 if( (
IsPcbLayer( aLayer ) && !c->layerTest.test( aLayer ) )
1671 || (
m_board->GetEnabledLayers() & c->layerTest ).count() == 0 )
1675 REPORT(
_(
"Constraint layer not matched." ) )
1677 else if( c->parentRule )
1679 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1680 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1684 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1691 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1694 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1700 REPORT(
_(
"Unconditional constraint applied." ) )
1704 REPORT(
_(
"Unconditional rule applied." ) )
1709 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1713 applyConstraint( c );
1721 if( c->implicitKeepoutZone && !aReporter )
1724 BOX2I zoneBBox = c->implicitKeepoutZone->GetBoundingBox();
1736 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1737 EscapeHTML( c->condition->GetExpression() ) ) )
1740 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1746 REPORT(
_(
"Constraint applied." ) )
1750 REPORT(
_(
"Rule applied." ) )
1755 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1759 applyConstraint( c );
1763 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1764 :
_(
"Condition not satisfied; rule ignored." ) )
1775 && ( !b || !b_is_non_copper ) )
1800 if( !ncNameA.empty() || !ncNameB.empty() )
1804 if( !ncNameA.empty() )
1812 if( !ncNameB.empty() )
1834 processConstraint( rule );
1852 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
1856 a = parentFootprint;
1858 b = parentFootprint;
1865 processConstraint( rule );
1875 constraint.
SetName(
_(
"board setup" ) );
1882 constraint.
SetName(
_(
"board setup" ) );
1889 constraint.
SetName(
_(
"board setup" ) );
1902 bool needBlankLine =
true;
1911 needBlankLine =
false;
1914 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1935 needBlankLine =
false;
1938 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1952 if( !a_is_non_copper && !b_is_non_copper )
1957 needBlankLine =
false;
1960 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1966 constraint.
SetName(
_(
"board minimum" ) );
1976 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1982 constraint.
SetName(
_(
"board minimum" ) );
1990 if(
pad && parentFootprint )
1997 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
2002 constraint.
SetName(
_(
"footprint" ) );
2013 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
2030 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
2047 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
2112 auto testAssertion =
2115 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
2116 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
2118 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2121 REPORT(
_(
"Assertion passed." ) )
2126 aFailureHandler( &c->constraint );
2130 auto processConstraint =
2134 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
2138 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
2139 EscapeHTML( c->parentRule->m_LayerSource ) ) )
2142 if( !c->condition || c->condition->GetExpression().IsEmpty() )
2144 REPORT(
_(
"Unconditional rule applied." ) )
2149 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
2150 EscapeHTML( c->condition->GetExpression() ) ) )
2152 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2155 REPORT(
_(
"Rule applied." ) )
2160 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
2169 for(
int ii = 0; ii < (int) it->second->size(); ++ii )
2170 processConstraint( it->second->at( ii ) );
2180 assert( error_code >= 0 && error_code <=
DRCE_LAST );
2187 int aMarkerLayer,
const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
2196 static std::mutex handlerLock;
2197 std::lock_guard<std::mutex> guard( handlerLock );
2203 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
2204 aItem->GetViolatingTest()->GetName(),
2205 aItem->GetErrorMessage(
false ),
2206 aItem->GetErrorCode() );
2208 DRC_RULE* rule = aItem->GetViolatingRule();
2211 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
2215 wxString violatingItemsStr = wxT(
"Violating items: " );
2217 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
2281 bool aUnconditionalOnly )
2290 if( aUnconditionalOnly && c->
condition )
2295 if( current > worst )
2331 std::set<int> distinctMinimums;
2340 return distinctMinimums;
2346 wxString& aBaseDpName )
2351 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2355 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
2359 else if( ch ==
'+' )
2361 aComplementNet = wxT(
"-" );
2364 else if( ch ==
'-' )
2366 aComplementNet = wxT(
"+" );
2369 else if( ch ==
'N' )
2371 aComplementNet = wxT(
"P" );
2374 else if ( ch ==
'P' )
2376 aComplementNet = wxT(
"N" );
2385 if( rv != 0 && count >= 1 )
2387 aBaseDpName = aNetName.Left( aNetName.Length() - count );
2388 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
2398 wxString
dummy, coupledNetName;
2434 if( parentFootprint && parentFootprint->
IsNetTie() )
2441 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2443 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2455enum class SHOWMATCH_DOMAIN
2462 MASK_EXPANSION_ITEMS,
2475struct SHOWMATCH_DOMAIN_SPEC
2477 SHOWMATCH_DOMAIN primary;
2478 SHOWMATCH_DOMAIN secondary = SHOWMATCH_DOMAIN::ALL_ITEMS;
2479 bool hasSecondary =
false;
2480 bool secondaryUnary =
false;
2484bool isShowMatchSkippable(
const BOARD_ITEM* aItem )
2486 switch( aItem->
Type() )
2492 default:
return false;
2497bool matchesShowMatchDomain(
const BOARD_ITEM* aItem, SHOWMATCH_DOMAIN aDomain )
2499 if( !aItem || isShowMatchSkippable( aItem ) )
2504 case SHOWMATCH_DOMAIN::ALL_ITEMS:
return true;
2508 case SHOWMATCH_DOMAIN::EDGE_ITEMS:
2514 const PAD*
pad =
static_cast<const PAD*
>( aItem );
2522 case SHOWMATCH_DOMAIN::HOLE_ITEMS:
return aItem->
HasHole();
2524 case SHOWMATCH_DOMAIN::MASK_EXPANSION_ITEMS:
2525 switch( aItem->
Type() )
2534 default:
return false;
2539 case SHOWMATCH_DOMAIN::PADS:
return aItem->
Type() ==
PCB_PAD_T;
2545 case SHOWMATCH_DOMAIN::ROUTING_ITEMS:
2546 switch( aItem->
Type() )
2553 default:
return false;
2558 case SHOWMATCH_DOMAIN::SILK_TARGET_ITEMS:
2565 case SHOWMATCH_DOMAIN::TEXT_ITEMS:
2569 case SHOWMATCH_DOMAIN::VIAS:
return aItem->
Type() ==
PCB_VIA_T;
2576SHOWMATCH_DOMAIN_SPEC getShowMatchDomainSpec(
DRC_CONSTRAINT_T aConstraint )
2578 switch( aConstraint )
2595 return { SHOWMATCH_DOMAIN::SILK_ITEMS, SHOWMATCH_DOMAIN::SILK_TARGET_ITEMS,
true,
false };
2627 default:
return { SHOWMATCH_DOMAIN::ALL_ITEMS };
2632std::vector<BOARD_ITEM*> collectShowMatchCandidates(
BOARD* aBoard, SHOWMATCH_DOMAIN aDomain )
2634 std::vector<BOARD_ITEM*> items;
2641 if( matchesShowMatchDomain( item, aDomain ) )
2642 items.push_back( item );
2649std::vector<PCB_LAYER_ID> getShowMatchLayers(
const BOARD_ITEM* aItem )
2651 std::vector<PCB_LAYER_ID> layers;
2653 switch( aItem->
Type() )
2655 case PCB_PAD_T: layers =
static_cast<const PAD*
>( aItem )->Padstack().UniqueLayers();
break;
2657 case PCB_VIA_T: layers =
static_cast<const PCB_VIA*
>( aItem )->Padstack().UniqueLayers();
break;
2661 layers.push_back( layer );
2666 if( layers.empty() )
2676 bool testedLayer =
false;
2678 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItem ) )
2703std::vector<PCB_LAYER_ID> getShowMatchPairLayers(
const DRC_RULE& aRule,
const BOARD_ITEM* aItemA,
2706 std::vector<PCB_LAYER_ID> layers;
2707 std::set<int> seenLayers;
2714 if( seenLayers.insert(
static_cast<int>( aLayer ) ).second )
2715 layers.push_back( aLayer );
2718 switch( aConstraint )
2721 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemA ) )
2729 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemA ) )
2732 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemB ) )
2738 if( layers.empty() )
2748 for(
PCB_LAYER_ID layer : getShowMatchPairLayers( aRule, aItemA, aItemB, aConstraint ) )
2766 if(
name == prov->GetName() )
2778 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2779 wxS(
"[ShowMatches] engine enter: expr='%s', constraint=%d" ), aExpression, (
int) aConstraint );
2780 std::vector<BOARD_ITEM*> matches;
2789 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine: compile failed" ) );
2796 if(
auto connectivity =
m_board->GetConnectivity() )
2798 if(
auto ftCache = connectivity->GetFromToCache() )
2803 size_t totalItems = 0;
2804 size_t skippedItems = 0;
2805 size_t noLayerItems = 0;
2806 size_t checkedItems = 0;
2808 for(
auto& [kiid, item] :
m_board->GetItemByIdCache() )
2813 switch( item->Type() )
2825 LSET itemLayers = item->GetLayerSet();
2827 if( itemLayers.none() )
2834 bool matched =
false;
2838 if( condition.
EvaluateFor( item,
nullptr,
static_cast<int>( aConstraint ), layer,
2841 matches.push_back( item );
2842 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2843 wxS(
"[ShowMatches] engine: match type=%d kiid=%s layer=%d" ),
2844 (
int) item->Type(), kiid.AsString(), (
int) layer );
2851 if( !matched && matches.size() == 0 && checkedItems <= 5 )
2853 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2854 wxS(
"[ShowMatches] engine: no-match sample type=%d kiid=%s layers=%s" ),
2855 (
int) item->Type(), kiid.AsString(), itemLayers.
FmtHex() );
2859 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2860 wxS(
"[ShowMatches] engine stats: total=%zu skipped=%zu noLayer=%zu checked=%zu" ),
2861 totalItems, skippedItems, noLayerItems, checkedItems );
2863 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine exit: total=%zu" ), matches.size() );
2870 std::vector<BOARD_ITEM*> matches;
2875 const wxString condition = aRule->m_Condition ? aRule->m_Condition->GetExpression() : wxString();
2876 const bool requiresPairwise = condition.Contains( wxS(
"B." ) );
2877 std::set<BOARD_ITEM*> matchedItems;
2879 if(
auto connectivity =
m_board->GetConnectivity() )
2881 if(
auto ftCache = connectivity->GetFromToCache() )
2890 SHOWMATCH_DOMAIN_SPEC domainSpec = getShowMatchDomainSpec( constraint.
m_Type );
2891 std::vector<BOARD_ITEM*> primaryItems = collectShowMatchCandidates(
m_board, domainSpec.primary );
2892 std::vector<BOARD_ITEM*> secondaryItems;
2894 if( domainSpec.hasSecondary )
2895 secondaryItems = collectShowMatchCandidates(
m_board, domainSpec.secondary );
2897 if( requiresPairwise )
2899 if( secondaryItems.empty() )
2901 for(
size_t ii = 0; ii < primaryItems.size(); ++ii )
2905 for(
size_t jj = ii + 1; jj < primaryItems.size(); ++jj )
2909 if( ruleMatchesPair( *aRule, itemA, itemB, constraint.
m_Type,
2912 matchedItems.insert( itemA );
2913 matchedItems.insert( itemB );
2924 if( itemA == itemB )
2927 if( ruleMatchesPair( *aRule, itemA, itemB, constraint.
m_Type,
2930 matchedItems.insert( itemA );
2931 matchedItems.insert( itemB );
2941 if( ruleMatchesUnary( *aRule, item, constraint.
m_Type, aReporter ? aReporter :
m_logReporter ) )
2943 matchedItems.insert( item );
2947 if( domainSpec.hasSecondary && domainSpec.secondaryUnary )
2951 if( ruleMatchesUnary( *aRule, item, constraint.
m_Type, aReporter ? aReporter :
m_logReporter ) )
2953 matchedItems.insert( item );
2960 matches.assign( matchedItems.begin(), matchedItems.end() );
2990 const PAD*
pad =
static_cast<const PAD*
>( aItem );
3005 *aSource = constraint.
GetName();
3039 if( it->first.m_uuid == aUuid )
3065 using CLEARANCE_MAP = std::unordered_map<DRC_OWN_CLEARANCE_CACHE_KEY, int>;
3069 std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>> itemsToProcess;
3070 size_t estimatedPads = 0;
3073 estimatedPads += footprint->Pads().size();
3075 itemsToProcess.reserve(
m_board->Tracks().size() + estimatedPads * 2 );
3082 itemsToProcess.emplace_back( track, layer );
3086 itemsToProcess.emplace_back( track, track->GetLayer() );
3092 for(
PAD*
pad : footprint->Pads() )
3095 itemsToProcess.emplace_back(
pad, layer );
3099 if( itemsToProcess.empty() )
3109 auto processItems = [
this](
size_t aStart,
size_t aEnd,
3110 const std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>>& aItems )
3113 CLEARANCE_MAP localCache;
3115 for(
size_t i = aStart; i < aEnd; ++i )
3124 const PAD*
pad =
static_cast<const PAD*
>( item );
3143 auto results =
tp.submit_blocks( 0, itemsToProcess.size(),
3144 [&](
size_t aStart,
size_t aEnd ) -> CLEARANCE_MAP
3146 return processItems( aStart, aEnd, itemsToProcess );
3153 std::vector<CLEARANCE_MAP> collectedResults;
3154 collectedResults.reserve( results.size() );
3156 for(
size_t i = 0; i < results.size(); ++i )
3158 if( results[i].valid() )
3159 collectedResults.push_back( results[i].get() );
3166 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 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
@ SOLDER_MASK_SLIVER_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ MIN_RESOLVED_SPOKES_CONSTRAINT
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
@ TEXT_THICKNESS_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
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