Better inspection reporting for netclasses, custom rules and DRC.

This commit is contained in:
Jeff Young 2022-04-16 00:57:08 +01:00
parent 250a246761
commit 9ff1ae5bdc
3 changed files with 244 additions and 85 deletions

View File

@ -550,7 +550,12 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
} }
else if( rcItem->GetErrorCode() == DRCE_TEXT_HEIGHT else if( rcItem->GetErrorCode() == DRCE_TEXT_HEIGHT
|| rcItem->GetErrorCode() == DRCE_TEXT_THICKNESS || rcItem->GetErrorCode() == DRCE_TEXT_THICKNESS
|| rcItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG ) || rcItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
|| rcItem->GetErrorCode() == DRCE_TRACK_WIDTH
|| rcItem->GetErrorCode() == DRCE_VIA_DIAMETER
|| rcItem->GetErrorCode() == DRCE_ANNULAR_WIDTH
|| rcItem->GetErrorCode() == DRCE_DRILL_OUT_OF_RANGE
|| rcItem->GetErrorCode() == DRCE_MICROVIA_DRILL_OUT_OF_RANGE )
{ {
menu.Append( 3, _( "Run constraints resolution tool..." ) ); menu.Append( 3, _( "Run constraints resolution tool..." ) );
} }

View File

@ -925,30 +925,49 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
case EDGE_CLEARANCE_CONSTRAINT: case EDGE_CLEARANCE_CONSTRAINT:
case MECHANICAL_CLEARANCE_CONSTRAINT: case MECHANICAL_CLEARANCE_CONSTRAINT:
case MECHANICAL_HOLE_CLEARANCE_CONSTRAINT: case MECHANICAL_HOLE_CLEARANCE_CONSTRAINT:
{
int val = c->constraint.m_Value.Min();
REPORT( wxString::Format( _( "Checking %s clearance: %s." ), REPORT( wxString::Format( _( "Checking %s clearance: %s." ),
EscapeHTML( c->constraint.GetName() ), EscapeHTML( c->constraint.GetName() ),
REPORT_VALUE( val ) ) ) REPORT_VALUE( c->constraint.m_Value.Min() ) ) )
break; break;
}
case DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT: case DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT:
{
int val = c->constraint.m_Value.Max();
REPORT( wxString::Format( _( "Checking %s max uncoupled length: %s." ), REPORT( wxString::Format( _( "Checking %s max uncoupled length: %s." ),
EscapeHTML( c->constraint.GetName() ), EscapeHTML( c->constraint.GetName() ),
REPORT_VALUE( val ) ) ) REPORT_VALUE( c->constraint.m_Value.Max() ) ) )
break; break;
}
case SKEW_CONSTRAINT:
REPORT( wxString::Format( _( "Checking %s max skew: %s." ),
EscapeHTML( c->constraint.GetName() ),
REPORT_VALUE( c->constraint.m_Value.Max() ) ) )
break;
case THERMAL_RELIEF_GAP_CONSTRAINT:
REPORT( wxString::Format( _( "Checking %s gap: %s." ),
EscapeHTML( c->constraint.GetName() ),
REPORT_VALUE( c->constraint.m_Value.Min() ) ) )
break;
case THERMAL_SPOKE_WIDTH_CONSTRAINT:
REPORT( wxString::Format( _( "Checking %s thermal spoke width: %s." ),
EscapeHTML( c->constraint.GetName() ),
REPORT_VALUE( c->constraint.m_Value.Opt() ) ) )
break;
case ZONE_CONNECTION_CONSTRAINT:
REPORT( wxString::Format( _( "Checking %s zone connection: %s." ),
EscapeHTML( c->constraint.GetName() ),
EscapeHTML( PrintZoneConnection( c->constraint.m_ZoneConnection ) ) ) )
break;
case TRACK_WIDTH_CONSTRAINT: case TRACK_WIDTH_CONSTRAINT:
case ANNULAR_WIDTH_CONSTRAINT: case ANNULAR_WIDTH_CONSTRAINT:
case VIA_DIAMETER_CONSTRAINT: case VIA_DIAMETER_CONSTRAINT:
case HOLE_SIZE_CONSTRAINT:
case TEXT_HEIGHT_CONSTRAINT: case TEXT_HEIGHT_CONSTRAINT:
case TEXT_THICKNESS_CONSTRAINT: case TEXT_THICKNESS_CONSTRAINT:
case DIFF_PAIR_GAP_CONSTRAINT: case DIFF_PAIR_GAP_CONSTRAINT:
case LENGTH_CONSTRAINT:
{ {
if( aReporter ) if( aReporter )
{ {
@ -959,21 +978,97 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
if( implicit ) if( implicit )
{ {
min = StringFromValue( UNITS, c->constraint.m_Value.Min(), true );
opt = StringFromValue( UNITS, c->constraint.m_Value.Opt(), true ); opt = StringFromValue( UNITS, c->constraint.m_Value.Opt(), true );
switch( c->constraint.m_Type ) switch( c->constraint.m_Type )
{ {
case TRACK_WIDTH_CONSTRAINT: msg = _( "track width" ); break; case TRACK_WIDTH_CONSTRAINT:
case ANNULAR_WIDTH_CONSTRAINT: msg = _( "annular width" ); break; if( c->constraint.m_Value.HasOpt() )
case VIA_DIAMETER_CONSTRAINT: msg = _( "via diameter" ); break; {
case DIFF_PAIR_GAP_CONSTRAINT: msg = _( "diff pair gap" ); break; REPORT( wxString::Format( _( "Checking %s track width: opt %s." ),
default: msg = _( "constraint" ); break; EscapeHTML( c->constraint.GetName() ),
} opt ) )
}
else if( c->constraint.m_Value.HasMin() )
{
REPORT( wxString::Format( _( "Checking board setup constraints "
"track width: min %s." ),
min ) )
}
REPORT( wxString::Format( _( "Checking %s %s: opt %s." ), break;
EscapeHTML( c->constraint.GetName() ),
EscapeHTML( msg ), case ANNULAR_WIDTH_CONSTRAINT:
opt ) ) REPORT( wxString::Format( _( "Checking %s annular width: min %s." ),
EscapeHTML( c->constraint.GetName() ),
opt ) )
break;
case VIA_DIAMETER_CONSTRAINT:
if( c->constraint.m_Value.HasOpt() )
{
REPORT( wxString::Format( _( "Checking %s via diameter: opt %s." ),
EscapeHTML( c->constraint.GetName() ),
opt ) )
}
else if( c->constraint.m_Value.HasMin() )
{
REPORT( wxString::Format( _( "Checking board setup constraints "
"via diameter: min %s." ),
min ) )
}
break;
case HOLE_SIZE_CONSTRAINT:
if( c->constraint.m_Value.HasOpt() )
{
REPORT( wxString::Format( _( "Checking %s hole size: opt %s." ),
EscapeHTML( c->constraint.GetName() ),
opt ) )
}
else if( c->constraint.m_Value.HasMin() )
{
REPORT( wxString::Format( _( "Checking board setup constraints "
"hole size: min %s." ),
min ) )
}
break;
case TEXT_HEIGHT_CONSTRAINT:
REPORT( wxString::Format( _( "Checking %s: min %s." ),
EscapeHTML( c->constraint.GetName() ),
min ) )
break;
case TEXT_THICKNESS_CONSTRAINT:
REPORT( wxString::Format( _( "Checking %s: min %s." ),
EscapeHTML( c->constraint.GetName() ),
min ) )
break;
case DIFF_PAIR_GAP_CONSTRAINT:
if( c->constraint.m_Value.HasOpt() )
{
REPORT( wxString::Format( _( "Checking %s diff pair gap: "
"opt %s." ),
EscapeHTML( c->constraint.GetName() ),
opt ) )
}
else if( c->constraint.m_Value.HasMin() )
{
REPORT( wxString::Format( _( "Checking board setup constraints "
"clearance: min %s." ),
min ) )
}
break;
default:
REPORT( wxString::Format( _( "Checking %s." ),
EscapeHTML( c->constraint.GetName() ) ) )
}
} }
else else
{ {

View File

@ -282,9 +282,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
constraint = drcEngine.EvalRules( TEXT_HEIGHT_CONSTRAINT, a, b, layer, r ); constraint = drcEngine.EvalRules( TEXT_HEIGHT_CONSTRAINT, a, b, layer, r );
r->Report( "" ); r->Report( "" );
r->Report( wxString::Format( _( "Resolved text height constraints: min %s; opt %s; max %s." ), r->Report( wxString::Format( _( "Resolved height constraints: min %s; max %s." ),
reportMin( r->GetUnits(), constraint ), reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) ); reportMax( r->GetUnits(), constraint ) ) );
break; break;
@ -298,9 +297,69 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
constraint = drcEngine.EvalRules( TEXT_THICKNESS_CONSTRAINT, a, b, layer, r ); constraint = drcEngine.EvalRules( TEXT_THICKNESS_CONSTRAINT, a, b, layer, r );
r->Report( "" ); r->Report( "" );
r->Report( wxString::Format( _( "Resolved text thickness constraints: min %s; opt %s; max %s." ), r->Report( wxString::Format( _( "Resolved thickness constraints: min %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
break;
case DRCE_TRACK_WIDTH:
r = m_inspectClearanceDialog->AddPage( _( "Track Width" ) );
reportHeader( _( "Track width resolution for:" ), a, r );
if( compileError )
reportCompileError( r );
constraint = drcEngine.EvalRules( TRACK_WIDTH_CONSTRAINT, a, b, layer, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved width constraints: min %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
break;
case DRCE_VIA_DIAMETER:
r = m_inspectClearanceDialog->AddPage( _( "Via Diameter" ) );
reportHeader( _( "Via diameter resolution for:" ), a, r );
if( compileError )
reportCompileError( r );
constraint = drcEngine.EvalRules( VIA_DIAMETER_CONSTRAINT, a, b, layer, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
break;
case DRCE_ANNULAR_WIDTH:
r = m_inspectClearanceDialog->AddPage( _( "Via Annulus" ) );
reportHeader( _( "Via annular width resolution for:" ), a, r );
if( compileError )
reportCompileError( r );
constraint = drcEngine.EvalRules( ANNULAR_WIDTH_CONSTRAINT, a, b, layer, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved annular width constraints: min %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
break;
case DRCE_DRILL_OUT_OF_RANGE:
case DRCE_MICROVIA_DRILL_OUT_OF_RANGE:
r = m_inspectClearanceDialog->AddPage( _( "Hole Size" ) );
reportHeader( _( "Hose diameter resolution for:" ), a, r );
if( compileError )
reportCompileError( r );
constraint = drcEngine.EvalRules( HOLE_SIZE_CONSTRAINT, a, b, layer, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; max %s." ),
reportMin( r->GetUnits(), constraint ), reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) ); reportMax( r->GetUnits(), constraint ) ) );
break; break;
@ -934,9 +993,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
r->Report( "" ); r->Report( "" );
r->Report( wxString::Format( _( "Width constraints: min %s; opt %s; max %s." ), r->Report( wxString::Format( _( "Width constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ), reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ), reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) ); reportMax( r->GetUnits(), constraint ) ) );
r->Flush(); r->Flush();
} }
@ -954,9 +1013,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
r->Report( "" ); r->Report( "" );
r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ), r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ), reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ), reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) ); reportMax( r->GetUnits(), constraint ) ) );
r->Flush(); r->Flush();
@ -971,9 +1030,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
r->Report( "" ); r->Report( "" );
r->Report( wxString::Format( _( "Annular width constraints: min %s; opt %s; max %s." ), r->Report( wxString::Format( _( "Annular width constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ), reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ), reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) ); reportMax( r->GetUnits(), constraint ) ) );
r->Flush(); r->Flush();
} }
@ -990,13 +1049,11 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
if( compileError ) if( compileError )
reportCompileError( r ); reportCompileError( r );
wxString min = _( "undefined" );
if( constraint.m_Value.HasMin() )
min = StringFromValue( r->GetUnits(), constraint.m_Value.Min(), true );
r->Report( "" ); r->Report( "" );
r->Report( wxString::Format( _( "Hole constraint: min %s." ), min ) ); r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
r->Flush(); r->Flush();
} }
@ -1338,6 +1395,7 @@ int BOARD_INSPECTION_TOOL::ClearHighlight( const TOOL_EVENT& aEvent )
return 0; return 0;
} }
#if 0 #if 0
int BOARD_INSPECTION_TOOL::HighlightNetTool( const TOOL_EVENT& aEvent ) int BOARD_INSPECTION_TOOL::HighlightNetTool( const TOOL_EVENT& aEvent )
{ {
@ -1372,6 +1430,7 @@ int BOARD_INSPECTION_TOOL::HighlightNetTool( const TOOL_EVENT& aEvent )
} }
#endif #endif
int BOARD_INSPECTION_TOOL::LocalRatsnestTool( const TOOL_EVENT& aEvent ) int BOARD_INSPECTION_TOOL::LocalRatsnestTool( const TOOL_EVENT& aEvent )
{ {
std::string tool = aEvent.GetCommandStr().get(); std::string tool = aEvent.GetCommandStr().get();
@ -1382,68 +1441,68 @@ int BOARD_INSPECTION_TOOL::LocalRatsnestTool( const TOOL_EVENT& aEvent )
Activate(); Activate();
picker->SetClickHandler( picker->SetClickHandler(
[this, board]( const VECTOR2D& pt ) -> bool [this, board]( const VECTOR2D& pt ) -> bool
{
PCB_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true, EDIT_TOOL::PadFilter );
PCB_SELECTION& selection = selectionTool->GetSelection();
if( selection.Empty() )
{ {
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true, PCB_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
EDIT_TOOL::FootprintFilter );
selection = selectionTool->GetSelection();
}
if( selection.Empty() ) m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
{ m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true, EDIT_TOOL::PadFilter );
// Clear the previous local ratsnest if we click off all items PCB_SELECTION& selection = selectionTool->GetSelection();
for( FOOTPRINT* fp : board->Footprints() )
if( selection.Empty() )
{ {
for( PAD* pad : fp->Pads() ) m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true,
pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest ); EDIT_TOOL::FootprintFilter );
selection = selectionTool->GetSelection();
} }
}
else
{
for( EDA_ITEM* item : selection )
{
if( PAD* pad = dyn_cast<PAD*>( item) )
{
pad->SetLocalRatsnestVisible( !pad->GetLocalRatsnestVisible() );
}
else if( FOOTPRINT* fp = dyn_cast<FOOTPRINT*>( item) )
{
if( !fp->Pads().empty() )
{
bool enable = !fp->Pads()[0]->GetLocalRatsnestVisible();
for( PAD* childPad : fp->Pads() ) if( selection.Empty() )
childPad->SetLocalRatsnestVisible( enable ); {
// Clear the previous local ratsnest if we click off all items
for( FOOTPRINT* fp : board->Footprints() )
{
for( PAD* pad : fp->Pads() )
pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
}
}
else
{
for( EDA_ITEM* item : selection )
{
if( PAD* pad = dyn_cast<PAD*>( item) )
{
pad->SetLocalRatsnestVisible( !pad->GetLocalRatsnestVisible() );
}
else if( FOOTPRINT* fp = dyn_cast<FOOTPRINT*>( item) )
{
if( !fp->Pads().empty() )
{
bool enable = !fp->Pads()[0]->GetLocalRatsnestVisible();
for( PAD* childPad : fp->Pads() )
childPad->SetLocalRatsnestVisible( enable );
}
} }
} }
} }
}
m_toolMgr->GetView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY ); m_toolMgr->GetView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
return true; return true;
} ); } );
picker->SetFinalizeHandler( picker->SetFinalizeHandler(
[this, board]( int aCondition ) [this, board]( int aCondition )
{
if( aCondition != PCB_PICKER_TOOL::END_ACTIVATE )
{ {
for( FOOTPRINT* fp : board->Footprints() ) if( aCondition != PCB_PICKER_TOOL::END_ACTIVATE )
{ {
for( PAD* pad : fp->Pads() ) for( FOOTPRINT* fp : board->Footprints() )
pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest ); {
for( PAD* pad : fp->Pads() )
pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
}
} }
} } );
} );
m_toolMgr->RunAction( ACTIONS::pickerTool, true, &tool ); m_toolMgr->RunAction( ACTIONS::pickerTool, true, &tool );