ADDED Clearance Inspector.
This commit is contained in:
parent
e31705d4b3
commit
fc1665ff28
|
@ -81,7 +81,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetEffectiveNetclass() const
|
|||
* LEVEL 3: Accumulated local settings, netclass settings, & board design settings
|
||||
*/
|
||||
int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem,
|
||||
wxString* aSource ) const
|
||||
wxString* aSource, REPORTER* aReporter ) const
|
||||
{
|
||||
BOARD* board = GetBoard();
|
||||
int clearance = 0;
|
||||
|
@ -111,7 +111,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem,
|
|||
|
||||
// LEVEL 2: Rules
|
||||
//
|
||||
if( GetRuleClearance( aItem, aLayer, &clearance, aSource ) )
|
||||
if( GetRuleClearance( aItem, aLayer, &clearance, aSource, aReporter ) )
|
||||
return clearance;
|
||||
|
||||
// LEVEL 3: Accumulated local settings, netclass settings, & board design settings
|
||||
|
@ -153,10 +153,11 @@ int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem,
|
|||
|
||||
|
||||
bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer,
|
||||
int* aClearance, wxString* aSource ) const
|
||||
int* aClearance, wxString* aSource,
|
||||
REPORTER* aReporter ) const
|
||||
{
|
||||
const DRC_CONSTRAINT* constraint = GetConstraint( this, aItem, DRC_RULE_ID_CLEARANCE, aLayer,
|
||||
aSource );
|
||||
aSource, aReporter );
|
||||
|
||||
if( constraint )
|
||||
{
|
||||
|
@ -164,6 +165,13 @@ bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLa
|
|||
*aSource = wxString::Format( _( "'%s' rule" ), *aSource );
|
||||
|
||||
*aClearance = constraint->m_Value.Min();
|
||||
|
||||
if( aReporter )
|
||||
{
|
||||
wxString clearance = StringFromValue( aReporter->GetUnits(), *aClearance, true );
|
||||
aReporter->Report( wxString::Format( _( "Clearance: %s." ), clearance ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <class_board_item.h>
|
||||
#include <netinfo.h>
|
||||
#include <reporter.h>
|
||||
#include <kicad_string.h>
|
||||
|
||||
class NETCLASS;
|
||||
|
@ -167,7 +168,7 @@ public:
|
|||
* @return int - the clearance in internal units.
|
||||
*/
|
||||
virtual int GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem = nullptr,
|
||||
wxString* aSource = nullptr ) const;
|
||||
wxString* aSource = nullptr, REPORTER* aReporter = nullptr ) const;
|
||||
|
||||
/**
|
||||
* Function GetRuleClearance
|
||||
|
@ -178,7 +179,7 @@ public:
|
|||
* @return true if a rule was fired
|
||||
*/
|
||||
virtual bool GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int* aClearance,
|
||||
wxString* aSource ) const;
|
||||
wxString* aSource, REPORTER* aReporter = nullptr ) const;
|
||||
|
||||
/**
|
||||
* Function GetLocalClearanceOverrides
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
|
||||
|
||||
const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
|
||||
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName )
|
||||
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName,
|
||||
REPORTER* aReporter )
|
||||
{
|
||||
BOARD* board = aItem->GetBoard();
|
||||
|
||||
|
@ -40,33 +41,76 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM*
|
|||
|
||||
for( DRC_RULE* rule : board->GetDesignSettings().m_DRCRules )
|
||||
{
|
||||
if( !rule->m_LayerCondition.test( aLayer ) )
|
||||
continue;
|
||||
|
||||
for( const DRC_CONSTRAINT& constraint : rule->m_Constraints )
|
||||
if( aReporter )
|
||||
{
|
||||
if( constraint.m_Type != aConstraint )
|
||||
continue;
|
||||
aReporter->Report( wxString::Format( _( "Checking rule \"%s\"." ),
|
||||
rule->m_Name ) );
|
||||
}
|
||||
|
||||
if( !rule->m_LayerCondition.test( aLayer ) )
|
||||
{
|
||||
if( aReporter )
|
||||
{
|
||||
aReporter->Report( wxString::Format( _( "Rule layer \"%s\" not matched." ),
|
||||
rule->m_LayerSource ) );
|
||||
aReporter->Report( "Rule not applied." );
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const DRC_CONSTRAINT* constraint = nullptr;
|
||||
|
||||
for( const DRC_CONSTRAINT& candidate : rule->m_Constraints )
|
||||
{
|
||||
if( candidate.m_Type == aConstraint )
|
||||
{
|
||||
constraint = &candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( aReporter && !constraint )
|
||||
{
|
||||
aReporter->Report( _( "Rule contains no applicable constraints." ) );
|
||||
aReporter->Report( _( "Rule not applied." ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aReporter )
|
||||
{
|
||||
aReporter->Report( wxString::Format( _( "Checking rule condition \"%s\"." ),
|
||||
rule->m_Condition.m_Expression ) );
|
||||
}
|
||||
|
||||
if( rule->m_Condition.EvaluateFor( aItem, bItem, aLayer ) )
|
||||
{
|
||||
if( aReporter )
|
||||
aReporter->Report( "Rule applied." );
|
||||
|
||||
if( aRuleName )
|
||||
*aRuleName = rule->m_Name;
|
||||
|
||||
return &constraint;
|
||||
return constraint;
|
||||
}
|
||||
|
||||
if( bItem && rule->m_Condition.EvaluateFor( bItem, aItem, aLayer ) )
|
||||
{
|
||||
if( aReporter )
|
||||
aReporter->Report( "Rule applied." );
|
||||
|
||||
if( aRuleName )
|
||||
*aRuleName = rule->m_Name;
|
||||
|
||||
return &constraint;
|
||||
return constraint;
|
||||
}
|
||||
|
||||
if( aReporter )
|
||||
aReporter->Report( "Condition not satisfied; rule not applied." );
|
||||
}
|
||||
|
||||
if( aReporter )
|
||||
aReporter->Report( "" );
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -97,21 +141,37 @@ DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
|
|||
|
||||
|
||||
bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
|
||||
PCB_LAYER_ID aLayer )
|
||||
PCB_LAYER_ID aLayer, REPORTER* aReporter )
|
||||
{
|
||||
// An unconditional rule is always true
|
||||
if( m_Expression.IsEmpty() )
|
||||
return true;
|
||||
{
|
||||
if( aReporter )
|
||||
aReporter->Report( _( "Unconditional constraint." ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( aReporter )
|
||||
aReporter->Report( _( "Evaluating expression \"" + m_Expression + "\"." ) );
|
||||
|
||||
// A rule which failed to compile is always false
|
||||
if( !m_ucode )
|
||||
{
|
||||
if( aReporter )
|
||||
aReporter->Report( _( "ERROR in expression." ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
|
||||
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
|
||||
|
||||
PCB_EXPR_CONTEXT ctx( aLayer );
|
||||
ctx.SetItems( a, b );
|
||||
ctx.SetErrorCallback( [&]( const wxString& aMessage, int aOffset )
|
||||
{
|
||||
if( aReporter )
|
||||
aReporter->Report( _( "ERROR: " ) + aMessage );
|
||||
} );
|
||||
|
||||
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
|
||||
}
|
||||
|
|
|
@ -88,8 +88,7 @@ class DRC_CONSTRAINT
|
|||
public:
|
||||
DRC_CONSTRAINT() :
|
||||
m_Type( DRC_RULE_ID_UNKNOWN ),
|
||||
m_DisallowFlags( 0 ),
|
||||
m_LayerCondition( LSET::AllLayersMask() )
|
||||
m_DisallowFlags( 0 )
|
||||
{}
|
||||
|
||||
const MINOPTMAX<int>& GetValue() const { return m_Value; }
|
||||
|
@ -99,7 +98,6 @@ public:
|
|||
DRC_CONSTRAINT_TYPE_T m_Type;
|
||||
MINOPTMAX<int> m_Value;
|
||||
int m_DisallowFlags;
|
||||
LSET m_LayerCondition;
|
||||
};
|
||||
|
||||
|
||||
|
@ -109,7 +107,8 @@ public:
|
|||
DRC_RULE_CONDITION();
|
||||
~DRC_RULE_CONDITION();
|
||||
|
||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer );
|
||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer,
|
||||
REPORTER* aReporter = nullptr );
|
||||
bool Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset );
|
||||
|
||||
public:
|
||||
|
@ -128,6 +127,7 @@ public:
|
|||
|
||||
public:
|
||||
wxString m_Name;
|
||||
wxString m_LayerSource;
|
||||
LSET m_LayerCondition;
|
||||
wxString m_TestProviderName;
|
||||
DRC_RULE_CONDITION m_Condition;
|
||||
|
@ -136,7 +136,9 @@ public:
|
|||
|
||||
|
||||
const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
|
||||
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName );
|
||||
int aConstraint, PCB_LAYER_ID aLayer,
|
||||
wxString* aRuleName = nullptr,
|
||||
REPORTER* aReporter = nullptr );
|
||||
|
||||
|
||||
#endif // DRC_RULE_H
|
||||
|
|
|
@ -215,6 +215,7 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
|||
break;
|
||||
|
||||
case T_layer:
|
||||
rule->m_LayerSource = FromUTF8();
|
||||
rule->m_LayerCondition = parseLayer();
|
||||
break;
|
||||
|
||||
|
@ -453,7 +454,7 @@ LSET DRC_RULES_PARSER::parseLayer()
|
|||
}
|
||||
|
||||
if( !retVal.any() )
|
||||
reportError( wxString::Format( _( "Unrecognized layer '%s' " ), layerName ) );
|
||||
reportError( wxString::Format( _( "Unrecognized layer '%s'." ), layerName ) );
|
||||
}
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
|
|
|
@ -372,6 +372,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
|
|||
|
||||
inspectMenu->AppendSeparator();
|
||||
inspectMenu->Add( PCB_ACTIONS::runDRC );
|
||||
inspectMenu->Add( PCB_ACTIONS::inspectClearance );
|
||||
|
||||
|
||||
//-- Tools menu ----------------------------------------------------------
|
||||
|
|
|
@ -204,23 +204,21 @@ bool EDIT_TOOL::Init()
|
|||
auto specialToolsSubMenu = std::make_shared<SPECIAL_TOOLS_CONTEXT_MENU>( this );
|
||||
menu.AddSeparator();
|
||||
m_selectionTool->GetToolMenu().AddSubMenu( specialToolsSubMenu );
|
||||
menu.AddMenu( specialToolsSubMenu.get(), SELECTION_CONDITIONS::NotEmpty );
|
||||
menu.AddMenu( specialToolsSubMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
|
||||
|
||||
menu.AddSeparator();
|
||||
menu.AddItem( ACTIONS::cut, SELECTION_CONDITIONS::NotEmpty );
|
||||
menu.AddItem( ACTIONS::copy, SELECTION_CONDITIONS::NotEmpty );
|
||||
menu.AddSeparator( 150 );
|
||||
menu.AddItem( ACTIONS::cut, SELECTION_CONDITIONS::NotEmpty, 150 );
|
||||
menu.AddItem( ACTIONS::copy, SELECTION_CONDITIONS::NotEmpty, 150 );
|
||||
// Selection tool handles the context menu for some other tools, such as the Picker.
|
||||
// Don't add things like Paste when another tool is active.
|
||||
menu.AddItem( ACTIONS::paste, noActiveToolCondition );
|
||||
|
||||
menu.AppendSeparator();
|
||||
menu.AddItem( ACTIONS::selectAll, noItemsCondition );
|
||||
menu.AddItem( ACTIONS::paste, noActiveToolCondition, 150 );
|
||||
menu.AddItem( ACTIONS::selectAll, noItemsCondition, 150 );
|
||||
|
||||
// Footprint actions
|
||||
menu.AddSeparator();
|
||||
menu.AddItem( PCB_ACTIONS::editFpInFpEditor, singleModuleCondition );
|
||||
menu.AddItem( PCB_ACTIONS::updateFootprint, singleModuleCondition );
|
||||
menu.AddItem( PCB_ACTIONS::changeFootprint, singleModuleCondition );
|
||||
menu.AddSeparator( 150 );
|
||||
menu.AddItem( PCB_ACTIONS::editFpInFpEditor, singleModuleCondition, 150 );
|
||||
menu.AddItem( PCB_ACTIONS::updateFootprint, singleModuleCondition, 150 );
|
||||
menu.AddItem( PCB_ACTIONS::changeFootprint, singleModuleCondition, 150 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1025,6 +1025,12 @@ TOOL_ACTION PCB_ACTIONS::boardStatistics( "pcbnew.InspectionTool.ShowStatisticsD
|
|||
_( "Show Board Statistics" ), _( "Shows board statistics" ),
|
||||
pcbnew_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::inspectClearance( "pcbnew.InspectionTool.InspectClearance",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Clearance Resolution..." ),
|
||||
_( "Show clearance resolution for the active layer between two selected objects" ),
|
||||
mw_add_gap_xpm );
|
||||
|
||||
//Geographic re-annotation tool
|
||||
TOOL_ACTION PCB_ACTIONS::boardReannotate( "pcbnew.ReannotateTool.ShowReannotateDialog",
|
||||
AS_GLOBAL, 0, "",
|
||||
|
|
|
@ -417,6 +417,7 @@ public:
|
|||
static TOOL_ACTION boardStatistics;
|
||||
static TOOL_ACTION boardReannotate;
|
||||
static TOOL_ACTION repairBoard;
|
||||
static TOOL_ACTION inspectClearance;
|
||||
|
||||
// Appearance controls
|
||||
static TOOL_ACTION clearHighlight;
|
||||
|
|
|
@ -243,9 +243,10 @@ bool PCB_EDITOR_CONTROL::Init()
|
|||
toolMenu.AddSubMenu( lockMenu );
|
||||
toolMenu.AddSubMenu( groupMenu );
|
||||
|
||||
menu.AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
|
||||
menu.AddMenu( lockMenu.get(), SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::LockableItems ), 100 );
|
||||
|
||||
menu.AddMenu( zoneMenu.get(), SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ), 200 );
|
||||
menu.AddMenu( lockMenu.get(), SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::LockableItems ), 200 );
|
||||
menu.AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 200 );
|
||||
}
|
||||
|
||||
DRAWING_TOOL* drawingTool = m_toolMgr->GetTool<DRAWING_TOOL>();
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <pcb_painter.h>
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <profile.h>
|
||||
#include <dialogs/wx_html_report_box.h>
|
||||
#include "pcb_inspection_tool.h"
|
||||
|
||||
|
||||
|
@ -77,7 +78,9 @@ bool PCB_INSPECTION_TOOL::Init()
|
|||
CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu();
|
||||
|
||||
selectionTool->GetToolMenu().AddSubMenu( netSubMenu );
|
||||
menu.AddMenu( netSubMenu.get(), SELECTION_CONDITIONS::OnlyTypes( connectedTypes ) );
|
||||
|
||||
menu.AddMenu( netSubMenu.get(), SELECTION_CONDITIONS::OnlyTypes( connectedTypes ), 200 );
|
||||
menu.AddItem( PCB_ACTIONS::inspectClearance, SELECTION_CONDITIONS::Count( 2 ), 200 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -97,6 +100,195 @@ int PCB_INSPECTION_TOOL::ShowStatisticsDialog( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
void reportZoneConnection( ZONE_CONTAINER* aZone, D_PAD* aPad, REPORTER* r )
|
||||
{
|
||||
ENUM_MAP<ZONE_CONNECTION> connectionEnum = ENUM_MAP<ZONE_CONNECTION>::Instance();
|
||||
wxString source;
|
||||
ZONE_CONNECTION connection = aZone->GetPadConnection( aPad, &source );
|
||||
|
||||
r->Report( "" );
|
||||
|
||||
r->Report( wxString::Format( _( "Zone connection type: %s." ),
|
||||
connectionEnum.ToString( aZone->GetPadConnection() ) ) );
|
||||
|
||||
if( source != _( "zone" ) )
|
||||
{
|
||||
r->Report( wxString::Format( _( "Overridden by %s; connection type: %s." ),
|
||||
source,
|
||||
connectionEnum.ToString( connection ) ) );
|
||||
}
|
||||
|
||||
// Resolve complex connection types into simple types
|
||||
if( connection == ZONE_CONNECTION::THT_THERMAL )
|
||||
{
|
||||
if( aPad->GetAttribute() == PAD_ATTRIB_STANDARD )
|
||||
{
|
||||
connection = ZONE_CONNECTION::THERMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
connection = ZONE_CONNECTION::FULL;
|
||||
r->Report( wxString::Format( _( "Pad is not a PTH pad; connection will be: %s." ),
|
||||
connectionEnum.ToString( ZONE_CONNECTION::FULL ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
r->Report( "" );
|
||||
|
||||
// Process simple connection types
|
||||
if( connection == ZONE_CONNECTION::THERMAL )
|
||||
{
|
||||
int gap = aZone->GetThermalReliefGap();
|
||||
|
||||
r->Report( wxString::Format( _( "Zone thermal relief: %s." ),
|
||||
StringFromValue( r->GetUnits(), gap, true ) ) );
|
||||
|
||||
gap = aZone->GetThermalReliefGap( aPad, &source );
|
||||
|
||||
if( source != _( "zone" ) )
|
||||
{
|
||||
r->Report( wxString::Format( _( "Overridden by %s; thermal relief: %s." ),
|
||||
source,
|
||||
StringFromValue( r->GetUnits(), gap, true ) ) );
|
||||
}
|
||||
}
|
||||
else if( connection == ZONE_CONNECTION::NONE )
|
||||
{
|
||||
int clearance = aZone->GetLocalClearance();
|
||||
|
||||
r->Report( wxString::Format( _( "Zone clearance: %s." ),
|
||||
StringFromValue( r->GetUnits(), clearance, true ) ) );
|
||||
|
||||
if( aZone->GetThermalReliefGap( aPad ) > clearance )
|
||||
{
|
||||
clearance = aZone->GetThermalReliefGap( aPad, &source );
|
||||
|
||||
if( source != _( "zone" ) )
|
||||
{
|
||||
r->Report( wxString::Format( _( "Overridden by larger thermal relief from %s;"
|
||||
"clearance: %s." ),
|
||||
source,
|
||||
StringFromValue( r->GetUnits(), clearance, true ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r->Report( _( "Clearance is 0." ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reportCopperClearance( PCB_LAYER_ID aLayer, BOARD_CONNECTED_ITEM* aA, BOARD_ITEM* aB,
|
||||
REPORTER* r )
|
||||
{
|
||||
wxString source;
|
||||
|
||||
r->Report( "" );
|
||||
|
||||
// JEY TODO: hook this up to new DRC engine to get "classic" sources as well; right now
|
||||
// we're just reporting on rules....
|
||||
aA->GetClearance( aLayer, aB, &source, r );
|
||||
}
|
||||
|
||||
|
||||
int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const PCBNEW_SELECTION& selection = selTool->GetSelection();
|
||||
PCB_LAYER_ID layer = m_frame->GetActiveLayer();
|
||||
|
||||
if( selection.Size() != 2 )
|
||||
{
|
||||
m_frame->ShowInfoBarError( _( "Select two items for a clearance resolution report." ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( m_inspectClearanceDialog == nullptr )
|
||||
{
|
||||
m_inspectClearanceDialog = std::make_unique<DIALOG_HTML_REPORTER>( m_frame );
|
||||
m_inspectClearanceDialog->SetTitle( _( "Clearance Report" ) );
|
||||
|
||||
m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW,
|
||||
wxCommandEventHandler( PCB_INSPECTION_TOOL::onInspectClearanceDialogClosed ),
|
||||
nullptr, this );
|
||||
}
|
||||
|
||||
WX_HTML_REPORT_BOX* r = m_inspectClearanceDialog->m_Reporter;
|
||||
r->SetUnits( m_frame->GetUserUnits() );
|
||||
r->Clear();
|
||||
|
||||
BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
|
||||
BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection.GetItem( 1 ) );
|
||||
|
||||
if( a->Type() != PCB_ZONE_AREA_T && b->Type() == PCB_ZONE_AREA_T )
|
||||
std::swap( a, b );
|
||||
else if( !a->IsConnected() && b->IsConnected() )
|
||||
std::swap( a, b );
|
||||
|
||||
if( !IsCopperLayer( layer ) )
|
||||
{
|
||||
r->Report( wxString::Format( _( "Active layer (%s) is not a copper layer. "
|
||||
"No clearance defined." ),
|
||||
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
||||
}
|
||||
else if( !a->GetLayerSet().test( layer ) )
|
||||
{
|
||||
r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
|
||||
a->GetSelectMenuText( r->GetUnits() ),
|
||||
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
||||
}
|
||||
else if( !b->GetLayerSet().test( layer ) )
|
||||
{
|
||||
r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
|
||||
b->GetSelectMenuText( r->GetUnits() ),
|
||||
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
||||
}
|
||||
else if( !a->IsConnected() )
|
||||
{
|
||||
r->Report( _( "Items have no electrical connections. No clearance defined." ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
r->Report( _( "<h7>Clearance resolution for:</h7>" ) );
|
||||
|
||||
r->Report( wxString::Format( _( "<ul><li>Layer %s</li><li>%s</li><li>%s</li></ul>" ),
|
||||
m_frame->GetBoard()->GetLayerName( layer ),
|
||||
a->GetSelectMenuText( r->GetUnits() ),
|
||||
b->GetSelectMenuText( r->GetUnits() ) ) );
|
||||
|
||||
BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
|
||||
BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
|
||||
|
||||
if( ac && bc && ac->GetNetCode() > 0 && ac->GetNetCode() == bc->GetNetCode() )
|
||||
{
|
||||
// Same nets....
|
||||
|
||||
if( ac->Type() == PCB_ZONE_AREA_T && bc->Type() == PCB_PAD_T )
|
||||
{
|
||||
reportZoneConnection( static_cast<ZONE_CONTAINER*>( ac ),
|
||||
static_cast<D_PAD*>( bc ), r );
|
||||
}
|
||||
else
|
||||
{
|
||||
r->Report( _( "Items belong to the same net. Clearance is 0." ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Different nets (or second unconnected)....
|
||||
|
||||
reportCopperClearance( layer, ac, b, r );
|
||||
}
|
||||
}
|
||||
|
||||
r->Flush();
|
||||
|
||||
m_inspectClearanceDialog->Show( true );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PCB_INSPECTION_TOOL::CrossProbePcbToSch( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
// Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ...
|
||||
|
@ -537,6 +729,16 @@ void PCB_INSPECTION_TOOL::onListNetsDialogClosed( wxCommandEvent& event )
|
|||
}
|
||||
|
||||
|
||||
void PCB_INSPECTION_TOOL::onInspectClearanceDialogClosed( wxCommandEvent& event )
|
||||
{
|
||||
m_inspectClearanceDialog->Disconnect( wxEVT_CLOSE_WINDOW,
|
||||
wxCommandEventHandler( PCB_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr, this );
|
||||
|
||||
m_inspectClearanceDialog->Destroy();
|
||||
m_inspectClearanceDialog.release();
|
||||
}
|
||||
|
||||
|
||||
int PCB_INSPECTION_TOOL::HideNet( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
doHideNet( aEvent.Parameter<intptr_t>(), true );
|
||||
|
@ -595,6 +797,7 @@ void PCB_INSPECTION_TOOL::setTransitions()
|
|||
|
||||
Go( &PCB_INSPECTION_TOOL::ListNets, PCB_ACTIONS::listNets.MakeEvent() );
|
||||
Go( &PCB_INSPECTION_TOOL::ShowStatisticsDialog, PCB_ACTIONS::boardStatistics.MakeEvent() );
|
||||
Go( &PCB_INSPECTION_TOOL::InspectClearance, PCB_ACTIONS::inspectClearance.MakeEvent() );
|
||||
|
||||
Go( &PCB_INSPECTION_TOOL::HighlightNet, PCB_ACTIONS::highlightNet.MakeEvent() );
|
||||
Go( &PCB_INSPECTION_TOOL::HighlightNet, PCB_ACTIONS::highlightNetSelection.MakeEvent() );
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <dialogs/dialog_board_statistics.h>
|
||||
#include <dialogs/dialog_select_net_from_list.h>
|
||||
#include <dialogs/dialog_HTML_reporter_base.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/pcb_tool_base.h>
|
||||
|
@ -89,6 +90,9 @@ public:
|
|||
///> Show the ratsnest for a given net
|
||||
int ShowNet( const TOOL_EVENT& aEvent );
|
||||
|
||||
///> Show the clearance resolution for two selected items
|
||||
int InspectClearance( const TOOL_EVENT& aEvent );
|
||||
|
||||
private:
|
||||
///> Event handler to recalculate dynamic ratsnest
|
||||
void ratsnestTimer( wxTimerEvent& aEvent );
|
||||
|
@ -103,7 +107,8 @@ private:
|
|||
///> Bind handlers to corresponding TOOL_ACTIONs
|
||||
void setTransitions() override;
|
||||
|
||||
void onListNetsDialogClosed( wxCommandEvent& event );
|
||||
void onListNetsDialogClosed( wxCommandEvent& aEvent );
|
||||
void onInspectClearanceDialogClosed( wxCommandEvent& aEvent );
|
||||
|
||||
private:
|
||||
PCB_EDIT_FRAME* m_frame; // Pointer to the currently used edit frame.
|
||||
|
@ -116,6 +121,7 @@ private:
|
|||
std::unique_ptr<DIALOG_SELECT_NET_FROM_LIST> m_listNetsDialog;
|
||||
DIALOG_SELECT_NET_FROM_LIST::SETTINGS m_listNetsDialogSettings;
|
||||
|
||||
std::unique_ptr<DIALOG_HTML_REPORTER> m_inspectClearanceDialog;
|
||||
};
|
||||
|
||||
#endif //__BOARD_STATISTICS_TOOL_H
|
||||
|
|
Loading…
Reference in New Issue