Add ignore-line-widths mode to CONVERT_TOOL.

Fixes https://gitlab.com/kicad/code/kicad/issues/5911
This commit is contained in:
Jeff Young 2022-07-29 20:56:55 +01:00
parent 3245aec5b5
commit f0b9e67212
8 changed files with 407 additions and 109 deletions

View File

@ -247,7 +247,19 @@ public:
*/ */
bool IsPolyShapeValid() const; bool IsPolyShapeValid() const;
void SetPolyShape( const SHAPE_POLY_SET& aShape ) { m_poly = aShape; } void SetPolyShape( const SHAPE_POLY_SET& aShape )
{
m_poly = aShape;
for( int ii = 0; ii < m_poly.OutlineCount(); ++ii )
{
if( m_poly.HoleCount( ii ) )
{
m_poly.Fracture( SHAPE_POLY_SET::PM_FAST );
break;
}
}
}
void SetPolyPoints( const std::vector<VECTOR2I>& aPoints ); void SetPolyPoints( const std::vector<VECTOR2I>& aPoints );

View File

@ -28,7 +28,6 @@
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <pcbnew_settings.h> #include <pcbnew_settings.h>
#include <zones.h> #include <zones.h>
#include <bitmaps.h>
#include <widgets/unit_binder.h> #include <widgets/unit_binder.h>
#include <zone.h> #include <zone.h>
#include <pad.h> #include <pad.h>
@ -43,7 +42,8 @@
class DIALOG_COPPER_ZONE : public DIALOG_COPPER_ZONE_BASE class DIALOG_COPPER_ZONE : public DIALOG_COPPER_ZONE_BASE
{ {
public: public:
DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings ); DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings );
private: private:
using NET_FILTER = std::unique_ptr<EDA_PATTERN_MATCH>; using NET_FILTER = std::unique_ptr<EDA_PATTERN_MATCH>;
@ -56,36 +56,6 @@ private:
static constexpr int HIDE_ANONYMOUS_NETS{ 1 << 0 }; static constexpr int HIDE_ANONYMOUS_NETS{ 1 << 0 };
static constexpr int SORT_BY_PAD_COUNT{ 1 << 1 }; static constexpr int SORT_BY_PAD_COUNT{ 1 << 1 };
PCB_BASE_FRAME* m_Parent;
bool m_settingsExported; // settings will be written to all other zones
ZONE_SETTINGS m_settings;
ZONE_SETTINGS* m_ptr;
bool m_netSortingByPadCount;
NET_FILTER_LIST m_showNetsFilter;
int m_cornerSmoothingType;
int m_maxNetCode;
int m_currentlySelectedNetcode;
UNIT_BINDER m_outlineHatchPitch;
UNIT_BINDER m_cornerRadius;
UNIT_BINDER m_clearance;
UNIT_BINDER m_minWidth;
UNIT_BINDER m_antipadClearance;
UNIT_BINDER m_spokeWidth;
UNIT_BINDER m_gridStyleRotation;
UNIT_BINDER m_gridStyleThickness;
UNIT_BINDER m_gridStyleGap;
UNIT_BINDER m_islandThreshold;
bool m_hideAutoGeneratedNets;
bool m_isTeardrop;
std::map<wxString, int> m_netNameToNetCode;
std::vector<NETINFO_ITEM*> m_netInfoItemList;
bool TransferDataToWindow() override; bool TransferDataToWindow() override;
bool TransferDataFromWindow() override; bool TransferDataFromWindow() override;
@ -127,12 +97,48 @@ private:
void handleRemoveIslandsSelection(); void handleRemoveIslandsSelection();
void storePersistentNetSortConfigurations(); void storePersistentNetSortConfigurations();
void loadPersistentNetSortConfigurations(); void loadPersistentNetSortConfigurations();
private:
PCB_BASE_FRAME* m_Parent;
bool m_settingsExported; // settings will be written to all other zones
ZONE_SETTINGS m_settings;
ZONE_SETTINGS* m_ptr;
bool m_netSortingByPadCount;
NET_FILTER_LIST m_showNetsFilter;
int m_cornerSmoothingType;
int m_maxNetCode;
int m_currentlySelectedNetcode;
UNIT_BINDER m_outlineHatchPitch;
UNIT_BINDER m_cornerRadius;
UNIT_BINDER m_clearance;
UNIT_BINDER m_minWidth;
UNIT_BINDER m_antipadClearance;
UNIT_BINDER m_spokeWidth;
UNIT_BINDER m_gridStyleRotation;
UNIT_BINDER m_gridStyleThickness;
UNIT_BINDER m_gridStyleGap;
UNIT_BINDER m_islandThreshold;
bool m_hideAutoGeneratedNets;
bool m_isTeardrop;
std::map<wxString, int> m_netNameToNetCode;
std::vector<NETINFO_ITEM*> m_netInfoItemList;
CONVERT_SETTINGS* m_convertSettings;
wxCheckBox* m_cbIgnoreLineWidths;
wxCheckBox* m_cbDeleteOriginals;
}; };
int InvokeCopperZonesEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings ) int InvokeCopperZonesEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings )
{ {
DIALOG_COPPER_ZONE dlg( aCaller, aSettings ); DIALOG_COPPER_ZONE dlg( aCaller, aSettings, aConvertSettings );
return dlg.ShowQuasiModal(); return dlg.ShowQuasiModal();
} }
@ -164,7 +170,8 @@ static bool sortNetsByNames( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
} }
DIALOG_COPPER_ZONE::DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings ) : DIALOG_COPPER_ZONE::DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings ) :
DIALOG_COPPER_ZONE_BASE( aParent ), DIALOG_COPPER_ZONE_BASE( aParent ),
m_cornerSmoothingType( ZONE_SETTINGS::SMOOTHING_UNDEFINED ), m_cornerSmoothingType( ZONE_SETTINGS::SMOOTHING_UNDEFINED ),
m_outlineHatchPitch( aParent, m_stBorderHatchPitchText, m_outlineHatchPitch( aParent, m_stBorderHatchPitchText,
@ -181,7 +188,8 @@ DIALOG_COPPER_ZONE::DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS*
m_gridStyleGap( aParent, m_staticTextGridGap, m_tcGridStyleGap, m_GridStyleGapUnits ), m_gridStyleGap( aParent, m_staticTextGridGap, m_tcGridStyleGap, m_GridStyleGapUnits ),
m_islandThreshold( aParent, m_islandThresholdLabel, m_tcIslandThreshold, m_islandThreshold( aParent, m_islandThresholdLabel, m_tcIslandThreshold,
m_islandThresholdUnits ), m_islandThresholdUnits ),
m_hideAutoGeneratedNets{ false } m_hideAutoGeneratedNets{ false },
m_convertSettings( aConvertSettings )
{ {
m_Parent = aParent; m_Parent = aParent;
@ -211,6 +219,29 @@ DIALOG_COPPER_ZONE::DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS*
break; break;
} }
if( aConvertSettings )
{
wxStaticBox* bConvertBox = new wxStaticBox( this, wxID_ANY,
_( "Conversion Settings" ) );
wxStaticBoxSizer* bConvertSizer = new wxStaticBoxSizer( bConvertBox, wxVERTICAL );
m_cbIgnoreLineWidths = new wxCheckBox( this, wxID_ANY,
_( "Ignore source object line widths" ) );
bConvertSizer->Add( m_cbIgnoreLineWidths, 0, wxLEFT|wxRIGHT, 5 );
m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
_( "Delete source objects after conversion" ) );
bConvertSizer->Add( m_cbDeleteOriginals, 0, wxALL, 5 );
GetSizer()->Insert( 0, bConvertSizer, 0, wxALL|wxEXPAND, 10 );
wxStaticLine* line = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxLI_HORIZONTAL );
GetSizer()->Insert( 1, line, 0, wxLEFT|wxRIGHT|wxEXPAND, 10 );
SetTitle( _( "Convert to Copper Zone" ) );
}
m_settingsExported = false; m_settingsExported = false;
m_currentlySelectedNetcode = INVALID_NET_CODE; m_currentlySelectedNetcode = INVALID_NET_CODE;
m_maxNetCode = INVALID_NET_CODE; m_maxNetCode = INVALID_NET_CODE;
@ -238,6 +269,12 @@ DIALOG_COPPER_ZONE::DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS*
bool DIALOG_COPPER_ZONE::TransferDataToWindow() bool DIALOG_COPPER_ZONE::TransferDataToWindow()
{ {
if( m_convertSettings )
{
m_cbIgnoreLineWidths->SetValue( m_convertSettings->m_IgnoreLineWidths );
m_cbDeleteOriginals->SetValue( m_convertSettings->m_DeleteOriginals );
}
m_cbLocked->SetValue( m_settings.m_Locked ); m_cbLocked->SetValue( m_settings.m_Locked );
m_cornerSmoothingChoice->SetSelection( m_settings.GetCornerSmoothingType() ); m_cornerSmoothingChoice->SetSelection( m_settings.GetCornerSmoothingType() );
m_cornerRadius.SetValue( m_settings.GetCornerRadius() ); m_cornerRadius.SetValue( m_settings.GetCornerRadius() );
@ -461,6 +498,12 @@ bool DIALOG_COPPER_ZONE::TransferDataFromWindow()
if( !AcceptOptions() ) if( !AcceptOptions() )
return false; return false;
if( m_convertSettings )
{
m_convertSettings->m_IgnoreLineWidths = m_cbIgnoreLineWidths->GetValue();
m_convertSettings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
}
m_settings.m_HatchOrientation = m_gridStyleRotation.GetAngleValue(); m_settings.m_HatchOrientation = m_gridStyleRotation.GetAngleValue();
m_settings.m_HatchThickness = m_gridStyleThickness.GetValue(); m_settings.m_HatchThickness = m_gridStyleThickness.GetValue();
m_settings.m_HatchGap = m_gridStyleGap.GetValue(); m_settings.m_HatchGap = m_gridStyleGap.GetValue();
@ -917,12 +960,14 @@ wxString DIALOG_COPPER_ZONE::getUnescapedNetName( const NETINFO_ITEM* net )
void DIALOG_COPPER_ZONE::updateInfoBar() void DIALOG_COPPER_ZONE::updateInfoBar()
{ {
if( m_currentlySelectedNetcode <= INVALID_NET_CODE && !m_copperZoneInfo->IsShown() ) if( m_currentlySelectedNetcode <= INVALID_NET_CODE
&& !m_copperZoneInfo->IsShown()
&& !m_convertSettings )
{ {
m_copperZoneInfo->ShowMessage( m_copperZoneInfo->ShowMessage( _( "<no net> will result in an isolated copper island." ),
_( "Selecting <no net> will create an isolated copper island." ), wxICON_WARNING ); wxICON_WARNING );
} }
else if( m_currentlySelectedNetcode > INVALID_NET_CODE && m_copperZoneInfo->IsShown() ) else if( m_copperZoneInfo->IsShown() )
{ {
m_copperZoneInfo->Dismiss(); m_copperZoneInfo->Dismiss();
} }

View File

@ -28,6 +28,7 @@
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <pcbnew_settings.h> #include <pcbnew_settings.h>
#include <widgets/unit_binder.h> #include <widgets/unit_binder.h>
#include <wx/statbox.h>
#include <zones.h> #include <zones.h>
#include <dialog_non_copper_zones_properties_base.h> #include <dialog_non_copper_zones_properties_base.h>
@ -35,18 +36,11 @@
class DIALOG_NON_COPPER_ZONES_EDITOR : public DIALOG_NONCOPPER_ZONES_PROPERTIES_BASE class DIALOG_NON_COPPER_ZONES_EDITOR : public DIALOG_NONCOPPER_ZONES_PROPERTIES_BASE
{ {
private: public:
PCB_BASE_FRAME* m_parent; DIALOG_NON_COPPER_ZONES_EDITOR( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings,
ZONE_SETTINGS* m_ptr; CONVERT_SETTINGS* aConvertSettings );
ZONE_SETTINGS m_settings; // working copy of zone settings
UNIT_BINDER m_outlineHatchPitch;
UNIT_BINDER m_minWidth;
UNIT_BINDER m_hatchRotation;
UNIT_BINDER m_hatchWidth;
UNIT_BINDER m_hatchGap;
int m_cornerSmoothingType;
UNIT_BINDER m_cornerRadius;
private:
bool TransferDataToWindow() override; bool TransferDataToWindow() override;
bool TransferDataFromWindow() override; bool TransferDataFromWindow() override;
@ -54,14 +48,28 @@ private:
void OnLayerSelection( wxDataViewEvent& event ) override; void OnLayerSelection( wxDataViewEvent& event ) override;
void OnUpdateUI( wxUpdateUIEvent& ) override; void OnUpdateUI( wxUpdateUIEvent& ) override;
public: private:
DIALOG_NON_COPPER_ZONES_EDITOR( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings ); PCB_BASE_FRAME* m_parent;
ZONE_SETTINGS* m_ptr;
ZONE_SETTINGS m_settings; // working copy of zone settings
UNIT_BINDER m_outlineHatchPitch;
UNIT_BINDER m_minWidth;
UNIT_BINDER m_hatchRotation;
UNIT_BINDER m_hatchWidth;
UNIT_BINDER m_hatchGap;
int m_cornerSmoothingType;
UNIT_BINDER m_cornerRadius;
CONVERT_SETTINGS* m_convertSettings;
wxCheckBox* m_cbIgnoreLineWidths;
wxCheckBox* m_cbDeleteOriginals;
}; };
int InvokeNonCopperZonesEditor( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings ) int InvokeNonCopperZonesEditor( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings )
{ {
DIALOG_NON_COPPER_ZONES_EDITOR dlg( aParent, aSettings ); DIALOG_NON_COPPER_ZONES_EDITOR dlg( aParent, aSettings, aConvertSettings );
return dlg.ShowQuasiModal(); return dlg.ShowQuasiModal();
} }
@ -69,7 +77,8 @@ int InvokeNonCopperZonesEditor( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSetting
#define MIN_THICKNESS 10*IU_PER_MILS #define MIN_THICKNESS 10*IU_PER_MILS
DIALOG_NON_COPPER_ZONES_EDITOR::DIALOG_NON_COPPER_ZONES_EDITOR( PCB_BASE_FRAME* aParent, DIALOG_NON_COPPER_ZONES_EDITOR::DIALOG_NON_COPPER_ZONES_EDITOR( PCB_BASE_FRAME* aParent,
ZONE_SETTINGS* aSettings ) : ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings ) :
DIALOG_NONCOPPER_ZONES_PROPERTIES_BASE( aParent ), DIALOG_NONCOPPER_ZONES_PROPERTIES_BASE( aParent ),
m_outlineHatchPitch( aParent, m_stBorderHatchPitchText, m_outlineHatchPitch( aParent, m_stBorderHatchPitchText,
m_outlineHatchPitchCtrl, m_outlineHatchUnits ), m_outlineHatchPitchCtrl, m_outlineHatchUnits ),
@ -78,15 +87,41 @@ DIALOG_NON_COPPER_ZONES_EDITOR::DIALOG_NON_COPPER_ZONES_EDITOR( PCB_BASE_FRAME*
m_hatchWidth( aParent, m_hatchWidthLabel, m_hatchWidthCtrl, m_hatchWidthUnits), m_hatchWidth( aParent, m_hatchWidthLabel, m_hatchWidthCtrl, m_hatchWidthUnits),
m_hatchGap( aParent, m_hatchGapLabel, m_hatchGapCtrl, m_hatchGapUnits ), m_hatchGap( aParent, m_hatchGapLabel, m_hatchGapCtrl, m_hatchGapUnits ),
m_cornerSmoothingType( ZONE_SETTINGS::SMOOTHING_UNDEFINED ), m_cornerSmoothingType( ZONE_SETTINGS::SMOOTHING_UNDEFINED ),
m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ) m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
m_convertSettings( aConvertSettings )
{ {
m_parent = aParent; m_parent = aParent;
m_ptr = aSettings; m_ptr = aSettings;
m_settings = *aSettings; m_settings = *aSettings;
if( aConvertSettings )
{
wxStaticBox* bConvertBox = new wxStaticBox( this, wxID_ANY,
_( "Conversion Settings" ) );
wxStaticBoxSizer* bConvertSizer = new wxStaticBoxSizer( bConvertBox, wxVERTICAL );
m_cbIgnoreLineWidths = new wxCheckBox( this, wxID_ANY,
_( "Ignore source object line widths" ) );
bConvertSizer->Add( m_cbIgnoreLineWidths, 0, wxLEFT|wxRIGHT, 5 );
m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
_( "Delete source objects after conversion" ) );
bConvertSizer->Add( m_cbDeleteOriginals, 0, wxALL, 5 );
GetSizer()->Insert( 0, bConvertSizer, 0, wxALL|wxEXPAND, 10 );
wxStaticLine* line = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxLI_HORIZONTAL );
GetSizer()->Insert( 1, line, 0, wxLEFT|wxRIGHT|wxEXPAND, 10 );
SetTitle( _( "Convert to Non Copper Zone" ) );
}
bool fpEditorMode = m_parent->IsType( FRAME_FOOTPRINT_EDITOR ); bool fpEditorMode = m_parent->IsType( FRAME_FOOTPRINT_EDITOR );
m_staticTextLayerSelection->SetFont( KIUI::GetInfoFont( this ) );
m_settings.SetupLayersList( m_layers, m_parent, LSET::AllNonCuMask(), fpEditorMode ); m_settings.SetupLayersList( m_layers, m_parent, LSET::AllNonCuMask(), fpEditorMode );
SetupStandardButtons(); SetupStandardButtons();
@ -113,6 +148,12 @@ void DIALOG_NON_COPPER_ZONES_EDITOR::OnUpdateUI( wxUpdateUIEvent& )
bool DIALOG_NON_COPPER_ZONES_EDITOR::TransferDataToWindow() bool DIALOG_NON_COPPER_ZONES_EDITOR::TransferDataToWindow()
{ {
if( m_convertSettings )
{
m_cbIgnoreLineWidths->SetValue( m_convertSettings->m_IgnoreLineWidths );
m_cbDeleteOriginals->SetValue( m_convertSettings->m_DeleteOriginals );
}
m_cornerSmoothingChoice->SetSelection( m_settings.GetCornerSmoothingType() ); m_cornerSmoothingChoice->SetSelection( m_settings.GetCornerSmoothingType() );
m_cornerRadius.SetValue( m_settings.GetCornerRadius() ); m_cornerRadius.SetValue( m_settings.GetCornerRadius() );
@ -199,6 +240,12 @@ void DIALOG_NON_COPPER_ZONES_EDITOR::OnLayerSelection( wxDataViewEvent& event )
bool DIALOG_NON_COPPER_ZONES_EDITOR::TransferDataFromWindow() bool DIALOG_NON_COPPER_ZONES_EDITOR::TransferDataFromWindow()
{ {
if( m_convertSettings )
{
m_convertSettings->m_IgnoreLineWidths = m_cbIgnoreLineWidths->GetValue();
m_convertSettings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
}
m_settings.SetCornerSmoothingType( m_cornerSmoothingChoice->GetSelection() ); m_settings.SetCornerSmoothingType( m_cornerSmoothingChoice->GetSelection() );
m_settings.SetCornerRadius( m_settings.GetCornerSmoothingType() == ZONE_SETTINGS::SMOOTHING_NONE m_settings.SetCornerRadius( m_settings.GetCornerSmoothingType() == ZONE_SETTINGS::SMOOTHING_NONE

View File

@ -30,6 +30,7 @@
#include <zone_settings.h> #include <zone_settings.h>
#include <dialog_rule_area_properties_base.h> #include <dialog_rule_area_properties_base.h>
#include <widgets/unit_binder.h> #include <widgets/unit_binder.h>
#include <wx/statbox.h>
#define LAYER_LIST_COLUMN_CHECK 0 #define LAYER_LIST_COLUMN_CHECK 0
#define LAYER_LIST_COLUMN_ICON 1 #define LAYER_LIST_COLUMN_ICON 1
@ -40,36 +41,44 @@
class DIALOG_RULE_AREA_PROPERTIES : public DIALOG_RULE_AREA_PROPERTIES_BASE class DIALOG_RULE_AREA_PROPERTIES : public DIALOG_RULE_AREA_PROPERTIES_BASE
{ {
public: public:
DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings ); DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings );
private: private:
UNIT_BINDER m_outlineHatchPitch;
PCB_BASE_FRAME* m_parent;
ZONE_SETTINGS m_zonesettings; ///< the working copy of zone settings
ZONE_SETTINGS* m_ptr; ///< the pointer to the zone settings
///< of the zone to edit
bool m_isFpEditor;
bool TransferDataToWindow() override; bool TransferDataToWindow() override;
bool TransferDataFromWindow() override; bool TransferDataFromWindow() override;
void OnLayerSelection( wxDataViewEvent& event ) override; void OnLayerSelection( wxDataViewEvent& event ) override;
private:
UNIT_BINDER m_outlineHatchPitch;
PCB_BASE_FRAME* m_parent;
ZONE_SETTINGS m_zonesettings; ///< the working copy of zone settings
ZONE_SETTINGS* m_ptr; ///< the pointer to the zone settings of the zone to edit
bool m_isFpEditor;
CONVERT_SETTINGS* m_convertSettings;
wxCheckBox* m_cbIgnoreLineWidths;
wxCheckBox* m_cbDeleteOriginals;
}; };
int InvokeRuleAreaEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings ) int InvokeRuleAreaEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aZoneSettings,
CONVERT_SETTINGS* aConvertSettings )
{ {
DIALOG_RULE_AREA_PROPERTIES dlg( aCaller, aSettings ); DIALOG_RULE_AREA_PROPERTIES dlg( aCaller, aZoneSettings, aConvertSettings );
return dlg.ShowModal(); return dlg.ShowModal();
} }
DIALOG_RULE_AREA_PROPERTIES::DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aParent, DIALOG_RULE_AREA_PROPERTIES::DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aParent,
ZONE_SETTINGS* aSettings ) : ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings ) :
DIALOG_RULE_AREA_PROPERTIES_BASE( aParent ), DIALOG_RULE_AREA_PROPERTIES_BASE( aParent ),
m_outlineHatchPitch( aParent, m_stBorderHatchPitchText, m_outlineHatchPitch( aParent, m_stBorderHatchPitchText,
m_outlineHatchPitchCtrl, m_outlineHatchUnits ) m_outlineHatchPitchCtrl, m_outlineHatchUnits ),
m_convertSettings( aConvertSettings )
{ {
m_parent = aParent; m_parent = aParent;
@ -77,6 +86,31 @@ DIALOG_RULE_AREA_PROPERTIES::DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aParen
m_ptr = aSettings; m_ptr = aSettings;
m_zonesettings = *aSettings; m_zonesettings = *aSettings;
if( aConvertSettings )
{
wxBoxSizer* bConvertSizer = new wxBoxSizer( wxVERTICAL );
wxStaticText* conversionSettingsLabel = new wxStaticText( this, wxID_ANY,
_( "Conversion settings:" ) );
bConvertSizer->Add( conversionSettingsLabel, 0, wxLEFT|wxRIGHT|wxEXPAND, 5 );
m_cbIgnoreLineWidths = new wxCheckBox( this, wxID_ANY,
_( "Ignore source object line widths" ) );
bConvertSizer->Add( m_cbIgnoreLineWidths, 0, wxLEFT|wxRIGHT|wxTOP, 5 );
m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
_( "Delete source objects after conversion" ) );
bConvertSizer->Add( m_cbDeleteOriginals, 0, wxALL, 5 );
GetSizer()->Insert( 0, bConvertSizer, 0, wxALL|wxEXPAND, 10 );
wxStaticLine* line = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxLI_HORIZONTAL );
GetSizer()->Insert( 1, line, 0, wxLEFT|wxRIGHT|wxEXPAND, 10 );
SetTitle( _( "Convert to Rule Area" ) );
}
m_isFpEditor = m_parent->IsType( FRAME_FOOTPRINT_EDITOR ); m_isFpEditor = m_parent->IsType( FRAME_FOOTPRINT_EDITOR );
BOARD* board = m_parent->GetBoard(); BOARD* board = m_parent->GetBoard();
@ -92,6 +126,12 @@ DIALOG_RULE_AREA_PROPERTIES::DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aParen
bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow() bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow()
{ {
if( m_convertSettings )
{
m_cbIgnoreLineWidths->SetValue( m_convertSettings->m_IgnoreLineWidths );
m_cbDeleteOriginals->SetValue( m_convertSettings->m_DeleteOriginals );
}
// Init keepout parameters: // Init keepout parameters:
m_cbTracksCtrl->SetValue( m_zonesettings.GetDoNotAllowTracks() ); m_cbTracksCtrl->SetValue( m_zonesettings.GetDoNotAllowTracks() );
m_cbViasCtrl->SetValue( m_zonesettings.GetDoNotAllowVias() ); m_cbViasCtrl->SetValue( m_zonesettings.GetDoNotAllowVias() );
@ -147,6 +187,12 @@ void DIALOG_RULE_AREA_PROPERTIES::OnLayerSelection( wxDataViewEvent& event )
bool DIALOG_RULE_AREA_PROPERTIES::TransferDataFromWindow() bool DIALOG_RULE_AREA_PROPERTIES::TransferDataFromWindow()
{ {
if( m_convertSettings )
{
m_convertSettings->m_IgnoreLineWidths = m_cbIgnoreLineWidths->GetValue();
m_convertSettings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
}
// Init keepout parameters: // Init keepout parameters:
m_zonesettings.SetIsRuleArea( true ); m_zonesettings.SetIsRuleArea( true );
m_zonesettings.SetDoNotAllowTracks( m_cbTracksCtrl->GetValue() ); m_zonesettings.SetDoNotAllowTracks( m_cbTracksCtrl->GetValue() );

View File

@ -31,6 +31,15 @@ namespace PNS
} }
// Settings for the CONVERT_TOOL.
struct CONVERT_SETTINGS
{
bool m_IgnoreLineWidths;
bool m_DeleteOriginals;
};
enum class MAGNETIC_OPTIONS enum class MAGNETIC_OPTIONS
{ {
NO_EFFECT = 0, NO_EFFECT = 0,

View File

@ -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) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* @author Jon Evans <jon@craftyjon.com> * @author Jon Evans <jon@craftyjon.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -23,6 +23,10 @@
*/ */
#include <bitmaps.h> #include <bitmaps.h>
#include <dialog_shim.h>
#include <wx/statline.h>
#include <wx/checkbox.h>
#include <wx/button.h>
#include <board.h> #include <board.h>
#include <board_commit.h> #include <board_commit.h>
#include <board_design_settings.h> #include <board_design_settings.h>
@ -33,7 +37,6 @@
#include <footprint_edit_frame.h> #include <footprint_edit_frame.h>
#include <fp_shape.h> #include <fp_shape.h>
#include <geometry/shape_compound.h> #include <geometry/shape_compound.h>
#include <menus_helpers.h>
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <pcb_shape.h> #include <pcb_shape.h>
#include <pcb_track.h> #include <pcb_track.h>
@ -47,6 +50,75 @@
#include "convert_tool.h" #include "convert_tool.h"
class CONVERT_SETTINGS_DIALOG : public DIALOG_SHIM
{
public:
CONVERT_SETTINGS_DIALOG( wxWindow* aParent, CONVERT_SETTINGS* aSettings ) :
DIALOG_SHIM( aParent, wxID_ANY, _( "Conversion Settings" ), wxDefaultPosition,
wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
m_settings( aSettings )
{
wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
SetSizer( mainSizer );
m_cbIgnoreLineWidths = new wxCheckBox( this, wxID_ANY,
_( "Ignore source object line widths" ) );
topSizer->Add( m_cbIgnoreLineWidths, 0, wxLEFT|wxRIGHT, 5 );
m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
_( "Delete source objects after conversion" ) );
topSizer->Add( m_cbDeleteOriginals, 0, wxALL, 5 );
wxStaticLine* line = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxLI_HORIZONTAL );
topSizer->Add( line, 0, wxLEFT|wxRIGHT|wxTOP|wxEXPAND, 5 );
mainSizer->Add( topSizer, 1, wxALL|wxEXPAND, 10 );
wxBoxSizer* buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
buttonsSizer->AddStretchSpacer();
wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
wxButton* sdbSizerOK = new wxButton( this, wxID_OK );
sdbSizer->AddButton( sdbSizerOK );
wxButton* sdbSizerCancel = new wxButton( this, wxID_CANCEL );
sdbSizer->AddButton( sdbSizerCancel );
sdbSizer->Realize();
buttonsSizer->Add( sdbSizer, 1, 0, 5 );
mainSizer->Add( buttonsSizer, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 5 );
SetupStandardButtons();
finishDialogSettings();
}
~CONVERT_SETTINGS_DIALOG()
{};
protected:
bool TransferDataToWindow() override
{
m_cbIgnoreLineWidths->SetValue( m_settings->m_IgnoreLineWidths );
m_cbDeleteOriginals->SetValue( m_settings->m_DeleteOriginals );
return true;
}
bool TransferDataFromWindow() override
{
m_settings->m_IgnoreLineWidths = m_cbIgnoreLineWidths->GetValue();
m_settings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
return true;
}
private:
CONVERT_SETTINGS* m_settings;
wxCheckBox* m_cbIgnoreLineWidths;
wxCheckBox* m_cbDeleteOriginals;
};
CONVERT_TOOL::CONVERT_TOOL() : CONVERT_TOOL::CONVERT_TOOL() :
TOOL_INTERACTIVE( "pcbnew.Convert" ), TOOL_INTERACTIVE( "pcbnew.Convert" ),
m_selectionTool( nullptr ), m_selectionTool( nullptr ),
@ -123,7 +195,12 @@ bool CONVERT_TOOL::Init()
int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent ) int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
{ {
FOOTPRINT* parentFootprint = nullptr; std::vector<SHAPE_POLY_SET> polys;
CONVERT_SETTINGS convertSettings;
PCB_LAYER_ID destLayer = m_frame->GetActiveLayer();
FOOTPRINT* parentFootprint = nullptr;
bool foundChainedSegs = false;
bool foundFilledShape = false;
PCB_SELECTION& selection = m_selectionTool->RequestSelection( PCB_SELECTION& selection = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool ) []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
@ -133,18 +210,57 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
PCB_LAYER_ID destLayer = m_frame->GetActiveLayer(); auto getPolys =
SHAPE_POLY_SET polySet; [&]()
{
polys.clear();
if( !IsCopperLayer( destLayer ) ) for( EDA_ITEM* item : selection )
polySet = makePolysFromChainedSegs( selection.GetItems() ); {
item->ClearTempFlags();
polySet.Append( makePolysFromGraphics( selection.GetItems() ) ); if( item->Type() == PCB_SHAPE_T || item->Type() == PCB_FP_SHAPE_T )
foundFilledShape = static_cast<PCB_SHAPE*>( item )->IsFilled();
}
if( polySet.IsEmpty() ) SHAPE_POLY_SET polySet;
if( convertSettings.m_IgnoreLineWidths )
{
polySet.Append( makePolysFromChainedSegs( selection.GetItems() ) );
foundChainedSegs = polySet.OutlineCount() > 0;
}
polySet.Append( makePolysFromGraphics( selection.GetItems(),
convertSettings.m_IgnoreLineWidths ) );
if( polySet.IsEmpty() )
return false;
polySet.Simplify( SHAPE_POLY_SET::PM_FAST );
for( int ii = 0; ii < polySet.OutlineCount(); ++ii )
{
polys.emplace_back( SHAPE_POLY_SET( polySet.COutline( ii ) ) );
for( int jj = 0; jj < polySet.HoleCount( ii ); ++jj )
polys.back().AddHole( polySet.Hole( ii, jj ) );
}
return true;
};
// Pre-flight getPolys(). If we find any chained segments then we default m_IgnoreLineWidths
// to true.
// We also use the pre-flight to keep from putting up any of the dialogs if there's nothing
// to convert.
convertSettings.m_IgnoreLineWidths = true;
convertSettings.m_DeleteOriginals = false;
if( !getPolys() )
return 0; return 0;
polySet.Simplify( SHAPE_POLY_SET::PM_FAST ); convertSettings.m_IgnoreLineWidths = foundChainedSegs;
bool isFootprint = m_frame->IsType( FRAME_FOOTPRINT_EDITOR ); bool isFootprint = m_frame->IsType( FRAME_FOOTPRINT_EDITOR );
@ -160,33 +276,28 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
// For now, we convert each outline in the returned shape to its own polygon
std::vector<SHAPE_POLY_SET> polys;
for( int ii = 0; ii < polySet.OutlineCount(); ++ii )
{
polys.emplace_back( SHAPE_POLY_SET( polySet.COutline( ii ) ) );
for( int jj = 0; jj < polySet.HoleCount( ii ); ++jj )
polys.back().AddHole( polySet.Hole( ii, jj ) );
}
if( aEvent.IsAction( &PCB_ACTIONS::convertToPoly ) ) if( aEvent.IsAction( &PCB_ACTIONS::convertToPoly ) )
{ {
CONVERT_SETTINGS_DIALOG dlg( m_frame, &convertSettings );
if( dlg.ShowModal() != wxID_OK )
return 0;
if( !getPolys() )
return 0;
for( const SHAPE_POLY_SET& poly : polys ) for( const SHAPE_POLY_SET& poly : polys )
{ {
PCB_SHAPE* graphic = isFootprint ? new FP_SHAPE( parentFootprint ) : new PCB_SHAPE; PCB_SHAPE* graphic = isFootprint ? new FP_SHAPE( parentFootprint ) : new PCB_SHAPE;
graphic->SetShape( SHAPE_T::POLY ); graphic->SetShape( SHAPE_T::POLY );
graphic->SetFilled( false ); graphic->SetFilled( !convertSettings.m_IgnoreLineWidths || foundFilledShape );
graphic->SetStroke( STROKE_PARAMS( poly.Outline( 0 ).Width() ) ); graphic->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID, COLOR4D::UNSPECIFIED ) );
graphic->SetLayer( destLayer ); graphic->SetLayer( destLayer );
graphic->SetPolyShape( poly ); graphic->SetPolyShape( poly );
commit.Add( graphic ); commit.Add( graphic );
} }
commit.Push( _( "Convert shapes to polygon" ) );
} }
else else
{ {
@ -204,22 +315,25 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
if( aEvent.IsAction( &PCB_ACTIONS::convertToKeepout ) ) if( aEvent.IsAction( &PCB_ACTIONS::convertToKeepout ) )
{ {
zoneInfo.SetIsRuleArea( true ); zoneInfo.SetIsRuleArea( true );
ret = InvokeRuleAreaEditor( frame, &zoneInfo ); ret = InvokeRuleAreaEditor( frame, &zoneInfo, &convertSettings );
} }
else if( nonCopper ) else if( nonCopper )
{ {
zoneInfo.SetIsRuleArea( false ); zoneInfo.SetIsRuleArea( false );
ret = InvokeNonCopperZonesEditor( frame, &zoneInfo ); ret = InvokeNonCopperZonesEditor( frame, &zoneInfo, &convertSettings );
} }
else else
{ {
zoneInfo.SetIsRuleArea( false ); zoneInfo.SetIsRuleArea( false );
ret = InvokeCopperZonesEditor( frame, &zoneInfo ); ret = InvokeCopperZonesEditor( frame, &zoneInfo, &convertSettings );
} }
if( ret == wxID_CANCEL ) if( ret == wxID_CANCEL )
return 0; return 0;
if( !getPolys() )
return 0;
for( const SHAPE_POLY_SET& poly : polys ) for( const SHAPE_POLY_SET& poly : polys )
{ {
ZONE* zone = isFootprint ? new FP_ZONE( parent ) : new ZONE( parent ); ZONE* zone = isFootprint ? new FP_ZONE( parent ) : new ZONE( parent );
@ -231,10 +345,22 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
commit.Add( zone ); commit.Add( zone );
} }
commit.Push( _( "Convert shapes to zone" ) );
} }
if( convertSettings.m_DeleteOriginals )
{
for( EDA_ITEM* item : selection )
{
if( item->GetFlags() & SKIP_STRUCT )
commit.Remove( item );
}
}
if( aEvent.IsAction( &PCB_ACTIONS::convertToPoly ) )
commit.Push( _( "Convert shapes to polygon" ) );
else
commit.Push( _( "Convert shapes to zone" ) );
return 0; return 0;
} }
@ -410,7 +536,8 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromChainedSegs( const std::deque<EDA_ITEM
} }
SHAPE_POLY_SET CONVERT_TOOL::makePolysFromGraphics( const std::deque<EDA_ITEM*>& aItems ) SHAPE_POLY_SET CONVERT_TOOL::makePolysFromGraphics( const std::deque<EDA_ITEM*>& aItems,
bool aIgnoreLineWidths )
{ {
BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings(); BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
SHAPE_POLY_SET poly; SHAPE_POLY_SET poly;
@ -425,16 +552,22 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromGraphics( const std::deque<EDA_ITEM*>&
case PCB_SHAPE_T: case PCB_SHAPE_T:
case PCB_FP_SHAPE_T: case PCB_FP_SHAPE_T:
{ {
PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( item ); PCB_SHAPE* temp = static_cast<PCB_SHAPE*>( item->Clone() );
graphic->TransformShapeWithClearanceToPolygon( poly, UNDEFINED_LAYER, 0, if( aIgnoreLineWidths )
bds.m_MaxError, ERROR_INSIDE ); temp->SetFilled( true );
temp->TransformShapeWithClearanceToPolygon( poly, UNDEFINED_LAYER, 0,
bds.m_MaxError, ERROR_INSIDE,
aIgnoreLineWidths );
item->SetFlags( SKIP_STRUCT );
break; break;
} }
case PCB_ZONE_T: case PCB_ZONE_T:
case PCB_FP_ZONE_T: case PCB_FP_ZONE_T:
poly.Append( *static_cast<ZONE*>( item )->Outline() ); poly.Append( *static_cast<ZONE*>( item )->Outline() );
item->SetFlags( SKIP_STRUCT );
break; break;
default: default:

View File

@ -90,7 +90,8 @@ private:
* @param aItems is a list of items to process. * @param aItems is a list of items to process.
* @return a #SHAPE_POLY_SET containing any polygons that were created. * @return a #SHAPE_POLY_SET containing any polygons that were created.
*/ */
SHAPE_POLY_SET makePolysFromGraphics( const std::deque<EDA_ITEM*>& aItems ); SHAPE_POLY_SET makePolysFromGraphics( const std::deque<EDA_ITEM*>& aItems,
bool aIgnoreLineWidths );
PCB_SELECTION_TOOL* m_selectionTool; PCB_SELECTION_TOOL* m_selectionTool;
CONDITIONAL_MENU* m_menu; CONDITIONAL_MENU* m_menu;

View File

@ -2,7 +2,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) 2008-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2008-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -27,6 +27,8 @@
#include <wx/translation.h> #include <wx/translation.h>
struct CONVERT_SETTINGS;
// Default values in mils for parameters in ZONE // Default values in mils for parameters in ZONE
#define ZONE_THERMAL_RELIEF_GAP_MIL 20 // default value for ZONE_SETTINGS::m_ThermalReliefGap #define ZONE_THERMAL_RELIEF_GAP_MIL 20 // default value for ZONE_SETTINGS::m_ThermalReliefGap
#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL 20 // default value for ZONE_SETTINGS::m_ThermalReliefCopperBridge #define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL 20 // default value for ZONE_SETTINGS::m_ThermalReliefCopperBridge
@ -81,7 +83,8 @@ class PCB_BASE_FRAME;
* @param aSettings points to the ZONE_SETTINGS to edit. * @param aSettings points to the ZONE_SETTINGS to edit.
* @return int - tells if user aborted, changed only one zone, or all of them. * @return int - tells if user aborted, changed only one zone, or all of them.
*/ */
int InvokeNonCopperZonesEditor( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings ); int InvokeNonCopperZonesEditor( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings = nullptr );
/** /**
* Function InvokeCopperZonesEditor * Function InvokeCopperZonesEditor
@ -92,7 +95,8 @@ int InvokeNonCopperZonesEditor( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSetting
* @param aSettings points to the ZONE_SETTINGS to edit. * @param aSettings points to the ZONE_SETTINGS to edit.
* @return int - tells if user aborted, changed only one zone, or all of them. * @return int - tells if user aborted, changed only one zone, or all of them.
*/ */
int InvokeCopperZonesEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings ); int InvokeCopperZonesEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings = nullptr );
/** /**
* Function InvokeRuleAreaEditor * Function InvokeRuleAreaEditor
@ -103,6 +107,7 @@ int InvokeCopperZonesEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings )
* @param aSettings points to the ZONE_SETTINGS to edit. * @param aSettings points to the ZONE_SETTINGS to edit.
* @return int - tells if user aborted, changed only one zone, or all of them. * @return int - tells if user aborted, changed only one zone, or all of them.
*/ */
int InvokeRuleAreaEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings ); int InvokeRuleAreaEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings,
CONVERT_SETTINGS* aConvertSettings = nullptr );
#endif // ZONES_H_ #endif // ZONES_H_