Allow thermal spokes to be same width as minimum width.

Also some changes for readability and clarity, both in the code
and in the Feature Constraints panel.

Fixes: lp:1835674
* https://bugs.launchpad.net/kicad/+bug/1835674
This commit is contained in:
Jeff Young 2019-07-12 13:56:02 +01:00
parent 2d17d2b91f
commit a3855cb4f2
7 changed files with 1061 additions and 219 deletions

View File

@ -552,7 +552,7 @@ void SHAPE_POLY_SET::InflateWithLinkedHoles( int aFactor, int aCircleSegmentsCou
} }
void SHAPE_POLY_SET::Inflate( int aFactor, int aCircleSegmentsCount, bool aPreseveCorners ) void SHAPE_POLY_SET::Inflate( int aFactor, int aCircleSegmentsCount, bool aPreserveCorners )
{ {
// A static table to avoid repetitive calculations of the coefficient // A static table to avoid repetitive calculations of the coefficient
// 1.0 - cos( M_PI/aCircleSegmentsCount) // 1.0 - cos( M_PI/aCircleSegmentsCount)
@ -564,7 +564,7 @@ void SHAPE_POLY_SET::Inflate( int aFactor, int aCircleSegmentsCount, bool aPrese
// N.B. using jtSquare here does not create square corners. They end up mitered by // N.B. using jtSquare here does not create square corners. They end up mitered by
// aFactor. Setting jtMiter and forcing the limit to be aFactor creates sharp corners. // aFactor. Setting jtMiter and forcing the limit to be aFactor creates sharp corners.
JoinType type = aPreseveCorners ? jtMiter : jtRound; JoinType type = aPreserveCorners ? jtMiter : jtRound;
for( const POLYGON& poly : m_polys ) for( const POLYGON& poly : m_polys )
{ {

View File

@ -840,13 +840,18 @@ class SHAPE_POLY_SET : public SHAPE
* *
* @param aFactor - number of units to offset edges * @param aFactor - number of units to offset edges
* @param aCircleSegmentsCount - number of segments per 360° to use in curve approx * @param aCircleSegmentsCount - number of segments per 360° to use in curve approx
* @param aPreseveCorners - If true, use square joints to keep angles preserved * @param aPreserveCorners - If true, use square joints to keep angles preserved
*/ */
void Inflate( int aFactor, int aCircleSegmentsCount, bool aPreseveCorners = false ); void Inflate( int aFactor, int aCircleSegmentsCount, bool aPreserveCorners = false );
void Inflate( int aFactor, bool aPreseveCorners ) void Inflate( int aFactor, bool aPreserveCorners )
{ {
Inflate( aFactor, 32, aPreseveCorners ); Inflate( aFactor, 32, aPreserveCorners );
}
void Deflate( int aFactor, int aCircleSegmentsCount, bool aPreserveCorners = false )
{
Inflate( -aFactor, aPreserveCorners, aPreserveCorners );
} }
///> Performs outline inflation/deflation, using round corners. ///> Performs outline inflation/deflation, using round corners.

View File

@ -355,10 +355,9 @@ bool DIALOG_COPPER_ZONE::AcceptOptions( bool aUseExportableSetupOnly )
m_settings.m_ThermalReliefGap = m_antipadClearance.GetValue(); m_settings.m_ThermalReliefGap = m_antipadClearance.GetValue();
m_settings.m_ThermalReliefCopperBridge = m_spokeWidth.GetValue(); m_settings.m_ThermalReliefCopperBridge = m_spokeWidth.GetValue();
if( m_settings.m_ThermalReliefCopperBridge <= m_settings.m_ZoneMinThickness ) if( m_settings.m_ThermalReliefCopperBridge < m_settings.m_ZoneMinThickness )
{ {
DisplayError( this, DisplayError( this, _( "Thermal spoke width cannot be smaller than the minimum width." ) );
_( "Thermal relief spoke must be greater than the minimum width." ) );
return false; return false;
} }

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Dec 1 2018) // C++ code generated with wxFormBuilder (version Dec 30 2017)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -9,240 +9,240 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{ {
wxBoxSizer* bMainSizer; wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxHORIZONTAL ); bMainSizer = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* sbFeatureRules; wxBoxSizer* sbFeatureRules;
sbFeatureRules = new wxBoxSizer( wxVERTICAL ); sbFeatureRules = new wxBoxSizer( wxVERTICAL );
m_OptAllowBlindBuriedVias = new wxCheckBox( this, wxID_ANY, _("Allow blind/buried vias"), wxDefaultPosition, wxDefaultSize, 0 ); m_OptAllowBlindBuriedVias = new wxCheckBox( this, wxID_ANY, _("Allow blind/buried vias"), wxDefaultPosition, wxDefaultSize, 0 );
sbFeatureRules->Add( m_OptAllowBlindBuriedVias, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); sbFeatureRules->Add( m_OptAllowBlindBuriedVias, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_OptAllowMicroVias = new wxCheckBox( this, wxID_ANY, _("Allow micro vias (uVias)"), wxDefaultPosition, wxDefaultSize, 0 ); m_OptAllowMicroVias = new wxCheckBox( this, wxID_ANY, _("Allow micro vias (uVias)"), wxDefaultPosition, wxDefaultSize, 0 );
sbFeatureRules->Add( m_OptAllowMicroVias, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); sbFeatureRules->Add( m_OptAllowMicroVias, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
sbFeatureRules->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); sbFeatureRules->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 );
m_OptRequireCourtyards = new wxCheckBox( this, wxID_ANY, _("Require courtyard definitions in footprints"), wxDefaultPosition, wxDefaultSize, 0 ); m_OptRequireCourtyards = new wxCheckBox( this, wxID_ANY, _("Require courtyard definitions in footprints"), wxDefaultPosition, wxDefaultSize, 0 );
sbFeatureRules->Add( m_OptRequireCourtyards, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); sbFeatureRules->Add( m_OptRequireCourtyards, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_OptOverlappingCourtyards = new wxCheckBox( this, wxID_ANY, _("Prohibit overlapping courtyards"), wxDefaultPosition, wxDefaultSize, 0 ); m_OptOverlappingCourtyards = new wxCheckBox( this, wxID_ANY, _("Prohibit overlapping courtyards"), wxDefaultPosition, wxDefaultSize, 0 );
sbFeatureRules->Add( m_OptOverlappingCourtyards, 0, wxALL, 5 ); sbFeatureRules->Add( m_OptOverlappingCourtyards, 0, wxALL, 5 );
sbFeatureRules->Add( 0, 0, 0, wxBOTTOM|wxEXPAND|wxTOP, 5 ); sbFeatureRules->Add( 0, 0, 0, wxEXPAND|wxBOTTOM, 5 );
wxBoxSizer* bSizerArcToPoly; wxBoxSizer* bSizerArcToPoly;
bSizerArcToPoly = new wxBoxSizer( wxVERTICAL ); bSizerArcToPoly = new wxBoxSizer( wxVERTICAL );
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizerArcToPoly->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 ); bSizerArcToPoly->Add( m_staticline2, 0, wxEXPAND | wxALL, 2 );
m_stCircleToPolyOpt = new wxStaticText( this, wxID_ANY, _("Arc to polygon approximation:"), wxDefaultPosition, wxDefaultSize, 0 ); m_stCircleToPolyOpt = new wxStaticText( this, wxID_ANY, _("Arc/circle drawing"), wxDefaultPosition, wxDefaultSize, 0 );
m_stCircleToPolyOpt->Wrap( -1 ); m_stCircleToPolyOpt->Wrap( -1 );
m_stCircleToPolyOpt->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); m_stCircleToPolyOpt->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
bSizerArcToPoly->Add( m_stCircleToPolyOpt, 0, wxALL, 5 ); bSizerArcToPoly->Add( m_stCircleToPolyOpt, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
wxFlexGridSizer* fgSizer2; wxFlexGridSizer* fgSizer2;
fgSizer2 = new wxFlexGridSizer( 0, 4, 3, 0 ); fgSizer2 = new wxFlexGridSizer( 0, 4, 3, 0 );
fgSizer2->AddGrowableCol( 2 ); fgSizer2->AddGrowableCol( 2 );
fgSizer2->SetFlexibleDirection( wxBOTH ); fgSizer2->SetFlexibleDirection( wxBOTH );
fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
fgSizer2->Add( 15, 0, 1, wxEXPAND, 5 ); fgSizer2->Add( 15, 0, 1, wxEXPAND, 5 );
m_maxErrorTitle = new wxStaticText( this, wxID_ANY, _("Maximum error:"), wxDefaultPosition, wxDefaultSize, 0 ); m_maxErrorTitle = new wxStaticText( this, wxID_ANY, _("Maximum deviation:"), wxDefaultPosition, wxDefaultSize, 0 );
m_maxErrorTitle->Wrap( -1 ); m_maxErrorTitle->Wrap( -1 );
m_maxErrorTitle->SetToolTip( _("This is the maximum distance between a circle and the polygonal shape that approximate it.\nThe error max defines the number of segments of this polygon.") ); m_maxErrorTitle->SetToolTip( _("This is the maximum distance between a circle and the polygonal shape that approximate it.\nThe error max defines the number of segments of this polygon.") );
fgSizer2->Add( m_maxErrorTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxLEFT, 5 ); fgSizer2->Add( m_maxErrorTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxLEFT, 5 );
m_maxErrorCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_maxErrorCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer2->Add( m_maxErrorCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND|wxLEFT|wxRIGHT, 5 ); fgSizer2->Add( m_maxErrorCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND|wxLEFT|wxRIGHT, 5 );
m_maxErrorUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); m_maxErrorUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
m_maxErrorUnits->Wrap( -1 ); m_maxErrorUnits->Wrap( -1 );
fgSizer2->Add( m_maxErrorUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); fgSizer2->Add( m_maxErrorUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
bSizerArcToPoly->Add( fgSizer2, 0, wxEXPAND, 5 ); bSizerArcToPoly->Add( fgSizer2, 0, wxEXPAND|wxBOTTOM, 5 );
sbFeatureRules->Add( bSizerArcToPoly, 0, wxEXPAND, 5 ); sbFeatureRules->Add( bSizerArcToPoly, 0, wxEXPAND|wxTOP, 5 );
m_bSizerPolygonFillOption = new wxBoxSizer( wxVERTICAL ); m_bSizerPolygonFillOption = new wxBoxSizer( wxVERTICAL );
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
m_bSizerPolygonFillOption->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 ); m_bSizerPolygonFillOption->Add( m_staticline1, 0, wxEXPAND | wxALL, 2 );
m_stZoneFilledPolysOpt = new wxStaticText( this, wxID_ANY, _("Option to fill polygons in zones:"), wxDefaultPosition, wxDefaultSize, 0 ); m_stZoneFilledPolysOpt = new wxStaticText( this, wxID_ANY, _("Zone fill strategy"), wxDefaultPosition, wxDefaultSize, 0 );
m_stZoneFilledPolysOpt->Wrap( -1 ); m_stZoneFilledPolysOpt->Wrap( -1 );
m_stZoneFilledPolysOpt->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); m_stZoneFilledPolysOpt->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
m_bSizerPolygonFillOption->Add( m_stZoneFilledPolysOpt, 0, wxALL, 5 ); m_bSizerPolygonFillOption->Add( m_stZoneFilledPolysOpt, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizer5; wxBoxSizer* bSizer5;
bSizer5 = new wxBoxSizer( wxVERTICAL ); bSizer5 = new wxBoxSizer( wxVERTICAL );
m_cbOutlinePolygonBestQ = new wxCheckBox( this, wxID_ANY, _("Thick outlines (old algorithm)"), wxDefaultPosition, wxDefaultSize, 0 ); m_cbOutlinePolygonBestQ = new wxCheckBox( this, wxID_ANY, _("Stroked outlines (legacy)"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer5->Add( m_cbOutlinePolygonBestQ, 0, wxALL, 5 ); bSizer5->Add( m_cbOutlinePolygonBestQ, 0, wxALL, 4 );
m_cbOutlinePolygonFastest = new wxCheckBox( this, wxID_ANY, _("No outline (fastest draw mode)"), wxDefaultPosition, wxDefaultSize, 0 ); m_cbOutlinePolygonFastest = new wxCheckBox( this, wxID_ANY, _("Smoothed polygons (best performance)"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbOutlinePolygonFastest->SetValue(true); m_cbOutlinePolygonFastest->SetValue(true);
bSizer5->Add( m_cbOutlinePolygonFastest, 0, wxALL, 5 ); bSizer5->Add( m_cbOutlinePolygonFastest, 0, wxBOTTOM|wxRIGHT|wxLEFT, 4 );
m_bSizerPolygonFillOption->Add( bSizer5, 1, wxEXPAND|wxLEFT, 15 ); m_bSizerPolygonFillOption->Add( bSizer5, 1, wxEXPAND|wxLEFT, 15 );
sbFeatureRules->Add( m_bSizerPolygonFillOption, 0, wxEXPAND, 5 ); sbFeatureRules->Add( m_bSizerPolygonFillOption, 0, wxEXPAND|wxTOP, 5 );
bMainSizer->Add( sbFeatureRules, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); bMainSizer->Add( sbFeatureRules, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
bMainSizer->Add( 0, 0, 0, wxEXPAND|wxRIGHT|wxLEFT, 15 ); bMainSizer->Add( 0, 0, 0, wxEXPAND|wxRIGHT|wxLEFT, 15 );
wxBoxSizer* sbFeatureConstraints; wxBoxSizer* sbFeatureConstraints;
sbFeatureConstraints = new wxBoxSizer( wxVERTICAL ); sbFeatureConstraints = new wxBoxSizer( wxVERTICAL );
wxFlexGridSizer* fgFeatureConstraints; wxFlexGridSizer* fgFeatureConstraints;
fgFeatureConstraints = new wxFlexGridSizer( 0, 3, 3, 0 ); fgFeatureConstraints = new wxFlexGridSizer( 0, 3, 2, 0 );
fgFeatureConstraints->AddGrowableCol( 1 ); fgFeatureConstraints->AddGrowableCol( 1 );
fgFeatureConstraints->SetFlexibleDirection( wxBOTH ); fgFeatureConstraints->SetFlexibleDirection( wxBOTH );
fgFeatureConstraints->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); fgFeatureConstraints->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_TrackMinWidthTitle = new wxStaticText( this, wxID_ANY, _("Minimum track width:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_TrackMinWidthTitle = new wxStaticText( this, wxID_ANY, _("Minimum track width:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_TrackMinWidthTitle->Wrap( -1 ); m_TrackMinWidthTitle->Wrap( -1 );
fgFeatureConstraints->Add( m_TrackMinWidthTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxBOTTOM, 5 ); fgFeatureConstraints->Add( m_TrackMinWidthTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxBOTTOM, 5 );
m_TrackMinWidthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_TrackMinWidthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_TrackMinWidthCtrl->SetMinSize( wxSize( 120,-1 ) ); m_TrackMinWidthCtrl->SetMinSize( wxSize( 120,-1 ) );
fgFeatureConstraints->Add( m_TrackMinWidthCtrl, 0, wxALIGN_LEFT|wxALIGN_TOP|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); fgFeatureConstraints->Add( m_TrackMinWidthCtrl, 0, wxALIGN_LEFT|wxALIGN_TOP|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_TrackMinWidthUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_TrackMinWidthUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_TrackMinWidthUnits->Wrap( -1 ); m_TrackMinWidthUnits->Wrap( -1 );
fgFeatureConstraints->Add( m_TrackMinWidthUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxBOTTOM, 5 ); fgFeatureConstraints->Add( m_TrackMinWidthUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxBOTTOM, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxALL|wxEXPAND, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxALL|wxEXPAND, 5 );
m_ViaMinTitle = new wxStaticText( this, wxID_ANY, _("Minimum via diameter:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_ViaMinTitle = new wxStaticText( this, wxID_ANY, _("Minimum via diameter:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_ViaMinTitle->Wrap( -1 ); m_ViaMinTitle->Wrap( -1 );
fgFeatureConstraints->Add( m_ViaMinTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); fgFeatureConstraints->Add( m_ViaMinTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
m_SetViasMinSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_SetViasMinSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgFeatureConstraints->Add( m_SetViasMinSizeCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); fgFeatureConstraints->Add( m_SetViasMinSizeCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_ViaMinUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_ViaMinUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_ViaMinUnits->Wrap( -1 ); m_ViaMinUnits->Wrap( -1 );
fgFeatureConstraints->Add( m_ViaMinUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); fgFeatureConstraints->Add( m_ViaMinUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
m_ViaMinDrillTitle = new wxStaticText( this, wxID_ANY, _("Minimum via drill:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_ViaMinDrillTitle = new wxStaticText( this, wxID_ANY, _("Minimum via drill:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_ViaMinDrillTitle->Wrap( -1 ); m_ViaMinDrillTitle->Wrap( -1 );
fgFeatureConstraints->Add( m_ViaMinDrillTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); fgFeatureConstraints->Add( m_ViaMinDrillTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
m_SetViasMinDrillCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_SetViasMinDrillCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgFeatureConstraints->Add( m_SetViasMinDrillCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); fgFeatureConstraints->Add( m_SetViasMinDrillCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_ViaMinDrillUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_ViaMinDrillUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_ViaMinDrillUnits->Wrap( -1 ); m_ViaMinDrillUnits->Wrap( -1 );
fgFeatureConstraints->Add( m_ViaMinDrillUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); fgFeatureConstraints->Add( m_ViaMinDrillUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP, 5 );
m_uviaMinSizeLabel = new wxStaticText( this, wxID_ANY, _("Minimum uVia diameter:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_uviaMinSizeLabel = new wxStaticText( this, wxID_ANY, _("Minimum uVia diameter:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_uviaMinSizeLabel->Wrap( -1 ); m_uviaMinSizeLabel->Wrap( -1 );
fgFeatureConstraints->Add( m_uviaMinSizeLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); fgFeatureConstraints->Add( m_uviaMinSizeLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
m_uviaMinSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_uviaMinSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgFeatureConstraints->Add( m_uviaMinSizeCtrl, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); fgFeatureConstraints->Add( m_uviaMinSizeCtrl, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
m_uviaMinSizeUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_uviaMinSizeUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_uviaMinSizeUnits->Wrap( -1 ); m_uviaMinSizeUnits->Wrap( -1 );
fgFeatureConstraints->Add( m_uviaMinSizeUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); fgFeatureConstraints->Add( m_uviaMinSizeUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
m_uviaMinDrillLabel = new wxStaticText( this, wxID_ANY, _("Minimum uVia drill:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_uviaMinDrillLabel = new wxStaticText( this, wxID_ANY, _("Minimum uVia drill:"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_uviaMinDrillLabel->Wrap( -1 ); m_uviaMinDrillLabel->Wrap( -1 );
fgFeatureConstraints->Add( m_uviaMinDrillLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); fgFeatureConstraints->Add( m_uviaMinDrillLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
m_uviaMinDrillCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_uviaMinDrillCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgFeatureConstraints->Add( m_uviaMinDrillCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); fgFeatureConstraints->Add( m_uviaMinDrillCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_uviaMinDrillUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); m_uviaMinDrillUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
m_uviaMinDrillUnits->Wrap( -1 ); m_uviaMinDrillUnits->Wrap( -1 );
fgFeatureConstraints->Add( m_uviaMinDrillUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); fgFeatureConstraints->Add( m_uviaMinDrillUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
m_HoleToHoleTitle = new wxStaticText( this, wxID_ANY, _("Minimum hole to hole:"), wxDefaultPosition, wxDefaultSize, 0 ); m_HoleToHoleTitle = new wxStaticText( this, wxID_ANY, _("Minimum hole to hole:"), wxDefaultPosition, wxDefaultSize, 0 );
m_HoleToHoleTitle->Wrap( -1 ); m_HoleToHoleTitle->Wrap( -1 );
fgFeatureConstraints->Add( m_HoleToHoleTitle, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 ); fgFeatureConstraints->Add( m_HoleToHoleTitle, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 );
m_SetHoleToHoleCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_SetHoleToHoleCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgFeatureConstraints->Add( m_SetHoleToHoleCtrl, 0, wxEXPAND|wxALL, 5 ); fgFeatureConstraints->Add( m_SetHoleToHoleCtrl, 0, wxEXPAND|wxALL, 5 );
m_HoleToHoleUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); m_HoleToHoleUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
m_HoleToHoleUnits->Wrap( -1 ); m_HoleToHoleUnits->Wrap( -1 );
fgFeatureConstraints->Add( m_HoleToHoleUnits, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 ); fgFeatureConstraints->Add( m_HoleToHoleUnits, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 ); fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
m_EdgeClearanceLabel = new wxStaticText( this, wxID_ANY, _("Copper edge clearance:"), wxDefaultPosition, wxDefaultSize, 0 ); m_EdgeClearanceLabel = new wxStaticText( this, wxID_ANY, _("Copper edge clearance:"), wxDefaultPosition, wxDefaultSize, 0 );
m_EdgeClearanceLabel->Wrap( -1 ); m_EdgeClearanceLabel->Wrap( -1 );
fgFeatureConstraints->Add( m_EdgeClearanceLabel, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); fgFeatureConstraints->Add( m_EdgeClearanceLabel, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 );
m_EdgeClearanceCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_EdgeClearanceCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgFeatureConstraints->Add( m_EdgeClearanceCtrl, 0, wxALL|wxEXPAND, 5 ); fgFeatureConstraints->Add( m_EdgeClearanceCtrl, 0, wxALL|wxEXPAND, 5 );
m_EdgeClearanceUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); m_EdgeClearanceUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
m_EdgeClearanceUnits->Wrap( -1 ); m_EdgeClearanceUnits->Wrap( -1 );
fgFeatureConstraints->Add( m_EdgeClearanceUnits, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); fgFeatureConstraints->Add( m_EdgeClearanceUnits, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 );
sbFeatureConstraints->Add( fgFeatureConstraints, 1, wxEXPAND|wxTOP|wxLEFT, 5 ); sbFeatureConstraints->Add( fgFeatureConstraints, 1, wxEXPAND|wxTOP|wxLEFT, 5 );
bMainSizer->Add( sbFeatureConstraints, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); bMainSizer->Add( sbFeatureConstraints, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
this->SetSizer( bMainSizer ); this->SetSizer( bMainSizer );
this->Layout(); this->Layout();
bMainSizer->Fit( this ); bMainSizer->Fit( this );
// Connect Events // Connect Events
m_cbOutlinePolygonBestQ->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::onChangeOutlineOpt ), NULL, this ); m_cbOutlinePolygonBestQ->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::onChangeOutlineOpt ), NULL, this );
m_cbOutlinePolygonFastest->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::onChangeOutlineOpt ), NULL, this ); m_cbOutlinePolygonFastest->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::onChangeOutlineOpt ), NULL, this );
@ -253,5 +253,5 @@ PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::~PANEL_SETUP_FEATURE_CONSTRAINTS_BASE()
// Disconnect Events // Disconnect Events
m_cbOutlinePolygonBestQ->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::onChangeOutlineOpt ), NULL, this ); m_cbOutlinePolygonBestQ->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::onChangeOutlineOpt ), NULL, this );
m_cbOutlinePolygonFastest->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::onChangeOutlineOpt ), NULL, this ); m_cbOutlinePolygonFastest->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::onChangeOutlineOpt ), NULL, this );
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,12 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Dec 1 2018) // C++ code generated with wxFormBuilder (version Dec 30 2017)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
#pragma once #ifndef __PANEL_SETUP_FEATURE_CONSTRAINTS_BASE_H__
#define __PANEL_SETUP_FEATURE_CONSTRAINTS_BASE_H__
#include <wx/artprov.h> #include <wx/artprov.h>
#include <wx/xrc/xmlres.h> #include <wx/xrc/xmlres.h>
@ -28,10 +29,10 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// Class PANEL_SETUP_FEATURE_CONSTRAINTS_BASE /// Class PANEL_SETUP_FEATURE_CONSTRAINTS_BASE
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class PANEL_SETUP_FEATURE_CONSTRAINTS_BASE : public wxPanel class PANEL_SETUP_FEATURE_CONSTRAINTS_BASE : public wxPanel
{ {
private: private:
protected: protected:
wxCheckBox* m_OptAllowBlindBuriedVias; wxCheckBox* m_OptAllowBlindBuriedVias;
wxCheckBox* m_OptAllowMicroVias; wxCheckBox* m_OptAllowMicroVias;
@ -68,15 +69,16 @@ class PANEL_SETUP_FEATURE_CONSTRAINTS_BASE : public wxPanel
wxStaticText* m_EdgeClearanceLabel; wxStaticText* m_EdgeClearanceLabel;
wxTextCtrl* m_EdgeClearanceCtrl; wxTextCtrl* m_EdgeClearanceCtrl;
wxStaticText* m_EdgeClearanceUnits; wxStaticText* m_EdgeClearanceUnits;
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
virtual void onChangeOutlineOpt( wxCommandEvent& event ) { event.Skip(); } virtual void onChangeOutlineOpt( wxCommandEvent& event ) { event.Skip(); }
public: public:
PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL );
~PANEL_SETUP_FEATURE_CONSTRAINTS_BASE(); ~PANEL_SETUP_FEATURE_CONSTRAINTS_BASE();
}; };
#endif //__PANEL_SETUP_FEATURE_CONSTRAINTS_BASE_H__

View File

@ -672,40 +672,46 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
{ {
m_high_def = m_board->GetDesignSettings().m_MaxError; m_high_def = m_board->GetDesignSettings().m_MaxError;
m_low_def = std::min( ARC_LOW_DEF, int( m_high_def*1.5 ) ); // Reasonable value m_low_def = std::min( ARC_LOW_DEF, int( m_high_def*1.5 ) ); // Reasonable value
int outline_half_thickness = aZone->GetMinThickness() / 2;
int numSegs = std::max( GetArcToSegmentCount( outline_half_thickness, m_high_def, 360.0 ), 6 ); // Features which are min_width should survive pruning; features that are *less* than
// min_width should not. Therefore we subtract epsilon from the min_width when
// deflating/inflating.
int half_min_width = aZone->GetMinThickness() / 2;
int epsilon = Millimeter2iu( 0.001 );
int numSegs = std::max( GetArcToSegmentCount( half_min_width, m_high_def, 360.0 ), 6 );
std::deque<SHAPE_LINE_CHAIN> thermalSpokes;
SHAPE_POLY_SET clearanceHoles;
std::unique_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO( std::unique_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO(
s_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) ); s_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) );
aRawPolys = aSmoothedOutline;
if( s_DumpZonesWhenFilling ) if( s_DumpZonesWhenFilling )
dumper->BeginGroup( "clipper-zone" ); dumper->BeginGroup( "clipper-zone" );
SHAPE_POLY_SET solidAreas = aSmoothedOutline; knockoutThermalReliefs( aZone, aRawPolys );
std::deque<SHAPE_LINE_CHAIN> thermalSpokes;
SHAPE_POLY_SET clearanceHoles;
knockoutThermalReliefs( aZone, solidAreas );
if( s_DumpZonesWhenFilling ) if( s_DumpZonesWhenFilling )
dumper->Write( &solidAreas, "solid-areas-minus-thermal-reliefs" ); dumper->Write( &aRawPolys, "solid-areas-minus-thermal-reliefs" );
buildCopperItemClearances( aZone, clearanceHoles ); buildCopperItemClearances( aZone, clearanceHoles );
if( s_DumpZonesWhenFilling ) if( s_DumpZonesWhenFilling )
dumper->Write( &solidAreas, "clearance holes" ); dumper->Write( &aRawPolys, "clearance holes" );
buildThermalSpokes( aZone, thermalSpokes ); buildThermalSpokes( aZone, thermalSpokes );
// Create a temporary zone that we can hit-test spoke-ends against. It's only temporary // Create a temporary zone that we can hit-test spoke-ends against. It's only temporary
// because the "real" subtract-clearance-holes has to be done after the spokes are added. // because the "real" subtract-clearance-holes has to be done after the spokes are added.
static const bool USE_BBOX_CACHES = true; static const bool USE_BBOX_CACHES = true;
SHAPE_POLY_SET testAreas = solidAreas; SHAPE_POLY_SET testAreas = aRawPolys;
testAreas.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST ); testAreas.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
// Remove areas that don't meet minimum-width criteria // Prune features that don't meet minimum-width criteria
testAreas.Inflate( -outline_half_thickness, numSegs, true ); testAreas.Deflate( half_min_width - epsilon, numSegs, true );
testAreas.Inflate( outline_half_thickness, numSegs, true ); testAreas.Inflate( half_min_width - epsilon, numSegs, true );
// Spoke-end-testing is hugely expensive so we generate cached bounding-boxes to speed // Spoke-end-testing is hugely expensive so we generate cached bounding-boxes to speed
// things up a bit. // things up a bit.
@ -718,7 +724,7 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
// Hit-test against zone body // Hit-test against zone body
if( testAreas.Contains( testPt, -1, false, true, USE_BBOX_CACHES ) ) if( testAreas.Contains( testPt, -1, false, true, USE_BBOX_CACHES ) )
{ {
solidAreas.AddOutline( spoke ); aRawPolys.AddOutline( spoke );
continue; continue;
} }
@ -727,53 +733,49 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
{ {
if( &other != &spoke && other.PointInside( testPt, 1, USE_BBOX_CACHES ) ) if( &other != &spoke && other.PointInside( testPt, 1, USE_BBOX_CACHES ) )
{ {
solidAreas.AddOutline( spoke ); aRawPolys.AddOutline( spoke );
break; break;
} }
} }
} }
solidAreas.Simplify( SHAPE_POLY_SET::PM_FAST ); aRawPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
if( s_DumpZonesWhenFilling ) if( s_DumpZonesWhenFilling )
dumper->Write( &solidAreas, "solid-areas-with-thermal-spokes" ); dumper->Write( &aRawPolys, "solid-areas-with-thermal-spokes" );
solidAreas.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST ); aRawPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
solidAreas.Inflate( -outline_half_thickness, numSegs ); // Prune features that don't meet minimum-width criteria
aRawPolys.Deflate( half_min_width - epsilon, numSegs );
if( s_DumpZonesWhenFilling ) if( s_DumpZonesWhenFilling )
dumper->Write( &solidAreas, "solid-areas-before-hatching" ); dumper->Write( &aRawPolys, "solid-areas-before-hatching" );
// Now remove the non filled areas due to the hatch pattern // Now remove the non filled areas due to the hatch pattern
if( aZone->GetFillMode() == ZFM_HATCH_PATTERN ) if( aZone->GetFillMode() == ZFM_HATCH_PATTERN )
addHatchFillTypeOnZone( aZone, solidAreas ); addHatchFillTypeOnZone( aZone, aRawPolys );
if( s_DumpZonesWhenFilling ) if( s_DumpZonesWhenFilling )
dumper->Write( &solidAreas, "solid-areas-after-hatching" ); dumper->Write( &aRawPolys, "solid-areas-after-hatching" );
SHAPE_POLY_SET areas_fractured = solidAreas; // Re-inflate after pruning of areas that don't meet minimum-width criteria
if( aZone->GetFilledPolysUseThickness() )
// Inflate polygon to recreate the polygon (without the too narrow areas)
// if the filled polygons have a outline thickness = 0
int inflate_value = aZone->GetFilledPolysUseThickness() ? 0 : outline_half_thickness;
if( inflate_value <= Millimeter2iu( 0.001 ) ) // avoid very small outline thickness
inflate_value = 0;
if( inflate_value )
{ {
areas_fractured.Simplify( SHAPE_POLY_SET::PM_FAST ); // if we're stroking the zone with a min-width stroke then this will naturally
areas_fractured.Inflate( outline_half_thickness, 16 ); // inflate the zone
}
else if( half_min_width - epsilon > epsilon ) // avoid very small outline thickness
{
aRawPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
aRawPolys.Inflate( half_min_width - epsilon, 16 );
} }
areas_fractured.Fracture( SHAPE_POLY_SET::PM_FAST ); aRawPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
if( s_DumpZonesWhenFilling ) if( s_DumpZonesWhenFilling )
dumper->Write( &areas_fractured, "areas_fractured" ); dumper->Write( &aRawPolys, "areas_fractured" );
aFinalPolys = areas_fractured; aFinalPolys = aRawPolys;
aRawPolys = aFinalPolys;
if( s_DumpZonesWhenFilling ) if( s_DumpZonesWhenFilling )
dumper->EndGroup(); dumper->EndGroup();
@ -802,12 +804,17 @@ bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aRawPol
} }
else else
{ {
// Features which are min_width should survive pruning; features that are *less* than
// min_width should not. Therefore we subtract epsilon from the min_width when
// deflating/inflating.
int half_min_width = aZone->GetMinThickness() / 2;
int epsilon = Millimeter2iu( 0.001 );
int numSegs = std::max( GetArcToSegmentCount( half_min_width, m_high_def, 360.0 ), 6 );
if( m_brdOutlinesValid ) if( m_brdOutlinesValid )
smoothedPoly.BooleanIntersection( m_boardOutline, SHAPE_POLY_SET::PM_FAST ); smoothedPoly.BooleanIntersection( m_boardOutline, SHAPE_POLY_SET::PM_FAST );
int numSegs = std::max( GetArcToSegmentCount( aZone->GetMinThickness() / 2, smoothedPoly.Deflate( half_min_width - epsilon, numSegs );
m_board->GetDesignSettings().m_MaxError, 360.0 ), 6 );
smoothedPoly.Inflate( -aZone->GetMinThickness() / 2, numSegs );
// Remove the non filled areas due to the hatch pattern // Remove the non filled areas due to the hatch pattern
if( aZone->GetFillMode() == ZFM_HATCH_PATTERN ) if( aZone->GetFillMode() == ZFM_HATCH_PATTERN )
@ -1055,7 +1062,7 @@ void ZONE_FILLER::addHatchFillTypeOnZone( const ZONE_CONTAINER* aZone, SHAPE_POL
// Clamp holes to the area of filled zones with a outline thickness // Clamp holes to the area of filled zones with a outline thickness
// > aZone->GetMinThickness() to be sure the thermal pads can be built // > aZone->GetMinThickness() to be sure the thermal pads can be built
int outline_margin = std::max( (aZone->GetMinThickness()*10)/9, linethickness/2 ); int outline_margin = std::max( (aZone->GetMinThickness()*10)/9, linethickness/2 );
filledPolys.Inflate( -outline_margin, 16 ); filledPolys.Deflate( outline_margin, 16 );
holes.BooleanIntersection( filledPolys, SHAPE_POLY_SET::PM_FAST ); holes.BooleanIntersection( filledPolys, SHAPE_POLY_SET::PM_FAST );
if( orientation != 0.0 ) if( orientation != 0.0 )