From 49d75d58506e563fbca7823d104f4635a4d88c5c Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 16 Nov 2015 19:42:58 +0100 Subject: [PATCH] Drill file generation: add the option to merge NPTH and PTH, which was disabled recently, due to code changes. Add missing translator name in AUTHORS.txt and About dialog (patch from Eldar Khayrullin) --- AUTHORS.txt | 1 + common/dialog_about/AboutDialog_main.cpp | 2 + pcbnew/dialogs/dialog_gendrill.cpp | 12 +- pcbnew/dialogs/dialog_gendrill.h | 1 + pcbnew/dialogs/dialog_gendrill_base.cpp | 43 +++--- pcbnew/dialogs/dialog_gendrill_base.fbp | 94 ++++++++++++- pcbnew/dialogs/dialog_gendrill_base.h | 5 +- pcbnew/exporters/gen_drill_report_files.cpp | 123 ++++++++++-------- pcbnew/exporters/gendrill_Excellon_writer.cpp | 78 ++++++++--- pcbnew/exporters/gendrill_Excellon_writer.h | 22 ++-- 10 files changed, 276 insertions(+), 105 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index eda3e160e0..c20122fa39 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -49,6 +49,7 @@ Polish (PL) Kerusey Karyu Portuguese (PT) Renie Marquet " Russian (RU) Igor Plyatov Russian (RU) Andrey Fedorushkov +Russian (RU) Eldar Khayrullin Spanish (ES) Pedro Martin del Valle Spanish (ES) IƱigo Zuluaga German (DE) Rafael Sokolowski Read( ZerosFormatKey, &m_ZerosFormat ); m_config->Read( MirrorKey, &m_Mirror ); + m_config->Read( MergePTHNPTHKey, &m_Merge_PTH_NPTH ); m_config->Read( MinimalHeaderKey, &m_MinimalHeader ); m_config->Read( UnitDrillInchKey, &m_UnitDrillIsInch ); m_config->Read( DrillOriginIsAuxAxisKey, &m_DrillOriginIsAuxAxis ); @@ -126,6 +129,7 @@ void DIALOG_GENDRILL::InitDisplayParams() m_Choice_Drill_Offset->SetSelection( 1 ); m_Check_Mirror->SetValue( m_Mirror ); + m_Check_Merge_PTH_NPTH->SetValue( m_Merge_PTH_NPTH ); m_Choice_Drill_Map->SetSelection( m_mapFileType ); m_ViaDrillValue->SetLabel( _( "Use Netclasses values" ) ); m_MicroViaDrillValue->SetLabel( _( "Use Netclasses values" ) ); @@ -226,6 +230,7 @@ void DIALOG_GENDRILL::UpdateConfig() m_config->Write( ZerosFormatKey, m_ZerosFormat ); m_config->Write( MirrorKey, m_Mirror ); + m_config->Write( MergePTHNPTHKey, m_Merge_PTH_NPTH ); m_config->Write( MinimalHeaderKey, m_MinimalHeader ); m_config->Write( UnitDrillInchKey, m_UnitDrillIsInch ); m_config->Write( DrillOriginIsAuxAxisKey, m_DrillOriginIsAuxAxis ); @@ -328,6 +333,7 @@ void DIALOG_GENDRILL::SetParams() m_UnitDrillIsInch = (m_Choice_Unit->GetSelection() == 0) ? false : true; m_MinimalHeader = m_Check_Minimal->IsChecked(); m_Mirror = m_Check_Mirror->IsChecked(); + m_Merge_PTH_NPTH = m_Check_Merge_PTH_NPTH->IsChecked(); m_ZerosFormat = m_Choice_Zeros_Format->GetSelection(); m_DrillOriginIsAuxAxis = m_Choice_Drill_Offset->GetSelection(); @@ -367,7 +373,8 @@ void DIALOG_GENDRILL::GenDrillAndMapFiles(bool aGenDrill, bool aGenMap) excellonWriter.SetFormat( !m_UnitDrillIsInch, (EXCELLON_WRITER::ZEROS_FMT) m_ZerosFormat, m_Precision.m_lhs, m_Precision.m_rhs ); - excellonWriter.SetOptions( m_Mirror, m_MinimalHeader, m_FileDrillOffset ); + excellonWriter.SetOptions( m_Mirror, m_MinimalHeader, + m_FileDrillOffset, m_Merge_PTH_NPTH ); excellonWriter.SetMapFileFormat( filefmt[choice] ); excellonWriter.CreateDrillandMapFilesSet( defaultPath, aGenDrill, aGenMap, @@ -400,7 +407,8 @@ void DIALOG_GENDRILL::OnGenReportFile( wxCommandEvent& event ) excellonWriter.SetFormat( !m_UnitDrillIsInch, (EXCELLON_WRITER::ZEROS_FMT) m_ZerosFormat, m_Precision.m_lhs, m_Precision.m_rhs ); - excellonWriter.SetOptions( m_Mirror, m_MinimalHeader, m_FileDrillOffset ); + excellonWriter.SetOptions( m_Mirror, m_MinimalHeader, + m_FileDrillOffset, m_Merge_PTH_NPTH ); bool success = excellonWriter.GenDrillReportFile( dlg.GetPath() ); diff --git a/pcbnew/dialogs/dialog_gendrill.h b/pcbnew/dialogs/dialog_gendrill.h index 184d302f2b..85a7087adc 100644 --- a/pcbnew/dialogs/dialog_gendrill.h +++ b/pcbnew/dialogs/dialog_gendrill.h @@ -41,6 +41,7 @@ public: static int m_ZerosFormat; static bool m_MinimalHeader; static bool m_Mirror; + static bool m_Merge_PTH_NPTH; static bool m_DrillOriginIsAuxAxis; /* Axis selection (main / auxiliary) * for drill origin coordinates */ DRILL_PRECISION m_Precision; // Selected precision for drill files diff --git a/pcbnew/dialogs/dialog_gendrill_base.cpp b/pcbnew/dialogs/dialog_gendrill_base.cpp index 3c5bf3bda5..e868e1f9f9 100644 --- a/pcbnew/dialogs/dialog_gendrill_base.cpp +++ b/pcbnew/dialogs/dialog_gendrill_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jun 6 2014) +// C++ code generated with wxFormBuilder (version Jun 17 2015) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -22,11 +22,11 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con wxStaticBoxSizer* bdirnameSizer; bdirnameSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Output directory:") ), wxHORIZONTAL ); - m_outputDirectoryName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_outputDirectoryName = new wxTextCtrl( bdirnameSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_outputDirectoryName->SetMaxLength( 0 ); bdirnameSizer->Add( m_outputDirectoryName, 1, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_buttonBrowse = new wxButton( this, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonBrowse = new wxButton( bdirnameSizer->GetStaticBox(), wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); bdirnameSizer->Add( m_buttonBrowse, 0, wxBOTTOM|wxLEFT, 5 ); @@ -58,7 +58,7 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con wxStaticBoxSizer* sbSizerPrecision; sbSizerPrecision = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Precision") ), wxVERTICAL ); - m_staticTextPrecision = new wxStaticText( this, wxID_ANY, _("Precision"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextPrecision = new wxStaticText( sbSizerPrecision->GetStaticBox(), wxID_ANY, _("Precision"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextPrecision->Wrap( -1 ); sbSizerPrecision->Add( m_staticTextPrecision, 0, wxALL, 5 ); @@ -82,12 +82,21 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con wxStaticBoxSizer* sbOptSizer; sbOptSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Drill File Options:") ), wxVERTICAL ); - m_Check_Mirror = new wxCheckBox( this, wxID_ANY, _("Mirror y axis"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Check_Mirror = new wxCheckBox( sbOptSizer->GetStaticBox(), wxID_ANY, _("Mirror y axis"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Check_Mirror->SetToolTip( _("Not recommanded.\nUsed mostly by users who make themselves the boards.") ); + sbOptSizer->Add( m_Check_Mirror, 0, wxRIGHT|wxLEFT, 5 ); - m_Check_Minimal = new wxCheckBox( this, wxID_ANY, _("Minimal header"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Check_Minimal = new wxCheckBox( sbOptSizer->GetStaticBox(), wxID_ANY, _("Minimal header"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Check_Minimal->SetToolTip( _("Not recommanded.\nUse it only for board houses which do not accept fully featured headers.") ); + sbOptSizer->Add( m_Check_Minimal, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_Check_Merge_PTH_NPTH = new wxCheckBox( sbOptSizer->GetStaticBox(), wxID_ANY, _("Merge PTH and NPTH holes into one file"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Check_Merge_PTH_NPTH->SetToolTip( _("Not recommanded.\nUse it only for board houses which ask for merged PTH and NPTH into onlu one file") ); + + sbOptSizer->Add( m_Check_Merge_PTH_NPTH, 0, wxALL, 5 ); + bMiddleBoxSizer->Add( sbOptSizer, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); @@ -108,18 +117,18 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con wxStaticBoxSizer* sbSizerInfo; sbSizerInfo = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Info:") ), wxVERTICAL ); - m_DefaultViasDrillSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Default Vias Drill:") ), wxVERTICAL ); + m_DefaultViasDrillSizer = new wxStaticBoxSizer( new wxStaticBox( sbSizerInfo->GetStaticBox(), wxID_ANY, _("Default Vias Drill:") ), wxVERTICAL ); - m_ViaDrillValue = new wxStaticText( this, wxID_ANY, _("Via Drill Value"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ViaDrillValue = new wxStaticText( m_DefaultViasDrillSizer->GetStaticBox(), wxID_ANY, _("Via Drill Value"), wxDefaultPosition, wxDefaultSize, 0 ); m_ViaDrillValue->Wrap( -1 ); m_DefaultViasDrillSizer->Add( m_ViaDrillValue, 0, wxALL, 5 ); sbSizerInfo->Add( m_DefaultViasDrillSizer, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - m_MicroViasDrillSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Micro Vias Drill:") ), wxVERTICAL ); + m_MicroViasDrillSizer = new wxStaticBoxSizer( new wxStaticBox( sbSizerInfo->GetStaticBox(), wxID_ANY, _("Micro Vias Drill:") ), wxVERTICAL ); - m_MicroViaDrillValue = new wxStaticText( this, wxID_ANY, _("Micro Via Drill Value"), wxDefaultPosition, wxDefaultSize, 0 ); + m_MicroViaDrillValue = new wxStaticText( m_MicroViasDrillSizer->GetStaticBox(), wxID_ANY, _("Micro Via Drill Value"), wxDefaultPosition, wxDefaultSize, 0 ); m_MicroViaDrillValue->Wrap( -1 ); m_MicroViasDrillSizer->Add( m_MicroViaDrillValue, 0, wxALL, 5 ); @@ -127,25 +136,25 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con sbSizerInfo->Add( m_MicroViasDrillSizer, 0, wxEXPAND|wxBOTTOM, 5 ); wxStaticBoxSizer* sbSizerHoles; - sbSizerHoles = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Holes Count:") ), wxVERTICAL ); + sbSizerHoles = new wxStaticBoxSizer( new wxStaticBox( sbSizerInfo->GetStaticBox(), wxID_ANY, _("Holes Count:") ), wxVERTICAL ); - m_PlatedPadsCountInfoMsg = new wxStaticText( this, wxID_ANY, _("Plated Pads:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_PlatedPadsCountInfoMsg = new wxStaticText( sbSizerHoles->GetStaticBox(), wxID_ANY, _("Plated Pads:"), wxDefaultPosition, wxDefaultSize, 0 ); m_PlatedPadsCountInfoMsg->Wrap( -1 ); sbSizerHoles->Add( m_PlatedPadsCountInfoMsg, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_NotPlatedPadsCountInfoMsg = new wxStaticText( this, wxID_ANY, _("Not Plated Pads:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_NotPlatedPadsCountInfoMsg = new wxStaticText( sbSizerHoles->GetStaticBox(), wxID_ANY, _("Not Plated Pads:"), wxDefaultPosition, wxDefaultSize, 0 ); m_NotPlatedPadsCountInfoMsg->Wrap( -1 ); sbSizerHoles->Add( m_NotPlatedPadsCountInfoMsg, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_ThroughViasInfoMsg = new wxStaticText( this, wxID_ANY, _("Through Vias:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ThroughViasInfoMsg = new wxStaticText( sbSizerHoles->GetStaticBox(), wxID_ANY, _("Through Vias:"), wxDefaultPosition, wxDefaultSize, 0 ); m_ThroughViasInfoMsg->Wrap( -1 ); sbSizerHoles->Add( m_ThroughViasInfoMsg, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_MicroViasInfoMsg = new wxStaticText( this, wxID_ANY, _("Micro Vias:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_MicroViasInfoMsg = new wxStaticText( sbSizerHoles->GetStaticBox(), wxID_ANY, _("Micro Vias:"), wxDefaultPosition, wxDefaultSize, 0 ); m_MicroViasInfoMsg->Wrap( -1 ); sbSizerHoles->Add( m_MicroViasInfoMsg, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_BuriedViasInfoMsg = new wxStaticText( this, wxID_ANY, _("Buried Vias:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_BuriedViasInfoMsg = new wxStaticText( sbSizerHoles->GetStaticBox(), wxID_ANY, _("Buried Vias:"), wxDefaultPosition, wxDefaultSize, 0 ); m_BuriedViasInfoMsg->Wrap( -1 ); sbSizerHoles->Add( m_BuriedViasInfoMsg, 0, wxALL, 5 ); @@ -186,7 +195,7 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con wxStaticBoxSizer* bmsgSizer; bmsgSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Messages:") ), wxVERTICAL ); - m_messagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); + m_messagesBox = new wxTextCtrl( bmsgSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); m_messagesBox->SetMinSize( wxSize( -1,90 ) ); bmsgSizer->Add( m_messagesBox, 1, wxALL|wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/dialog_gendrill_base.fbp b/pcbnew/dialogs/dialog_gendrill_base.fbp index ac39e5d756..73fef3250b 100644 --- a/pcbnew/dialogs/dialog_gendrill_base.fbp +++ b/pcbnew/dialogs/dialog_gendrill_base.fbp @@ -44,7 +44,7 @@ DIALOG_GENDRILL_BASE - 506,471 + 506,518 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Drill Files Generation @@ -759,7 +759,7 @@ 0 - + Not recommanded. Used mostly by users who make themselves the boards. wxFILTER_NONE wxDefaultValidator @@ -847,7 +847,95 @@ 0 - + Not recommanded. Use it only for board houses which do not accept fully featured headers. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Merge PTH and NPTH holes into one file + + 0 + + + 0 + + 1 + m_Check_Merge_PTH_NPTH + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Not recommanded. Use it only for board houses which ask for merged PTH and NPTH into onlu one file wxFILTER_NONE wxDefaultValidator diff --git a/pcbnew/dialogs/dialog_gendrill_base.h b/pcbnew/dialogs/dialog_gendrill_base.h index 4aef0e0624..d0b57069fb 100644 --- a/pcbnew/dialogs/dialog_gendrill_base.h +++ b/pcbnew/dialogs/dialog_gendrill_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jun 6 2014) +// C++ code generated with wxFormBuilder (version Jun 17 2015) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -48,6 +48,7 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM wxRadioBox* m_Choice_Drill_Map; wxCheckBox* m_Check_Mirror; wxCheckBox* m_Check_Minimal; + wxCheckBox* m_Check_Merge_PTH_NPTH; wxRadioBox* m_Choice_Drill_Offset; wxStaticBoxSizer* m_DefaultViasDrillSizer; wxStaticText* m_ViaDrillValue; @@ -76,7 +77,7 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM public: - DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Drill Files Generation"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 506,471 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Drill Files Generation"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 506,473 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_GENDRILL_BASE(); }; diff --git a/pcbnew/exporters/gen_drill_report_files.cpp b/pcbnew/exporters/gen_drill_report_files.cpp index 806e9eca7f..94a6c75e52 100644 --- a/pcbnew/exporters/gen_drill_report_files.cpp +++ b/pcbnew/exporters/gen_drill_report_files.cpp @@ -6,8 +6,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 1992-2012 Jean_Pierre Charras - * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 1992-2015 Jean_Pierre Charras + * Copyright (C) 1992-2015 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -228,41 +228,45 @@ bool EXCELLON_WRITER::GenDrillMapFile( const wxString& aFullFileName, for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ ) { - int plot_diam; + DRILL_TOOL& tool = m_toolListBuffer[ii]; - if( m_toolListBuffer[ii].m_TotalCount == 0 ) + if( tool.m_TotalCount == 0 ) continue; plotY += intervalle; - plot_diam = KiROUND( m_toolListBuffer[ii].m_Diameter ); + int plot_diam = KiROUND( tool.m_Diameter ); x = KiROUND( plotX - textmarginaftersymbol * charScale - plot_diam / 2.0 ); y = KiROUND( plotY + charSize * charScale ); plotter->Marker( wxPoint( x, y ), plot_diam, ii ); // List the diameter of each drill in mm and inches. sprintf( line, "%2.2fmm / %2.3f\" ", - diameter_in_mm( m_toolListBuffer[ii].m_Diameter ), - diameter_in_inches( m_toolListBuffer[ii].m_Diameter ) ); + diameter_in_mm( tool.m_Diameter ), + diameter_in_inches( tool.m_Diameter ) ); msg = FROM_UTF8( line ); // Now list how many holes and ovals are associated with each drill. - if( ( m_toolListBuffer[ii].m_TotalCount == 1 ) - && ( m_toolListBuffer[ii].m_OvalCount == 0 ) ) + if( ( tool.m_TotalCount == 1 ) + && ( tool.m_OvalCount == 0 ) ) sprintf( line, "(1 hole)" ); - else if( m_toolListBuffer[ii].m_TotalCount == 1 ) // && ( m_toolListBuffer[ii]m_OvalCount == 1 ) + else if( tool.m_TotalCount == 1 ) // && ( toolm_OvalCount == 1 ) sprintf( line, "(1 slot)" ); - else if( m_toolListBuffer[ii].m_OvalCount == 0 ) - sprintf( line, "(%d holes)", m_toolListBuffer[ii].m_TotalCount ); - else if( m_toolListBuffer[ii].m_OvalCount == 1 ) - sprintf( line, "(%d holes + 1 slot)", m_toolListBuffer[ii].m_TotalCount - 1 ); - else // if ( m_toolListBuffer[ii]m_OvalCount > 1 ) + else if( tool.m_OvalCount == 0 ) + sprintf( line, "(%d holes)", tool.m_TotalCount ); + else if( tool.m_OvalCount == 1 ) + sprintf( line, "(%d holes + 1 slot)", tool.m_TotalCount - 1 ); + else // if ( toolm_OvalCount > 1 ) sprintf( line, "(%d holes + %d slots)", - m_toolListBuffer[ii].m_TotalCount - m_toolListBuffer[ii].m_OvalCount, - m_toolListBuffer[ii].m_OvalCount ); + tool.m_TotalCount - tool.m_OvalCount, + tool.m_OvalCount ); msg += FROM_UTF8( line ); + + if( tool.m_Hole_NotPlated ) + msg += wxT( " (not plated)" ); + plotter->Text( wxPoint( plotX, y ), UNSPECIFIED_COLOR, msg, 0, wxSize( KiROUND( charSize * charScale ), KiROUND( charSize * charScale ) ), @@ -323,12 +327,14 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName ) * 3 - Non Plated through holes */ + bool buildNPTHlist = false; + // in this loop are plated only: for( unsigned pair_ndx = 0; pair_ndx < hole_sets.size(); ++pair_ndx ) { LAYER_PAIR pair = hole_sets[pair_ndx]; - BuildHolesList( pair, false ); + BuildHolesList( pair, buildNPTHlist ); if( pair == LAYER_PAIR( F_Cu, B_Cu ) ) { @@ -337,7 +343,7 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName ) out.Print( 0, " plated through holes:\n" ); out.Print( 0, separator ); - totalHoleCount = printToolSummary( out ); + totalHoleCount = printToolSummary( out, false ); out.Print( 0, " Total plated holes count %u\n", totalHoleCount ); } else // blind/buried @@ -352,25 +358,31 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName ) ); out.Print( 0, separator ); - totalHoleCount = printToolSummary( out ); + totalHoleCount = printToolSummary( out, false ); out.Print( 0, " Total plated holes count %u\n", totalHoleCount ); } out.Print( 0, "\n\n" ); } - // NPTHoles: - BuildHolesList( LAYER_PAIR( F_Cu, B_Cu ), true ); + // NPTHoles. Generate the full list (pads+vias) if PTH and NPTH are merged, + // or only the NPTH list (which never has vias) + if( !m_merge_PTH_NPTH ) + buildNPTHlist = true; - // if( m_toolListBuffer.size() ) nothing wrong with an empty NPTH file. - { + BuildHolesList( LAYER_PAIR( F_Cu, B_Cu ), buildNPTHlist ); + + // nothing wrong with an empty NPTH file in report. + if( m_merge_PTH_NPTH ) + out.Print( 0, "Not plated through holes are merged with plated holes\n" ); + else out.Print( 0, "Drill file '%s' contains\n", TO_UTF8( drillFileName( LAYER_PAIR( F_Cu, B_Cu ), true ) ) ); - out.Print( 0, " unplated through holes:\n" ); - out.Print( 0, separator ); - totalHoleCount = printToolSummary( out ); - out.Print( 0, " Total unplated holes count %u\n", totalHoleCount ); - } + + out.Print( 0, " unplated through holes:\n" ); + out.Print( 0, separator ); + totalHoleCount = printToolSummary( out, true ); + out.Print( 0, " Total unplated holes count %u\n", totalHoleCount ); return true; } @@ -383,18 +395,16 @@ bool EXCELLON_WRITER::PlotDrillMarks( PLOTTER* aPlotter ) for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ ) { - pos = m_holeListBuffer[ii].m_Hole_Pos; + const HOLE_INFO& hole = m_holeListBuffer[ii]; + pos = hole.m_Hole_Pos; // Always plot the drill symbol (for slots identifies the needed cutter! - aPlotter->Marker( pos, m_holeListBuffer[ii].m_Hole_Diameter, - m_holeListBuffer[ii].m_Tool_Reference - 1 ); + aPlotter->Marker( pos, hole.m_Hole_Diameter, hole.m_Tool_Reference - 1 ); - if( m_holeListBuffer[ii].m_Hole_Shape != 0 ) + if( hole.m_Hole_Shape != 0 ) { - wxSize oblong_size; - oblong_size = m_holeListBuffer[ii].m_Hole_Size; - aPlotter->FlashPadOval( pos, oblong_size, - m_holeListBuffer[ii].m_Hole_Orient, SKETCH ); + wxSize oblong_size = hole.m_Hole_Size; + aPlotter->FlashPadOval( pos, oblong_size, hole.m_Hole_Orient, SKETCH ); } } @@ -402,36 +412,41 @@ bool EXCELLON_WRITER::PlotDrillMarks( PLOTTER* aPlotter ) } -unsigned EXCELLON_WRITER::printToolSummary( OUTPUTFORMATTER& out ) const +unsigned EXCELLON_WRITER::printToolSummary( OUTPUTFORMATTER& out, bool aSummaryNPTH ) const { unsigned totalHoleCount = 0; for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ ) { + const DRILL_TOOL& tool = m_toolListBuffer[ii]; + + if( aSummaryNPTH && !tool.m_Hole_NotPlated ) + continue; + + if( !aSummaryNPTH && tool.m_Hole_NotPlated ) + continue; + // List the tool number assigned to each drill, // in mm then in inches. - out.Print( 0, " T%d %2.2fmm %2.3f\" ", - ii + 1, - diameter_in_mm( m_toolListBuffer[ii].m_Diameter ), - diameter_in_inches( m_toolListBuffer[ii].m_Diameter ) ); + int tool_number = ii+1; + out.Print( 0, " T%d %2.2fmm %2.3f\" ", tool_number, + diameter_in_mm( tool.m_Diameter ), + diameter_in_inches( tool.m_Diameter ) ); // Now list how many holes and ovals are associated with each drill. - if( ( m_toolListBuffer[ii].m_TotalCount == 1 ) - && ( m_toolListBuffer[ii].m_OvalCount == 0 ) ) + if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) ) out.Print( 0, "(1 hole)\n" ); - else if( m_toolListBuffer[ii].m_TotalCount == 1 ) + else if( tool.m_TotalCount == 1 ) out.Print( 0, "(1 hole) (with 1 slot)\n" ); - else if( m_toolListBuffer[ii].m_OvalCount == 0 ) - out.Print( 0, "(%d holes)\n", m_toolListBuffer[ii].m_TotalCount ); - else if( m_toolListBuffer[ii].m_OvalCount == 1 ) - out.Print( 0, "(%d holes) (with 1 slot)\n", - m_toolListBuffer[ii].m_TotalCount ); - else // if ( buffer[ii]m_OvalCount > 1 ) + else if( tool.m_OvalCount == 0 ) + out.Print( 0, "(%d holes)\n", tool.m_TotalCount ); + else if( tool.m_OvalCount == 1 ) + out.Print( 0, "(%d holes) (with 1 slot)\n", tool.m_TotalCount ); + else // tool.m_OvalCount > 1 out.Print( 0, "(%d holes) (with %d slots)\n", - m_toolListBuffer[ii].m_TotalCount, - m_toolListBuffer[ii].m_OvalCount ); + tool.m_TotalCount, tool.m_OvalCount ); - totalHoleCount += m_toolListBuffer[ii].m_TotalCount; + totalHoleCount += tool.m_TotalCount; } out.Print( 0, "\n" ); diff --git a/pcbnew/exporters/gendrill_Excellon_writer.cpp b/pcbnew/exporters/gendrill_Excellon_writer.cpp index 20dcc01393..b6d0bfe6d0 100644 --- a/pcbnew/exporters/gendrill_Excellon_writer.cpp +++ b/pcbnew/exporters/gendrill_Excellon_writer.cpp @@ -56,8 +56,11 @@ #include #include +// Comment/uncomment this to write or not a comment +// in drill file when PTH and NPTH are merged to flag +// tools used for PTH and tools used for NPTH +// #define WRITE_PTH_NPTH_COMMENT -//#include // Dialog box for drill file generation EXCELLON_WRITER::EXCELLON_WRITER( BOARD* aPcb ) { @@ -67,6 +70,7 @@ EXCELLON_WRITER::EXCELLON_WRITER( BOARD* aPcb ) m_conversionUnits = 0.0001; m_unitsDecimal = true; m_mirror = false; + m_merge_PTH_NPTH = false; m_minimalHeader = false; m_ShortHeader = false; m_mapFileFmt = PLOT_FORMAT_PDF; @@ -83,14 +87,16 @@ void EXCELLON_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory, std::vector hole_sets = getUniqueLayerPairs(); - // append a pair representing the NPTH set of holes. - hole_sets.push_back( LAYER_PAIR( F_Cu, B_Cu ) ); + // append a pair representing the NPTH set of holes, for separate drill files. + if( !m_merge_PTH_NPTH ) + hole_sets.push_back( LAYER_PAIR( F_Cu, B_Cu ) ); for( std::vector::const_iterator it = hole_sets.begin(); it != hole_sets.end(); ++it ) { LAYER_PAIR pair = *it; - bool doing_npth = ( it == hole_sets.end() - 1 ); + // For separate drill files, the last layer pair is the NPTH dril file. + bool doing_npth = m_merge_PTH_NPTH ? false : ( it == hole_sets.end() - 1 ); BuildHolesList( pair, doing_npth ); @@ -185,10 +191,32 @@ int EXCELLON_WRITER::CreateDrillFile( FILE* aFile ) holes_count = 0; +#ifdef WRITE_PTH_NPTH_COMMENT + // if PTH_ and NPTH are merged write a comment in drill file at the + // beginning of NPTH section + bool writePTHcomment = m_merge_PTH_NPTH; + bool writeNPTHcomment = m_merge_PTH_NPTH; +#endif + /* Write the tool list */ for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ ) { DRILL_TOOL& tool_descr = m_toolListBuffer[ii]; + +#ifdef WRITE_PTH_NPTH_COMMENT + if( writePTHcomment && !tool_descr.m_Hole_NotPlated ) + { + writePTHcomment = false; + fprintf( m_file, ";TYPE=PLATED\n" ); + } + + if( writeNPTHcomment && tool_descr.m_Hole_NotPlated ) + { + writeNPTHcomment = false; + fprintf( m_file, ";TYPE=NON_PLATED\n" ); + } +#endif + fprintf( m_file, "T%dC%.3f\n", ii + 1, tool_descr.m_Diameter * m_conversionUnits ); } @@ -520,11 +548,14 @@ void EXCELLON_WRITER::WriteEXCELLONEndOfFile() /* Helper function for sorting hole list. - * Compare function used for sorting holes by increasing diameter value - * and X value + * Compare function used for sorting holes type type (plated then not plated) + * then by increasing diameter value and X value */ -static bool CmpHoleDiameterValue( const HOLE_INFO& a, const HOLE_INFO& b ) +static bool CmpHoleSettings( const HOLE_INFO& a, const HOLE_INFO& b ) { + if( a.m_Hole_NotPlated != b.m_Hole_NotPlated ) + return b.m_Hole_NotPlated; + if( a.m_Hole_Diameter != b.m_Hole_Diameter ) return a.m_Hole_Diameter < b.m_Hole_Diameter; @@ -558,6 +589,7 @@ void EXCELLON_WRITER::BuildHolesList( LAYER_PAIR aLayerPair, new_hole.m_Tool_Reference = -1; // Flag value for Not initialized new_hole.m_Hole_Orient = 0; new_hole.m_Hole_Diameter = hole_sz; + new_hole.m_Hole_NotPlated = false; new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter; new_hole.m_Hole_Shape = 0; // hole shape: round @@ -583,11 +615,14 @@ void EXCELLON_WRITER::BuildHolesList( LAYER_PAIR aLayerPair, { for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { - if( !aGenerateNPTH_list && pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) - continue; + if( !m_merge_PTH_NPTH ) + { + if( !aGenerateNPTH_list && pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) + continue; - if( aGenerateNPTH_list && pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED ) - continue; + if( aGenerateNPTH_list && pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED ) + continue; + } if( pad->GetDrillSize().x == 0 ) continue; @@ -603,30 +638,35 @@ void EXCELLON_WRITER::BuildHolesList( LAYER_PAIR aLayerPair, new_hole.m_Hole_Shape = 1; // oval flag set new_hole.m_Hole_Size = pad->GetDrillSize(); - new_hole.m_Hole_Pos = pad->GetPosition(); // hole position + new_hole.m_Hole_Pos = pad->GetPosition(); // hole position new_hole.m_Hole_Bottom_Layer = B_Cu; - new_hole.m_Hole_Top_Layer = F_Cu;// pad holes are through holes + new_hole.m_Hole_Top_Layer = F_Cu; // pad holes are through holes m_holeListBuffer.push_back( new_hole ); } } } // Sort holes per increasing diameter value - sort( m_holeListBuffer.begin(), m_holeListBuffer.end(), CmpHoleDiameterValue ); + sort( m_holeListBuffer.begin(), m_holeListBuffer.end(), CmpHoleSettings ); // build the tool list - int last_hole = -1; /* Set to not initialized (this is a value not used - * for m_holeListBuffer[ii].m_Hole_Diameter) */ - DRILL_TOOL new_tool( 0 ); + int last_hole = -1; // Set to not initialized (this is a value not used + // for m_holeListBuffer[ii].m_Hole_Diameter) + bool last_notplated_opt = false; + + DRILL_TOOL new_tool( 0, false ); unsigned jj; for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ ) { - if( m_holeListBuffer[ii].m_Hole_Diameter != last_hole ) + if( m_holeListBuffer[ii].m_Hole_Diameter != last_hole || + m_holeListBuffer[ii].m_Hole_NotPlated != last_notplated_opt ) { - new_tool.m_Diameter = ( m_holeListBuffer[ii].m_Hole_Diameter ); + new_tool.m_Diameter = m_holeListBuffer[ii].m_Hole_Diameter; + new_tool.m_Hole_NotPlated = m_holeListBuffer[ii].m_Hole_NotPlated; m_toolListBuffer.push_back( new_tool ); last_hole = new_tool.m_Diameter; + last_notplated_opt = new_tool.m_Hole_NotPlated; } jj = m_toolListBuffer.size(); diff --git a/pcbnew/exporters/gendrill_Excellon_writer.h b/pcbnew/exporters/gendrill_Excellon_writer.h index 1bc08bee24..9a4d9c1f9b 100644 --- a/pcbnew/exporters/gendrill_Excellon_writer.h +++ b/pcbnew/exporters/gendrill_Excellon_writer.h @@ -37,20 +37,22 @@ class BOARD; class PLOTTER; -/* the DRILL_TOOL class handles tools used in the excellon drill file */ +// the DRILL_TOOL class handles tools used in the excellon drill file: class DRILL_TOOL { public: int m_Diameter; // the diameter of the used tool (for oblong, the smaller size) int m_TotalCount; // how many times it is used (round and oblong) int m_OvalCount; // oblong count + bool m_Hole_NotPlated; // Is the hole plated or not plated public: - DRILL_TOOL( int diametre ) + DRILL_TOOL( int aDiameter, bool a_NotPlated ) { - m_TotalCount = 0; - m_OvalCount = 0; - m_Diameter = diametre; + m_TotalCount = 0; + m_OvalCount = 0; + m_Diameter = aDiameter; + m_Hole_NotPlated = a_NotPlated; } }; @@ -73,7 +75,7 @@ public: LAYER_ID m_Hole_Bottom_Layer; // hole ending layer (usually back layer) LAYER_ID m_Hole_Top_Layer; // hole starting layer (usually front layer): // m_Hole_Top_Layer < m_Hole_Bottom_Layer - bool m_Hole_NotPlated; // hole not plated. Must be in a specific drill file + bool m_Hole_NotPlated; // hole not plated. Must be in a specific drill file or section public: HOLE_INFO() @@ -145,6 +147,7 @@ private: // (i.e inches or mm) bool m_mirror; wxPoint m_offset; // Drill offset coordinates + bool m_merge_PTH_NPTH; // True to generate only one drill file std::vector m_holeListBuffer; // Buffer containing holes std::vector m_toolListBuffer; // Buffer containing tools @@ -204,11 +207,12 @@ public: * @param aMinimalHeader = true to use a minimal header (no comments, no info) * @param aOffset = drill coordinates offset */ - void SetOptions( bool aMirror, bool aMinimalHeader, wxPoint aOffset ) + void SetOptions( bool aMirror, bool aMinimalHeader, wxPoint aOffset, bool aMerge_PTH_NPTH ) { m_mirror = aMirror; m_offset = aOffset; m_minimalHeader = aMinimalHeader; + m_merge_PTH_NPTH = aMerge_PTH_NPTH; } /** @@ -349,8 +353,10 @@ private: /** * Function printToolSummary * prints m_toolListBuffer[] tools to aOut and returns total hole count. + * @param aOut = the current OUTPUTFORMATTER to print summary + * @param aSummaryNPTH = true to print summary for NPTH, false for PTH */ - unsigned printToolSummary( OUTPUTFORMATTER& aOut ) const; + unsigned printToolSummary( OUTPUTFORMATTER& aOut, bool aSummaryNPTH ) const; const std::string layerPairName( LAYER_PAIR aPair ) const;