Handle holes in shapes when creating bounding hulls.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16347
This commit is contained in:
parent
e8b16fc64f
commit
0ead8a14a1
|
@ -61,7 +61,11 @@ private:
|
||||||
|
|
||||||
CONVERT_SETTINGS* m_convertSettings;
|
CONVERT_SETTINGS* m_convertSettings;
|
||||||
wxRadioButton* m_rbCenterline;
|
wxRadioButton* m_rbCenterline;
|
||||||
wxRadioButton* m_rbEnvelope;
|
wxRadioButton* m_rbBoundingHull;
|
||||||
|
wxStaticText* m_gapLabel;
|
||||||
|
wxTextCtrl* m_gapCtrl;
|
||||||
|
wxStaticText* m_gapUnits;
|
||||||
|
UNIT_BINDER* m_gap;
|
||||||
wxCheckBox* m_cbDeleteOriginals;
|
wxCheckBox* m_cbDeleteOriginals;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,7 +87,7 @@ DIALOG_RULE_AREA_PROPERTIES::DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aParen
|
||||||
m_outlineHatchPitchCtrl, m_outlineHatchUnits ),
|
m_outlineHatchPitchCtrl, m_outlineHatchUnits ),
|
||||||
m_convertSettings( aConvertSettings ),
|
m_convertSettings( aConvertSettings ),
|
||||||
m_rbCenterline( nullptr ),
|
m_rbCenterline( nullptr ),
|
||||||
m_rbEnvelope( nullptr ),
|
m_rbBoundingHull( nullptr ),
|
||||||
m_cbDeleteOriginals( nullptr )
|
m_cbDeleteOriginals( nullptr )
|
||||||
{
|
{
|
||||||
m_parent = aParent;
|
m_parent = aParent;
|
||||||
|
@ -101,8 +105,21 @@ DIALOG_RULE_AREA_PROPERTIES::DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aParen
|
||||||
bConvertSizer->Add( m_rbCenterline, 0, wxLEFT|wxRIGHT, 5 );
|
bConvertSizer->Add( m_rbCenterline, 0, wxLEFT|wxRIGHT, 5 );
|
||||||
|
|
||||||
bConvertSizer->AddSpacer( 2 );
|
bConvertSizer->AddSpacer( 2 );
|
||||||
m_rbEnvelope = new wxRadioButton( this, wxID_ANY, _( "Create bounding hull" ) );
|
m_rbBoundingHull = new wxRadioButton( this, wxID_ANY, _( "Create bounding hull" ) );
|
||||||
bConvertSizer->Add( m_rbEnvelope, 0, wxLEFT|wxRIGHT, 5 );
|
bConvertSizer->Add( m_rbBoundingHull, 0, wxLEFT|wxRIGHT, 5 );
|
||||||
|
|
||||||
|
m_gapLabel = new wxStaticText( this, wxID_ANY, _( "Gap:" ) );
|
||||||
|
m_gapCtrl = new wxTextCtrl( this, wxID_ANY );
|
||||||
|
m_gapUnits = new wxStaticText( this, wxID_ANY, _( "mm" ) );
|
||||||
|
m_gap = new UNIT_BINDER( aParent, m_gapLabel, m_gapCtrl, m_gapUnits );
|
||||||
|
|
||||||
|
wxBoxSizer* hullParamsSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
hullParamsSizer->Add( m_gapLabel, 0, wxALIGN_CENTRE_VERTICAL, 5 );
|
||||||
|
hullParamsSizer->Add( m_gapCtrl, 1, wxALIGN_CENTRE_VERTICAL|wxLEFT|wxRIGHT, 3 );
|
||||||
|
hullParamsSizer->Add( m_gapUnits, 0, wxALIGN_CENTRE_VERTICAL, 5 );
|
||||||
|
|
||||||
|
bConvertSizer->AddSpacer( 2 );
|
||||||
|
bConvertSizer->Add( hullParamsSizer, 0, wxLEFT, 26 );
|
||||||
|
|
||||||
bConvertSizer->AddSpacer( 6 );
|
bConvertSizer->AddSpacer( 6 );
|
||||||
m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
|
m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
|
||||||
|
@ -136,7 +153,7 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow()
|
||||||
if( m_convertSettings )
|
if( m_convertSettings )
|
||||||
{
|
{
|
||||||
if( m_convertSettings->m_Strategy == BOUNDING_HULL )
|
if( m_convertSettings->m_Strategy == BOUNDING_HULL )
|
||||||
m_rbEnvelope->SetValue( true );
|
m_rbBoundingHull->SetValue( true );
|
||||||
else
|
else
|
||||||
m_rbCenterline->SetValue( true );
|
m_rbCenterline->SetValue( true );
|
||||||
|
|
||||||
|
@ -201,10 +218,15 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataFromWindow()
|
||||||
{
|
{
|
||||||
if( m_convertSettings )
|
if( m_convertSettings )
|
||||||
{
|
{
|
||||||
if( m_rbEnvelope->GetValue() )
|
if( m_rbBoundingHull->GetValue() )
|
||||||
|
{
|
||||||
m_convertSettings->m_Strategy = BOUNDING_HULL;
|
m_convertSettings->m_Strategy = BOUNDING_HULL;
|
||||||
|
m_convertSettings->m_Gap = m_gap->GetIntValue();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m_convertSettings->m_Strategy = CENTERLINE;
|
m_convertSettings->m_Strategy = CENTERLINE;
|
||||||
|
}
|
||||||
|
|
||||||
m_convertSettings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
|
m_convertSettings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ public:
|
||||||
m_rbCenterline->Hide();
|
m_rbCenterline->Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rbEnvelope = new wxRadioButton( this, wxID_ANY, _( "Create bounding hull" ) );
|
m_rbBoundingHull = new wxRadioButton( this, wxID_ANY, _( "Create bounding hull" ) );
|
||||||
|
|
||||||
m_gapLabel = new wxStaticText( this, wxID_ANY, _( "Gap:" ) );
|
m_gapLabel = new wxStaticText( this, wxID_ANY, _( "Gap:" ) );
|
||||||
m_gapCtrl = new wxTextCtrl( this, wxID_ANY );
|
m_gapCtrl = new wxTextCtrl( this, wxID_ANY );
|
||||||
|
@ -108,7 +108,7 @@ public:
|
||||||
if( aShowBoundingHullOption )
|
if( aShowBoundingHullOption )
|
||||||
{
|
{
|
||||||
topSizer->AddSpacer( 6 );
|
topSizer->AddSpacer( 6 );
|
||||||
topSizer->Add( m_rbEnvelope, 0, wxLEFT|wxRIGHT, 5 );
|
topSizer->Add( m_rbBoundingHull, 0, wxLEFT|wxRIGHT, 5 );
|
||||||
|
|
||||||
wxBoxSizer* hullParamsSizer = new wxBoxSizer( wxHORIZONTAL );
|
wxBoxSizer* hullParamsSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
hullParamsSizer->Add( m_gapLabel, 0, wxALIGN_CENTRE_VERTICAL, 5 );
|
hullParamsSizer->Add( m_gapLabel, 0, wxALIGN_CENTRE_VERTICAL, 5 );
|
||||||
|
@ -126,7 +126,7 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_rbEnvelope->Hide();
|
m_rbBoundingHull->Hide();
|
||||||
m_gap->Show( false, true );
|
m_gap->Show( false, true );
|
||||||
m_width->Show( false, true );
|
m_width->Show( false, true );
|
||||||
}
|
}
|
||||||
|
@ -157,9 +157,9 @@ public:
|
||||||
m_rbCenterline->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED,
|
m_rbCenterline->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED,
|
||||||
wxCommandEventHandler( CONVERT_SETTINGS_DIALOG::onRadioButton ),
|
wxCommandEventHandler( CONVERT_SETTINGS_DIALOG::onRadioButton ),
|
||||||
nullptr, this );
|
nullptr, this );
|
||||||
m_rbEnvelope->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED,
|
m_rbBoundingHull->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED,
|
||||||
wxCommandEventHandler( CONVERT_SETTINGS_DIALOG::onRadioButton ),
|
wxCommandEventHandler( CONVERT_SETTINGS_DIALOG::onRadioButton ),
|
||||||
nullptr, this );
|
nullptr, this );
|
||||||
|
|
||||||
finishDialogSettings();
|
finishDialogSettings();
|
||||||
}
|
}
|
||||||
|
@ -177,11 +177,11 @@ protected:
|
||||||
{
|
{
|
||||||
case COPY_LINEWIDTH: m_rbMimicLineWidth->SetValue( true ); break;
|
case COPY_LINEWIDTH: m_rbMimicLineWidth->SetValue( true ); break;
|
||||||
case CENTERLINE: m_rbCenterline->SetValue( true ); break;
|
case CENTERLINE: m_rbCenterline->SetValue( true ); break;
|
||||||
case BOUNDING_HULL: m_rbEnvelope->SetValue( true ); break;
|
case BOUNDING_HULL: m_rbBoundingHull->SetValue( true ); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_gap->Enable( m_rbEnvelope->GetValue() );
|
m_gap->Enable( m_rbBoundingHull->GetValue() );
|
||||||
m_width->Enable( m_rbEnvelope->GetValue() );
|
m_width->Enable( m_rbBoundingHull->GetValue() );
|
||||||
m_gap->SetValue( m_settings->m_Gap );
|
m_gap->SetValue( m_settings->m_Gap );
|
||||||
m_width->SetValue( m_settings->m_LineWidth );
|
m_width->SetValue( m_settings->m_LineWidth );
|
||||||
|
|
||||||
|
@ -191,15 +191,15 @@ protected:
|
||||||
|
|
||||||
bool TransferDataFromWindow() override
|
bool TransferDataFromWindow() override
|
||||||
{
|
{
|
||||||
if( m_rbEnvelope->GetValue() )
|
if( m_rbBoundingHull->GetValue() )
|
||||||
m_settings->m_Strategy = BOUNDING_HULL;
|
m_settings->m_Strategy = BOUNDING_HULL;
|
||||||
else if( m_rbCenterline->GetValue() )
|
else if( m_rbCenterline->GetValue() )
|
||||||
m_settings->m_Strategy = CENTERLINE;
|
m_settings->m_Strategy = CENTERLINE;
|
||||||
else
|
else
|
||||||
m_settings->m_Strategy = COPY_LINEWIDTH;
|
m_settings->m_Strategy = COPY_LINEWIDTH;
|
||||||
|
|
||||||
m_settings->m_Gap = m_gap->GetValue();
|
m_settings->m_Gap = m_gap->GetIntValue();
|
||||||
m_settings->m_LineWidth = m_width->GetValue();
|
m_settings->m_LineWidth = m_width->GetIntValue();
|
||||||
|
|
||||||
m_settings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
|
m_settings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
|
||||||
return true;
|
return true;
|
||||||
|
@ -207,8 +207,8 @@ protected:
|
||||||
|
|
||||||
void onRadioButton( wxCommandEvent& aEvent )
|
void onRadioButton( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
m_gap->Enable( m_rbEnvelope->GetValue() );
|
m_gap->Enable( m_rbBoundingHull->GetValue() );
|
||||||
m_width->Enable( m_rbEnvelope->GetValue() );
|
m_width->Enable( m_rbBoundingHull->GetValue() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -216,7 +216,7 @@ private:
|
||||||
|
|
||||||
wxRadioButton* m_rbMimicLineWidth;
|
wxRadioButton* m_rbMimicLineWidth;
|
||||||
wxRadioButton* m_rbCenterline;
|
wxRadioButton* m_rbCenterline;
|
||||||
wxRadioButton* m_rbEnvelope;
|
wxRadioButton* m_rbBoundingHull;
|
||||||
wxStaticText* m_gapLabel;
|
wxStaticText* m_gapLabel;
|
||||||
wxTextCtrl* m_gapCtrl;
|
wxTextCtrl* m_gapCtrl;
|
||||||
wxStaticText* m_gapUnits;
|
wxStaticText* m_gapUnits;
|
||||||
|
@ -346,16 +346,18 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
|
||||||
|
|
||||||
polySet.Append( makePolysFromClosedGraphics( selection.GetItems(), cfg.m_Strategy ) );
|
polySet.Append( makePolysFromClosedGraphics( selection.GetItems(), cfg.m_Strategy ) );
|
||||||
|
|
||||||
polySet.Append( makePolysFromChainedSegs( selection.GetItems(), cfg.m_Strategy ) );
|
|
||||||
|
|
||||||
if( cfg.m_Strategy == BOUNDING_HULL )
|
if( cfg.m_Strategy == BOUNDING_HULL )
|
||||||
{
|
{
|
||||||
|
polySet.Append( makePolysFromOpenGraphics( selection.GetItems(), cfg.m_Gap ) );
|
||||||
|
|
||||||
polySet.ClearArcs();
|
polySet.ClearArcs();
|
||||||
polySet.Simplify( SHAPE_POLY_SET::PM_FAST );
|
polySet.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||||
polySet.Inflate( cfg.m_Gap, CORNER_STRATEGY::ROUND_ALL_CORNERS, bds.m_MaxError,
|
polySet.Inflate( cfg.m_Gap, CORNER_STRATEGY::ROUND_ALL_CORNERS, bds.m_MaxError,
|
||||||
ERROR_OUTSIDE );
|
ERROR_OUTSIDE );
|
||||||
|
}
|
||||||
polySet.Append( makePolysFromOpenGraphics( selection.GetItems(), cfg.m_Gap ) );
|
else
|
||||||
|
{
|
||||||
|
polySet.Append( makePolysFromChainedSegs( selection.GetItems(), cfg.m_Strategy ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( polySet.IsEmpty() )
|
if( polySet.IsEmpty() )
|
||||||
|
@ -836,10 +838,15 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromClosedGraphics( const std::deque<EDA_I
|
||||||
if( !shape->IsClosed() )
|
if( !shape->IsClosed() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
shape->SetFilled( true );
|
if( aStrategy != BOUNDING_HULL )
|
||||||
|
shape->SetFilled( true );
|
||||||
|
|
||||||
shape->TransformShapeToPolygon( poly, UNDEFINED_LAYER, 0, bds.m_MaxError, ERROR_INSIDE,
|
shape->TransformShapeToPolygon( poly, UNDEFINED_LAYER, 0, bds.m_MaxError, ERROR_INSIDE,
|
||||||
aStrategy == COPY_LINEWIDTH || aStrategy == CENTERLINE );
|
aStrategy == COPY_LINEWIDTH || aStrategy == CENTERLINE );
|
||||||
shape->SetFillMode( wasFilled );
|
|
||||||
|
if( aStrategy != BOUNDING_HULL )
|
||||||
|
shape->SetFillMode( wasFilled );
|
||||||
|
|
||||||
shape->SetFlags( SKIP_STRUCT );
|
shape->SetFlags( SKIP_STRUCT );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue