Add pad-recombining to FPEditor's Cleanup Graphics.
Fixes https://gitlab.com/kicad/code/kicad/issues/12487
This commit is contained in:
parent
22cd2a3428
commit
328cc27020
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors.
|
* Copyright (C) 2020-2022 KiCad Developers, see change_log.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -43,20 +43,21 @@ wxString CLEANUP_ITEM::GetErrorText( int aCode, bool aTranslate ) const
|
||||||
switch( aCode )
|
switch( aCode )
|
||||||
{
|
{
|
||||||
// For cleanup tracks and vias:
|
// For cleanup tracks and vias:
|
||||||
case CLEANUP_SHORTING_TRACK: msg = _HKI( "Remove track shorting two nets" ); break;
|
case CLEANUP_SHORTING_TRACK: msg = _HKI( "Remove track shorting two nets" ); break;
|
||||||
case CLEANUP_SHORTING_VIA: msg = _HKI( "Remove via shorting two nets" ); break;
|
case CLEANUP_SHORTING_VIA: msg = _HKI( "Remove via shorting two nets" ); break;
|
||||||
case CLEANUP_REDUNDANT_VIA: msg = _HKI( "Remove redundant via" ); break;
|
case CLEANUP_REDUNDANT_VIA: msg = _HKI( "Remove redundant via" ); break;
|
||||||
case CLEANUP_DUPLICATE_TRACK: msg = _HKI( "Remove duplicate track" ); break;
|
case CLEANUP_DUPLICATE_TRACK: msg = _HKI( "Remove duplicate track" ); break;
|
||||||
case CLEANUP_MERGE_TRACKS: msg = _HKI( "Merge co-linear tracks" ); break;
|
case CLEANUP_MERGE_TRACKS: msg = _HKI( "Merge co-linear tracks" ); break;
|
||||||
case CLEANUP_DANGLING_TRACK: msg = _HKI( "Remove track not connected at both ends" ); break;
|
case CLEANUP_DANGLING_TRACK: msg = _HKI( "Remove track not connected at both ends" ); break;
|
||||||
case CLEANUP_DANGLING_VIA: msg = _HKI( "Remove via connected on fewer than two layers" ); break;
|
case CLEANUP_DANGLING_VIA: msg = _HKI( "Remove via connected on less than 2 layers" ); break;
|
||||||
case CLEANUP_ZERO_LENGTH_TRACK: msg = _HKI( "Remove zero-length track" ); break;
|
case CLEANUP_ZERO_LENGTH_TRACK: msg = _HKI( "Remove zero-length track" ); break;
|
||||||
case CLEANUP_TRACK_IN_PAD: msg = _HKI( "Remove track inside pad" ); break;
|
case CLEANUP_TRACK_IN_PAD: msg = _HKI( "Remove track inside pad" ); break;
|
||||||
|
|
||||||
// For cleanup graphics:
|
// For cleanup graphics:
|
||||||
case CLEANUP_NULL_GRAPHIC: msg = _HKI( "Remove zero-size graphic" ); break;
|
case CLEANUP_NULL_GRAPHIC: msg = _HKI( "Remove zero-size graphic" ); break;
|
||||||
case CLEANUP_DUPLICATE_GRAPHIC: msg = _HKI( "Remove duplicated graphic" ); break;
|
case CLEANUP_DUPLICATE_GRAPHIC: msg = _HKI( "Remove duplicated graphic" ); break;
|
||||||
case CLEANUP_LINES_TO_RECT: msg = _HKI( "Convert lines to rectangle" ); break;
|
case CLEANUP_LINES_TO_RECT: msg = _HKI( "Convert lines to rectangle" ); break;
|
||||||
|
case CLEANUP_MERGE_PAD: msg = _HKI( "Merge overlapping shapes into pad" ); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
wxFAIL_MSG( wxT( "Missing cleanup item description" ) );
|
wxFAIL_MSG( wxT( "Missing cleanup item description" ) );
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -42,7 +42,8 @@ enum CLEANUP_RC_CODE {
|
||||||
CLEANUP_TRACK_IN_PAD,
|
CLEANUP_TRACK_IN_PAD,
|
||||||
CLEANUP_NULL_GRAPHIC,
|
CLEANUP_NULL_GRAPHIC,
|
||||||
CLEANUP_DUPLICATE_GRAPHIC,
|
CLEANUP_DUPLICATE_GRAPHIC,
|
||||||
CLEANUP_LINES_TO_RECT
|
CLEANUP_LINES_TO_RECT,
|
||||||
|
CLEANUP_MERGE_PAD
|
||||||
};
|
};
|
||||||
|
|
||||||
class CLEANUP_ITEM : public RC_ITEM
|
class CLEANUP_ITEM : public RC_ITEM
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <dialog_cleanup_graphics.h>
|
#include <dialog_cleanup_graphics.h>
|
||||||
#include <board_commit.h>
|
#include <board_commit.h>
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
|
#include <pad.h>
|
||||||
#include <tool/tool_manager.h>
|
#include <tool/tool_manager.h>
|
||||||
#include <tools/pcb_actions.h>
|
#include <tools/pcb_actions.h>
|
||||||
#include <graphics_cleaner.h>
|
#include <graphics_cleaner.h>
|
||||||
|
@ -40,9 +41,16 @@ DIALOG_CLEANUP_GRAPHICS::DIALOG_CLEANUP_GRAPHICS( PCB_BASE_FRAME* aParent,
|
||||||
m_changesDataView->AssociateModel( m_changesTreeModel );
|
m_changesDataView->AssociateModel( m_changesTreeModel );
|
||||||
|
|
||||||
if( aIsFootprintEditor )
|
if( aIsFootprintEditor )
|
||||||
|
{
|
||||||
SetupStandardButtons( { { wxID_OK, _( "Update Footprint" ) } } );
|
SetupStandardButtons( { { wxID_OK, _( "Update Footprint" ) } } );
|
||||||
|
m_nettieHint->SetFont( KIUI::GetInfoFont( aParent ).Italic() );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
SetupStandardButtons( { { wxID_OK, _( "Update PCB" ) } } );
|
SetupStandardButtons( { { wxID_OK, _( "Update PCB" ) } } );
|
||||||
|
m_mergePadsOpt->Show( false );
|
||||||
|
m_nettieHint->Show( false );
|
||||||
|
}
|
||||||
|
|
||||||
GetSizer()->SetSizeHints(this);
|
GetSizer()->SetSizeHints(this);
|
||||||
Centre();
|
Centre();
|
||||||
|
@ -84,7 +92,8 @@ void DIALOG_CLEANUP_GRAPHICS::doCleanup( bool aDryRun )
|
||||||
BOARD_COMMIT commit( m_parentFrame );
|
BOARD_COMMIT commit( m_parentFrame );
|
||||||
BOARD* board = m_parentFrame->GetBoard();
|
BOARD* board = m_parentFrame->GetBoard();
|
||||||
FOOTPRINT* fp = m_isFootprintEditor ? board->GetFirstFootprint() : nullptr;
|
FOOTPRINT* fp = m_isFootprintEditor ? board->GetFirstFootprint() : nullptr;
|
||||||
GRAPHICS_CLEANER cleaner( fp ? fp->GraphicalItems() : board->Drawings(), fp, commit );
|
GRAPHICS_CLEANER cleaner( fp ? fp->GraphicalItems() : board->Drawings(), fp, commit,
|
||||||
|
m_parentFrame->GetToolManager() );
|
||||||
|
|
||||||
if( !aDryRun )
|
if( !aDryRun )
|
||||||
{
|
{
|
||||||
|
@ -101,7 +110,8 @@ void DIALOG_CLEANUP_GRAPHICS::doCleanup( bool aDryRun )
|
||||||
m_parentFrame->Compile_Ratsnest( false );
|
m_parentFrame->Compile_Ratsnest( false );
|
||||||
|
|
||||||
cleaner.CleanupBoard( aDryRun, &m_items, m_createRectanglesOpt->GetValue(),
|
cleaner.CleanupBoard( aDryRun, &m_items, m_createRectanglesOpt->GetValue(),
|
||||||
m_deleteRedundantOpt->GetValue() );
|
m_deleteRedundantOpt->GetValue(),
|
||||||
|
m_mergePadsOpt->GetValue() );
|
||||||
|
|
||||||
if( aDryRun )
|
if( aDryRun )
|
||||||
{
|
{
|
||||||
|
@ -123,6 +133,9 @@ void DIALOG_CLEANUP_GRAPHICS::OnSelectItem( wxDataViewEvent& aEvent )
|
||||||
BOARD_ITEM* item = m_parentFrame->GetBoard()->GetItem( itemID );
|
BOARD_ITEM* item = m_parentFrame->GetBoard()->GetItem( itemID );
|
||||||
WINDOW_THAWER thawer( m_parentFrame );
|
WINDOW_THAWER thawer( m_parentFrame );
|
||||||
|
|
||||||
|
if( item && !item->GetLayerSet().test( m_parentFrame->GetActiveLayer() ) )
|
||||||
|
m_parentFrame->SetActiveLayer( item->GetLayerSet().UIOrder().front() );
|
||||||
|
|
||||||
m_parentFrame->FocusOnItem( item );
|
m_parentFrame->FocusOnItem( item );
|
||||||
m_parentFrame->GetCanvas()->Refresh();
|
m_parentFrame->GetCanvas()->Refresh();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
@ -23,7 +23,20 @@ DIALOG_CLEANUP_GRAPHICS_BASE::DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wx
|
||||||
bSizerUpper->Add( m_createRectanglesOpt, 0, wxALL, 5 );
|
bSizerUpper->Add( m_createRectanglesOpt, 0, wxALL, 5 );
|
||||||
|
|
||||||
m_deleteRedundantOpt = new wxCheckBox( this, wxID_ANY, _("Delete redundant graphics"), wxDefaultPosition, wxDefaultSize, 0 );
|
m_deleteRedundantOpt = new wxCheckBox( this, wxID_ANY, _("Delete redundant graphics"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
bSizerUpper->Add( m_deleteRedundantOpt, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
bSizerUpper->Add( m_deleteRedundantOpt, 0, wxALL, 5 );
|
||||||
|
|
||||||
|
m_mergePadsOpt = new wxCheckBox( this, wxID_ANY, _("Merge overlapping graphics into pads"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
bSizerUpper->Add( m_mergePadsOpt, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizerMargins;
|
||||||
|
bSizerMargins = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
m_nettieHint = new wxStaticText( this, wxID_ANY, _("(Pads which appear in a Net Tie pad group will not be considered for merging.)"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_nettieHint->Wrap( -1 );
|
||||||
|
bSizerMargins->Add( m_nettieHint, 0, wxLEFT, 25 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizerUpper->Add( bSizerMargins, 1, wxEXPAND|wxALL, 3 );
|
||||||
|
|
||||||
|
|
||||||
bSizerMain->Add( bSizerUpper, 0, wxEXPAND|wxALL, 5 );
|
bSizerMain->Add( bSizerUpper, 0, wxEXPAND|wxALL, 5 );
|
||||||
|
@ -40,7 +53,7 @@ DIALOG_CLEANUP_GRAPHICS_BASE::DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wx
|
||||||
bLowerSizer->Add( m_changesDataView, 1, wxALL|wxEXPAND, 5 );
|
bLowerSizer->Add( m_changesDataView, 1, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
bSizerMain->Add( bLowerSizer, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
|
bSizerMain->Add( bLowerSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||||
|
|
||||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||||
|
@ -61,6 +74,7 @@ DIALOG_CLEANUP_GRAPHICS_BASE::DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wx
|
||||||
// Connect Events
|
// Connect Events
|
||||||
m_createRectanglesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
m_createRectanglesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||||
m_deleteRedundantOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
m_deleteRedundantOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||||
|
m_mergePadsOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||||
m_changesDataView->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnSelectItem ), NULL, this );
|
m_changesDataView->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnSelectItem ), NULL, this );
|
||||||
m_changesDataView->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnLeftDClickItem ), NULL, this );
|
m_changesDataView->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnLeftDClickItem ), NULL, this );
|
||||||
}
|
}
|
||||||
|
@ -70,6 +84,7 @@ DIALOG_CLEANUP_GRAPHICS_BASE::~DIALOG_CLEANUP_GRAPHICS_BASE()
|
||||||
// Disconnect Events
|
// Disconnect Events
|
||||||
m_createRectanglesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
m_createRectanglesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||||
m_deleteRedundantOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
m_deleteRedundantOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||||
|
m_mergePadsOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||||
m_changesDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnSelectItem ), NULL, this );
|
m_changesDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnSelectItem ), NULL, this );
|
||||||
m_changesDataView->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnLeftDClickItem ), NULL, this );
|
m_changesDataView->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnLeftDClickItem ), NULL, this );
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
<wxFormBuilder_Project>
|
<wxFormBuilder_Project>
|
||||||
<FileVersion major="1" minor="15" />
|
<FileVersion major="1" minor="16" />
|
||||||
<object class="Project" expanded="1">
|
<object class="Project" expanded="1">
|
||||||
<property name="class_decoration"></property>
|
<property name="class_decoration"></property>
|
||||||
<property name="code_generation">C++</property>
|
<property name="code_generation">C++</property>
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
<property name="file">dialog_cleanup_graphics_base</property>
|
<property name="file">dialog_cleanup_graphics_base</property>
|
||||||
<property name="first_id">1000</property>
|
<property name="first_id">1000</property>
|
||||||
<property name="help_provider">none</property>
|
<property name="help_provider">none</property>
|
||||||
|
<property name="image_path_wrapper_function_name"></property>
|
||||||
<property name="indent_with_spaces"></property>
|
<property name="indent_with_spaces"></property>
|
||||||
<property name="internationalize">1</property>
|
<property name="internationalize">1</property>
|
||||||
<property name="name">dialog_cleanup_graphics</property>
|
<property name="name">dialog_cleanup_graphics</property>
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
<property name="skip_php_events">1</property>
|
<property name="skip_php_events">1</property>
|
||||||
<property name="skip_python_events">1</property>
|
<property name="skip_python_events">1</property>
|
||||||
<property name="ui_table">UI</property>
|
<property name="ui_table">UI</property>
|
||||||
|
<property name="use_array_enum">0</property>
|
||||||
<property name="use_enum">0</property>
|
<property name="use_enum">0</property>
|
||||||
<property name="use_microsoft_bom">0</property>
|
<property name="use_microsoft_bom">0</property>
|
||||||
<object class="Dialog" expanded="1">
|
<object class="Dialog" expanded="1">
|
||||||
|
@ -50,6 +52,7 @@
|
||||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||||
<property name="title">Cleanup Graphics</property>
|
<property name="title">Cleanup Graphics</property>
|
||||||
<property name="tooltip"></property>
|
<property name="tooltip"></property>
|
||||||
|
<property name="two_step_creation">0</property>
|
||||||
<property name="window_extra_style"></property>
|
<property name="window_extra_style"></property>
|
||||||
<property name="window_name"></property>
|
<property name="window_name"></property>
|
||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
|
@ -134,7 +137,7 @@
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="1">
|
<object class="sizeritem" expanded="1">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
|
<property name="flag">wxALL</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxCheckBox" expanded="1">
|
<object class="wxCheckBox" expanded="1">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
|
@ -197,11 +200,148 @@
|
||||||
<event name="OnCheckBox">OnCheckBox</event>
|
<event name="OnCheckBox">OnCheckBox</event>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="wxCheckBox" expanded="1">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="checked">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="label">Merge overlapping graphics into pads</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_mergePadsOpt</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style"></property>
|
||||||
|
<property name="subclass">; ; forward_declare</property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="validator_data_type"></property>
|
||||||
|
<property name="validator_style">wxFILTER_NONE</property>
|
||||||
|
<property name="validator_type">wxDefaultValidator</property>
|
||||||
|
<property name="validator_variable"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<event name="OnCheckBox">OnCheckBox</event>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">3</property>
|
||||||
|
<property name="flag">wxEXPAND|wxALL</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="wxBoxSizer" expanded="1">
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="name">bSizerMargins</property>
|
||||||
|
<property name="orient">wxVERTICAL</property>
|
||||||
|
<property name="permission">none</property>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">25</property>
|
||||||
|
<property name="flag">wxLEFT</property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="wxStaticText" expanded="1">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="label">(Pads which appear in a Net Tie pad group will not be considered for merging.)</property>
|
||||||
|
<property name="markup">0</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_nettieHint</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style"></property>
|
||||||
|
<property name="subclass">; ; forward_declare</property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<property name="wrap">-1</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="1">
|
<object class="sizeritem" expanded="1">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
|
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
|
||||||
<property name="proportion">1</property>
|
<property name="proportion">1</property>
|
||||||
<object class="wxBoxSizer" expanded="1">
|
<object class="wxBoxSizer" expanded="1">
|
||||||
<property name="minimum_size">660,250</property>
|
<property name="minimum_size">660,250</property>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
@ -17,8 +17,8 @@
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/sizer.h>
|
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
|
@ -36,13 +36,15 @@ class DIALOG_CLEANUP_GRAPHICS_BASE : public DIALOG_SHIM
|
||||||
protected:
|
protected:
|
||||||
wxCheckBox* m_createRectanglesOpt;
|
wxCheckBox* m_createRectanglesOpt;
|
||||||
wxCheckBox* m_deleteRedundantOpt;
|
wxCheckBox* m_deleteRedundantOpt;
|
||||||
|
wxCheckBox* m_mergePadsOpt;
|
||||||
|
wxStaticText* m_nettieHint;
|
||||||
wxStaticText* staticChangesLabel;
|
wxStaticText* staticChangesLabel;
|
||||||
wxDataViewCtrl* m_changesDataView;
|
wxDataViewCtrl* m_changesDataView;
|
||||||
wxStdDialogButtonSizer* m_sdbSizer;
|
wxStdDialogButtonSizer* m_sdbSizer;
|
||||||
wxButton* m_sdbSizerOK;
|
wxButton* m_sdbSizerOK;
|
||||||
wxButton* m_sdbSizerCancel;
|
wxButton* m_sdbSizerCancel;
|
||||||
|
|
||||||
// Virtual event handlers, overide them in your derived class
|
// Virtual event handlers, override them in your derived class
|
||||||
virtual void OnCheckBox( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnCheckBox( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnSelectItem( wxDataViewEvent& event ) { event.Skip(); }
|
virtual void OnSelectItem( wxDataViewEvent& event ) { event.Skip(); }
|
||||||
virtual void OnLeftDClickItem( wxMouseEvent& event ) { event.Skip(); }
|
virtual void OnLeftDClickItem( wxMouseEvent& event ) { event.Skip(); }
|
||||||
|
@ -51,6 +53,7 @@ class DIALOG_CLEANUP_GRAPHICS_BASE : public DIALOG_SHIM
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Cleanup Graphics"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Cleanup Graphics"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||||
|
|
||||||
~DIALOG_CLEANUP_GRAPHICS_BASE();
|
~DIALOG_CLEANUP_GRAPHICS_BASE();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,15 +29,19 @@
|
||||||
#include <cleanup_item.h>
|
#include <cleanup_item.h>
|
||||||
#include <pcb_shape.h>
|
#include <pcb_shape.h>
|
||||||
#include <fp_shape.h>
|
#include <fp_shape.h>
|
||||||
|
#include <pad.h>
|
||||||
|
#include <footprint.h>
|
||||||
#include <graphics_cleaner.h>
|
#include <graphics_cleaner.h>
|
||||||
#include <board_design_settings.h>
|
#include <board_design_settings.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
#include <tools/pad_tool.h>
|
||||||
|
|
||||||
GRAPHICS_CLEANER::GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootprint,
|
GRAPHICS_CLEANER::GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootprint,
|
||||||
BOARD_COMMIT& aCommit ) :
|
BOARD_COMMIT& aCommit, TOOL_MANAGER* aToolMgr ) :
|
||||||
m_drawings( aDrawings ),
|
m_drawings( aDrawings ),
|
||||||
m_parentFootprint( aParentFootprint ),
|
m_parentFootprint( aParentFootprint ),
|
||||||
m_commit( aCommit ),
|
m_commit( aCommit ),
|
||||||
|
m_toolMgr( aToolMgr ),
|
||||||
m_dryRun( true ),
|
m_dryRun( true ),
|
||||||
m_epsilon( 0 ),
|
m_epsilon( 0 ),
|
||||||
m_itemsList( nullptr )
|
m_itemsList( nullptr )
|
||||||
|
@ -47,7 +51,7 @@ GRAPHICS_CLEANER::GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootp
|
||||||
|
|
||||||
void GRAPHICS_CLEANER::CleanupBoard( bool aDryRun,
|
void GRAPHICS_CLEANER::CleanupBoard( bool aDryRun,
|
||||||
std::vector<std::shared_ptr<CLEANUP_ITEM>>* aItemsList,
|
std::vector<std::shared_ptr<CLEANUP_ITEM>>* aItemsList,
|
||||||
bool aMergeRects, bool aDeleteRedundant )
|
bool aMergeRects, bool aDeleteRedundant, bool aMergePads )
|
||||||
{
|
{
|
||||||
m_dryRun = aDryRun;
|
m_dryRun = aDryRun;
|
||||||
m_itemsList = aItemsList;
|
m_itemsList = aItemsList;
|
||||||
|
@ -64,6 +68,9 @@ void GRAPHICS_CLEANER::CleanupBoard( bool aDryRun,
|
||||||
if( aMergeRects )
|
if( aMergeRects )
|
||||||
mergeRects();
|
mergeRects();
|
||||||
|
|
||||||
|
if( aMergePads )
|
||||||
|
mergePads();
|
||||||
|
|
||||||
// Clear the flag used to mark some shapes:
|
// Clear the flag used to mark some shapes:
|
||||||
for( BOARD_ITEM* drawing : m_drawings )
|
for( BOARD_ITEM* drawing : m_drawings )
|
||||||
drawing->ClearFlags( IS_DELETED );
|
drawing->ClearFlags( IS_DELETED );
|
||||||
|
@ -339,3 +346,49 @@ void GRAPHICS_CLEANER::mergeRects()
|
||||||
delete side;
|
delete side;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_CLEANER::mergePads()
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( m_parentFootprint, /*void*/, wxT( "mergePads() is FootprintEditor only" ) );
|
||||||
|
|
||||||
|
PAD_TOOL* padTool = m_toolMgr->GetTool<PAD_TOOL>();
|
||||||
|
|
||||||
|
for( PAD* pad : m_parentFootprint->Pads() )
|
||||||
|
pad->SetFlags( CANDIDATE );
|
||||||
|
|
||||||
|
if( m_parentFootprint->IsNetTie() )
|
||||||
|
{
|
||||||
|
for( const wxString& group : m_parentFootprint->GetNetTiePadGroups() )
|
||||||
|
{
|
||||||
|
wxStringTokenizer groupParser( group, "," );
|
||||||
|
|
||||||
|
while( groupParser.HasMoreTokens() )
|
||||||
|
{
|
||||||
|
wxString number = groupParser.GetNextToken().Trim( false ).Trim( true );
|
||||||
|
|
||||||
|
if( PAD* pad = m_parentFootprint->FindPadByNumber( number ) )
|
||||||
|
pad->ClearFlags( CANDIDATE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( PAD* pad : m_parentFootprint->Pads() )
|
||||||
|
{
|
||||||
|
if( !( pad->GetFlags() & CANDIDATE ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector<FP_SHAPE*> shapes = padTool->RecombinePad( pad, m_dryRun, m_commit );
|
||||||
|
|
||||||
|
if( !shapes.empty() )
|
||||||
|
{
|
||||||
|
std::shared_ptr<CLEANUP_ITEM> item = std::make_shared<CLEANUP_ITEM>( CLEANUP_MERGE_PAD );
|
||||||
|
|
||||||
|
for( FP_SHAPE* shape : shapes )
|
||||||
|
item->AddItem( shape );
|
||||||
|
|
||||||
|
item->AddItem( pad );
|
||||||
|
|
||||||
|
m_itemsList->push_back( item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,21 +29,25 @@
|
||||||
class FOOTPRINT;
|
class FOOTPRINT;
|
||||||
class BOARD_COMMIT;
|
class BOARD_COMMIT;
|
||||||
class CLEANUP_ITEM;
|
class CLEANUP_ITEM;
|
||||||
|
class TOOL_MANAGER;
|
||||||
|
|
||||||
|
|
||||||
// Helper class used to clean tracks and vias
|
// Helper class used to clean tracks and vias
|
||||||
class GRAPHICS_CLEANER
|
class GRAPHICS_CLEANER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootprint, BOARD_COMMIT& aCommit );
|
GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootprint, BOARD_COMMIT& aCommit,
|
||||||
|
TOOL_MANAGER* aToolManager );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the cleanup function.
|
* the cleanup function.
|
||||||
* @param aMergeRects = merge for segments forming a rectangle into a rect
|
* @param aMergeRects = merge for segments forming a rectangle into a rect
|
||||||
* @param aDeleteRedundant = true to delete null graphics and duplicated graphics
|
* @param aDeleteRedundant = true to delete null graphics and duplicated graphics
|
||||||
|
* @param aMergePads = true to apply Pad Editor's merge algorithm to all pads in footprint
|
||||||
|
* (it is assumed this will only be run on FPEditor boards)
|
||||||
*/
|
*/
|
||||||
void CleanupBoard( bool aDryRun, std::vector<std::shared_ptr<CLEANUP_ITEM> >* aItemsList,
|
void CleanupBoard( bool aDryRun, std::vector<std::shared_ptr<CLEANUP_ITEM> >* aItemsList,
|
||||||
bool aMergeRects, bool aDeleteRedundant );
|
bool aMergeRects, bool aDeleteRedundant, bool aMergePads );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isNullShape( PCB_SHAPE* aShape );
|
bool isNullShape( PCB_SHAPE* aShape );
|
||||||
|
@ -51,11 +55,13 @@ private:
|
||||||
|
|
||||||
void cleanupShapes();
|
void cleanupShapes();
|
||||||
void mergeRects();
|
void mergeRects();
|
||||||
|
void mergePads();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DRAWINGS& m_drawings;
|
DRAWINGS& m_drawings;
|
||||||
FOOTPRINT* m_parentFootprint; // nullptr if not in Footprint Editor
|
FOOTPRINT* m_parentFootprint; // nullptr if not in Footprint Editor
|
||||||
BOARD_COMMIT& m_commit;
|
BOARD_COMMIT& m_commit;
|
||||||
|
TOOL_MANAGER* m_toolMgr;
|
||||||
bool m_dryRun;
|
bool m_dryRun;
|
||||||
int m_epsilon;
|
int m_epsilon;
|
||||||
|
|
||||||
|
|
|
@ -577,7 +577,11 @@ int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
|
||||||
PAD* pad = dynamic_cast<PAD*>( frame()->GetItem( m_editPad ) );
|
PAD* pad = dynamic_cast<PAD*>( frame()->GetItem( m_editPad ) );
|
||||||
|
|
||||||
if( pad )
|
if( pad )
|
||||||
recombinePad( pad );
|
{
|
||||||
|
BOARD_COMMIT commit( frame() );
|
||||||
|
RecombinePad( pad, false, commit );
|
||||||
|
commit.Push( _( "Recombine pad" ) );
|
||||||
|
}
|
||||||
|
|
||||||
m_editPad = niluuid;
|
m_editPad = niluuid;
|
||||||
}
|
}
|
||||||
|
@ -698,14 +702,18 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PAD_TOOL::recombinePad( PAD* aPad )
|
std::vector<FP_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun, BOARD_COMMIT& aCommit )
|
||||||
{
|
{
|
||||||
int maxError = board()->GetDesignSettings().m_MaxError;
|
int maxError = board()->GetDesignSettings().m_MaxError;
|
||||||
|
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aPad->GetParentFootprint() );
|
||||||
|
|
||||||
// Don't leave an object in the point editor that might no longer exist after
|
// Don't leave an object in the point editor that might no longer exist after
|
||||||
// recombining the pad.
|
// recombining the pad.
|
||||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||||
|
|
||||||
|
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||||
|
item->ClearFlags( SKIP_STRUCT );
|
||||||
|
|
||||||
auto findNext =
|
auto findNext =
|
||||||
[&]( PCB_LAYER_ID aLayer ) -> FP_SHAPE*
|
[&]( PCB_LAYER_ID aLayer ) -> FP_SHAPE*
|
||||||
{
|
{
|
||||||
|
@ -713,11 +721,11 @@ void PAD_TOOL::recombinePad( PAD* aPad )
|
||||||
aPad->TransformShapeWithClearanceToPolygon( padPoly, aLayer, 0, maxError,
|
aPad->TransformShapeWithClearanceToPolygon( padPoly, aLayer, 0, maxError,
|
||||||
ERROR_INSIDE );
|
ERROR_INSIDE );
|
||||||
|
|
||||||
for( BOARD_ITEM* item : board()->GetFirstFootprint()->GraphicalItems() )
|
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||||
{
|
{
|
||||||
PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( item );
|
FP_SHAPE* shape = dynamic_cast<FP_SHAPE*>( item );
|
||||||
|
|
||||||
if( !shape || ( shape->GetEditFlags() & STRUCT_DELETED ) )
|
if( !shape || ( shape->GetFlags() & SKIP_STRUCT ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( shape->GetLayer() != aLayer )
|
if( shape->GetLayer() != aLayer )
|
||||||
|
@ -738,8 +746,30 @@ void PAD_TOOL::recombinePad( PAD* aPad )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
BOARD_COMMIT commit( frame() );
|
auto findMatching =
|
||||||
PCB_LAYER_ID layer;
|
[&]( FP_SHAPE* aShape ) -> std::vector<FP_SHAPE*>
|
||||||
|
{
|
||||||
|
std::vector<FP_SHAPE*> matching;
|
||||||
|
|
||||||
|
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||||
|
{
|
||||||
|
FP_SHAPE* other = dynamic_cast<FP_SHAPE*>( item );
|
||||||
|
|
||||||
|
if( !other || ( other->GetFlags() & SKIP_STRUCT ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( aPad->GetLayerSet().test( other->GetLayer() )
|
||||||
|
&& aShape->Compare( other ) == 0 )
|
||||||
|
{
|
||||||
|
matching.push_back( other );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matching;
|
||||||
|
};
|
||||||
|
|
||||||
|
PCB_LAYER_ID layer;
|
||||||
|
std::vector<FP_SHAPE*> mergedShapes;
|
||||||
|
|
||||||
if( aPad->IsOnLayer( F_Cu ) )
|
if( aPad->IsOnLayer( F_Cu ) )
|
||||||
layer = F_Cu;
|
layer = F_Cu;
|
||||||
|
@ -750,92 +780,116 @@ void PAD_TOOL::recombinePad( PAD* aPad )
|
||||||
|
|
||||||
while( FP_SHAPE* fpShape = findNext( layer ) )
|
while( FP_SHAPE* fpShape = findNext( layer ) )
|
||||||
{
|
{
|
||||||
commit.Modify( aPad );
|
// We've found an intersecting item to combine.
|
||||||
|
|
||||||
// We've found an intersecting item. First convert the pad to a custom-shape
|
|
||||||
// pad (if it isn't already)
|
|
||||||
//
|
//
|
||||||
if( aPad->GetShape() == PAD_SHAPE::RECT || aPad->GetShape() == PAD_SHAPE::CIRCLE )
|
fpShape->SetFlags( SKIP_STRUCT );
|
||||||
|
|
||||||
|
// First convert the pad to a custom-shape pad (if it isn't already)
|
||||||
|
//
|
||||||
|
if( !aIsDryRun )
|
||||||
{
|
{
|
||||||
aPad->SetAnchorPadShape( aPad->GetShape() );
|
aCommit.Modify( aPad );
|
||||||
|
|
||||||
|
if( aPad->GetShape() == PAD_SHAPE::RECT || aPad->GetShape() == PAD_SHAPE::CIRCLE )
|
||||||
|
{
|
||||||
|
aPad->SetAnchorPadShape( aPad->GetShape() );
|
||||||
|
}
|
||||||
|
else if( aPad->GetShape() != PAD_SHAPE::CUSTOM )
|
||||||
|
{
|
||||||
|
// Create a new minimally-sized circular anchor and convert existing pad
|
||||||
|
// to a polygon primitive
|
||||||
|
SHAPE_POLY_SET existingOutline;
|
||||||
|
aPad->TransformShapeWithClearanceToPolygon( existingOutline, layer, 0, maxError,
|
||||||
|
ERROR_INSIDE );
|
||||||
|
|
||||||
|
aPad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
|
||||||
|
if( aPad->GetSizeX() > aPad->GetSizeY() )
|
||||||
|
aPad->SetSizeX( aPad->GetSizeY() );
|
||||||
|
|
||||||
|
aPad->SetOffset( VECTOR2I( 0, 0 ) );
|
||||||
|
|
||||||
|
PCB_SHAPE* shape = new PCB_SHAPE( nullptr, SHAPE_T::POLY );
|
||||||
|
shape->SetFilled( true );
|
||||||
|
shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) );
|
||||||
|
shape->SetPolyShape( existingOutline );
|
||||||
|
shape->Move( - aPad->GetPosition() );
|
||||||
|
shape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
|
||||||
|
|
||||||
|
aPad->AddPrimitive( shape );
|
||||||
|
}
|
||||||
|
|
||||||
|
aPad->SetShape( PAD_SHAPE::CUSTOM );
|
||||||
}
|
}
|
||||||
else if( aPad->GetShape() != PAD_SHAPE::CUSTOM )
|
|
||||||
{
|
|
||||||
// Create a new minimally-sized circular anchor and convert existing pad
|
|
||||||
// to a polygon primitive
|
|
||||||
SHAPE_POLY_SET existingOutline;
|
|
||||||
aPad->TransformShapeWithClearanceToPolygon( existingOutline, layer, 0, maxError,
|
|
||||||
ERROR_INSIDE );
|
|
||||||
|
|
||||||
aPad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
|
|
||||||
if( aPad->GetSizeX() > aPad->GetSizeY() )
|
|
||||||
aPad->SetSizeX( aPad->GetSizeY() );
|
|
||||||
|
|
||||||
aPad->SetOffset( VECTOR2I( 0, 0 ) );
|
|
||||||
|
|
||||||
PCB_SHAPE* shape = new PCB_SHAPE( nullptr, SHAPE_T::POLY );
|
|
||||||
shape->SetFilled( true );
|
|
||||||
shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) );
|
|
||||||
shape->SetPolyShape( existingOutline );
|
|
||||||
shape->Move( - aPad->GetPosition() );
|
|
||||||
shape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
|
|
||||||
|
|
||||||
aPad->AddPrimitive( shape );
|
|
||||||
}
|
|
||||||
|
|
||||||
aPad->SetShape( PAD_SHAPE::CUSTOM );
|
|
||||||
|
|
||||||
// Now add the new shape to the primitives list
|
// Now add the new shape to the primitives list
|
||||||
//
|
//
|
||||||
PCB_SHAPE* pcbShape = new PCB_SHAPE;
|
mergedShapes.push_back( fpShape );
|
||||||
|
|
||||||
pcbShape->SetShape( fpShape->GetShape() );
|
if( !aIsDryRun )
|
||||||
pcbShape->SetFilled( fpShape->IsFilled() );
|
|
||||||
pcbShape->SetStroke( fpShape->GetStroke() );
|
|
||||||
|
|
||||||
|
|
||||||
switch( pcbShape->GetShape() )
|
|
||||||
{
|
{
|
||||||
case SHAPE_T::SEGMENT:
|
PCB_SHAPE* pcbShape = new PCB_SHAPE;
|
||||||
case SHAPE_T::RECT:
|
|
||||||
case SHAPE_T::CIRCLE:
|
|
||||||
pcbShape->SetStart( fpShape->GetStart() );
|
|
||||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SHAPE_T::ARC:
|
pcbShape->SetShape( fpShape->GetShape() );
|
||||||
pcbShape->SetStart( fpShape->GetStart() );
|
pcbShape->SetFilled( fpShape->IsFilled() );
|
||||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
pcbShape->SetStroke( fpShape->GetStroke() );
|
||||||
pcbShape->SetCenter( fpShape->GetCenter() );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SHAPE_T::BEZIER:
|
switch( pcbShape->GetShape() )
|
||||||
pcbShape->SetStart( fpShape->GetStart() );
|
{
|
||||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
case SHAPE_T::SEGMENT:
|
||||||
pcbShape->SetBezierC1( fpShape->GetBezierC1() );
|
case SHAPE_T::RECT:
|
||||||
pcbShape->SetBezierC2( fpShape->GetBezierC2() );
|
case SHAPE_T::CIRCLE:
|
||||||
break;
|
pcbShape->SetStart( fpShape->GetStart() );
|
||||||
|
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||||
|
break;
|
||||||
|
|
||||||
case SHAPE_T::POLY:
|
case SHAPE_T::ARC:
|
||||||
pcbShape->SetPolyShape( fpShape->GetPolyShape() );
|
pcbShape->SetStart( fpShape->GetStart() );
|
||||||
break;
|
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||||
|
pcbShape->SetCenter( fpShape->GetCenter() );
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
case SHAPE_T::BEZIER:
|
||||||
UNIMPLEMENTED_FOR( pcbShape->SHAPE_T_asString() );
|
pcbShape->SetStart( fpShape->GetStart() );
|
||||||
|
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||||
|
pcbShape->SetBezierC1( fpShape->GetBezierC1() );
|
||||||
|
pcbShape->SetBezierC2( fpShape->GetBezierC2() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHAPE_T::POLY:
|
||||||
|
pcbShape->SetPolyShape( fpShape->GetPolyShape() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UNIMPLEMENTED_FOR( pcbShape->SHAPE_T_asString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
pcbShape->Move( - aPad->GetPosition() );
|
||||||
|
pcbShape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
|
||||||
|
pcbShape->SetIsAnnotationProxy( fpShape->IsAnnotationProxy());
|
||||||
|
aPad->AddPrimitive( pcbShape );
|
||||||
|
|
||||||
|
aCommit.Remove( fpShape );
|
||||||
}
|
}
|
||||||
|
|
||||||
pcbShape->Move( - aPad->GetPosition() );
|
// See if there are other shapes that match and mark them for delete. (KiCad won't
|
||||||
pcbShape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
|
// produce these, but old footprints from other vendors have them.)
|
||||||
pcbShape->SetIsAnnotationProxy( fpShape->IsAnnotationProxy());
|
for( FP_SHAPE* other : findMatching( fpShape ) )
|
||||||
aPad->AddPrimitive( pcbShape );
|
{
|
||||||
|
other->SetFlags( SKIP_STRUCT );
|
||||||
|
mergedShapes.push_back( other );
|
||||||
|
|
||||||
fpShape->SetFlags( STRUCT_DELETED );
|
if( !aIsDryRun )
|
||||||
commit.Remove( fpShape );
|
aCommit.Remove( other );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aPad->ClearFlags( ENTERED );
|
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||||
|
item->ClearFlags( SKIP_STRUCT );
|
||||||
|
|
||||||
commit.Push( _( "Recombine pads" ) );
|
if( !aIsDryRun )
|
||||||
|
aPad->ClearFlags( ENTERED );
|
||||||
|
|
||||||
|
return mergedShapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <tools/pcb_tool_base.h>
|
#include <tools/pcb_tool_base.h>
|
||||||
|
|
||||||
class ACTION_MENU;
|
class ACTION_MENU;
|
||||||
|
class FP_SHAPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tool relating to pads and pad settings.
|
* Tool relating to pads and pad settings.
|
||||||
|
@ -64,6 +65,15 @@ public:
|
||||||
wxString GetLastPadNumber() const { return m_lastPadNumber; }
|
wxString GetLastPadNumber() const { return m_lastPadNumber; }
|
||||||
void SetLastPadNumber( const wxString& aPadNumber ) { m_lastPadNumber = aPadNumber; }
|
void SetLastPadNumber( const wxString& aPadNumber ) { m_lastPadNumber = aPadNumber; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recombine an exploded pad (or one produced with overlapping polygons in an older version).
|
||||||
|
* @param aPad the pad to run the recombination algorithm on
|
||||||
|
* @param aIsDryRun if true the list will be generated but no changes will be made
|
||||||
|
* @param aCommit the commit to add any changes to
|
||||||
|
* @return a list of FP_SHAPEs that will be combined
|
||||||
|
*/
|
||||||
|
std::vector<FP_SHAPE*> RecombinePad( PAD* aPad, bool aIsDryRun, BOARD_COMMIT& aCommit );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///< Bind handlers to corresponding TOOL_ACTIONs.
|
///< Bind handlers to corresponding TOOL_ACTIONs.
|
||||||
void setTransitions() override;
|
void setTransitions() override;
|
||||||
|
@ -78,8 +88,8 @@ private:
|
||||||
int pushPadSettings( const TOOL_EVENT& aEvent );
|
int pushPadSettings( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
PCB_LAYER_ID explodePad( PAD* aPad );
|
PCB_LAYER_ID explodePad( PAD* aPad );
|
||||||
void recombinePad( PAD* aPad );
|
|
||||||
|
|
||||||
|
private:
|
||||||
wxString m_lastPadNumber;
|
wxString m_lastPadNumber;
|
||||||
|
|
||||||
bool m_wasHighContrast;
|
bool m_wasHighContrast;
|
||||||
|
|
Loading…
Reference in New Issue