Browse Source

multi-channel tool: anchor footprints

adds a dropdown menu to select an anchor footprint from the
reference rule area. The corresponding footprints in the
target areas determine displacement and rotation off all the
replicated items. If no anchor footprint has been selected
the previous behavior is unchanged, i.e. rule area position
determines placement.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20603
pull/18/head
Alexander Boehm 7 months ago
committed by eurofun1
parent
commit
6dd366f7bf
  1. 29
      pcbnew/dialogs/dialog_multichannel_repeat_layout.cpp
  2. 1359
      pcbnew/dialogs/dialog_multichannel_repeat_layout.fbp
  3. 2
      pcbnew/dialogs/dialog_multichannel_repeat_layout.h
  4. 41
      pcbnew/dialogs/dialog_multichannel_repeat_layout_base.cpp
  5. 6
      pcbnew/dialogs/dialog_multichannel_repeat_layout_base.h
  6. 58
      pcbnew/tools/multichannel_tool.cpp
  7. 1
      pcbnew/tools/multichannel_tool.h

29
pcbnew/dialogs/dialog_multichannel_repeat_layout.cpp

@ -27,6 +27,8 @@
#include <pcb_edit_frame.h>
#include <tools/multichannel_tool.h>
#include <zone.h>
#include <board.h>
DIALOG_MULTICHANNEL_REPEAT_LAYOUT::DIALOG_MULTICHANNEL_REPEAT_LAYOUT (
PCB_BASE_FRAME* aFrame,
@ -34,6 +36,7 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT::DIALOG_MULTICHANNEL_REPEAT_LAYOUT (
DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE( aFrame ),
m_parentTool( aParentTool )
{
m_board = aFrame->GetBoard();
auto data = m_parentTool->GetData();
m_refRAName->SetLabelText( data->m_refRA->m_area->GetZoneName() );
@ -69,6 +72,7 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT::DIALOG_MULTICHANNEL_REPEAT_LAYOUT (
m_raGrid->SetColLabelValue( 0, wxT("Copy") );
m_raGrid->SetColLabelValue( 1, wxT("Target Rule Area") );
m_raGrid->SetColLabelValue( 2, wxT("Status") );
m_raGrid->SetColLabelValue( 3, wxT( "RefFp" ) );
m_raGrid->AutoSizeColumn( 1 );
m_raGrid->AppendRows( m_targetRAs.size() - 1 );
@ -82,9 +86,19 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT::DIALOG_MULTICHANNEL_REPEAT_LAYOUT (
i++;
}
m_raGrid->SetMaxSize( wxSize( -1, 800 ) );
m_raGrid->SetMaxSize( wxSize( -1, 400 ) );
m_raGrid->Fit();
wxArrayString refFpNames;
refFpNames.push_back( "" );
for( FOOTPRINT* fp : data->m_refRA->m_raFootprints )
refFpNames.push_back( fp->GetReference() );
refFpNames.Sort();
m_refAnchorFp->Set( refFpNames );
m_refAnchorFp->SetSelection( 0 );
m_cbCopyPlacement->SetValue( data->m_options.m_copyPlacement );
m_cbCopyRouting->SetValue( data->m_options.m_copyRouting );
m_cbGroupItems->SetValue( data->m_options.m_groupItems );
@ -117,6 +131,19 @@ bool DIALOG_MULTICHANNEL_REPEAT_LAYOUT::TransferDataFromWindow()
data->m_options.m_includeLockedItems = m_cbIncludeLockedComponents->GetValue();
data->m_options.m_moveOffRAComponents = m_cbIncludeOffRAComponents->GetValue();
if( m_refAnchorFp->GetString( m_refAnchorFp->GetSelection() ) == "" )
{
data->m_options.m_anchorFp = nullptr;
}
else
{
for( FOOTPRINT* fp : m_board->Footprints() )
{
if( fp->GetReference() == m_refAnchorFp->GetString( m_refAnchorFp->GetSelection() ) )
data->m_options.m_anchorFp = fp;
}
}
return true;
}

1359
pcbnew/dialogs/dialog_multichannel_repeat_layout.fbp
File diff suppressed because it is too large
View File

2
pcbnew/dialogs/dialog_multichannel_repeat_layout.h

@ -25,6 +25,7 @@
#define __DIALOG_MULTICHANNEL_REPEAT_LAYOUT__
#include <vector>
#include <board.h>
#include <widgets/unit_binder.h>
#include <dialogs/dialog_multichannel_repeat_layout_base.h>
@ -54,6 +55,7 @@ private:
std::vector<TABLE_ENTRY> m_targetRAs;
MULTICHANNEL_TOOL* m_parentTool;
BOARD* m_board;
};
#endif

41
pcbnew/dialogs/dialog_multichannel_repeat_layout_base.cpp

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -11,24 +11,21 @@
DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxSize( 800,-1 ), wxDefaultSize );
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
m_GeneralBoxSizer = new wxBoxSizer( wxVERTICAL );
m_GeneralBoxSizer->SetMinSize( wxSize( 800,300 ) );
wxFlexGridSizer* fgSizer3;
fgSizer3 = new wxFlexGridSizer( 0, 1, 0, 0 );
fgSizer3->AddGrowableCol( 0 );
fgSizer3->AddGrowableRow( 2 );
fgSizer3->AddGrowableRow( 1 );
fgSizer3->SetFlexibleDirection( wxBOTH );
fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
fgSizer3->SetMinSize( wxSize( 800,300 ) );
fgSizer3->SetMinSize( wxSize( 600,-1 ) );
m_staticText4 = new wxStaticText( this, wxID_ANY, _("Target areas:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText4->Wrap( -1 );
fgSizer3->Add( m_staticText4, 0, wxALL, 5 );
m_raGrid = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_raGrid = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL );
// Grid
m_raGrid->CreateGrid( 1, 3 );
@ -39,8 +36,9 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE(
// Columns
m_raGrid->AutoSizeColumns();
m_raGrid->EnableDragColMove( true );
m_raGrid->EnableDragColMove( false );
m_raGrid->EnableDragColSize( true );
m_raGrid->SetColLabelSize( wxGRID_AUTOSIZE );
m_raGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Rows
@ -71,6 +69,24 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE(
fgSizer3->Add( bSizer4, 1, wxEXPAND, 5 );
wxBoxSizer* bSizer41;
bSizer41 = new wxBoxSizer( wxHORIZONTAL );
m_staticText2 = new wxStaticText( this, wxID_ANY, _("Anchor footprint:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText2->Wrap( -1 );
bSizer41->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
wxArrayString m_refAnchorFpChoices;
m_refAnchorFp = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_refAnchorFpChoices, 0 );
m_refAnchorFp->SetSelection( 0 );
m_refAnchorFp->SetToolTip( _("Optional, use for precise and/or rotated placement.\nSelect reference rule area footprint, place corresponding\ntarget rule area footprint(s).") );
m_refAnchorFp->SetMaxSize( wxSize( -1,400 ) );
bSizer41->Add( m_refAnchorFp, 0, wxALL, 5 );
fgSizer3->Add( bSizer41, 1, wxEXPAND, 5 );
wxBoxSizer* bSizer13;
bSizer13 = new wxBoxSizer( wxVERTICAL );
@ -118,12 +134,9 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE(
fgSizer3->Add( bottomButtonsSizer, 0, wxEXPAND|wxLEFT, 5 );
m_GeneralBoxSizer->Add( fgSizer3, 1, wxEXPAND, 5 );
this->SetSizer( m_GeneralBoxSizer );
this->SetSizer( fgSizer3 );
this->Layout();
m_GeneralBoxSizer->Fit( this );
fgSizer3->Fit( this );
// Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::OnInitDlg ) );

6
pcbnew/dialogs/dialog_multichannel_repeat_layout_base.h

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -19,6 +19,7 @@
#include <wx/settings.h>
#include <wx/grid.h>
#include <wx/sizer.h>
#include <wx/choice.h>
#include <wx/checkbox.h>
#include <wx/button.h>
#include <wx/dialog.h>
@ -31,13 +32,14 @@
class DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE : public DIALOG_SHIM
{
private:
wxBoxSizer* m_GeneralBoxSizer;
protected:
wxStaticText* m_staticText4;
wxGrid* m_raGrid;
wxStaticText* m_staticText1;
wxStaticText* m_refRAName;
wxStaticText* m_staticText2;
wxChoice* m_refAnchorFp;
wxCheckBox* m_cbCopyPlacement;
wxCheckBox* m_cbCopyRouting;
wxCheckBox* m_cbCopyOtherItems;

58
pcbnew/tools/multichannel_tool.cpp

@ -528,7 +528,6 @@ int MULTICHANNEL_TOOL::RepeatLayout( const TOOL_EVENT& aEvent, ZONE* aRefZone )
int totalCopied = 0;
BOARD_COMMIT commit( GetManager(), true );
for( auto& targetArea : m_areas.m_compatMap )
{
if( !targetArea.second.m_doCopy )
@ -541,9 +540,8 @@ int MULTICHANNEL_TOOL::RepeatLayout( const TOOL_EVENT& aEvent, ZONE* aRefZone )
if( !targetArea.second.m_isOk )
continue;
if( !copyRuleAreaContents( targetArea.second.m_matchingComponents, &commit, m_areas.m_refRA,
targetArea.first, m_areas.m_options, targetArea.second.m_affectedItems,
if( !copyRuleAreaContents( targetArea.second.m_matchingComponents, &commit, m_areas.m_refRA, targetArea.first,
m_areas.m_options, targetArea.second.m_affectedItems,
targetArea.second.m_groupableItems ) )
{
auto errMsg = wxString::Format(
@ -561,6 +559,7 @@ int MULTICHANNEL_TOOL::RepeatLayout( const TOOL_EVENT& aEvent, ZONE* aRefZone )
return -1;
}
totalCopied++;
wxSafeYield();
}
if( m_areas.m_options.m_groupItems )
@ -707,10 +706,8 @@ int MULTICHANNEL_TOOL::findRoutedConnections( std::set<BOARD_ITEM*>&
}
bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatches,
BOARD_COMMIT* aCommit,
RULE_AREA* aRefArea, RULE_AREA* aTargetArea,
REPEAT_LAYOUT_OPTIONS aOpts,
bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatches, BOARD_COMMIT* aCommit,
RULE_AREA* aRefArea, RULE_AREA* aTargetArea, REPEAT_LAYOUT_OPTIONS aOpts,
std::unordered_set<BOARD_ITEM*>& aAffectedItems,
std::unordered_set<BOARD_ITEM*>& aGroupableItems )
{
@ -718,7 +715,29 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
SHAPE_LINE_CHAIN refOutline = aRefArea->m_area->Outline()->COutline( 0 );
SHAPE_LINE_CHAIN targetOutline = aTargetArea->m_area->Outline()->COutline( 0 );
FOOTPRINT* targetAnchorFp = nullptr;
VECTOR2I disp = aTargetArea->m_center - aRefArea->m_center;
EDA_ANGLE rot = EDA_ANGLE( 0 );
if( aOpts.m_anchorFp )
{
for( auto& fpPair : aMatches )
{
if( fpPair.first->GetReference() == aOpts.m_anchorFp->GetReference() )
targetAnchorFp = fpPair.second;
}
if( targetAnchorFp )
{
VECTOR2I oldpos = aOpts.m_anchorFp->GetPosition();
rot = EDA_ANGLE( targetAnchorFp->GetOrientationDegrees() - aOpts.m_anchorFp->GetOrientationDegrees() );
aOpts.m_anchorFp->Rotate( VECTOR2( 0, 0 ), EDA_ANGLE( rot ) );
oldpos = aOpts.m_anchorFp->GetPosition();
VECTOR2I newpos = targetAnchorFp->GetPosition();
disp = newpos - oldpos;
aOpts.m_anchorFp->Rotate( VECTOR2( 0, 0 ), EDA_ANGLE( -rot ) );
}
}
SHAPE_POLY_SET refPoly;
refPoly.AddOutline( refOutline );
@ -727,6 +746,7 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
SHAPE_POLY_SET targetPoly;
SHAPE_LINE_CHAIN newTargetOutline( refOutline );
newTargetOutline.Rotate( rot, VECTOR2( 0, 0 ) );
newTargetOutline.Move( disp );
targetPoly.AddOutline( newTargetOutline );
targetPoly.CacheTriangulation( false );
@ -786,6 +806,7 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
fixupNet( static_cast<BOARD_CONNECTED_ITEM*>( item ), static_cast<BOARD_CONNECTED_ITEM*>( copied ),
aMatches );
}
copied->Rotate( VECTOR2( 0, 0 ), rot );
copied->Move( disp );
copied->SetParentGroup( nullptr );
const_cast<KIID&>( copied->m_Uuid ) = KIID();
@ -900,6 +921,7 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
copied->ClearFlags();
copied->SetParentGroup( nullptr );
const_cast<KIID&>( copied->m_Uuid ) = KIID();
copied->Rotate( VECTOR2( 0, 0 ), rot );
copied->Move( disp );
aGroupableItems.insert( copied );
aCommit->Add( copied );
@ -907,11 +929,6 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
}
}
aTargetArea->m_area->RemoveAllContours();
aTargetArea->m_area->AddPolygon( newTargetOutline );
aTargetArea->m_area->UnHatchBorder();
aTargetArea->m_area->HatchBorder();
if( aOpts.m_copyPlacement )
{
for( auto& fpPair : aMatches )
@ -943,9 +960,9 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
targetFP->SetLayerAndFlip( refFP->GetLayer() );
targetFP->SetOrientation( refFP->GetOrientation() );
VECTOR2I targetPos = refFP->GetPosition() + disp;
targetFP->SetPosition( targetPos );
targetFP->SetPosition( refFP->GetPosition() );
targetFP->Rotate( VECTOR2( 0, 0 ), rot );
targetFP->Move( disp );
for( PCB_FIELD* refField : refFP->GetFields() )
{
if( !refField->IsVisible() )
@ -955,7 +972,9 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
wxCHECK2( targetField, continue );
targetField->SetAttributes( refField->GetAttributes() );
targetField->SetPosition( refField->GetPosition() + disp );
targetField->SetPosition( refField->GetPosition() );
targetField->Rotate( VECTOR2( 0, 0 ), rot );
targetField->Move( disp );
targetField->SetIsKnockout( refField->IsKnockout() );
}
@ -964,6 +983,11 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
}
}
aTargetArea->m_area->RemoveAllContours();
aTargetArea->m_area->AddPolygon( newTargetOutline );
aTargetArea->m_area->UnHatchBorder();
aTargetArea->m_area->HatchBorder();
return true;
}

1
pcbnew/tools/multichannel_tool.h

@ -55,6 +55,7 @@ struct REPEAT_LAYOUT_OPTIONS
bool m_includeLockedItems = true;
bool m_keepOldRouting = false;
bool m_copyOnlyMatchingRAShapes = false;
FOOTPRINT* m_anchorFp = nullptr;
REPEAT_LAYOUT_EDGE_MODE m_edgeMode = REPEAT_LAYOUT_EDGE_MODE::INSIDE;
};

Loading…
Cancel
Save