56#define ERROR_LIMIT 199
57#define EXTENDED_ERROR_LIMIT 499
74 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
76 int setLevel = wxAtoi( valueStr );
78 if( level <= setLevel )
79 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
122 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
149 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
152 rule->SetImplicitSource( aImplicitSource );
163 wxString expr, expr2, ncName;
167 std::shared_ptr<DRC_RULE> rule =
172 rule->AddConstraint( widthConstraint );
176 rule->AddConstraint( connectionConstraint );
180 rule->AddConstraint( drillConstraint );
184 rule->AddConstraint( annulusConstraint );
188 rule->AddConstraint( diameterConstraint );
192 rule->AddConstraint( holeToHoleConstraint );
198 rule->AddConstraint( thermalSpokeCountConstraint );
204 rule->AddConstraint( silkClearanceConstraint );
211 rule->AddConstraint( silkTextHeightConstraint );
218 rule->AddConstraint( silkTextThicknessConstraint );
223 rule->AddConstraint( holeClearanceConstraint );
228 rule->AddConstraint( edgeClearanceConstraint );
233 rule->AddConstraint( courtyardClearanceConstraint );
237 std::shared_ptr<DRC_RULE> uViaRule =
244 uViaRule->AddConstraint( uViaDrillConstraint );
248 uViaRule->AddConstraint( uViaDiameterConstraint );
252 std::shared_ptr<DRC_RULE> barcodeRule =
256 barcodeRule->AddConstraint( barcodeSeparationConstraint );
261 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
262 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
264 auto makeNetclassRules =
265 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
267 ncName = nc->GetName();
268 ncName.Replace(
"'",
"\\'" );
270 if( nc->HasClearance() )
272 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
273 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
274 nc->GetClearanceParent()->GetHumanReadableName() );
277 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
279 netclassClearanceRules.push_back( netclassRule );
283 netclassRule->AddConstraint( constraint );
291 if( nc->HasTrackWidth() )
293 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
294 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
295 nc->GetTrackWidthParent()->GetHumanReadableName() );
298 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
300 netclassClearanceRules.push_back( netclassRule );
305 netclassRule->AddConstraint( constraint );
308 if( nc->HasDiffPairWidth() )
310 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
311 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
312 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
315 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
317 netclassItemSpecificRules.push_back( netclassRule );
321 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
322 netclassRule->AddConstraint( constraint );
325 if( nc->HasDiffPairGap() )
327 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
328 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
329 nc->GetDiffPairGapParent()->GetHumanReadableName() );
332 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
334 netclassItemSpecificRules.push_back( netclassRule );
339 netclassRule->AddConstraint( constraint );
342 if( nc->GetDiffPairGap() < nc->GetClearance() )
344 netclassRule = std::make_shared<DRC_RULE>();
345 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
346 nc->GetDiffPairGapParent()->GetHumanReadableName() );
349 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
351 netclassItemSpecificRules.push_back( netclassRule );
354 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
355 netclassRule->AddConstraint( min_clearanceConstraint );
361 if( nc->HasViaDiameter() )
363 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
364 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
365 nc->GetViaDiameterParent()->GetHumanReadableName() );
368 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
370 netclassItemSpecificRules.push_back( netclassRule );
375 netclassRule->AddConstraint( constraint );
378 if( nc->HasViaDrill() )
380 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
381 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
382 nc->GetViaDrillParent()->GetHumanReadableName() );
385 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
387 netclassItemSpecificRules.push_back( netclassRule );
392 netclassRule->AddConstraint( constraint );
395 if( nc->HasuViaDiameter() )
397 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
398 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
399 nc->GetuViaDiameterParent()->GetHumanReadableName() );
402 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
404 netclassItemSpecificRules.push_back( netclassRule );
408 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
409 netclassRule->AddConstraint( constraint );
412 if( nc->HasuViaDrill() )
414 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
415 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
416 nc->GetuViaDrillParent()->GetHumanReadableName() );
419 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
421 netclassItemSpecificRules.push_back( netclassRule );
426 netclassRule->AddConstraint( constraint );
430 m_board->SynchronizeNetsAndNetClasses(
false );
434 makeNetclassRules( netclass,
false );
437 makeNetclassRules( netclass,
false );
444 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
445 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
447 return lhs->m_Constraints[0].m_Value.Min()
448 < rhs->m_Constraints[0].m_Value.Min();
451 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
454 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
458 auto addTuningSingleRule =
460 const wxString& aNetclassName )
465 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
467 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
470 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s'" ),
479 tuningRule->AddConstraint( constraint );
484 auto addTuningDifferentialRules =
491 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
493 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
496 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
497 aNetclass->GetName(),
505 tuningRule->AddConstraint( constraint );
509 std::shared_ptr<DRC_RULE> tuningRule2 = std::make_shared<DRC_RULE>();
511 tuningRule2->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
514 expr2 = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
515 aNetclass->GetName(),
523 tuningRule2->AddConstraint( constraint2 );
530 std::shared_ptr<DRC_RULE> diffPairClearanceRule = std::make_shared<DRC_RULE>();
532 diffPairClearanceRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
535 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
536 aNetclass->GetName(),
542 diffPairClearanceRule->AddConstraint( min_clearanceConstraint );
544 addRule( diffPairClearanceRule );
550 std::shared_ptr<TUNING_PROFILES> tuningParams =
project->GetProjectFile().TuningProfileParameters();
552 auto addNetclassTuningProfileRules =
553 [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules](
NETCLASS* aNetclass )
555 if( aNetclass->HasTuningProfile() )
557 const wxString delayProfileName = aNetclass->GetTuningProfile();
558 const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName );
566 addTuningSingleRule( entry, delayProfileName, aNetclass->GetName() );
568 addTuningDifferentialRules( entry, delayProfileName, aNetclass );
576 addNetclassTuningProfileRules( netclass.get() );
579 addNetclassTuningProfileRules( netclass.get() );
583 auto addKeepoutZoneRule =
593 wxString::Format(
_(
"keepout area of %s" ),
DescribeRef( parentFP->GetReference() ) ),
617 rule->m_ImplicitItemId = zone->
m_Uuid;
619 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsArea('%s')" ),
624 int disallowFlags = 0;
643 rule->AddConstraint( disallowConstraint );
649 addKeepoutZoneRule( zone,
nullptr );
654 for(
ZONE* zone : footprint->Zones() )
657 addKeepoutZoneRule( zone, footprint );
665 if(
m_board && aPath.FileExists() )
667 std::vector<std::shared_ptr<DRC_RULE>> rules;
669 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
674 std::function<bool( wxString* )>
resolver =
675 [&]( wxString* token ) ->
bool
677 return m_board->ResolveTextVar( token, 0 );
680 while(
char* line = lineReader.
ReadLine() )
682 wxString str( line );
683 str =
m_board->ConvertCrossReferencesToKIIDs( str );
686 rulesText << str <<
'\n';
696 for( std::shared_ptr<DRC_RULE>& rule : rules )
709 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
713 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
715 condition = rule->m_Condition;
716 condition->
Compile( &error_semaphore );
721 TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
728 ruleVec =
new std::vector<DRC_ENGINE_CONSTRAINT*>();
732 engineConstraint->
layerTest = rule->m_LayerCondition;
736 ruleVec->push_back( engineConstraint );
747 if( c->parentRule && !c->parentRule->IsImplicit() )
766 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
768 provider->SetDRCEngine(
this );
793 throw original_parse_error;
810 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
812 provider->SetDRCEngine(
this );
857 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
860 throw original_parse_error;
897 if( !cacheGenerator.
Run() )
901 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
903 int timestamp =
m_board->GetTimeStamp();
908 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
910 if( !provider->RunTests( aUnits ) )
919 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
923#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
931 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
939 pad =
static_cast<const PAD*
>( a );
941 pad =
static_cast<const PAD*
>( b );
949 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
975 const ZONE* zone =
nullptr;
976 const FOOTPRINT* parentFootprint =
nullptr;
986 pad =
static_cast<const PAD*
>( a );
988 zone =
static_cast<const ZONE*
>( a );
991 pad =
static_cast<const PAD*
>( b );
993 zone =
static_cast<const ZONE*
>( b );
996 parentFootprint =
pad->GetParentFootprint();
1000 constraint.
m_Type = aConstraintType;
1002 auto applyConstraint =
1005 if( c->constraint.m_Value.HasMin() )
1007 if( c->parentRule && c->parentRule->IsImplicit() )
1013 if( c->constraint.m_Value.HasOpt() )
1016 if( c->constraint.m_Value.HasMax() )
1019 switch( c->constraint.m_Type )
1054 && ( ( ( !ac ) ^ ( !bc ) )
1057 || ( ( footprints[0] == footprints[1] )
1058 && footprints[0] ) )
1060 && !b_is_non_copper )
1067 for(
int ii = 0; ii < 2; ++ii )
1070 if( !footprints[ii] || !alt_items[ii] )
1073 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
1075 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
1077 if( it != netcodes.end() )
1080 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
1081 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
1083 constraint.
SetName(
_(
"net tie" ) );
1093 int override_val = 0;
1094 std::optional<int> overrideA;
1095 std::optional<int> overrideB;
1097 if( ac && !b_is_non_copper )
1100 if( bc && !a_is_non_copper )
1103 if( overrideA.has_value() || overrideB.has_value() )
1107 if( overrideA.has_value() )
1110 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1117 if( overrideB.has_value() )
1120 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1124 if( overrideB > override_val )
1132 if( override_val < m_designSettings->m_MinClearance )
1135 msg =
_(
"board minimum" );
1138 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1144 if( override_val < m_designSettings->m_HoleClearance )
1147 msg =
_(
"board minimum hole" );
1150 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
1169 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
1180 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
1183 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
1186 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
1197 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
1200 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
1203 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
1212 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
1224 std::optional<int>
override;
1227 override =
pad->GetLocalSolderMaskMargin();
1229 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
1236 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1246 std::optional<int>
override;
1249 override =
pad->GetLocalSolderPasteMargin();
1254 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1264 std::optional<double> overrideRatio;
1267 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1272 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1281 auto testAssertion =
1284 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1285 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1287 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1288 REPORT(
_(
"Assertion passed." ) )
1293 auto processConstraint =
1296 bool implicit = c->parentRule && c->parentRule->IsImplicit();
1300 switch( c->constraint.m_Type )
1309 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1314 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1319 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1325 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1331 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1337 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1343 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1349 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute clearance: %s." ),
1355 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1361 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1367 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1385 switch( c->constraint.m_Type )
1388 if( c->constraint.m_Value.HasOpt() )
1390 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1394 else if( c->constraint.m_Value.HasMin() )
1396 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1404 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1410 if( c->constraint.m_Value.HasOpt() )
1412 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1416 else if( c->constraint.m_Value.HasMin() )
1418 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1425 if( c->constraint.m_Value.HasOpt() )
1427 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1431 else if( c->constraint.m_Value.HasMin() )
1433 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1443 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1449 if( c->constraint.m_Value.HasOpt() )
1451 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1455 else if( c->constraint.m_Value.HasMin() )
1457 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1465 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1471 REPORT( wxString::Format(
_(
"Checking %s." ),
1477 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1479 c->constraint.m_Value.HasMin()
1481 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1482 c->constraint.m_Value.HasOpt()
1484 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1485 c->constraint.m_Value.HasMax()
1487 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ) ) )
1493 REPORT( wxString::Format(
_(
"Checking %s." ),
1499 if( a_is_non_copper || b_is_non_copper )
1503 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1505 else if( a_is_non_copper )
1507 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1510 else if( b_is_non_copper )
1512 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1531 if(
via->IsMicroVia() )
1533 else if(
via->IsBlindVia() )
1535 else if(
via->IsBuriedVia() )
1557 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1565 default: mask = 0;
break;
1569 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1572 REPORT(
_(
"Keepout constraint not met." ) )
1574 REPORT(
_(
"Disallow constraint not met." ) )
1592 if( !( c->layerTest & itemLayers ).any() )
1596 REPORT(
_(
"Keepout layer(s) not matched." ) )
1598 else if( c->parentRule )
1600 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1601 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1605 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1612 if( (
IsPcbLayer( aLayer ) && !c->layerTest.test( aLayer ) )
1613 || (
m_board->GetEnabledLayers() & c->layerTest ).count() == 0 )
1617 REPORT(
_(
"Constraint layer not matched." ) )
1619 else if( c->parentRule )
1621 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1622 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1626 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1633 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1636 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1642 REPORT(
_(
"Unconditional constraint applied." ) )
1646 REPORT(
_(
"Unconditional rule applied." ) )
1651 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1655 applyConstraint( c );
1665 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1666 EscapeHTML( c->condition->GetExpression() ) ) )
1669 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1675 REPORT(
_(
"Constraint applied." ) )
1679 REPORT(
_(
"Rule applied." ) )
1684 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1688 applyConstraint( c );
1692 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1693 :
_(
"Condition not satisfied; rule ignored." ) )
1704 && ( !b || !b_is_non_copper ) )
1729 if( !ncNameA.empty() || !ncNameB.empty() )
1733 if( !ncNameA.empty() )
1741 if( !ncNameB.empty() )
1763 processConstraint( rule );
1781 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
1785 a = parentFootprint;
1787 b = parentFootprint;
1794 processConstraint( rule );
1804 constraint.
SetName(
_(
"board setup" ) );
1811 constraint.
SetName(
_(
"board setup" ) );
1818 constraint.
SetName(
_(
"board setup" ) );
1831 bool needBlankLine =
true;
1840 needBlankLine =
false;
1843 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1864 needBlankLine =
false;
1867 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1881 if( !a_is_non_copper && !b_is_non_copper )
1886 needBlankLine =
false;
1889 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1895 constraint.
SetName(
_(
"board minimum" ) );
1905 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1911 constraint.
SetName(
_(
"board minimum" ) );
1919 if(
pad && parentFootprint )
1926 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
1931 constraint.
SetName(
_(
"footprint" ) );
1942 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
1959 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
1976 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
2041 auto testAssertion =
2044 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
2045 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
2047 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2050 REPORT(
_(
"Assertion passed." ) )
2055 aFailureHandler( &c->constraint );
2059 auto processConstraint =
2063 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
2067 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
2068 EscapeHTML( c->parentRule->m_LayerSource ) ) )
2071 if( !c->condition || c->condition->GetExpression().IsEmpty() )
2073 REPORT(
_(
"Unconditional rule applied." ) )
2078 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
2079 EscapeHTML( c->condition->GetExpression() ) ) )
2081 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2084 REPORT(
_(
"Rule applied." ) )
2089 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
2098 for(
int ii = 0; ii < (int) it->second->size(); ++ii )
2099 processConstraint( it->second->at( ii ) );
2109 assert( error_code >= 0 && error_code <=
DRCE_LAST );
2115 int aMarkerLayer,
const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
2117 static std::mutex globalLock;
2123 std::lock_guard<std::mutex> guard( globalLock );
2129 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
2130 aItem->GetViolatingTest()->GetName(),
2131 aItem->GetErrorMessage(
false ),
2132 aItem->GetErrorCode() );
2134 DRC_RULE* rule = aItem->GetViolatingRule();
2137 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
2141 wxString violatingItemsStr = wxT(
"Violating items: " );
2143 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
2190 wxSafeYield(
nullptr,
true );
2219 if( current > worst )
2233 std::set<int> distinctMinimums;
2242 return distinctMinimums;
2248 wxString& aBaseDpName )
2253 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2257 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
2261 else if( ch ==
'+' )
2263 aComplementNet = wxT(
"-" );
2266 else if( ch ==
'-' )
2268 aComplementNet = wxT(
"+" );
2271 else if( ch ==
'N' )
2273 aComplementNet = wxT(
"P" );
2276 else if ( ch ==
'P' )
2278 aComplementNet = wxT(
"N" );
2287 if( rv != 0 && count >= 1 )
2289 aBaseDpName = aNetName.Left( aNetName.Length() - count );
2290 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
2300 wxString
dummy, coupledNetName;
2336 if( parentFootprint && parentFootprint->
IsNetTie() )
2343 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2345 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2359 if(
name == prov->GetName() )
2371 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2372 wxS(
"[ShowMatches] engine enter: expr='%s', constraint=%d" ), aExpression, (
int) aConstraint );
2373 std::vector<BOARD_ITEM*> matches;
2382 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine: compile failed" ) );
2389 if(
auto connectivity =
m_board->GetConnectivity() )
2391 if(
auto ftCache = connectivity->GetFromToCache() )
2396 size_t totalItems = 0;
2397 size_t skippedItems = 0;
2398 size_t noLayerItems = 0;
2399 size_t checkedItems = 0;
2401 for(
auto& [kiid, item] :
m_board->GetItemByIdCache() )
2406 switch( item->Type() )
2418 LSET itemLayers = item->GetLayerSet();
2420 if( itemLayers.none() )
2427 bool matched =
false;
2431 if( condition.
EvaluateFor( item,
nullptr,
static_cast<int>( aConstraint ), layer,
2434 matches.push_back( item );
2435 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2436 wxS(
"[ShowMatches] engine: match type=%d kiid=%s layer=%d" ),
2437 (
int) item->Type(), kiid.AsString(), (
int) layer );
2444 if( !matched && matches.size() == 0 && checkedItems <= 5 )
2446 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2447 wxS(
"[ShowMatches] engine: no-match sample type=%d kiid=%s layers=%s" ),
2448 (
int) item->Type(), kiid.AsString(), itemLayers.
FmtHex() );
2452 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
2453 wxS(
"[ShowMatches] engine stats: total=%zu skipped=%zu noLayer=%zu checked=%zu" ),
2454 totalItems, skippedItems, noLayerItems, checkedItems );
2456 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine exit: total=%zu" ), matches.size() );
2485 const PAD*
pad =
static_cast<const PAD*
>( aItem );
2500 *aSource = constraint.
GetName();
2526 if( it->first.m_uuid == aUuid )
2551 using CLEARANCE_MAP = std::unordered_map<DRC_OWN_CLEARANCE_CACHE_KEY, int>;
2555 std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>> itemsToProcess;
2556 size_t estimatedPads = 0;
2559 estimatedPads += footprint->Pads().size();
2561 itemsToProcess.reserve(
m_board->Tracks().size() + estimatedPads * 2 );
2568 itemsToProcess.emplace_back( track, layer );
2572 itemsToProcess.emplace_back( track, track->GetLayer() );
2578 for(
PAD*
pad : footprint->Pads() )
2581 itemsToProcess.emplace_back(
pad, layer );
2585 if( itemsToProcess.empty() )
2595 auto processItems = [
this](
size_t aStart,
size_t aEnd,
2596 const std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>>& aItems )
2599 CLEARANCE_MAP localCache;
2601 for(
size_t i = aStart; i < aEnd; ++i )
2610 const PAD*
pad =
static_cast<const PAD*
>( item );
2629 auto results =
tp.submit_blocks( 0, itemsToProcess.size(),
2630 [&](
size_t aStart,
size_t aEnd ) -> CLEARANCE_MAP
2632 return processItems( aStart, aEnd, itemsToProcess );
2639 std::vector<CLEARANCE_MAP> collectedResults;
2640 collectedResults.reserve( results.size() );
2642 for(
size_t i = 0; i < results.size(); ++i )
2644 if( results[i].valid() )
2645 collectedResults.push_back( results[i].get() );
2652 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.
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
Information pertinent to a Pcbnew printed circuit board.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
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)
DS_PROXY_VIEW_ITEM * m_drawingSheet
NETLIST * m_schematicNetlist
std::shared_mutex m_clearanceCacheMutex
bool KeepRefreshing(bool aWait=false)
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
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 ...
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint)
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
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator={})
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)
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 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 & 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 LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
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
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ MIN_RESOLVED_SPOKES_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::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.
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
@ 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_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_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