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:
parent
2d17d2b91f
commit
a3855cb4f2
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,7 +9,7 @@
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
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 );
|
||||||
|
@ -33,19 +33,19 @@ PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWi
|
||||||
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 );
|
||||||
|
@ -56,7 +56,7 @@ PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWi
|
||||||
|
|
||||||
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.") );
|
||||||
|
|
||||||
|
@ -70,37 +70,37 @@ PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWi
|
||||||
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 );
|
||||||
|
@ -112,7 +112,7 @@ PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWi
|
||||||
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 );
|
||||||
|
@ -213,7 +213,7 @@ PANEL_SETUP_FEATURE_CONSTRAINTS_BASE::PANEL_SETUP_FEATURE_CONSTRAINTS_BASE( wxWi
|
||||||
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, 5 );
|
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND|wxTOP, 5 );
|
||||||
|
|
||||||
|
|
||||||
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
|
fgFeatureConstraints->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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>
|
||||||
|
@ -75,8 +76,9 @@ class PANEL_SETUP_FEATURE_CONSTRAINTS_BASE : public wxPanel
|
||||||
|
|
||||||
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__
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
Loading…
Reference in New Issue