From 1c6ff86768bd5e7fe8bc68d8aa354a7094b2b220 Mon Sep 17 00:00:00 2001 From: charras Date: Sat, 22 Nov 2008 20:50:30 +0000 Subject: [PATCH] Zones now have a min thickness filled area parameter --- change_log.txt | 5 + common/common_plotPS_functions.cpp | 2 +- pcbnew/class_zone.cpp | 32 +++++ pcbnew/class_zone.h | 1 + pcbnew/class_zone_setting.cpp | 19 +-- pcbnew/class_zone_setting.h | 21 ++-- pcbnew/dialog_copper_zones.cpp | 22 ++-- pcbnew/dialog_copper_zones_base.cpp | 17 ++- pcbnew/dialog_copper_zones_base.fbp | 114 +++++++++++++++++- pcbnew/dialog_copper_zones_base.h | 2 + pcbnew/pcbplot.h | 6 +- pcbnew/plot_rtn.cpp | 35 +++++- pcbnew/plotgerb.cpp | 28 ++++- .../zones_convert_brd_items_to_polygons.cpp | 91 ++++++++++++-- polygon/PolyLine.cpp | 4 +- 15 files changed, 340 insertions(+), 59 deletions(-) diff --git a/change_log.txt b/change_log.txt index 2de3af2b4e..adc6e3ac15 100644 --- a/change_log.txt +++ b/change_log.txt @@ -9,6 +9,11 @@ email address. ================================================================================ ++pcbnew Some cleanup in dialog pad edition. + Added: + Zones now have a min thickness filled area parameter + that ensure a minimun width for filled copper areas + (areas below this min thickness are removed) + Shapes also are better 2008-Nov-19 UPDATE Jerry Jacobs diff --git a/common/common_plotPS_functions.cpp b/common/common_plotPS_functions.cpp index ae1cc92c62..bcecb22adf 100644 --- a/common/common_plotPS_functions.cpp +++ b/common/common_plotPS_functions.cpp @@ -184,7 +184,7 @@ void PlotPolyPS( int nb_segm, int* coord, bool fill, int width ) /* Draw a polygon ( a filled polygon if fill == 1 ) in POSTSCRIPT format * @param nb_segm = corner count * @param coord = corner list (a corner uses 2 int = X coordinate followed by Y coordinate - * @param fill :if == 0 : filled polygon + * @param fill :if true : filled polygon * @param width = line width */ { diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 7d559114b8..f6ebe80697 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -149,6 +149,10 @@ bool ZONE_CONTAINER::Save( FILE* aFile ) const if( ret < 2 ) return false; + ret = fprintf( aFile, "ZMinThickness %d\n", m_ZoneMinThickness ); + if( ret < 1 ) + return false; + ret = fprintf( aFile, "ZOptions %d %d %c %d %d\n", m_GridFillValue, m_ArcToSegmentsCount, m_DrawOptions ? 'S' : 'F', m_ThermalReliefGapValue, m_ThermalReliefCopperBridgeValue ); if( ret < 3 ) @@ -332,6 +336,16 @@ int ZONE_CONTAINER::ReadDescr( FILE* aFile, int* aLineNum ) } } + if( strnicmp( Line, "ZMinThickness", 13 ) == 0 ) // Min Thickness info found + { + int thickness; + text = Line + 13; + ret = sscanf( text, "%d", &thickness ); + if( ret < 1 ) + error = true; + else + m_ZoneMinThickness = thickness; + } if( strnicmp( Line, "$POLYSCORNERS", 13 ) == 0 ) // Read the PolysList (polygons used for fill areas in the zone) { @@ -522,8 +536,26 @@ void ZONE_CONTAINER::DrawFilledArea( WinEDA_DrawPanel* panel, GRClosedPoly( &panel->m_ClipBox, DC, corners_count, CornersBuffer, false, 0, color, color ); else + { + // Draw outlines: + if ( m_ZoneMinThickness > 1 ) + { + int ilim = corners_count * 2; + for ( int is = 0, ie = ilim-2; is < ilim; ie = is, is+=2 ) + { + int x0 = CornersBuffer[is]; + int y0 = CornersBuffer[is+1]; + int x1 = CornersBuffer[ie]; + int y1 = CornersBuffer[ie+1]; + GRFillCSegm( &panel->m_ClipBox, DC, + x0, y0, x1 , y1, + m_ZoneMinThickness, color ); + } + } + // Draw areas: GRPoly( &panel->m_ClipBox, DC, corners_count, CornersBuffer, true, 0, color, color ); + } corners_count = 0; ii = 0; } diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index b31c5d7c5e..894ae08d7a 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -26,6 +26,7 @@ public: CPolyLine* m_Poly; // outlines int m_CornerSelection; // For corner moving, corner index to drag, or -1 if no selection int m_ZoneClearance; // clearance value + int m_ZoneMinThickness; // Min thickness value in filled areas int m_GridFillValue; // Grid used for filling, 0 = use polygonal areas to fill int m_ArcToSegmentsCount; // number of segments to convert a cirlce to a polygon (uses 16 or 32) int m_PadOption; // diff --git a/pcbnew/class_zone_setting.cpp b/pcbnew/class_zone_setting.cpp index d5737837cf..2a9bc27447 100644 --- a/pcbnew/class_zone_setting.cpp +++ b/pcbnew/class_zone_setting.cpp @@ -25,7 +25,8 @@ ZONE_SETTING::ZONE_SETTING( void ) { m_GridFillValue = 250; // Grid value for filling zone by segments, 0 to used polygons to fill - m_ZoneClearance = 200; // Clearance value + m_ZoneClearance = 200; // Clearance value + m_ZoneMinThickness = 0; // Min thickness value in filled areas m_NetcodeSelection = 0; // Net code selection for the current zone m_CurrentZone_Layer = 0; // Layer used to create the current zone m_Zone_HatchingStyle = CPolyLine::DIAGONAL_EDGE; // Option to show the zone area (outlines only, short hatches or full hatches @@ -47,6 +48,7 @@ void ZONE_SETTING::ImportSetting( const ZONE_CONTAINER& aSource ) { m_GridFillValue = aSource.m_GridFillValue; m_ZoneClearance = aSource.m_ZoneClearance; + m_ZoneMinThickness = aSource.m_ZoneMinThickness; m_NetcodeSelection = aSource.GetNet(); m_CurrentZone_Layer = aSource.GetLayer(); m_Zone_HatchingStyle = aSource.GetHatchStyle(); @@ -66,13 +68,14 @@ void ZONE_SETTING::ImportSetting( const ZONE_CONTAINER& aSource ) */ void ZONE_SETTING::ExportSetting( ZONE_CONTAINER& aTarget ) { - aTarget.m_GridFillValue = m_GridFillValue; - aTarget.m_ZoneClearance = m_ZoneClearance; - aTarget.SetNet(m_NetcodeSelection); - aTarget.SetLayer(m_CurrentZone_Layer); - aTarget.m_Poly->SetHatch(m_Zone_HatchingStyle); - aTarget.m_ArcToSegmentsCount = m_ArcToSegmentsCount; - aTarget.m_DrawOptions = m_FilledAreasShowMode; + aTarget.m_GridFillValue = m_GridFillValue; + aTarget.m_ZoneClearance = m_ZoneClearance; + aTarget.m_ZoneMinThickness = m_ZoneMinThickness; + aTarget.SetNet( m_NetcodeSelection ); + aTarget.SetLayer( m_CurrentZone_Layer ); + aTarget.m_Poly->SetHatch( m_Zone_HatchingStyle ); + aTarget.m_ArcToSegmentsCount = m_ArcToSegmentsCount; + aTarget.m_DrawOptions = m_FilledAreasShowMode; aTarget.m_ThermalReliefGapValue = m_ThermalReliefGapValue; aTarget.m_ThermalReliefCopperBridgeValue = m_ThermalReliefCopperBridgeValue; aTarget.m_PadOption = m_Zone_Pad_Options; diff --git a/pcbnew/class_zone_setting.h b/pcbnew/class_zone_setting.h index 4a1f861a48..08756cfff3 100644 --- a/pcbnew/class_zone_setting.h +++ b/pcbnew/class_zone_setting.h @@ -17,17 +17,18 @@ class ZONE_SETTING { public: - int m_GridFillValue; // Grid value for filling zone by segments, 0 to used polygons to fill - int m_ZoneClearance; // Clearance value - int m_NetcodeSelection; // Net code selection for the current zone - int m_CurrentZone_Layer; // Layer used to create the current zone - int m_Zone_HatchingStyle; // Option to show the zone area (outlines only, short hatches or full hatches + int m_GridFillValue; // Grid value for filling zone by segments, 0 to used polygons to fill + int m_ZoneClearance; // Clearance value + int m_ZoneMinThickness; // Min thickness value in filled areas + int m_NetcodeSelection; // Net code selection for the current zone + int m_CurrentZone_Layer; // Layer used to create the current zone + int m_Zone_HatchingStyle; // Option to show the zone area (outlines only, short hatches or full hatches int m_ArcToSegmentsCount; /* Option to select number of segments to approximate a circle - * 16 or 32 segments */ - int m_FilledAreasShowMode; // Used to select draw options for filled areas in a zone (currently normal =0, sketch = 1) - long m_ThermalReliefGapValue; // tickness of the gap in thermal reliefs - long m_ThermalReliefCopperBridgeValue; // tickness of the copper bridge in thermal reliefs - int m_Zone_Pad_Options; // How pads are covered by copper in zone + * 16 or 32 segments */ + int m_FilledAreasShowMode; // Used to select draw options for filled areas in a zone (currently normal =0, sketch = 1) + long m_ThermalReliefGapValue; // tickness of the gap in thermal reliefs + long m_ThermalReliefCopperBridgeValue; // tickness of the copper bridge in thermal reliefs + int m_Zone_Pad_Options; // How pads are covered by copper in zone public: ZONE_SETTING( void ); diff --git a/pcbnew/dialog_copper_zones.cpp b/pcbnew/dialog_copper_zones.cpp index 4bd0562f47..e147ceb9c6 100644 --- a/pcbnew/dialog_copper_zones.cpp +++ b/pcbnew/dialog_copper_zones.cpp @@ -64,17 +64,11 @@ void dialog_copper_zone::OnInitDialog( wxInitDialogEvent& event ) SetFocus(); // Required under wxGTK if we want to demiss the dialog with the ESC key - wxString msg = _( "Zone clearance value:" ) + ReturnUnitSymbol( g_UnitMetric ); - m_ClearanceValueTitle->SetLabel( msg ); + wxString msg; - msg = _( "Grid :" ) + ReturnUnitSymbol( g_UnitMetric ); + msg = m_GridCtrl->GetLabel() + ReturnUnitSymbol( g_UnitMetric ); m_GridCtrl->SetLabel( msg ); - msg = ReturnStringFromValue( g_UnitMetric, - m_Zone_Setting->m_ZoneClearance, - m_Parent->m_InternalUnits ); - m_ZoneClearanceCtrl->SetValue( msg ); - if( g_Zone_45_Only ) m_OrientEdgesOpt->SetSelection( 1 ); @@ -98,11 +92,18 @@ void dialog_copper_zone::OnInitDialog( wxInitDialogEvent& event ) m_GridCtrl->SetSelection( selection ); + AddUnitSymbol( *m_ClearanceValueTitle, g_UnitMetric ); msg = ReturnStringFromValue( g_UnitMetric, m_Zone_Setting->m_ZoneClearance, m_Parent->m_InternalUnits ); m_ZoneClearanceCtrl->SetValue( msg ); + AddUnitSymbol( *m_MinThicknessValueTitle, g_UnitMetric ); + msg = ReturnStringFromValue( g_UnitMetric, + m_Zone_Setting->m_ZoneMinThickness, + m_Parent->m_InternalUnits ); + m_ZoneMinThicknessCtrl->SetValue( msg ); + switch( m_Zone_Setting->m_Zone_Pad_Options ) { case PAD_NOT_IN_ZONE: // Pads are not covered @@ -324,6 +325,11 @@ bool dialog_copper_zone::AcceptOptions( bool aPromptForErrors, bool aUseExportab wxString txtvalue = m_ZoneClearanceCtrl->GetValue(); m_Zone_Setting->m_ZoneClearance = ReturnValueFromString( g_UnitMetric, txtvalue, m_Parent->m_InternalUnits ); + + txtvalue = m_ZoneMinThicknessCtrl->GetValue(); + m_Zone_Setting->m_ZoneMinThickness = + ReturnValueFromString( g_UnitMetric, txtvalue, m_Parent->m_InternalUnits ); + if( m_OrientEdgesOpt->GetSelection() == 0 ) g_Zone_45_Only = FALSE; else diff --git a/pcbnew/dialog_copper_zones_base.cpp b/pcbnew/dialog_copper_zones_base.cpp index c30e7674d5..70c75b9b39 100644 --- a/pcbnew/dialog_copper_zones_base.cpp +++ b/pcbnew/dialog_copper_zones_base.cpp @@ -39,8 +39,8 @@ dialog_copper_zone_base::dialog_copper_zone_base( wxWindow* parent, wxWindowID i wxString m_GridCtrlChoices[] = { _("0.00000"), _("0.00000"), _("0.00000"), _("0.00000"), _("No grid (For tests only!)") }; int m_GridCtrlNChoices = sizeof( m_GridCtrlChoices ) / sizeof( wxString ); - m_GridCtrl = new wxRadioBox( this, ID_RADIOBOX_GRID_SELECTION, _("Grid Size for Filling:"), wxDefaultPosition, wxDefaultSize, m_GridCtrlNChoices, m_GridCtrlChoices, 1, wxRA_SPECIFY_COLS ); - m_GridCtrl->SetSelection( 4 ); + m_GridCtrl = new wxRadioBox( this, ID_RADIOBOX_GRID_SELECTION, _("Grid Size for Filling"), wxDefaultPosition, wxDefaultSize, m_GridCtrlNChoices, m_GridCtrlChoices, 1, wxRA_SPECIFY_COLS ); + m_GridCtrl->SetSelection( 1 ); m_FillOptionsBox->Add( m_GridCtrl, 0, wxALL|wxEXPAND, 5 ); wxString m_PadInZoneOptChoices[] = { _("Include pads"), _("Thermal relief"), _("Exclude pads") }; @@ -119,13 +119,22 @@ dialog_copper_zone_base::dialog_copper_zone_base( wxWindow* parent, wxWindowID i m_OthersOptionsSizer->Add( m_ShowFilledAreasInSketchOpt, 0, wxALL, 5 ); - m_ClearanceValueTitle = new wxStaticText( this, wxID_ANY, _("Zone clearance value (mm):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ClearanceValueTitle = new wxStaticText( this, wxID_ANY, _("Zone clearance value"), wxDefaultPosition, wxDefaultSize, 0 ); m_ClearanceValueTitle->Wrap( -1 ); m_OthersOptionsSizer->Add( m_ClearanceValueTitle, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_ZoneClearanceCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_OthersOptionsSizer->Add( m_ZoneClearanceCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_MinThicknessValueTitle = new wxStaticText( this, wxID_ANY, _("Zone min thickness value"), wxDefaultPosition, wxDefaultSize, 0 ); + m_MinThicknessValueTitle->Wrap( -1 ); + m_OthersOptionsSizer->Add( m_MinThicknessValueTitle, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_ZoneMinThicknessCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_ZoneMinThicknessCtrl->SetToolTip( _("Value of minimun thickness of filled areas") ); + + m_OthersOptionsSizer->Add( m_ZoneMinThicknessCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_OutilinesBoxOpt->Add( m_OthersOptionsSizer, 1, wxEXPAND, 5 ); m_MiddleBoxSizer->Add( m_OutilinesBoxOpt, 1, wxEXPAND, 5 ); @@ -173,6 +182,8 @@ dialog_copper_zone_base::dialog_copper_zone_base( wxWindow* parent, wxWindowID i m_NetSortOptSizer->Add( m_staticText5, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_NetNameFilter = new wxTextCtrl( this, ID_TEXTCTRL_NETNAMES_FILTER, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_NetNameFilter->SetToolTip( _("Pattern in advanced mode, to filter net names in list\nNet names matching this pattern are not displayed") ); + m_NetSortOptSizer->Add( m_NetNameFilter, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); m_RightBoxSizer->Add( m_NetSortOptSizer, 1, wxEXPAND, 5 ); diff --git a/pcbnew/dialog_copper_zones_base.fbp b/pcbnew/dialog_copper_zones_base.fbp index af7543a741..8186138c5a 100644 --- a/pcbnew/dialog_copper_zones_base.fbp +++ b/pcbnew/dialog_copper_zones_base.fbp @@ -130,14 +130,14 @@ 0 ID_RADIOBOX_GRID_SELECTION - Grid Size for Filling: + Grid Size for Filling 1 m_GridCtrl protected - 4 + 1 wxRA_SPECIFY_COLS @@ -733,7 +733,7 @@ 0 wxID_ANY - Zone clearance value (mm): + Zone clearance value m_ClearanceValueTitle @@ -827,6 +827,112 @@ + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + + + 1 + + + 0 + wxID_ANY + Zone min thickness value + + + m_MinThicknessValueTitle + protected + + + + + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + + + 1 + + + 0 + wxID_ANY + + 0 + + m_ZoneMinThicknessCtrl + protected + + + + + Value of minimun thickness of filled areas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1160,7 +1266,7 @@ - + Pattern in advanced mode, to filter net names in list Net names matching this pattern are not displayed diff --git a/pcbnew/dialog_copper_zones_base.h b/pcbnew/dialog_copper_zones_base.h index 23df121eb4..14ae640178 100644 --- a/pcbnew/dialog_copper_zones_base.h +++ b/pcbnew/dialog_copper_zones_base.h @@ -73,6 +73,8 @@ class dialog_copper_zone_base : public wxDialog wxCheckBox* m_ShowFilledAreasInSketchOpt; wxStaticText* m_ClearanceValueTitle; wxTextCtrl* m_ZoneClearanceCtrl; + wxStaticText* m_MinThicknessValueTitle; + wxTextCtrl* m_ZoneMinThicknessCtrl; wxButton* m_ExportSetupButton; wxButton* m_OkButton; diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h index 7989950884..f6ab3e949e 100644 --- a/pcbnew/pcbplot.h +++ b/pcbnew/pcbplot.h @@ -146,7 +146,8 @@ void PlotTextePcb( TEXTE_PCB * pt_texte,int format_plot,int masque_layer); void PlotArc(int format_plot, wxPoint centre, int start_angle,int end_angle, int rayon,int width); void PlotCircle(int format_plot,int width, wxPoint centre, int rayon); -void PlotPolygon(int format_plot, bool filled, int nbpoints, int * coord); +void PlotFilledPolygon(int format_plot, int nbpoints, int * coord); +void PlotPolygon(int format_plot, int nbpoints, int * coord, int width); void Plot_1_texte( int format_plot, const wxString & Text, int t_orient, int width, int ox,int oy,int size_h,int size_v, @@ -166,7 +167,8 @@ void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat); /* PLOTGERB.CPP */ void PlotGERBERLine(wxPoint start, wxPoint end, int width); void PlotCircle_GERBER( wxPoint centre, int rayon, int width); -void PlotPolygon_GERBER(int nb_segm, int * coord, bool fill); +void PlotFilledPolygon_GERBER(int nb_segm, int * coord); +void PlotPolygon_GERBER(int nb_segm, int * coord, int width); void trace_1_contour_GERBER(wxPoint pos, wxSize size, wxSize delta, int penwidth, int orient); /* Trace 1 contour rectangulaire ou trapezoidal d'orientation quelconque diff --git a/pcbnew/plot_rtn.cpp b/pcbnew/plot_rtn.cpp index 5790f59ec6..805a2eae36 100644 --- a/pcbnew/plot_rtn.cpp +++ b/pcbnew/plot_rtn.cpp @@ -550,7 +550,7 @@ void Plot_1_EdgeModule( int format_plot, EDGE_MODULE* PtEdge ) *ptr++ = y; } - PlotPolygon( format_plot, TRUE, PtEdge->m_PolyCount, ptr_base ); + PlotFilledPolygon( format_plot, PtEdge->m_PolyCount, ptr_base ); free( ptr_base ); break; } @@ -748,7 +748,9 @@ void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat ) corners_count++; if( corner->end_contour ) { // Plot the current filled area - PlotPolygon( aFormat, true, corners_count, CornersBuffer ); + PlotFilledPolygon( aFormat, corners_count, CornersBuffer ); + if ( aZone->m_ZoneMinThickness > 0 ) + PlotPolygon( aFormat, corners_count, CornersBuffer, aZone->m_ZoneMinThickness ); corners_count = 0; ii = 0; } @@ -848,22 +850,43 @@ void PlotCircle( int format_plot, int thickness, wxPoint centre, int radius ) /**********************************************************************/ -void PlotPolygon( int format_plot, bool Filled, int nbpoints, int* coord ) +void PlotFilledPolygon( int format_plot, int nbpoints, int* coord ) /**********************************************************************/ /* plot a polygon */ { switch( format_plot ) { case PLOT_FORMAT_GERBER: - PlotPolygon_GERBER( nbpoints, coord, Filled ); + PlotFilledPolygon_GERBER( nbpoints, coord ); break; case PLOT_FORMAT_HPGL: - PlotPolyHPGL( nbpoints, coord, Filled ); + PlotPolyHPGL( nbpoints, coord, true ); break; case PLOT_FORMAT_POST: - PlotPolyPS( nbpoints, coord, Filled ); + PlotPolyPS( nbpoints, coord, true ); + break; + } +} + +/**********************************************************************/ +void PlotPolygon( int format_plot, int nbpoints, int* coord, int width ) +/**********************************************************************/ +/* plot a polygon */ +{ + switch( format_plot ) + { + case PLOT_FORMAT_GERBER: + PlotPolygon_GERBER( nbpoints, coord, width ); + break; + + case PLOT_FORMAT_HPGL: + PlotPolyHPGL( nbpoints, coord, false, width ); + break; + + case PLOT_FORMAT_POST: + PlotPolyPS( nbpoints, coord, false, width ); break; } } diff --git a/pcbnew/plotgerb.cpp b/pcbnew/plotgerb.cpp index 33bc757ea9..a082d1a919 100644 --- a/pcbnew/plotgerb.cpp +++ b/pcbnew/plotgerb.cpp @@ -632,7 +632,7 @@ void trace_1_pad_TRAPEZE_GERBER( wxPoint pos, wxSize size, wxSize delta, PlotGERBERLine( polygon[3], polygon[0], plotLine_width ); } else - PlotPolygon_GERBER( 4, coord, TRUE ); + PlotFilledPolygon_GERBER( 4, coord ); } @@ -701,7 +701,7 @@ void PlotCircle_GERBER( wxPoint centre, int rayon, int epaisseur ) /***************************************************************/ -void PlotPolygon_GERBER( int nb_segm, int* coord, bool fill ) +void PlotFilledPolygon_GERBER( int nb_segm, int* coord ) /***************************************************************/ { int ii; @@ -730,6 +730,30 @@ void PlotPolygon_GERBER( int nb_segm, int* coord, bool fill ) } +/***************************************************************/ +void PlotPolygon_GERBER( int nb_segm, int* coord, int width ) +/***************************************************************/ +{ + wxPoint start, end, startpoint; + startpoint.x = *coord++; + startpoint.y = *coord++; + start = startpoint; + for( int ii = 0; ii < nb_segm-1; ii++ ) + { + end.x = *coord; + coord++; + end.y = *coord; + coord++; + PlotGERBERLine(start, end, width ); + start = end; + } + + if ( startpoint != end ) // Close poly + PlotGERBERLine(end, startpoint, width ); + +} + + /*******************************************************/ D_CODE* get_D_code( int dx, int dy, int type, int drill ) /*******************************************************/ diff --git a/pcbnew/zones_convert_brd_items_to_polygons.cpp b/pcbnew/zones_convert_brd_items_to_polygons.cpp index ad92fd21db..489e154dc0 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons.cpp @@ -52,10 +52,11 @@ double s_Correction; /* mult coeff used to enlarge rounded and oval pads (an */ /** function AddClearanceAreasPolygonsToPolysList + * Supports a min thickness area constraint. * Add non copper areas polygons (pads and tracks with clearence) - * to a filled copper area - * used in BuildFilledPolysListData when calculating filled areas in a zone - * Non copper areas are pads and track and their clearance area + * to the filled copper area found + * in BuildFilledPolysListData after calculating filled areas in a zone + * Non filled copper areas are pads and track and their clearance areas * The filled copper area must be computed just before. * BuildFilledPolysListData() call this function just after creating the * filled copper area polygon (without clearence areas @@ -64,10 +65,17 @@ double s_Correction; /* mult coeff used to enlarge rounded and oval pads (an * this means the created polygons have no holes (hole are linked to outer outline by double overlapped segments * and are therefore compatible with draw functions (DC draw polygons and Gerber or PS outputs) * 2 - Add the main outline (zone outline) in group A - * 3 - Add all non filled areas (pads, tracks) in group B - * 4 - calculates the polygon A - B - * 5 - put resulting list of polygons (filled areas) in m_FilledPolysList - * 6 - Remove insulated copper islands + * 3 - Creates a correction using BOOL_CORRECTION operation to inflate the resulting area + * with m_ZoneMinThickness/2 value. + * The result is areas with a margin of m_ZoneMinThickness/2 + * When drawing outline with segments having a thickness of m_ZoneMinThickness, the outlines wilm + * match exactly the initial outlines + * 4 - recreates the same Bool_Engine, with no correction + * 3 - Add the main outline (zone outline) in group A + * 4 - Add all non filled areas (pads, tracks) in group B with a clearance of m_Clearance + m_ZoneMinThickness/2 + * 5 - calculates the polygon A - B + * 6 - put resulting list of polygons (filled areas) in m_FilledPolysList + * 7 - Remove insulated copper islands */ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) { @@ -87,16 +95,19 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) /* Uses a kbool engine to add holes in the m_FilledPolysList polygon. * Because this function is called just after creating the m_FilledPolysList, * only one polygon is in list. - * (initial holes in zonesare linked into outer contours by double overlapping segments). - * after adding holes, many polygons could be exist in this list. + * (initial holes in zones are linked into outer contours by double overlapping segments). + * because after adding holes, many polygons could be exist in this list. */ Bool_Engine* booleng = new Bool_Engine(); - ArmBoolEng( booleng, true ); - /* Add the main polygon (i.e. the filled area using only one outline) - * in GroupA in Bool_Engine + /* First, Add the main polygon (i.e. the filled area using only one outline) + * in GroupA in Bool_Engine to do a BOOL_CORRECTION operation + * to reserve a m_ZoneMinThickness/2 margind around the outlines and holes + * the margind will be filled when redraw outilnes with segments having a whidth set to + * m_ZoneMinThickness + * so m_ZoneMinThickness is the min thickness of the filled zones areas */ unsigned corners_count = m_FilledPolysList.size(); unsigned ic = 0; @@ -112,9 +123,59 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) booleng->EndPolygonAdd(); } + booleng->SetCorrectionFactor( (double) -m_ZoneMinThickness/2 ); + booleng->Do_Operation( BOOL_CORRECTION ); + + /* No copy the new outline in m_FilledPolysList */ + m_FilledPolysList.clear(); + while( booleng->StartPolygonGet() ) + { + CPolyPt corner( 0, 0, false ); + while( booleng->PolygonHasMorePoints() ) + { + corner.x = (int) booleng->GetPolygonXPoint(); + corner.y = (int) booleng->GetPolygonYPoint(); + corner.end_contour = false; + m_FilledPolysList.push_back( corner ); + } + + corner.end_contour = true; + m_FilledPolysList.pop_back(); + m_FilledPolysList.push_back( corner ); + booleng->EndPolygonGet(); + } + delete booleng; + + /* Second, Add the main (corrected) polygon (i.e. the filled area using only one outline) + * in GroupA in Bool_Engine to do a BOOL_A_SUB_B operation + * All areas to remove will be put in GroupB in Bool_Engine + */ + booleng = new Bool_Engine(); + ArmBoolEng( booleng, true ); + + /* Add the main corrected polygon (i.e. the filled area using only one outline) + * in GroupA in Bool_Engine + */ + corners_count = m_FilledPolysList.size(); + ic = 0; + if( booleng->StartPolygonAdd( GROUP_A ) ) + { + for( ; ic < corners_count; ic++ ) + { + CPolyPt* corner = &m_FilledPolysList[ic]; + booleng->AddPoint( corner->x, corner->y ); + if( corner->end_contour ) + break; + } + + booleng->EndPolygonAdd(); + } + // Calculates the clearance value that meet DRC requirements int clearance = max( m_ZoneClearance, g_DesignSettings.m_TrackClearence ); + clearance += m_ZoneMinThickness/2; + /* Add holes (i.e. tracks and pads areas as polygons outlines) * in GroupB in Bool_Engine @@ -155,7 +216,8 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) item_boundingbox.Inflate( m_ThermalReliefGapValue, m_ThermalReliefGapValue ); if( item_boundingbox.Intersects( zone_boundingbox ) ) AddThermalReliefPadPolygon( booleng, *pad, - m_ThermalReliefGapValue, m_ThermalReliefCopperBridgeValue ); + m_ThermalReliefGapValue/* + (m_ZoneMinThickness/2)*/, + m_ThermalReliefCopperBridgeValue /*- m_ZoneMinThickness*/ ); break; case PAD_IN_ZONE: @@ -401,6 +463,9 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng, int delta = 3600 / s_CircleToSegmentsCount; // rot angle in 0.1 degree + if ( aCopperThickness < 0 ) + aCopperThickness = 0; + copper_tickness.x = min( dx, aCopperThickness ); copper_tickness.y = min( dy, aCopperThickness ); diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 65c14566c5..c07fb88481 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -541,7 +541,7 @@ void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) double DGRID = 1.0; // round coordinate X or Y value in calculations to this (initial value = 1000.0 in kbool example) // Note: in kicad, coordinates are already integer so DGRID can be set to 1 - double MARGE = 0.1; // snap with in this range points to lines in the intersection routines + double MARGE = 0.001; // snap with in this range points to lines in the intersection routines // should always be > DGRID a MARGE >= 10*DGRID is ok // this is also used to remove small segments and to decide when // two segments are in line. ( initial value = 0.001 ) @@ -559,7 +559,7 @@ void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) Another scaling with Grid is applied on top of it to create space in the integer number for even smaller numbers. */ - int GRID = 100; // initial value = 10000 in kbool example + int GRID = 10000; // initial value = 10000 in kbool example aBooleng->SetMarge( MARGE ); aBooleng->SetGrid( GRID );