Add edge and margin clearances to message panel.
This commit is contained in:
parent
50bb7c93a1
commit
2de10080cd
|
@ -117,6 +117,11 @@ public:
|
|||
return IsCopperLayer( GetLayer() );
|
||||
}
|
||||
|
||||
virtual bool HasHole() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool IsTented() const
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -116,7 +116,7 @@ bool DRC_CACHE_GENERATOR::Run()
|
|||
{
|
||||
PAD* pad = static_cast<PAD*>( item );
|
||||
|
||||
if( pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
||||
if( pad->HasHole() )
|
||||
layers |= LSET::AllCuMask();
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ public:
|
|||
{
|
||||
PAD* pad = static_cast<PAD*>( aItem );
|
||||
|
||||
if( pad->GetDrillSizeX() )
|
||||
if( pad->HasHole() )
|
||||
{
|
||||
const SHAPE* hole = pad->GetEffectiveHoleShape();
|
||||
subshapes.push_back( const_cast<SHAPE*>( hole ) );
|
||||
|
|
|
@ -276,8 +276,7 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes,
|
|||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
// Careful: if a pad has a hole then it pierces all layers
|
||||
if( ( pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
||||
|| ( pad->GetLayerSet() & aLayers ).any() )
|
||||
if( pad->HasHole() || ( pad->GetLayerSet() & aLayers ).any() )
|
||||
{
|
||||
if( !aFunc( pad ) )
|
||||
return n;
|
||||
|
|
|
@ -244,7 +244,6 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
|
|||
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) )
|
||||
{
|
||||
ZONE* zone = dynamic_cast<ZONE*>( item );
|
||||
PAD* pad = dynamic_cast<PAD*>( item );
|
||||
|
||||
if( zone && zone->GetIsRuleArea() )
|
||||
return true;
|
||||
|
@ -253,22 +252,10 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
|
|||
|
||||
checkDisallow( item );
|
||||
|
||||
bool hasHole;
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_VIA_T: hasHole = true; break;
|
||||
case PCB_PAD_T: hasHole = pad && pad->GetDrillSizeX() > 0; break;
|
||||
default: hasHole = false; break;
|
||||
}
|
||||
|
||||
if( hasHole )
|
||||
if( item->HasHole() )
|
||||
{
|
||||
item->SetFlags( HOLE_PROXY );
|
||||
{
|
||||
checkDisallow( item );
|
||||
}
|
||||
|
||||
checkDisallow( item );
|
||||
item->ClearFlags( HOLE_PROXY );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,19 +136,9 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
|
|||
LSET layers = item->GetLayerSet();
|
||||
|
||||
// Special-case holes and edge-cuts which pierce all physical layers
|
||||
if( item->Type() == PCB_PAD_T )
|
||||
if( item->HasHole() )
|
||||
{
|
||||
PAD* pad = static_cast<PAD*>( item );
|
||||
|
||||
if( pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
||||
layers |= LSET::PhysicalLayersMask() | courtyards;
|
||||
}
|
||||
else if( item->Type() == PCB_VIA_T )
|
||||
{
|
||||
PCB_VIA* via = static_cast<PCB_VIA*>( item );
|
||||
|
||||
if( via->GetDrill() > 0 )
|
||||
layers |= LSET::PhysicalLayersMask() | courtyards;
|
||||
layers |= LSET::PhysicalLayersMask() | courtyards;
|
||||
}
|
||||
else if( item->Type() == PCB_FOOTPRINT_T )
|
||||
{
|
||||
|
|
|
@ -103,6 +103,11 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool HasHole() const override
|
||||
{
|
||||
return GetDrillSizeX() > 0 && GetDrillSizeY() > 0;
|
||||
}
|
||||
|
||||
FOOTPRINT* GetParent() const;
|
||||
|
||||
wxString GetParentAsString() const { return m_parent->m_Uuid.AsString(); }
|
||||
|
|
|
@ -353,6 +353,11 @@ public:
|
|||
VIATYPE GetViaType() const { return m_viaType; }
|
||||
void SetViaType( VIATYPE aViaType ) { m_viaType = aViaType; }
|
||||
|
||||
bool HasHole() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsTented() const override;
|
||||
int GetSolderMaskExpansion() const;
|
||||
|
||||
|
|
|
@ -2546,7 +2546,7 @@ void ALTIUM_PCB::ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, con
|
|||
break;
|
||||
}
|
||||
|
||||
if( pad->GetAttribute() == PAD_ATTRIB::NPTH && pad->GetDrillSizeX() )
|
||||
if( pad->GetAttribute() == PAD_ATTRIB::NPTH && pad->HasHole() )
|
||||
{
|
||||
// KiCad likes NPTH pads to be the same size & shape as their holes
|
||||
pad->SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE ? PAD_SHAPE::CIRCLE
|
||||
|
|
|
@ -138,12 +138,10 @@ void TEARDROP_MANAGER::collectPadsCandidate( std::vector< VIAPAD >& aList,
|
|||
continue;
|
||||
}
|
||||
|
||||
bool has_hole = pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0;
|
||||
|
||||
if( has_hole && !aDrilledViaPad )
|
||||
if( pad->HasHole() && !aDrilledViaPad )
|
||||
continue;
|
||||
|
||||
if( has_hole || aIncludeNotDrilled )
|
||||
if( pad->HasHole() || aIncludeNotDrilled )
|
||||
aList.emplace_back( pad );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -504,22 +504,6 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
|
|||
}
|
||||
|
||||
|
||||
bool hasHole( BOARD_ITEM* aItem )
|
||||
{
|
||||
PAD* pad = dynamic_cast<PAD*>( aItem );
|
||||
|
||||
if( pad && pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
||||
return true;
|
||||
|
||||
PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem );
|
||||
|
||||
if( via )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||
|
@ -878,17 +862,17 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
if( hasHole( a ) || hasHole( b ) )
|
||||
if( a->HasHole() || b->HasHole() )
|
||||
{
|
||||
PCB_LAYER_ID layer = UNDEFINED_LAYER;
|
||||
|
||||
if( hasHole( a ) && b->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
if( a->HasHole() && b->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
layer = active;
|
||||
else if( hasHole( b ) && a->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
else if( b->HasHole() && a->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
layer = active;
|
||||
else if( hasHole( a ) && b->IsOnCopperLayer() )
|
||||
else if( a->HasHole() && b->IsOnCopperLayer() )
|
||||
layer = b->GetLayer();
|
||||
else if( hasHole( b ) && b->IsOnCopperLayer() )
|
||||
else if( b->HasHole() && b->IsOnCopperLayer() )
|
||||
layer = a->GetLayer();
|
||||
|
||||
if( layer >= 0 )
|
||||
|
@ -1007,15 +991,15 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
|||
reportPhysicalClearance( B_CrtYd );
|
||||
}
|
||||
|
||||
if( hasHole( a ) || hasHole( b ) )
|
||||
if( a->HasHole() || b->HasHole() )
|
||||
{
|
||||
PCB_LAYER_ID layer;
|
||||
|
||||
if( hasHole( a ) && b->IsOnLayer( active ) )
|
||||
if( a->HasHole() && b->IsOnLayer( active ) )
|
||||
layer = active;
|
||||
else if( hasHole( b ) && a->IsOnLayer( active ) )
|
||||
else if( b->HasHole() && a->IsOnLayer( active ) )
|
||||
layer = active;
|
||||
else if( hasHole( a ) )
|
||||
else if( a->HasHole() )
|
||||
layer = b->GetLayer();
|
||||
else
|
||||
layer = a->GetLayer();
|
||||
|
|
|
@ -106,6 +106,8 @@ public:
|
|||
return !m_currentlyHighlighted.empty();
|
||||
}
|
||||
|
||||
static bool HasHole( BOARD_ITEM* aItem );
|
||||
|
||||
private:
|
||||
///< Recalculate dynamic ratsnest for the current selection.
|
||||
void calculateSelectionRatsnest( const VECTOR2I& aDelta );
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#include <tools/edit_tool.h>
|
||||
#include <tools/board_inspection_tool.h>
|
||||
#include <router/router_tool.h>
|
||||
#include <pgm_base.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
|
@ -1190,11 +1191,13 @@ int PCB_CONTROL::Redo( const TOOL_EVENT& aEvent )
|
|||
|
||||
int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||
ROUTER_TOOL* routerTool = m_toolMgr->GetTool<ROUTER_TOOL>();
|
||||
PCB_SELECTION& selection = selTool->GetSelection();
|
||||
FOOTPRINT_EDIT_FRAME* fpFrame = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( m_frame );
|
||||
PCB_EDIT_FRAME* pcbFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
|
||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||
ROUTER_TOOL* routerTool = m_toolMgr->GetTool<ROUTER_TOOL>();
|
||||
PCB_SELECTION& selection = selTool->GetSelection();
|
||||
FOOTPRINT_EDIT_FRAME* fpFrame = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( m_frame );
|
||||
PCB_EDIT_FRAME* pcbFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
|
||||
std::shared_ptr<DRC_ENGINE> drcEngine = m_frame->GetBoard()->GetDesignSettings().m_DRCEngine;
|
||||
DRC_CONSTRAINT constraint;
|
||||
|
||||
EDA_UNITS units = m_frame->GetUserUnits();
|
||||
std::vector<MSG_PANEL_ITEM> msgItems;
|
||||
|
@ -1214,7 +1217,7 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
|
|||
if( !footprint )
|
||||
return 0;
|
||||
|
||||
wxString msg;
|
||||
wxString msg;
|
||||
|
||||
msg = footprint->GetFPID().GetLibNickname().wx_str();
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Library" ), msg ) );
|
||||
|
@ -1244,90 +1247,105 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
// Pair selection broken into multiple, optional data, starting with the selection item names
|
||||
if( selection.GetSize() == 2 )
|
||||
if( pcbFrame && selection.GetSize() == 2 )
|
||||
{
|
||||
auto clearanceString =
|
||||
[&]( const DRC_CONSTRAINT& constraint )
|
||||
{
|
||||
return StringFromValue( units, constraint.m_Value.Min(), true );
|
||||
};
|
||||
|
||||
BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection[0] );
|
||||
BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection[1] );
|
||||
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( a->GetSelectMenuText( units ),
|
||||
b->GetSelectMenuText( units ) ) );
|
||||
}
|
||||
|
||||
if( BOARD_CONNECTED_ITEM *a, *b;
|
||||
selection.GetSize() == 2 && pcbFrame &&
|
||||
( a = dyn_cast<BOARD_CONNECTED_ITEM*>( selection[0] ) ) &&
|
||||
( b = dyn_cast<BOARD_CONNECTED_ITEM*>( selection[1] ) ) )
|
||||
{
|
||||
LSET overlap = a->GetLayerSet() & b->GetLayerSet() & LSET::AllCuMask();
|
||||
BOARD_CONNECTED_ITEM* a_conn = dyn_cast<BOARD_CONNECTED_ITEM*>( a );
|
||||
BOARD_CONNECTED_ITEM* b_conn = dyn_cast<BOARD_CONNECTED_ITEM*>( b );
|
||||
|
||||
BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
|
||||
|
||||
if( overlap.count() > 0
|
||||
&& ( a->GetNetCode() != b->GetNetCode()
|
||||
|| a->GetNetCode() < 0
|
||||
|| b->GetNetCode() < 0 ) )
|
||||
if( a_conn && b_conn )
|
||||
{
|
||||
PCB_LAYER_ID layer = overlap.CuStack().front();
|
||||
auto aShape = a->GetEffectiveShape( layer );
|
||||
auto bShape = b->GetEffectiveShape( layer );
|
||||
LSET overlap = a_conn->GetLayerSet() & b_conn->GetLayerSet() & LSET::AllCuMask();
|
||||
int a_netcode = a_conn->GetNetCode();
|
||||
int b_netcode = b_conn->GetNetCode();
|
||||
|
||||
DRC_CONSTRAINT constraint;
|
||||
int clearance = 0;
|
||||
if( overlap.count() > 0
|
||||
&& ( a_netcode != b_netcode || a_netcode < 0 || b_netcode < 0 ) )
|
||||
{
|
||||
constraint = drcEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b,
|
||||
overlap.CuStack().front() );
|
||||
|
||||
constraint = bds.m_DRCEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, layer );
|
||||
clearance = constraint.m_Value.Min();
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved clearance" ),
|
||||
StringFromValue( units, clearance, true ) ) );
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved clearance" ),
|
||||
clearanceString( constraint ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto hasHole = []( EDA_ITEM* aItem ) -> bool
|
||||
{
|
||||
PAD* pad = dyn_cast<PAD*>( aItem );
|
||||
|
||||
if( pad && pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
||||
return true;
|
||||
|
||||
return !!dyn_cast<PCB_VIA*>( aItem );
|
||||
};
|
||||
|
||||
if( selection.GetSize() == 2 && pcbFrame &&
|
||||
( hasHole( selection[0] ) || hasHole( selection[1] ) ) )
|
||||
{
|
||||
PCB_LAYER_ID active = m_frame->GetActiveLayer();
|
||||
PCB_LAYER_ID layer = UNDEFINED_LAYER;
|
||||
|
||||
BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection[0] );
|
||||
BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection[1] );
|
||||
|
||||
if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
layer = active;
|
||||
else if( hasHole( b ) && a->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
layer = active;
|
||||
else if( hasHole( a ) && b->IsOnCopperLayer() )
|
||||
layer = b->GetLayer();
|
||||
else if( hasHole( b ) && b->IsOnCopperLayer() )
|
||||
layer = a->GetLayer();
|
||||
|
||||
if( layer >= 0 )
|
||||
if( a->HasHole() || b->HasHole() )
|
||||
{
|
||||
PCB_LAYER_ID active = m_frame->GetActiveLayer();
|
||||
PCB_LAYER_ID layer = UNDEFINED_LAYER;
|
||||
|
||||
BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
|
||||
DRC_CONSTRAINT constraint;
|
||||
int clearance = 0;
|
||||
if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
layer = active;
|
||||
else if( b->HasHole() && a->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
layer = active;
|
||||
else if( a->HasHole() && b->IsOnCopperLayer() )
|
||||
layer = b->GetLayer();
|
||||
else if( b->HasHole() && b->IsOnCopperLayer() )
|
||||
layer = a->GetLayer();
|
||||
|
||||
constraint = bds.m_DRCEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer );
|
||||
clearance = constraint.m_Value.Min();
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved hole clearance" ),
|
||||
StringFromValue( units, clearance, true ) ) );
|
||||
if( layer >= 0 )
|
||||
{
|
||||
constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer );
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved hole clearance" ),
|
||||
clearanceString( constraint ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
for( PCB_LAYER_ID edgeLayer : { Edge_Cuts, Margin } )
|
||||
{
|
||||
PCB_LAYER_ID active = m_frame->GetActiveLayer();
|
||||
PCB_LAYER_ID layer = UNDEFINED_LAYER;
|
||||
|
||||
if( a->IsOnLayer( edgeLayer ) && b->Type() != PCB_FOOTPRINT_T )
|
||||
{
|
||||
if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
layer = active;
|
||||
else if( IsCopperLayer( b->GetLayer() ) )
|
||||
layer = b->GetLayer();
|
||||
}
|
||||
else if( b->IsOnLayer( edgeLayer ) && a->Type() != PCB_FOOTPRINT_T )
|
||||
{
|
||||
if( a->IsOnLayer( active ) && IsCopperLayer( active ) )
|
||||
layer = active;
|
||||
else if( IsCopperLayer( a->GetLayer() ) )
|
||||
layer = a->GetLayer();
|
||||
}
|
||||
|
||||
if( layer >= 0 )
|
||||
{
|
||||
constraint = drcEngine->EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer );
|
||||
|
||||
if( edgeLayer == Edge_Cuts )
|
||||
{
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved edge clearance" ),
|
||||
clearanceString( constraint ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved margin clearance" ),
|
||||
clearanceString( constraint ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( msgItems.empty() )
|
||||
msgItems.emplace_back(
|
||||
MSG_PANEL_ITEM( _( "Selected Items" ),
|
||||
wxString::Format( wxT( "%d" ), selection.GetSize() ) ) );
|
||||
{
|
||||
wxString msg = wxString::Format( wxT( "%d" ), selection.GetSize() );
|
||||
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Selected Items" ), msg ) );
|
||||
}
|
||||
|
||||
m_frame->SetMsgPanel( msgItems );
|
||||
|
||||
|
|
Loading…
Reference in New Issue