design blocks/multichannel: make apply layout do routing, etc.

This commit is contained in:
Mike Williams 2025-08-19 13:57:08 -04:00
parent 2f88ee9dee
commit 92ef03cf15
5 changed files with 68 additions and 17 deletions

View File

@ -2630,6 +2630,9 @@ void PCB_IO_KICAD_SEXPR::format( const ZONE* aZone ) const
case PLACEMENT_SOURCE_T::GROUP_PLACEMENT:
m_out->Print( "(group %s)", m_out->Quotew( aZone->GetPlacementAreaSource() ).c_str() );
break;
// These are transitory and should not be saved
case PLACEMENT_SOURCE_T::DESIGN_BLOCK:
break;
}
m_out->Print( ")" );

View File

@ -80,6 +80,21 @@ bool MULTICHANNEL_TOOL::findComponentsInRuleArea( RULE_AREA* aRuleAre
if( !aRuleArea || !aRuleArea->m_zone )
return false;
// When we're copying the layout of a design block, we are provided an exact list of items
// rather than querying the board for items that are inside the area.
if( aRuleArea->m_sourceType == PLACEMENT_SOURCE_T::DESIGN_BLOCK )
{
// Get all board connected items that are from the design bloc
for( EDA_ITEM* item : aRuleArea->m_designBlockItems )
{
if( item->Type() == PCB_FOOTPRINT_T )
aComponents.insert( static_cast<FOOTPRINT*>( item ) );
}
return (int) aComponents.size();
}
PCBEXPR_COMPILER compiler( new PCBEXPR_UNIT_RESOLVER );
PCBEXPR_UCODE ucode;
PCBEXPR_CONTEXT ctx, preflightCtx;
@ -110,6 +125,9 @@ bool MULTICHANNEL_TOOL::findComponentsInRuleArea( RULE_AREA* aRuleAre
case PLACEMENT_SOURCE_T::GROUP_PLACEMENT:
ruleText = wxT( "A.memberOfGroup('" ) + aRuleArea->m_zone->GetPlacementAreaSource() + wxT( "')" );
break;
case PLACEMENT_SOURCE_T::DESIGN_BLOCK:
// For design blocks, handled above outside the rules system
break;
}
auto ok = compiler.Compile( ruleText, &ucode, &preflightCtx );
@ -141,6 +159,27 @@ bool MULTICHANNEL_TOOL::findOtherItemsInRuleArea( RULE_AREA* aRuleArea, std::set
if( !aRuleArea || !aRuleArea->m_zone )
return false;
// When we're copying the layout of a design block, we are provided an exact list of items
// rather than querying the board for items that are inside the area.
if( aRuleArea->m_sourceType == PLACEMENT_SOURCE_T::DESIGN_BLOCK )
{
// Get all board items that aren't footprints or connected items,
// since they'll be handled in the the other findXInRuleArea routines
for( EDA_ITEM* item : aRuleArea->m_designBlockItems )
{
if( item->Type() == PCB_FOOTPRINT_T )
continue;
if( dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
continue;
if( item->IsBOARD_ITEM() )
aItems.insert( static_cast<BOARD_ITEM*>( item ) );
}
return (int) aItems.size();
}
std::vector<BOARD_ITEM*> result;
PCBEXPR_COMPILER compiler( new PCBEXPR_UNIT_RESOLVER );
@ -660,11 +699,28 @@ int MULTICHANNEL_TOOL::findRoutingInRuleArea( RULE_AREA* aRuleArea, std::set<BOA
std::shared_ptr<CONNECTIVITY_DATA> aConnectivity,
const SHAPE_POLY_SET& aRAPoly, const REPEAT_LAYOUT_OPTIONS& aOpts ) const
{
if( !aRuleArea || !aRuleArea->m_zone )
return 0;
// The user also will consider tracks and vias that are inside the source area but
// not connected to any of the source pads to count as "routing" (e.g. stitching vias)
int count = 0;
// When we're copying the layout of a design block, we are provided an exact list of items
// rather than querying the board for items that are inside the area.
if( aRuleArea->m_sourceType == PLACEMENT_SOURCE_T::DESIGN_BLOCK )
{
// Get all board connected items that are from the design bloc
for( EDA_ITEM* item : aRuleArea->m_designBlockItems )
{
if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
aOutput.insert( bci );
}
return (int) aOutput.size();
}
PCBEXPR_COMPILER compiler( new PCBEXPR_UNIT_RESOLVER );
PCBEXPR_UCODE ucode;
PCBEXPR_CONTEXT ctx, preflightCtx;

View File

@ -69,6 +69,7 @@ struct RULE_AREA
ZONE* m_oldZone = nullptr;
ZONE* m_zone = nullptr;
std::set<FOOTPRINT*> m_components;
std::unordered_set<EDA_ITEM*> m_designBlockItems;
bool m_existsAlready = false;
bool m_generateEnabled = false;
wxString m_sheetPath;

View File

@ -1419,7 +1419,7 @@ int PCB_CONTROL::ApplyDesignBlockLayout( const TOOL_EVENT& aEvent )
// If we succeeded in placing the linked design block, we're ready to apply the multichannel tool
if( m_toolMgr->RunSynchronousAction( PCB_ACTIONS::placeLinkedDesignBlock, &tempCommit, &placementPos ) )
{
// Make a lambda for the bounding box of all the components
// Lambda for the bounding box of all the components
auto generateBoundingBox = [&]( std::unordered_set<EDA_ITEM*> aItems )
{
std::vector<VECTOR2I> bbCorners;
@ -1440,30 +1440,20 @@ int PCB_CONTROL::ApplyDesignBlockLayout( const TOOL_EVENT& aEvent )
return KIGEOM::RectifyPolygon( hull );
};
// Build an outline that is the entire board editor since a design block can
// have anything within this space
SHAPE_LINE_CHAIN wholeEditorOutline;
wholeEditorOutline.Append( VECTOR2I( -INT_MAX, -INT_MAX ) );
wholeEditorOutline.Append( VECTOR2I( INT_MAX, -INT_MAX ) );
wholeEditorOutline.Append( VECTOR2I( INT_MAX, INT_MAX ) );
wholeEditorOutline.Append( VECTOR2I( -INT_MAX, INT_MAX ) );
wholeEditorOutline.SetClosed( true );
// Build a rule area that contains all the components in the design block,
// meaning all items without SKIP_STRUCT set.
RULE_AREA dbRA;
dbRA.m_sourceType = PLACEMENT_SOURCE_T::GROUP_PLACEMENT;
dbRA.m_sourceType = PLACEMENT_SOURCE_T::DESIGN_BLOCK;
dbRA.m_generateEnabled = true;
// Add all components that aren't marked MCT_SKIP_STRUCT to ra.m_components
std::unordered_set<EDA_ITEM*> allDbItems;
brd->Visit(
[&]( EDA_ITEM* item, void* data )
{
if( !item->HasFlag( MCT_SKIP_STRUCT ) )
{
allDbItems.insert( item );
dbRA.m_designBlockItems.insert( item );
if( item->Type() == PCB_FOOTPRINT_T )
dbRA.m_components.insert( static_cast<FOOTPRINT*>( item ) );
@ -1482,10 +1472,10 @@ int PCB_CONTROL::ApplyDesignBlockLayout( const TOOL_EVENT& aEvent )
dbRA.m_zone->SetDoNotAllowTracks( false );
dbRA.m_zone->SetDoNotAllowPads( false );
dbRA.m_zone->SetDoNotAllowFootprints( false );
dbRA.m_zone->SetPlacementAreaSourceType( PLACEMENT_SOURCE_T::GROUP_PLACEMENT );
dbRA.m_zone->SetPlacementAreaSourceType( dbRA.m_sourceType );
dbRA.m_zone->SetPlacementAreaSource( group->GetDesignBlockLibId().GetUniStringLibId() );
dbRA.m_zone->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::NO_HATCH );
dbRA.m_zone->AddPolygon( generateBoundingBox( allDbItems ) );
dbRA.m_zone->AddPolygon( generateBoundingBox( dbRA.m_designBlockItems ) );
dbRA.m_center = dbRA.m_zone->Outline()->COutline( 0 ).Centre();
tempCommit.Add( dbRA.m_zone );
@ -1525,7 +1515,7 @@ int PCB_CONTROL::ApplyDesignBlockLayout( const TOOL_EVENT& aEvent )
destRA.m_zone->SetDoNotAllowTracks( false );
destRA.m_zone->SetDoNotAllowPads( false );
destRA.m_zone->SetDoNotAllowFootprints( false );
destRA.m_zone->SetPlacementAreaSourceType( PLACEMENT_SOURCE_T::GROUP_PLACEMENT );
destRA.m_zone->SetPlacementAreaSourceType( destRA.m_sourceType );
destRA.m_zone->SetPlacementAreaSource( group->GetName() );
destRA.m_zone->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::NO_HATCH );
destRA.m_zone->AddPolygon( generateBoundingBox( group->GetItems() ) );

View File

@ -75,7 +75,8 @@ enum class PLACEMENT_SOURCE_T
{
SHEETNAME = 0,
COMPONENT_CLASS,
GROUP_PLACEMENT
GROUP_PLACEMENT,
DESIGN_BLOCK
};
/**