54#define ERROR_LIMIT 199 
   55#define EXTENDED_ERROR_LIMIT 499 
   72    if( wxGetEnv( wxT( 
"DRC_DEBUG" ), &valueStr ) )
 
   74        int setLevel = wxAtoi( valueStr );
 
   76        if( level <= setLevel )
 
   77            printf( 
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
 
 
  120    const ZONE* zone = 
static_cast<const ZONE*
>( aItem );
 
 
  146    std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
 
  149    rule->m_Implicit = 
true;
 
 
  160    wxString               expr, expr2, ncName;
 
  168    rule->AddConstraint( widthConstraint );
 
  172    rule->AddConstraint( connectionConstraint );
 
  176    rule->AddConstraint( drillConstraint );
 
  180    rule->AddConstraint( annulusConstraint );
 
  184    rule->AddConstraint( diameterConstraint );
 
  188    rule->AddConstraint( holeToHoleConstraint );
 
  193    rule->AddConstraint( thermalSpokeCountConstraint );
 
  199    rule->AddConstraint( silkClearanceConstraint );
 
  205    rule->AddConstraint( silkTextHeightConstraint );
 
  211    rule->AddConstraint( silkTextThicknessConstraint );
 
  216    rule->AddConstraint( holeClearanceConstraint );
 
  221    rule->AddConstraint( edgeClearanceConstraint );
 
  226    rule->AddConstraint( courtyardClearanceConstraint );
 
  230    std::shared_ptr<DRC_RULE> uViaRule = 
createImplicitRule( 
_( 
"board setup micro-via constraints" ) );
 
  236    uViaRule->AddConstraint( uViaDrillConstraint );
 
  240    uViaRule->AddConstraint( uViaDiameterConstraint );
 
  244    std::shared_ptr<DRC_RULE> barcodeRule = 
createImplicitRule( 
_( 
"barcode visual separation default" ) );
 
  247    barcodeRule->AddConstraint( barcodeSeparationConstraint );
 
  252    std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
 
  253    std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
 
  255    auto makeNetclassRules =
 
  256            [&]( 
const std::shared_ptr<NETCLASS>& nc, 
bool isDefault )
 
  258                ncName = nc->GetName();
 
  259                ncName.Replace( 
"'", 
"\\'" );
 
  261                if( nc->HasClearance() )
 
  263                    std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
 
  264                    netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s'" ),
 
  265                                                             nc->GetClearanceParent()->GetHumanReadableName() );
 
  266                    netclassRule->m_Implicit = 
true;
 
  268                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s')" ), ncName );
 
  270                    netclassClearanceRules.push_back( netclassRule );
 
  274                    netclassRule->AddConstraint( constraint );
 
  277                if( nc->HasTrackWidth() )
 
  279                    std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
 
  280                    netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s'" ),
 
  281                                                             nc->GetTrackWidthParent()->GetHumanReadableName() );
 
  282                    netclassRule->m_Implicit = 
true;
 
  284                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s')" ), ncName );
 
  286                    netclassClearanceRules.push_back( netclassRule );
 
  291                    netclassRule->AddConstraint( constraint );
 
  294                if( nc->HasDiffPairWidth() )
 
  296                    std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
 
  297                    netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s' (diff pair)" ),
 
  298                                                             nc->GetDiffPairWidthParent()->GetHumanReadableName() );
 
  299                    netclassRule->m_Implicit = 
true;
 
  301                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
 
  303                    netclassItemSpecificRules.push_back( netclassRule );
 
  307                    constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
 
  308                    netclassRule->AddConstraint( constraint );
 
  311                if( nc->HasDiffPairGap() )
 
  313                    std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
 
  314                    netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s' (diff pair)" ),
 
  315                                                             nc->GetDiffPairGapParent()->GetHumanReadableName() );
 
  316                    netclassRule->m_Implicit = 
true;
 
  318                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s')" ), ncName );
 
  320                    netclassItemSpecificRules.push_back( netclassRule );
 
  325                    netclassRule->AddConstraint( constraint );
 
  328                    if( nc->GetDiffPairGap() < nc->GetClearance() )
 
  330                        netclassRule = std::make_shared<DRC_RULE>();
 
  331                        netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s' (diff pair)" ),
 
  332                                                                 nc->GetDiffPairGapParent()->GetHumanReadableName() );
 
  333                        netclassRule->m_Implicit = 
true;
 
  335                        expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
 
  337                        netclassItemSpecificRules.push_back( netclassRule );
 
  340                        min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
 
  341                        netclassRule->AddConstraint( min_clearanceConstraint );
 
  345                if( nc->HasViaDiameter() )
 
  347                    std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
 
  348                    netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s'" ),
 
  349                                                             nc->GetViaDiameterParent()->GetHumanReadableName() );
 
  350                    netclassRule->m_Implicit = 
true;
 
  352                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
 
  354                    netclassItemSpecificRules.push_back( netclassRule );
 
  359                    netclassRule->AddConstraint( constraint );
 
  362                if( nc->HasViaDrill() )
 
  364                    std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
 
  365                    netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s'" ),
 
  366                                                             nc->GetViaDrillParent()->GetHumanReadableName() );
 
  367                    netclassRule->m_Implicit = 
true;
 
  369                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
 
  371                    netclassItemSpecificRules.push_back( netclassRule );
 
  376                    netclassRule->AddConstraint( constraint );
 
  379                if( nc->HasuViaDiameter() )
 
  381                    std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
 
  382                    netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s' (uvia)" ),
 
  383                                                             nc->GetuViaDiameterParent()->GetHumanReadableName() );
 
  384                    netclassRule->m_Implicit = 
true;
 
  386                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
 
  388                    netclassItemSpecificRules.push_back( netclassRule );
 
  392                    constraint.
Value().
SetMin( nc->GetuViaDiameter() );
 
  393                    netclassRule->AddConstraint( constraint );
 
  396                if( nc->HasuViaDrill() )
 
  398                    std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
 
  399                    netclassRule->m_Name = wxString::Format( 
_( 
"netclass '%s' (uvia)" ),
 
  400                                                             nc->GetuViaDrillParent()->GetHumanReadableName() );
 
  401                    netclassRule->m_Implicit = 
true;
 
  403                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
 
  405                    netclassItemSpecificRules.push_back( netclassRule );
 
  410                    netclassRule->AddConstraint( constraint );
 
  414    m_board->SynchronizeNetsAndNetClasses( 
false );
 
  418        makeNetclassRules( netclass, 
false );
 
  421        makeNetclassRules( netclass, 
false );
 
  428    std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
 
  429               []( 
const std::shared_ptr<DRC_RULE>& lhs, 
const std::shared_ptr<DRC_RULE>& rhs )
 
  431                   return lhs->m_Constraints[0].m_Value.Min()
 
  432                                < rhs->m_Constraints[0].m_Value.Min();
 
  435    for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
 
  438    for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
 
  442    auto addTuningSingleRule =
 
  444                 const wxString& aNetclassName )
 
  449                std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
 
  450                tuningRule->m_Name = wxString::Format( 
_( 
"tuning profile '%s'" ), aProfileName );
 
  451                tuningRule->m_Implicit = 
true;
 
  453                expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.Layer == '%s'" ),
 
  461                tuningRule->AddConstraint( constraint );
 
  466    auto addTuningDifferentialRules =
 
  473                std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
 
  474                tuningRule->m_Name = wxString::Format( 
_( 
"tuning profile '%s'" ), aProfileName );
 
  475                tuningRule->m_Implicit = 
true;
 
  477                expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
 
  478                                         aNetclass->GetName(),
 
  485                tuningRule->AddConstraint( constraint );
 
  489                std::shared_ptr<DRC_RULE> tuningRule2 = std::make_shared<DRC_RULE>();
 
  490                tuningRule2->m_Name = wxString::Format( 
_( 
"tuning profile '%s'" ), aProfileName );
 
  491                tuningRule2->m_Implicit = 
true;
 
  493                expr2 = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
 
  494                                          aNetclass->GetName(),
 
  501                tuningRule2->AddConstraint( constraint2 );
 
  508                    std::shared_ptr<DRC_RULE> diffPairClearanceRule = std::make_shared<DRC_RULE>();
 
  509                    diffPairClearanceRule->m_Name = wxString::Format( 
_( 
"tuning profile '%s'" ), aProfileName );
 
  510                    diffPairClearanceRule->m_Implicit = 
true;
 
  512                    expr = wxString::Format( wxT( 
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
 
  513                                             aNetclass->GetName(),
 
  519                    diffPairClearanceRule->AddConstraint( min_clearanceConstraint );
 
  521                    addRule( diffPairClearanceRule );
 
  527        std::shared_ptr<TUNING_PROFILES> tuningParams = 
project->GetProjectFile().TuningProfileParameters();
 
  529        auto addNetclassTuningProfileRules =
 
  530                [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules]( 
NETCLASS* aNetclass )
 
  532                    if( aNetclass->HasTuningProfile() )
 
  534                        const wxString        delayProfileName = aNetclass->GetTuningProfile();
 
  535                        const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName );
 
  546                                addTuningSingleRule( entry, delayProfileName, aNetclass->GetName() );
 
  548                                addTuningDifferentialRules( entry, delayProfileName, aNetclass );
 
  556            addNetclassTuningProfileRules( netclass.get() );
 
  559            addNetclassTuningProfileRules( netclass.get() );
 
  563    auto addKeepoutZoneRule =
 
  595                rule->m_ImplicitItemId = zone->
m_Uuid;
 
  597                rule->m_Condition = 
new DRC_RULE_CONDITION( wxString::Format( wxT( 
"A.intersectsArea('%s')" ),
 
  602                int disallowFlags = 0;
 
  621                rule->AddConstraint( disallowConstraint );
 
  627            addKeepoutZoneRule( zone, 
nullptr );
 
  632        for( 
ZONE* zone : footprint->Zones() )
 
  635                addKeepoutZoneRule( zone, footprint );
 
 
  643    if( 
m_board && aPath.FileExists() )
 
  645        std::vector<std::shared_ptr<DRC_RULE>> rules;
 
  647        if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT( 
"rt" ) ) )
 
  652            std::function<bool( wxString* )> 
resolver =
 
  653                    [&]( wxString* token ) -> 
bool 
  655                        return m_board->ResolveTextVar( token, 0 );
 
  658            while( 
char* line = lineReader.
ReadLine() )
 
  660                wxString str( line );
 
  661                str = 
m_board->ConvertCrossReferencesToKIIDs( str );
 
  664                rulesText << str << 
'\n';
 
  674        for( std::shared_ptr<DRC_RULE>& rule : rules )
 
 
  687    for( std::shared_ptr<DRC_RULE>& rule : 
m_rules )
 
  691        if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
 
  693            condition = rule->m_Condition;
 
  694            condition->
Compile( &error_semaphore );
 
  699                               TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
 
  708            engineConstraint->
layerTest = rule->m_LayerCondition;
 
 
  725            m_logReporter->Report( wxString::Format( wxT( 
"Create DRC provider: '%s'" ), provider->GetName() ) );
 
  727        provider->SetDRCEngine( 
this );
 
  762            wxFAIL_MSG( wxT( 
"Compiling implicit rules failed." ) );
 
  765        throw original_parse_error;
 
 
  802    if( !cacheGenerator.
Run() )         
 
  806    m_board->GetComponentClassManager().ForceComponentClassRecalculation();
 
  808    int timestamp = 
m_board->GetTimeStamp();
 
  813            m_logReporter->Report( wxString::Format( wxT( 
"Run DRC provider: '%s'" ), provider->GetName() ) );
 
  815        if( !provider->RunTests( aUnits ) )
 
  824    wxASSERT( timestamp == 
m_board->GetTimeStamp() );
 
 
  828#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } } 
  836    REPORT( wxString::Format( 
_( 
"Resolved zone connection type: %s." ),
 
  844            pad = 
static_cast<const PAD*
>( a );
 
  846            pad = 
static_cast<const PAD*
>( b );
 
  854            REPORT( wxString::Format( 
_( 
"Pad is not a through hole pad; connection will be: %s." ),
 
 
  882    const ZONE*      zone = 
nullptr;
 
  883    const FOOTPRINT* parentFootprint = 
nullptr;
 
  893            pad = 
static_cast<const PAD*
>( a );
 
  895            zone = 
static_cast<const ZONE*
>( a );
 
  898            pad = 
static_cast<const PAD*
>( b );
 
  900            zone = 
static_cast<const ZONE*
>( b );
 
  903            parentFootprint = 
pad->GetParentFootprint();
 
  907    constraint.
m_Type = aConstraintType;
 
  909    auto applyConstraint =
 
  912                if( c->constraint.m_Value.HasMin() )
 
  914                    if( c->parentRule && c->parentRule->m_Implicit )
 
  920                if( c->constraint.m_Value.HasOpt() )
 
  923                if( c->constraint.m_Value.HasMax() )
 
  926                switch( c->constraint.m_Type )
 
  961        && ( ( ( !ac ) ^ ( !bc ) )
 
  964            || ( ( footprints[0] == footprints[1] )  
 
  967        && !b_is_non_copper )
 
  974        for( 
int ii = 0; ii < 2; ++ii )
 
  977            if( !footprints[ii] || !alt_items[ii] )
 
  980            const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
 
  982            auto it = netcodes.find( alt_items[ii]->GetNetCode() );
 
  984            if( it != netcodes.end() )
 
  987                REPORT( wxString::Format( 
_( 
"Net tie on %s; clearance: 0." ),
 
  988                                          EscapeHTML( footprints[ii]->GetItemDescription( 
this, 
true ) ) ) )
 
  990                constraint.
SetName( 
_( 
"net tie" ) );
 
 1000        int                override_val = 0;
 
 1001        std::optional<int> overrideA;
 
 1002        std::optional<int> overrideB;
 
 1004        if( ac && !b_is_non_copper )
 
 1007        if( bc && !a_is_non_copper )
 
 1010        if( overrideA.has_value() || overrideB.has_value() )
 
 1014            if( overrideA.has_value() )
 
 1017                REPORT( wxString::Format( 
_( 
"Local override on %s; clearance: %s." ),
 
 1024            if( overrideB.has_value() )
 
 1027                REPORT( wxString::Format( 
_( 
"Local override on %s; clearance: %s." ),
 
 1031                if( overrideB > override_val )
 
 1039                    if( override_val < m_designSettings->m_MinClearance )
 
 1042                        msg = 
_( 
"board minimum" );
 
 1045                        REPORT( wxString::Format( 
_( 
"Board minimum clearance: %s." ),
 
 1051                    if( override_val < m_designSettings->m_HoleClearance )
 
 1054                        msg = 
_( 
"board minimum hole" );
 
 1057                        REPORT( wxString::Format( 
_( 
"Board minimum hole clearance: %s." ),
 
 1076            REPORT( wxString::Format( 
_( 
"Local override on %s; zone connection: %s." ),
 
 1087        if( 
pad && 
pad->GetLocalThermalGapOverride( 
nullptr ) > 0 )
 
 1090            int gap_override = 
pad->GetLocalThermalGapOverride( &msg );
 
 1093            REPORT( wxString::Format( 
_( 
"Local override on %s; thermal relief gap: %s." ),
 
 1104        if( 
pad && 
pad->GetLocalSpokeWidthOverride( 
nullptr ) > 0 )
 
 1107            int spoke_override = 
pad->GetLocalSpokeWidthOverride( &msg );
 
 1110            REPORT( wxString::Format( 
_( 
"Local override on %s; thermal spoke width: %s." ),
 
 1119                REPORT( wxString::Format( 
_( 
"%s min thickness: %s." ),
 
 1131        std::optional<int> 
override;
 
 1134            override = 
pad->GetLocalSolderMaskMargin();
 
 1136            override = 
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
 
 1143            REPORT( wxString::Format( 
_( 
"Local override on %s; solder mask expansion: %s." ),
 
 1153        std::optional<int> 
override;
 
 1156            override = 
pad->GetLocalSolderPasteMargin();
 
 1161            REPORT( wxString::Format( 
_( 
"Local override on %s; solder paste absolute clearance: %s." ),
 
 1171        std::optional<double> overrideRatio;
 
 1174            overrideRatio = 
pad->GetLocalSolderPasteMarginRatio();
 
 1179            REPORT( wxString::Format( 
_( 
"Local override on %s; solder paste relative clearance: %s." ),
 
 1188    auto testAssertion =
 
 1191                REPORT( wxString::Format( 
_( 
"Checking assertion '%s'." ),
 
 1192                                          EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
 
 1194                if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer,
 
 1197                    REPORT( 
_( 
"Assertion passed." ) )
 
 1205    auto processConstraint =
 
 1208                bool implicit = c->parentRule && c->parentRule->m_Implicit;
 
 1212                switch( c->constraint.m_Type )
 
 1221                    REPORT( wxString::Format( 
_( 
"Checking %s clearance: %s." ),
 
 1226                    REPORT( wxString::Format( 
_( 
"Checking %s creepage: %s." ),
 
 1231                    REPORT( wxString::Format( 
_( 
"Checking %s max uncoupled length: %s." ),
 
 1237                    REPORT( wxString::Format( 
_( 
"Checking %s max skew: %s." ),
 
 1243                    REPORT( wxString::Format( 
_( 
"Checking %s gap: %s." ),
 
 1249                    REPORT( wxString::Format( 
_( 
"Checking %s thermal spoke width: %s." ),
 
 1255                    REPORT( wxString::Format( 
_( 
"Checking %s solder mask expansion: %s." ),
 
 1261                    REPORT( wxString::Format( 
_( 
"Checking %s solder paste absolute clearance: %s." ),
 
 1267                    REPORT( wxString::Format( 
_( 
"Checking %s solder paste relative clearance: %s." ),
 
 1273                    REPORT( wxString::Format( 
_( 
"Checking %s min spoke count: %s." ),
 
 1276                                                                                        c->constraint.m_Value.Min() ) ) )
 
 1280                    REPORT( wxString::Format( 
_( 
"Checking %s zone connection: %s." ),
 
 1298                        wxString min = wxT( 
"<i>" ) + 
_( 
"undefined" ) + wxT( 
"</i>" );
 
 1299                        wxString opt = wxT( 
"<i>" ) + 
_( 
"undefined" ) + wxT( 
"</i>" );
 
 1300                        wxString max = wxT( 
"<i>" ) + 
_( 
"undefined" ) + wxT( 
"</i>" );
 
 1307                            switch( c->constraint.m_Type )
 
 1310                                if( c->constraint.m_Value.HasOpt() )
 
 1312                                    REPORT( wxString::Format( 
_( 
"Checking %s track width: opt %s." ),
 
 1316                                else if( c->constraint.m_Value.HasMin() )
 
 1318                                    REPORT( wxString::Format( 
_( 
"Checking %s track width: min %s." ),
 
 1326                                REPORT( wxString::Format( 
_( 
"Checking %s annular width: min %s." ),
 
 1332                                if( c->constraint.m_Value.HasOpt() )
 
 1334                                    REPORT( wxString::Format( 
_( 
"Checking %s via diameter: opt %s." ),
 
 1338                                else if( c->constraint.m_Value.HasMin() )
 
 1340                                    REPORT( wxString::Format( 
_( 
"Checking %s via diameter: min %s." ),
 
 1347                                if( c->constraint.m_Value.HasOpt() )
 
 1349                                    REPORT( wxString::Format( 
_( 
"Checking %s hole size: opt %s." ),
 
 1353                                else if( c->constraint.m_Value.HasMin() )
 
 1355                                    REPORT( wxString::Format( 
_( 
"Checking %s hole size: min %s." ),
 
 1365                                REPORT( wxString::Format( 
_( 
"Checking %s: min %s." ),
 
 1371                                if( c->constraint.m_Value.HasOpt() )
 
 1373                                    REPORT( wxString::Format( 
_( 
"Checking %s diff pair gap: opt %s." ),
 
 1377                                else if( c->constraint.m_Value.HasMin() )
 
 1379                                    REPORT( wxString::Format( 
_( 
"Checking %s clearance: min %s." ),
 
 1387                                REPORT( wxString::Format( 
_( 
"Checking %s hole to hole: min %s." ),
 
 1393                                REPORT( wxString::Format( 
_( 
"Checking %s." ),
 
 1399                            if( c->constraint.m_Value.HasMin() )
 
 1402                            if( c->constraint.m_Value.HasOpt() )
 
 1405                            if( c->constraint.m_Value.HasMax() )
 
 1408                            REPORT( wxString::Format( 
_( 
"Checking %s: min %s; opt %s; max %s." ),
 
 1419                    REPORT( wxString::Format( 
_( 
"Checking %s." ),
 
 1425                    if( a_is_non_copper || b_is_non_copper )
 
 1429                            REPORT( 
_( 
"Netclass clearances apply only between copper items." ) )
 
 1431                        else if( a_is_non_copper )
 
 1433                            REPORT( wxString::Format( 
_( 
"%s contains no copper.  Rule ignored." ),
 
 1436                        else if( b_is_non_copper )
 
 1438                            REPORT( wxString::Format( 
_( 
"%s contains no copper.  Rule ignored." ),
 
 1457                        if( 
via->IsMicroVia() )
 
 1459                        else if( 
via->IsBlindVia() )
 
 1461                        else if( 
via->IsBuriedVia() )
 
 1483                            if( 
static_cast<const ZONE*
>( a )->IsTeardropArea() )
 
 1491                        default:                 mask = 0;                       
break;
 
 1495                    if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
 
 1498                            REPORT( 
_( 
"Keepout constraint not met." ) )
 
 1500                            REPORT( 
_( 
"Disallow constraint not met." ) )
 
 1518                    if( !( c->layerTest & itemLayers ).any() )
 
 1522                            REPORT( 
_( 
"Keepout layer(s) not matched." ) )
 
 1524                        else if( c->parentRule )
 
 1526                            REPORT( wxString::Format( 
_( 
"Rule layer '%s' not matched; rule ignored." ),
 
 1527                                                      EscapeHTML( c->parentRule->m_LayerSource ) ) )
 
 1531                            REPORT( 
_( 
"Rule layer not matched; rule ignored." ) )
 
 1539                        || ( 
m_board->GetEnabledLayers() & c->layerTest ).count() == 0 )
 
 1543                        REPORT( 
_( 
"Constraint layer not matched." ) )
 
 1545                    else if( c->parentRule )
 
 1547                        REPORT( wxString::Format( 
_( 
"Rule layer '%s' not matched; rule ignored." ),
 
 1548                                                  EscapeHTML( c->parentRule->m_LayerSource ) ) )
 
 1552                        REPORT( 
_( 
"Rule layer not matched; rule ignored." ) )
 
 1559                    REPORT( wxString::Format( 
_( 
"%s is not a drilled hole; rule ignored." ),
 
 1562                else if( !c->condition || c->condition->GetExpression().IsEmpty() )
 
 1568                            REPORT( 
_( 
"Unconditional constraint applied." ) )
 
 1572                            REPORT( 
_( 
"Unconditional rule applied." ) )
 
 1577                            REPORT( 
_( 
"Unconditional rule applied; overrides previous constraints." ) )
 
 1581                    applyConstraint( c );
 
 1591                        REPORT( wxString::Format( 
_( 
"Checking rule condition '%s'." ),
 
 1592                                                  EscapeHTML( c->condition->GetExpression() ) ) )
 
 1595                    if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
 
 1601                                REPORT( 
_( 
"Constraint applied." ) )
 
 1605                                REPORT( 
_( 
"Rule applied." ) )
 
 1610                                REPORT( 
_( 
"Rule applied; overrides previous constraints." ) )
 
 1614                        applyConstraint( c );
 
 1618                        REPORT( implicit ? 
_( 
"Membership not satisfied; constraint ignored." )
 
 1619                                         : 
_( 
"Condition not satisfied; rule ignored." ) )
 
 1626        std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset = 
m_constraintMap[ aConstraintType ];
 
 1629            processConstraint( rule );
 
 1646        REPORT( wxString::Format( 
_( 
"Inheriting from parent: %s." ),
 
 1650            a = parentFootprint;
 
 1652            b = parentFootprint;
 
 1656            std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset = 
m_constraintMap[ aConstraintType ];
 
 1659                processConstraint( rule );
 
 1669            constraint.
SetName( 
_( 
"board setup" ) );
 
 1676            constraint.
SetName( 
_( 
"board setup" ) );
 
 1683            constraint.
SetName( 
_( 
"board setup" ) );
 
 1696        bool needBlankLine = 
true;
 
 1705                needBlankLine = 
false;
 
 1708            REPORT( wxString::Format( 
_( 
"Local clearance on %s: %s." ),
 
 1729                needBlankLine = 
false;
 
 1732            REPORT( wxString::Format( 
_( 
"Local clearance on %s: %s." ),
 
 1746        if( !a_is_non_copper && !b_is_non_copper )
 
 1751                needBlankLine = 
false;
 
 1754            REPORT( wxString::Format( 
_( 
"Board minimum clearance: %s." ),
 
 1760                constraint.
SetName( 
_( 
"board minimum" ) );
 
 1770        REPORT( wxString::Format( 
_( 
"Board minimum clearance: %s." ),
 
 1776            constraint.
SetName( 
_( 
"board minimum" ) );
 
 1784        if( 
pad && parentFootprint )
 
 1791                REPORT( wxString::Format( 
_( 
"%s zone connection: %s." ),
 
 1796                constraint.
SetName( 
_( 
"footprint" ) );
 
 1807            REPORT( wxString::Format( 
_( 
"%s pad connection: %s." ),
 
 1824            REPORT( wxString::Format( 
_( 
"%s thermal relief gap: %s." ),
 
 1841            REPORT( wxString::Format( 
_( 
"%s thermal spoke width: %s." ),
 
 
 1871    auto testAssertion =
 
 1874                REPORT( wxString::Format( 
_( 
"Checking rule assertion '%s'." ),
 
 1875                                          EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
 
 1877                if( c->constraint.m_Test->EvaluateFor( a, 
nullptr, c->constraint.m_Type,
 
 1880                    REPORT( 
_( 
"Assertion passed." ) )
 
 1885                    aFailureHandler( &c->constraint );
 
 1889    auto processConstraint =
 
 1893                REPORT( wxString::Format( 
_( 
"Checking %s." ), c->constraint.GetName() ) )
 
 1897                    REPORT( wxString::Format( 
_( 
"Rule layer '%s' not matched; rule ignored." ),
 
 1898                                              EscapeHTML( c->parentRule->m_LayerSource ) ) )
 
 1901                if( !c->condition || c->condition->GetExpression().IsEmpty() )
 
 1903                    REPORT( 
_( 
"Unconditional rule applied." ) )
 
 1908                    REPORT( wxString::Format( 
_( 
"Checking rule condition '%s'." ),
 
 1909                                              EscapeHTML( c->condition->GetExpression() ) ) )
 
 1911                    if( c->condition->EvaluateFor( a, 
nullptr, c->constraint.m_Type,
 
 1914                        REPORT( 
_( 
"Rule applied." ) )
 
 1919                        REPORT( 
_( 
"Condition not satisfied; rule ignored." ) )
 
 1928        for( 
int ii = 0; ii < (int) ruleset->size(); ++ii )
 
 1929            processConstraint( ruleset->at( ii ) );
 
 
 1939    assert( error_code >= 0 && error_code <= 
DRCE_LAST );
 
 
 1945                                  int aMarkerLayer, 
const std::function<
void( 
PCB_MARKER* )>& aPathGenerator )
 
 1947    static std::mutex globalLock;
 
 1953        std::lock_guard<std::mutex> guard( globalLock );
 
 1959        wxString msg = wxString::Format( wxT( 
"Test '%s': %s (code %d)" ),
 
 1960                                         aItem->GetViolatingTest()->GetName(),
 
 1961                                         aItem->GetErrorMessage(),
 
 1962                                         aItem->GetErrorCode() );
 
 1964        DRC_RULE* rule = aItem->GetViolatingRule();
 
 1967            msg += wxString::Format( wxT( 
", violating rule: '%s'" ), rule->
m_Name );
 
 1971        wxString violatingItemsStr = wxT( 
"Violating items: " );
 
 1973        m_logReporter->Report( wxString::Format( wxT( 
"  |- violating position (%d, %d)" ),
 
 
 2020    wxSafeYield( 
nullptr, 
true ); 
 
 
 2050            int current = c->constraint.GetValue().Min();
 
 2052            if( current > worst )
 
 2055                aConstraint = c->constraint;
 
 
 2066    std::set<int> distinctMinimums;
 
 2071            distinctMinimums.emplace( c->constraint.GetValue().Min() );
 
 2074    return distinctMinimums;
 
 
 2080                               wxString& aBaseDpName )
 
 2085    for( 
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
 
 2089        if( ( ch >= 
'0' && ch <= 
'9' ) || ch == 
'_' )
 
 2093        else if( ch == 
'+' )
 
 2095            aComplementNet = wxT( 
"-" );
 
 2098        else if( ch == 
'-' )
 
 2100            aComplementNet = wxT( 
"+" );
 
 2103        else if( ch == 
'N' )
 
 2105            aComplementNet = wxT( 
"P" );
 
 2108        else if ( ch == 
'P' )
 
 2110            aComplementNet = wxT( 
"N" );
 
 2119    if( rv != 0 && count >= 1 )
 
 2121        aBaseDpName = aNetName.Left( aNetName.Length() - count );
 
 2122        aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
 
 
 2132    wxString 
dummy, coupledNetName;
 
 
 2168    if( parentFootprint && parentFootprint->
IsNetTie() )
 
 2175            if( padToNetTieGroupMap[ 
pad->GetNumber() ] >= 0 && aTrackNetCode == 
pad->GetNetCode() )
 
 2177                if( 
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos, 
epsilon ) )
 
 
 2191        if( 
name == prov->GetName() )
 
 
 2203    std::vector<BOARD_ITEM*> matches;
 
 2215    for( 
auto& [kiid, item] : 
m_board->GetItemByIdCache() )
 
 2217        LSET itemLayers = item->GetLayerSet();
 
 2221            if( condition.
EvaluateFor( item, 
nullptr, 
static_cast<int>( aConstraint ), layer,
 
 2224                matches.push_back( item );
 
 
constexpr EDA_IU_SCALE pcbIUScale
 
constexpr EDA_IU_SCALE unityScale
 
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
 
#define MAXIMUM_CLEARANCE
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
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 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
 
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()
 
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
 
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
 
void addRule(std::shared_ptr< DRC_RULE > &rule)
 
PROGRESS_REPORTER * m_progressReporter
 
void loadRules(const wxFileName &aPath)
Load and parse a rule set from an sexpr text file.
 
std::vector< DRC_TEST_PROVIDER * > m_testProviders
 
std::set< int > QueryDistinctConstraints(DRC_CONSTRAINT_T aConstraintId)
 
DS_PROXY_VIEW_ITEM * m_drawingSheet
 
NETLIST * m_schematicNetlist
 
bool KeepRefreshing(bool aWait=false)
 
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)
 
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::shared_ptr< DRC_RULE > createImplicitRule(const wxString &name)
 
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)
 
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 * > 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.
 
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.
 
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
 
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)
 
@ 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)
 
PCB_LAYER_ID
A quick note on layer IDs:
 
KICOMMON_API wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
 
@ 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.
 
std::shared_ptr< DRC_RULE > parentRule
 
DRC_RULE_CONDITION * condition
 
DRC_CONSTRAINT constraint
 
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.
 
bool m_GenerateNetClassDRCRules
 
std::vector< DELAY_PROFILE_TRACK_PROPAGATION_ENTRY > m_TrackPropagationEntries
 
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
 
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
 
@ 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_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