Commit c41bb774 authored by jean-pierre charras's avatar jean-pierre charras

Pcbnew: drill files creation: better dialog to create driil files, map files...

Pcbnew: drill files creation: better dialog to create driil files, map files and report file. Code cleaning
parent 5951a7f9
...@@ -72,6 +72,7 @@ const wxString AllFilesWildcard( _( "All files (*)|*" ) ); ...@@ -72,6 +72,7 @@ const wxString AllFilesWildcard( _( "All files (*)|*" ) );
// Wildcard for cvpcb component to footprint link file // Wildcard for cvpcb component to footprint link file
const wxString ComponentFileWildcard( _( "KiCad cmp/footprint link files (*.cmp)|*.cmp" ) ); const wxString ComponentFileWildcard( _( "KiCad cmp/footprint link files (*.cmp)|*.cmp" ) );
// Wildcard for reports and fabrication documents
const wxString DrillFileWildcard( _( "Drill files (*.drl)|*.drl;*.DRL" ) ); const wxString DrillFileWildcard( _( "Drill files (*.drl)|*.drl;*.DRL" ) );
const wxString SVGFileWildcard( _( "SVG files (*.svg)|*.svg;*.SVG" ) ); const wxString SVGFileWildcard( _( "SVG files (*.svg)|*.svg;*.SVG" ) );
const wxString ReportFileWildcard = _( "Report files (*.rpt)|*.rpt" ); const wxString ReportFileWildcard = _( "Report files (*.rpt)|*.rpt" );
......
...@@ -151,9 +151,8 @@ set(PCBNEW_CLASS_SRCS ...@@ -151,9 +151,8 @@ set(PCBNEW_CLASS_SRCS
export_vrml.cpp export_vrml.cpp
files.cpp files.cpp
gen_drill_report_files.cpp gen_drill_report_files.cpp
gen_holes_and_tools_lists_for_drill.cpp
gen_modules_placefile.cpp gen_modules_placefile.cpp
gendrill.cpp gendrill_Excellon_writer.cpp
globaleditpad.cpp globaleditpad.cpp
gpcb_exchange.cpp gpcb_exchange.cpp
highlight.cpp highlight.cpp
......
...@@ -40,11 +40,11 @@ DIALOG_SVG_PRINT_base::DIALOG_SVG_PRINT_base( wxWindow* parent, wxWindowID id, c ...@@ -40,11 +40,11 @@ DIALOG_SVG_PRINT_base::DIALOG_SVG_PRINT_base( wxWindow* parent, wxWindowID id, c
m_TextPenWidth = new wxStaticText( this, wxID_ANY, _("Default pen size"), wxDefaultPosition, wxDefaultSize, 0 ); m_TextPenWidth = new wxStaticText( this, wxID_ANY, _("Default pen size"), wxDefaultPosition, wxDefaultSize, 0 );
m_TextPenWidth->Wrap( -1 ); m_TextPenWidth->Wrap( -1 );
m_TextPenWidth->SetToolTip( _("Selection of the pen size used to draw items which have no pen size specified.") );
sbOptionsSizer->Add( m_TextPenWidth, 0, wxRIGHT|wxLEFT, 5 ); sbOptionsSizer->Add( m_TextPenWidth, 0, wxRIGHT|wxLEFT, 5 );
m_DialogDefaultPenSize = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_DialogDefaultPenSize = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_DialogDefaultPenSize->SetToolTip( _("Selection of the pen size used to draw items which have no pen size speicfied.") );
sbOptionsSizer->Add( m_DialogDefaultPenSize, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); sbOptionsSizer->Add( m_DialogDefaultPenSize, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
wxString m_ModeColorOptionChoices[] = { _("Color"), _("Black and white") }; wxString m_ModeColorOptionChoices[] = { _("Color"), _("Black and white") };
...@@ -67,7 +67,7 @@ DIALOG_SVG_PRINT_base::DIALOG_SVG_PRINT_base( wxWindow* parent, wxWindowID id, c ...@@ -67,7 +67,7 @@ DIALOG_SVG_PRINT_base::DIALOG_SVG_PRINT_base( wxWindow* parent, wxWindowID id, c
sbOptionsSizer->Add( m_PrintBoardEdgesCtrl, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); sbOptionsSizer->Add( m_PrintBoardEdgesCtrl, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_printMirrorOpt = new wxCheckBox( this, wxID_ANY, _("Print mirror"), wxDefaultPosition, wxDefaultSize, 0 ); m_printMirrorOpt = new wxCheckBox( this, wxID_ANY, _("Print mirrored"), wxDefaultPosition, wxDefaultSize, 0 );
sbOptionsSizer->Add( m_printMirrorOpt, 0, wxRIGHT|wxLEFT, 5 ); sbOptionsSizer->Add( m_printMirrorOpt, 0, wxRIGHT|wxLEFT, 5 );
......
...@@ -207,7 +207,7 @@ ...@@ -207,7 +207,7 @@
<property name="style"></property> <property name="style"></property>
<property name="subclass"></property> <property name="subclass"></property>
<property name="toolbar_pane">0</property> <property name="toolbar_pane">0</property>
<property name="tooltip"></property> <property name="tooltip">Selection of the pen size used to draw items which have no pen size specified.</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
...@@ -290,7 +290,7 @@ ...@@ -290,7 +290,7 @@
<property name="style"></property> <property name="style"></property>
<property name="subclass"></property> <property name="subclass"></property>
<property name="toolbar_pane">0</property> <property name="toolbar_pane">0</property>
<property name="tooltip">Selection of the pen size used to draw items which have no pen size speicfied.</property> <property name="tooltip"></property>
<property name="validator_data_type"></property> <property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property> <property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property> <property name="validator_type">wxDefaultValidator</property>
...@@ -629,7 +629,7 @@ ...@@ -629,7 +629,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Print mirror</property> <property name="label">Print mirrored</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2010 Jean_Pierre Charras <jp.charras@ujf-grenoble.fr> * Copyright (C) 1992-2012 Jean_Pierre Charras <jp.charras at wanadoo.fr>
* Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -31,13 +31,14 @@ ...@@ -31,13 +31,14 @@
#include <pcbnew.h> #include <pcbnew.h>
#include <wxPcbStruct.h> #include <wxPcbStruct.h>
#include <pcbplot.h> #include <pcbplot.h>
#include <gendrill.h> #include <gendrill_Excellon_writer.h>
#include <class_board.h> #include <class_board.h>
#include <class_track.h> #include <class_track.h>
#include <class_module.h> #include <class_module.h>
#include <dialog_gendrill.h> #include <dialog_gendrill.h>
#include <wildcards_and_files_ext.h>
// Keywords for read and write config // Keywords for read and write config
...@@ -62,11 +63,26 @@ static DRILL_PRECISION precisionListForMetric[] = ...@@ -62,11 +63,26 @@ static DRILL_PRECISION precisionListForMetric[] =
}; };
/* This function displays the dialog frame for drill tools
*/
void PCB_EDIT_FRAME::InstallDrillFrame( wxCommandEvent& event )
{
DIALOG_GENDRILL dlg( this );
dlg.ShowModal();
}
DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* parent ) : DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* parent ) :
DIALOG_GENDRILL_BASE( parent ) DIALOG_GENDRILL_BASE( parent )
{ {
m_parent = parent; m_parent = parent;
m_board = parent->GetBoard(); m_board = parent->GetBoard();
m_config = wxGetApp().GetSettings();
m_plotOpts = m_parent->GetPlotSettings();
SetReturnCode( 1 ); SetReturnCode( 1 );
initDialog(); initDialog();
...@@ -75,14 +91,13 @@ DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* parent ) : ...@@ -75,14 +91,13 @@ DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* parent ) :
// Static members of DIALOG_GENDRILL // Static members of DIALOG_GENDRILL
int DIALOG_GENDRILL:: m_UnitDrillIsInch = true; int DIALOG_GENDRILL::m_UnitDrillIsInch = true;
int DIALOG_GENDRILL:: m_ZerosFormat = EXCELLON_WRITER::DECIMAL_FORMAT; int DIALOG_GENDRILL::m_ZerosFormat = EXCELLON_WRITER::DECIMAL_FORMAT;
bool DIALOG_GENDRILL::m_MinimalHeader = false; bool DIALOG_GENDRILL::m_MinimalHeader = false;
bool DIALOG_GENDRILL::m_Mirror = false; bool DIALOG_GENDRILL::m_Mirror = false;
bool DIALOG_GENDRILL::m_DrillOriginIsAuxAxis = false; bool DIALOG_GENDRILL::m_DrillOriginIsAuxAxis = false;
int DIALOG_GENDRILL:: m_PrecisionFormat = 1; int DIALOG_GENDRILL::m_PrecisionFormat = 1;
bool DIALOG_GENDRILL::m_createRpt = false; int DIALOG_GENDRILL::m_mapFileType = 1;
int DIALOG_GENDRILL::m_createMap = 0;
DIALOG_GENDRILL::~DIALOG_GENDRILL() DIALOG_GENDRILL::~DIALOG_GENDRILL()
...@@ -93,17 +108,12 @@ DIALOG_GENDRILL::~DIALOG_GENDRILL() ...@@ -93,17 +108,12 @@ DIALOG_GENDRILL::~DIALOG_GENDRILL()
void DIALOG_GENDRILL::initDialog() void DIALOG_GENDRILL::initDialog()
{ {
wxConfig* Config = wxGetApp().GetSettings(); m_config->Read( ZerosFormatKey, &DIALOG_GENDRILL::m_ZerosFormat );
m_config->Read( PrecisionKey, &DIALOG_GENDRILL::m_PrecisionFormat );
if( Config ) m_config->Read( MirrorKey, &DIALOG_GENDRILL::m_Mirror );
{ m_config->Read( MinimalHeaderKey, &DIALOG_GENDRILL::m_MinimalHeader );
Config->Read( ZerosFormatKey, &DIALOG_GENDRILL::m_ZerosFormat ); m_config->Read( UnitDrillInchKey, &DIALOG_GENDRILL::m_UnitDrillIsInch );
Config->Read( PrecisionKey, &DIALOG_GENDRILL::m_PrecisionFormat ); m_config->Read( DrillOriginIsAuxAxisKey, &DIALOG_GENDRILL::m_DrillOriginIsAuxAxis );
Config->Read( MirrorKey, &DIALOG_GENDRILL::m_Mirror );
Config->Read( MinimalHeaderKey, &DIALOG_GENDRILL::m_MinimalHeader );
Config->Read( UnitDrillInchKey, &DIALOG_GENDRILL::m_UnitDrillIsInch );
Config->Read( DrillOriginIsAuxAxisKey, &DIALOG_GENDRILL::m_DrillOriginIsAuxAxis );
}
InitDisplayParams(); InitDisplayParams();
} }
...@@ -129,8 +139,7 @@ void DIALOG_GENDRILL::InitDisplayParams() ...@@ -129,8 +139,7 @@ void DIALOG_GENDRILL::InitDisplayParams()
m_Check_Mirror->SetValue( m_Mirror ); m_Check_Mirror->SetValue( m_Mirror );
m_Choice_Drill_Map->SetSelection( m_createMap ); m_Choice_Drill_Map->SetSelection( m_mapFileType );
m_Choice_Drill_Report->SetSelection( m_createRpt );
m_ViaDrillValue->SetLabel( _( "Use Netclasses values" ) ); m_ViaDrillValue->SetLabel( _( "Use Netclasses values" ) );
...@@ -208,6 +217,9 @@ void DIALOG_GENDRILL::InitDisplayParams() ...@@ -208,6 +217,9 @@ void DIALOG_GENDRILL::InitDisplayParams()
msg = m_BuriedViasInfoMsg->GetLabel(); msg = m_BuriedViasInfoMsg->GetLabel();
msg << wxT( " " ) << m_blindOrBuriedViasCount; msg << wxT( " " ) << m_blindOrBuriedViasCount;
m_BuriedViasInfoMsg->SetLabel( msg ); m_BuriedViasInfoMsg->SetLabel( msg );
// Output directory
m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
} }
...@@ -215,17 +227,12 @@ void DIALOG_GENDRILL::UpdateConfig() ...@@ -215,17 +227,12 @@ void DIALOG_GENDRILL::UpdateConfig()
{ {
SetParams(); SetParams();
wxConfig* config = wxGetApp().GetSettings(); m_config->Write( ZerosFormatKey, m_ZerosFormat );
m_config->Write( PrecisionKey, m_PrecisionFormat );
if( config ) m_config->Write( MirrorKey, m_Mirror );
{ m_config->Write( MinimalHeaderKey, m_MinimalHeader );
config->Write( ZerosFormatKey, m_ZerosFormat ); m_config->Write( UnitDrillInchKey, m_UnitDrillIsInch );
config->Write( PrecisionKey, m_PrecisionFormat ); m_config->Write( DrillOriginIsAuxAxisKey, m_DrillOriginIsAuxAxis );
config->Write( MirrorKey, m_Mirror );
config->Write( MinimalHeaderKey, m_MinimalHeader );
config->Write( UnitDrillInchKey, m_UnitDrillIsInch );
config->Write( DrillOriginIsAuxAxisKey, m_DrillOriginIsAuxAxis );
}
} }
...@@ -234,11 +241,14 @@ void DIALOG_GENDRILL::OnSelDrillUnitsSelected( wxCommandEvent& event ) ...@@ -234,11 +241,14 @@ void DIALOG_GENDRILL::OnSelDrillUnitsSelected( wxCommandEvent& event )
UpdatePrecisionOptions(); UpdatePrecisionOptions();
} }
void DIALOG_GENDRILL::OnGenMapFile( wxCommandEvent& event )
{
GenDrillAndMapFiles( false, true);
}
void DIALOG_GENDRILL::OnOkClick( wxCommandEvent& event ) void DIALOG_GENDRILL::OnGenDrillFile( wxCommandEvent& event )
{ {
GenDrillAndReportFiles(); GenDrillAndMapFiles(true, false);
EndModal( wxID_OK );
} }
...@@ -276,17 +286,53 @@ void DIALOG_GENDRILL::UpdatePrecisionOptions() ...@@ -276,17 +286,53 @@ void DIALOG_GENDRILL::UpdatePrecisionOptions()
m_Choice_Precision->Enable( true ); m_Choice_Precision->Enable( true );
} }
void DIALOG_GENDRILL::OnOutputDirectoryBrowseClicked( wxCommandEvent& event )
{
// Build the absolute path of current output plot directory
// to preselect it when opening the dialog.
wxFileName fn( m_outputDirectoryName->GetValue() );
wxString path;
if( fn.IsRelative() )
path = wxGetCwd() + fn.GetPathSeparator() + m_outputDirectoryName->GetValue();
else
path = m_outputDirectoryName->GetValue();
wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
if( dirDialog.ShowModal() == wxID_CANCEL )
return;
wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
wxMessageDialog dialog( this, _( "Use a relative path? " ),
_( "Plot Output Directory" ),
wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
if( dialog.ShowModal() == wxID_YES )
{
wxString boardFilePath = ( (wxFileName) m_parent->GetBoard()->GetFileName() ).GetPath();
if( !dirName.MakeRelativeTo( boardFilePath ) )
wxMessageBox( _(
"Cannot make path relative (target volume different from board file volume)!" ),
_( "Plot Output Directory" ), wxOK | wxICON_ERROR );
}
m_outputDirectoryName->SetValue( dirName.GetFullPath() );
}
void DIALOG_GENDRILL::SetParams() void DIALOG_GENDRILL::SetParams()
{ {
wxString msg; wxString msg;
PCB_PLOT_PARAMS plot_opts = m_board->GetPlotOptions(); // Set output directory and replace backslashes with forward ones
wxString dirStr;
dirStr = m_outputDirectoryName->GetValue();
dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
m_plotOpts.SetOutputDirectory( dirStr );
m_plotDefaultpath = plot_opts.GetOutputDirectory(); m_mapFileType = m_Choice_Drill_Map->GetSelection();
m_createMap = m_Choice_Drill_Map->GetSelection();
m_createRpt = m_Choice_Drill_Report->GetSelection();
m_UnitDrillIsInch = (m_Choice_Unit->GetSelection() == 0) ? false : true; m_UnitDrillIsInch = (m_Choice_Unit->GetSelection() == 0) ? false : true;
m_MinimalHeader = m_Check_Minimal->IsChecked(); m_MinimalHeader = m_Check_Minimal->IsChecked();
...@@ -295,8 +341,6 @@ void DIALOG_GENDRILL::SetParams() ...@@ -295,8 +341,6 @@ void DIALOG_GENDRILL::SetParams()
m_DrillOriginIsAuxAxis = m_Choice_Drill_Offset->GetSelection(); m_DrillOriginIsAuxAxis = m_Choice_Drill_Offset->GetSelection();
m_PrecisionFormat = m_Choice_Precision->GetSelection(); m_PrecisionFormat = m_Choice_Precision->GetSelection();
plot_opts.SetHPGLPenNum( 1 );
if( m_Choice_Drill_Offset->GetSelection() == 0 ) if( m_Choice_Drill_Offset->GetSelection() == 0 )
m_FileDrillOffset = wxPoint( 0, 0 ); m_FileDrillOffset = wxPoint( 0, 0 );
else else
...@@ -310,5 +354,271 @@ void DIALOG_GENDRILL::SetParams() ...@@ -310,5 +354,271 @@ void DIALOG_GENDRILL::SetParams()
else else
m_Precision = precisionListForMetric[idx]; m_Precision = precisionListForMetric[idx];
m_board->SetPlotOptions( plot_opts ); m_board->SetPlotOptions( m_plotOpts );
}
/**
* Function GenDrillAndMapFiles
* Calls the functions to create EXCELLON drill files and/or drill map files
* >When all holes are through, only one excellon file is created.
* >When there are some partial holes (some blind or buried vias),
* one excellon file is created, for all plated through holes,
* and one file per layer pair, which have one or more holes, excluding
* through holes, already in the first file.
* one file for all Not Plated through holes
*/
void DIALOG_GENDRILL::GenDrillAndMapFiles(bool aGenDrill, bool aGenMap)
{
wxString layer_extend; /* added to the Board FileName to
* create FullFileName (= Board
* FileName + layer pair names) */
wxString msg;
bool hasBuriedVias = false; /* If true, drill files are created
* layer pair by layer pair for
* buried vias */
int layer1 = LAYER_N_BACK;
int layer2 = LAYER_N_FRONT;
bool gen_through_holes = true;
bool gen_NPTH_holes = false;
wxString currentWD = ::wxGetCwd();
UpdateConfig(); // set params and Save drill options
m_parent->ClearMsgPanel();
if( m_microViasCount || m_blindOrBuriedViasCount )
hasBuriedVias = true;
EXCELLON_WRITER excellonWriter( m_parent->GetBoard(),
m_FileDrillOffset );
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 );
wxFileName fn;
for( ; ; )
{
excellonWriter.BuildHolesList( layer1, layer2,
gen_through_holes ? false : true, gen_NPTH_holes );
if( excellonWriter.GetHolesCount() > 0 ) // has holes?
{
fn = m_parent->GetBoard()->GetFileName();
layer_extend.Empty();
if( gen_NPTH_holes )
{
layer_extend << wxT( "-NPTH" );
}
else if( !gen_through_holes )
{
if( layer1 == LAYER_N_BACK )
layer_extend << wxT( "-back" );
else
layer_extend << wxT( "-inner" ) << layer1;
if( layer2 == LAYER_N_FRONT )
layer_extend << wxT( "-front" );
else
layer_extend << wxT( "-inner" ) << layer2;
}
fn.SetName( fn.GetName() + layer_extend );
wxString defaultPath = m_plotOpts.GetOutputDirectory();
if( defaultPath.IsEmpty() )
defaultPath = ::wxGetCwd();
fn.SetPath( defaultPath );
if( aGenDrill )
{
fn.SetExt( DrillFileExtension );
wxString fullFilename = fn.GetFullPath();
FILE* file = wxFopen( fullFilename, wxT( "w" ) );
if( file == 0 )
{
msg.Printf( _( "** Unable to create %s **\n" ),
GetChars( fullFilename ) );
m_messagesBox->AppendText( msg );
break;
}
else
{
msg.Printf( _( "Plot: %s OK\n" ), GetChars( fullFilename ) );
m_messagesBox->AppendText( msg );
}
excellonWriter.CreateDrillFile( file );
}
if( aGenMap )
{
const PlotFormat filefmt[5] =
{ // Keep these format ids in the same order than m_Choice_Drill_Map choices
PLOT_FORMAT_HPGL, PLOT_FORMAT_POST, PLOT_FORMAT_GERBER,
PLOT_FORMAT_DXF, PLOT_FORMAT_SVG
};
unsigned choice = (unsigned) m_Choice_Drill_Map->GetSelection();
if( choice > 4 )
choice = 1;
fn.SetExt( wxEmptyString ); // Will be modified by GenDrillMap
GenDrillMap( fn.GetFullPath(), excellonWriter, filefmt[choice] );
}
}
if( gen_NPTH_holes ) // The last drill file was created
break;
if( !hasBuriedVias )
gen_NPTH_holes = true;
else
{
if( gen_through_holes )
layer2 = layer1 + 1; // prepare generation of first layer pair
else
{
if( layer2 >= LAYER_N_FRONT ) // no more layer pair to consider
{
layer1 = LAYER_N_BACK;
layer2 = LAYER_N_FRONT;
gen_NPTH_holes = true;
continue;
}
layer1++;
layer2++; // use next layer pair
if( layer2 == m_parent->GetBoard()->GetCopperLayerCount() - 1 )
layer2 = LAYER_N_FRONT; // the last layer is always the
// Front layer
}
gen_through_holes = false;
}
}
::wxSetWorkingDirectory( currentWD );
}
/*
* Create a plain text report file giving a list of drill values and drill count
* for through holes, oblong holes, and for buried vias,
* drill values and drill count per layer pair
*/
void DIALOG_GENDRILL::OnGenReportFile( wxCommandEvent& event )
{
UpdateConfig(); // set params and Save drill options
wxFileName fn = m_parent->GetBoard()->GetFileName();
fn.SetName( fn.GetName() + wxT( "-drl" ) );
fn.SetExt( ReportFileExtension );
wxString defaultPath = m_plotOpts.GetOutputDirectory();
if( defaultPath.IsEmpty() )
defaultPath = ::wxGetCwd();
wxFileDialog dlg( this, _( "Save Drill Report File" ), defaultPath,
fn.GetFullName(), wxGetTranslation( ReportFileWildcard ),
wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL )
return;
EXCELLON_WRITER excellonWriter( m_parent->GetBoard(),
m_FileDrillOffset );
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 );
bool success = excellonWriter.GenDrillReportFile( dlg.GetPath() );
wxString msg;
if( ! success )
{
msg.Printf( _( "** Unable to create %s **\n" ), GetChars( dlg.GetPath() ) );
m_messagesBox->AppendText( msg );
}
else
{
msg.Printf( _( "Create report file %s\n" ), GetChars( dlg.GetPath() ) );
m_messagesBox->AppendText( msg );
}
}
// Generate the drill map of the board
void DIALOG_GENDRILL::GenDrillMap( const wxString aFileName,
EXCELLON_WRITER& aExcellonWriter,
PlotFormat format )
{
wxString ext, wildcard;
/* Init extension */
switch( format )
{
case PLOT_FORMAT_HPGL:
ext = HPGL_PLOTTER::GetDefaultFileExtension();
wildcard = _( "HPGL plot files (.plt)|*.plt" );
break;
case PLOT_FORMAT_POST:
ext = PS_PLOTTER::GetDefaultFileExtension();
wildcard = _( "PostScript files (.ps)|*.ps" );
break;
case PLOT_FORMAT_GERBER:
ext = GERBER_PLOTTER::GetDefaultFileExtension();
wildcard = _( "Gerber files (.pho)|*.pho" );
break;
case PLOT_FORMAT_DXF:
ext = DXF_PLOTTER::GetDefaultFileExtension();
wildcard = _( "DXF files (.dxf)|*.dxf" );
break;
case PLOT_FORMAT_SVG:
ext = SVG_PLOTTER::GetDefaultFileExtension();
wildcard = SVGFileWildcard;
break;
default:
wxMessageBox( wxT( "DIALOG_GENDRILL::GenDrillMap() error" ) );
return;
}
/* Init file name */
wxFileName fn = aFileName;
fn.SetName( fn.GetName() + wxT( "-drl_map" ) );
fn.SetExt( ext );
wxString fullFilename = fn.GetFullPath();
bool success = aExcellonWriter.GenDrillMapFile( fullFilename,
m_parent->GetPageSettings(),
format );
wxString msg;
if( ! success )
{
msg.Printf( _( "** Unable to create %s **\n" ),
GetChars( fullFilename ) );
m_messagesBox->AppendText( msg );
return;
}
else
{
msg.Printf( _( "Plot: %s OK\n" ), GetChars( fullFilename ) );
m_messagesBox->AppendText( msg );
}
} }
...@@ -51,8 +51,9 @@ public: ...@@ -51,8 +51,9 @@ public:
private: private:
PCB_EDIT_FRAME* m_parent; PCB_EDIT_FRAME* m_parent;
wxConfig* m_config;
BOARD* m_board; BOARD* m_board;
wxString m_plotDefaultpath; // Current default plot dircetory. PCB_PLOT_PARAMS m_plotOpts;
int m_platedPadsHoleCount; int m_platedPadsHoleCount;
int m_notplatedPadsHoleCount; int m_notplatedPadsHoleCount;
...@@ -60,8 +61,7 @@ private: ...@@ -60,8 +61,7 @@ private:
int m_microViasCount; int m_microViasCount;
int m_blindOrBuriedViasCount; int m_blindOrBuriedViasCount;
static bool m_createRpt; // true to create a drill file report static int m_mapFileType; // HPGL, PS ...
static int m_createMap; // > 0 to create a map file report
void initDialog(); void initDialog();
...@@ -70,24 +70,25 @@ private: ...@@ -70,24 +70,25 @@ private:
// event functions // event functions
void OnSelDrillUnitsSelected( wxCommandEvent& event ); void OnSelDrillUnitsSelected( wxCommandEvent& event );
void OnSelZerosFmtSelected( wxCommandEvent& event ); void OnSelZerosFmtSelected( wxCommandEvent& event );
void OnOkClick( wxCommandEvent& event ); void OnGenDrillFile( wxCommandEvent& event );
void OnGenMapFile( wxCommandEvent& event );
void OnGenReportFile( wxCommandEvent& event );
void OnCancelClick( wxCommandEvent& event ); void OnCancelClick( wxCommandEvent& event );
void OnOutputDirectoryBrowseClicked( wxCommandEvent& event );
// Specific functions: // Specific functions:
void SetParams( void ); void SetParams( void );
void GenDrillAndReportFiles(); void GenDrillAndMapFiles(bool aGenDrill, bool aGenMap);
void GenDrillMap( const wxString aFileName, void GenDrillMap( const wxString aFileName,
std::vector<HOLE_INFO>& aHoleListBuffer, EXCELLON_WRITER& aExcellonWriter,
std::vector<DRILL_TOOL>& aToolListBuffer, PlotFormat format );
int format );
void UpdatePrecisionOptions(); void UpdatePrecisionOptions();
void UpdateConfig(); void UpdateConfig();
void GenDrillReport( const wxString aFileName ); int Create_Drill_File_EXCELLON( FILE* aFile,
int Create_Drill_File_EXCELLON( FILE* aFile, wxPoint aOffset );
wxPoint aOffset, int Gen_Liste_Tools( std::vector<DRILL_TOOL>& buffer,
std::vector<HOLE_INFO>& aHoleListBuffer, bool print_header );
std::vector<DRILL_TOOL>& aToolListBuffer );
int Gen_Liste_Tools( std::vector<DRILL_TOOL>& buffer, bool print_header );
/** /**
* Return the selected format for coordinates, if not decimal * Return the selected format for coordinates, if not decimal
......
...@@ -14,7 +14,28 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con ...@@ -14,7 +14,28 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
this->SetSizeHints( wxDefaultSize, wxDefaultSize ); this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bMainSizer; wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxHORIZONTAL ); bMainSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bupperSizer;
bupperSizer = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* bdirnameSizer;
bdirnameSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Output directory:") ), wxHORIZONTAL );
m_outputDirectoryName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
bdirnameSizer->Add( m_outputDirectoryName, 1, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_buttonBrowse = new wxButton( this, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 );
bdirnameSizer->Add( m_buttonBrowse, 0, wxBOTTOM|wxLEFT, 5 );
bupperSizer->Add( bdirnameSizer, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
bMainSizer->Add( bupperSizer, 0, wxEXPAND, 5 );
wxBoxSizer* bmiddlerSizer;
bmiddlerSizer = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* m_LeftBoxSizer; wxBoxSizer* m_LeftBoxSizer;
m_LeftBoxSizer = new wxBoxSizer( wxVERTICAL ); m_LeftBoxSizer = new wxBoxSizer( wxVERTICAL );
...@@ -41,36 +62,20 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con ...@@ -41,36 +62,20 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
m_LeftBoxSizer->Add( m_Choice_Precision, 0, wxALL|wxEXPAND, 5 ); m_LeftBoxSizer->Add( m_Choice_Precision, 0, wxALL|wxEXPAND, 5 );
wxString m_Choice_Drill_OffsetChoices[] = { _("Absolute"), _("Auxiliary axis") };
int m_Choice_Drill_OffsetNChoices = sizeof( m_Choice_Drill_OffsetChoices ) / sizeof( wxString );
m_Choice_Drill_Offset = new wxRadioBox( this, wxID_ANY, _("Drill Origin:"), wxDefaultPosition, wxDefaultSize, m_Choice_Drill_OffsetNChoices, m_Choice_Drill_OffsetChoices, 1, wxRA_SPECIFY_COLS );
m_Choice_Drill_Offset->SetSelection( 0 );
m_Choice_Drill_Offset->SetToolTip( _("Choose the coordinate origin: absolute or relative to the auxiliray axis") );
m_LeftBoxSizer->Add( m_Choice_Drill_Offset, 0, wxALL|wxEXPAND, 5 );
bmiddlerSizer->Add( m_LeftBoxSizer, 0, wxEXPAND, 5 );
bMainSizer->Add( m_LeftBoxSizer, 1, wxEXPAND, 5 );
wxBoxSizer* bMiddleBoxSizer; wxBoxSizer* bMiddleBoxSizer;
bMiddleBoxSizer = new wxBoxSizer( wxVERTICAL ); bMiddleBoxSizer = new wxBoxSizer( wxVERTICAL );
wxString m_Choice_Drill_MapChoices[] = { _("None"), _("Drill map (HPGL)"), _("Drill map (PostScript)"), _("Drill map (Gerber)"), _("Drill map (DXF)"), _("Drill map (SVG)") }; wxString m_Choice_Drill_MapChoices[] = { _("Drill map (HPGL)"), _("Drill map (PostScript)"), _("Drill map (Gerber)"), _("Drill map (DXF)"), _("Drill map (SVG)") };
int m_Choice_Drill_MapNChoices = sizeof( m_Choice_Drill_MapChoices ) / sizeof( wxString ); int m_Choice_Drill_MapNChoices = sizeof( m_Choice_Drill_MapChoices ) / sizeof( wxString );
m_Choice_Drill_Map = new wxRadioBox( this, wxID_ANY, _("Drill Map:"), wxDefaultPosition, wxDefaultSize, m_Choice_Drill_MapNChoices, m_Choice_Drill_MapChoices, 1, wxRA_SPECIFY_COLS ); m_Choice_Drill_Map = new wxRadioBox( this, wxID_ANY, _("Drill Map:"), wxDefaultPosition, wxDefaultSize, m_Choice_Drill_MapNChoices, m_Choice_Drill_MapChoices, 1, wxRA_SPECIFY_COLS );
m_Choice_Drill_Map->SetSelection( 0 ); m_Choice_Drill_Map->SetSelection( 1 );
m_Choice_Drill_Map->SetToolTip( _("Creates a drill map in PS, HPGL or other formats") ); m_Choice_Drill_Map->SetToolTip( _("Creates a drill map in PS, HPGL or other formats") );
bMiddleBoxSizer->Add( m_Choice_Drill_Map, 0, wxALL|wxEXPAND, 5 ); bMiddleBoxSizer->Add( m_Choice_Drill_Map, 0, wxALL|wxEXPAND, 5 );
wxString m_Choice_Drill_ReportChoices[] = { _("None"), _("Drill report") };
int m_Choice_Drill_ReportNChoices = sizeof( m_Choice_Drill_ReportChoices ) / sizeof( wxString );
m_Choice_Drill_Report = new wxRadioBox( this, wxID_ANY, _("Drill Report:"), wxDefaultPosition, wxDefaultSize, m_Choice_Drill_ReportNChoices, m_Choice_Drill_ReportChoices, 1, wxRA_SPECIFY_COLS );
m_Choice_Drill_Report->SetSelection( 0 );
m_Choice_Drill_Report->SetToolTip( _("Creates a plain text report") );
bMiddleBoxSizer->Add( m_Choice_Drill_Report, 0, wxALL|wxEXPAND, 5 );
wxStaticBoxSizer* sbOptSizer; wxStaticBoxSizer* sbOptSizer;
sbOptSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options:") ), wxVERTICAL ); sbOptSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options:") ), wxVERTICAL );
...@@ -81,10 +86,18 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con ...@@ -81,10 +86,18 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
sbOptSizer->Add( m_Check_Minimal, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); sbOptSizer->Add( m_Check_Minimal, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
bMiddleBoxSizer->Add( sbOptSizer, 0, wxEXPAND, 5 ); bMiddleBoxSizer->Add( sbOptSizer, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
wxString m_Choice_Drill_OffsetChoices[] = { _("Absolute"), _("Auxiliary axis") };
int m_Choice_Drill_OffsetNChoices = sizeof( m_Choice_Drill_OffsetChoices ) / sizeof( wxString );
m_Choice_Drill_Offset = new wxRadioBox( this, wxID_ANY, _("Drill Origin:"), wxDefaultPosition, wxDefaultSize, m_Choice_Drill_OffsetNChoices, m_Choice_Drill_OffsetChoices, 1, wxRA_SPECIFY_COLS );
m_Choice_Drill_Offset->SetSelection( 0 );
m_Choice_Drill_Offset->SetToolTip( _("Choose the coordinate origin: absolute or relative to the auxiliray axis") );
bMiddleBoxSizer->Add( m_Choice_Drill_Offset, 0, wxALL|wxEXPAND, 5 );
bMainSizer->Add( bMiddleBoxSizer, 1, wxEXPAND, 5 );
bmiddlerSizer->Add( bMiddleBoxSizer, 0, wxEXPAND, 5 );
wxBoxSizer* bRightBoxSizer; wxBoxSizer* bRightBoxSizer;
bRightBoxSizer = new wxBoxSizer( wxVERTICAL ); bRightBoxSizer = new wxBoxSizer( wxVERTICAL );
...@@ -108,7 +121,7 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con ...@@ -108,7 +121,7 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
m_MicroViasDrillSizer->Add( m_MicroViaDrillValue, 0, wxALL, 5 ); m_MicroViasDrillSizer->Add( m_MicroViaDrillValue, 0, wxALL, 5 );
sbSizerInfo->Add( m_MicroViasDrillSizer, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); sbSizerInfo->Add( m_MicroViasDrillSizer, 0, wxEXPAND|wxBOTTOM, 5 );
wxStaticBoxSizer* sbSizerHoles; wxStaticBoxSizer* sbSizerHoles;
sbSizerHoles = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Holes Count:") ), wxVERTICAL ); sbSizerHoles = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Holes Count:") ), wxVERTICAL );
...@@ -134,23 +147,49 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con ...@@ -134,23 +147,49 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
sbSizerHoles->Add( m_BuriedViasInfoMsg, 0, wxALL, 5 ); sbSizerHoles->Add( m_BuriedViasInfoMsg, 0, wxALL, 5 );
sbSizerInfo->Add( sbSizerHoles, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 ); sbSizerInfo->Add( sbSizerHoles, 1, wxEXPAND|wxBOTTOM, 5 );
bRightBoxSizer->Add( sbSizerInfo, 0, wxEXPAND|wxTOP, 5 ); bRightBoxSizer->Add( sbSizerInfo, 0, wxEXPAND|wxTOP, 5 );
bRightBoxSizer->Add( 10, 10, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); bmiddlerSizer->Add( bRightBoxSizer, 0, wxEXPAND, 5 );
wxBoxSizer* bSizerButtons;
bSizerButtons = new wxBoxSizer( wxVERTICAL );
bSizerButtons->Add( 10, 20, 0, 0, 5 );
m_buttonDrill = new wxButton( this, ID_GEN_DRILL_FILE, _("Drill Fille"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonDrill->SetDefault();
bSizerButtons->Add( m_buttonDrill, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
m_buttonMap = new wxButton( this, wxID_ANY, _("Map File"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerButtons->Add( m_buttonMap, 0, wxALL, 5 );
m_buttonReport = new wxButton( this, wxID_ANY, _("Report File"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerButtons->Add( m_buttonReport, 0, wxALL, 5 );
m_CancelButton = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerButtons->Add( m_CancelButton, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
bmiddlerSizer->Add( bSizerButtons, 1, wxEXPAND, 5 );
bMainSizer->Add( bmiddlerSizer, 0, wxEXPAND, 5 );
wxStaticBoxSizer* bmsgSizer;
bmsgSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Messages:") ), wxVERTICAL );
m_OkButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); m_messagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
m_OkButton->SetDefault(); m_messagesBox->SetMinSize( wxSize( -1,90 ) );
bRightBoxSizer->Add( m_OkButton, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
m_CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); bmsgSizer->Add( m_messagesBox, 1, wxALL|wxEXPAND, 5 );
bRightBoxSizer->Add( m_CancelButton, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
bMainSizer->Add( bRightBoxSizer, 1, wxEXPAND, 5 ); bMainSizer->Add( bmsgSizer, 1, wxEXPAND, 5 );
this->SetSizer( bMainSizer ); this->SetSizer( bMainSizer );
...@@ -159,18 +198,24 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con ...@@ -159,18 +198,24 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
this->Centre( wxBOTH ); this->Centre( wxBOTH );
// Connect Events // Connect Events
m_buttonBrowse->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnOutputDirectoryBrowseClicked ), NULL, this );
m_Choice_Unit->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnSelDrillUnitsSelected ), NULL, this ); m_Choice_Unit->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnSelDrillUnitsSelected ), NULL, this );
m_Choice_Zeros_Format->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnSelZerosFmtSelected ), NULL, this ); m_Choice_Zeros_Format->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnSelZerosFmtSelected ), NULL, this );
m_OkButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnOkClick ), NULL, this ); m_buttonDrill->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnGenDrillFile ), NULL, this );
m_buttonMap->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnGenMapFile ), NULL, this );
m_buttonReport->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnGenReportFile ), NULL, this );
m_CancelButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnCancelClick ), NULL, this ); m_CancelButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnCancelClick ), NULL, this );
} }
DIALOG_GENDRILL_BASE::~DIALOG_GENDRILL_BASE() DIALOG_GENDRILL_BASE::~DIALOG_GENDRILL_BASE()
{ {
// Disconnect Events // Disconnect Events
m_buttonBrowse->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnOutputDirectoryBrowseClicked ), NULL, this );
m_Choice_Unit->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnSelDrillUnitsSelected ), NULL, this ); m_Choice_Unit->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnSelDrillUnitsSelected ), NULL, this );
m_Choice_Zeros_Format->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnSelZerosFmtSelected ), NULL, this ); m_Choice_Zeros_Format->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnSelZerosFmtSelected ), NULL, this );
m_OkButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnOkClick ), NULL, this ); m_buttonDrill->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnGenDrillFile ), NULL, this );
m_buttonMap->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnGenMapFile ), NULL, this );
m_buttonReport->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnGenReportFile ), NULL, this );
m_CancelButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnCancelClick ), NULL, this ); m_CancelButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnCancelClick ), NULL, this );
} }
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -13,20 +13,22 @@ ...@@ -13,20 +13,22 @@
#include <wx/intl.h> #include <wx/intl.h>
#include "dialog_shim.h" #include "dialog_shim.h"
#include <wx/string.h> #include <wx/string.h>
#include <wx/radiobox.h> #include <wx/textctrl.h>
#include <wx/gdicmn.h> #include <wx/gdicmn.h>
#include <wx/font.h> #include <wx/font.h>
#include <wx/colour.h> #include <wx/colour.h>
#include <wx/settings.h> #include <wx/settings.h>
#include <wx/button.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/checkbox.h>
#include <wx/statbox.h> #include <wx/statbox.h>
#include <wx/radiobox.h>
#include <wx/checkbox.h>
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/button.h>
#include <wx/dialog.h> #include <wx/dialog.h>
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
#define ID_GEN_DRILL_FILE 1000
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_GENDRILL_BASE /// Class DIALOG_GENDRILL_BASE
...@@ -36,14 +38,15 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM ...@@ -36,14 +38,15 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
private: private:
protected: protected:
wxTextCtrl* m_outputDirectoryName;
wxButton* m_buttonBrowse;
wxRadioBox* m_Choice_Unit; wxRadioBox* m_Choice_Unit;
wxRadioBox* m_Choice_Zeros_Format; wxRadioBox* m_Choice_Zeros_Format;
wxRadioBox* m_Choice_Precision; wxRadioBox* m_Choice_Precision;
wxRadioBox* m_Choice_Drill_Offset;
wxRadioBox* m_Choice_Drill_Map; wxRadioBox* m_Choice_Drill_Map;
wxRadioBox* m_Choice_Drill_Report;
wxCheckBox* m_Check_Mirror; wxCheckBox* m_Check_Mirror;
wxCheckBox* m_Check_Minimal; wxCheckBox* m_Check_Minimal;
wxRadioBox* m_Choice_Drill_Offset;
wxStaticBoxSizer* m_DefaultViasDrillSizer; wxStaticBoxSizer* m_DefaultViasDrillSizer;
wxStaticText* m_ViaDrillValue; wxStaticText* m_ViaDrillValue;
wxStaticBoxSizer* m_MicroViasDrillSizer; wxStaticBoxSizer* m_MicroViasDrillSizer;
...@@ -53,19 +56,25 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM ...@@ -53,19 +56,25 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
wxStaticText* m_ThroughViasInfoMsg; wxStaticText* m_ThroughViasInfoMsg;
wxStaticText* m_MicroViasInfoMsg; wxStaticText* m_MicroViasInfoMsg;
wxStaticText* m_BuriedViasInfoMsg; wxStaticText* m_BuriedViasInfoMsg;
wxButton* m_OkButton; wxButton* m_buttonDrill;
wxButton* m_buttonMap;
wxButton* m_buttonReport;
wxButton* m_CancelButton; wxButton* m_CancelButton;
wxTextCtrl* m_messagesBox;
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
virtual void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSelDrillUnitsSelected( wxCommandEvent& event ) { event.Skip(); } virtual void OnSelDrillUnitsSelected( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSelZerosFmtSelected( wxCommandEvent& event ) { event.Skip(); } virtual void OnSelZerosFmtSelected( wxCommandEvent& event ) { event.Skip(); }
virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnGenDrillFile( wxCommandEvent& event ) { event.Skip(); }
virtual void OnGenMapFile( wxCommandEvent& event ) { event.Skip(); }
virtual void OnGenReportFile( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
public: public:
DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Drill Files Generation"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 455,358 ), 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,471 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_GENDRILL_BASE(); ~DIALOG_GENDRILL_BASE();
}; };
......
/************************************************************************/ /**
/* Functions to create drill data used to create files and report files */ * @file gen_drill_report_files.cpp
/************************************************************************/ * @brief Functions to create report and map files for EXCELLON drill files.
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2012 Jean_Pierre Charras <jp.charras at wanadoo.fr>
* Copyright (C) 1992-2012 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <fctsys.h> #include <fctsys.h>
#include <common.h> #include <common.h>
#include <plot_common.h> #include <plot_common.h>
#include <base_struct.h> #include <base_struct.h>
#include <colors.h>
#include <drawtxt.h> #include <drawtxt.h>
#include <confirm.h> #include <confirm.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <macros.h>
#include <class_board.h> #include <class_board.h>
#include <pcbnew.h> #include <pcbnew.h>
#include <pcbplot.h> #include <pcbplot.h>
#include <gendrill.h> #include <gendrill_Excellon_writer.h>
/* Conversion utilities - these will be used often in there... */ /* Conversion utilities - these will be used often in there... */
static double diameter_in_inches(double ius) inline double diameter_in_inches( double ius )
{ {
return ius * 0.001 / IU_PER_MILS; return ius * 0.001 / IU_PER_MILS;
} }
static double diameter_in_mm(double ius)
inline double diameter_in_mm( double ius )
{ {
return ius / IU_PER_MM; return ius / IU_PER_MM;
} }
void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName, /* Creates a hole map of the board in HPGL, POSTSCRIPT or other supported formats
const PAGE_INFO& aSheet, * Each hole size has a the drill mark symbol (circle, cross X, cross + ...) up to
std::vector<HOLE_INFO> aHoleListBuffer, * PLOTTER::MARKER_COUNT different values.
std::vector<DRILL_TOOL> aToolListBuffer, * If more than PLOTTER::MARKER_COUNT different values,
bool aUnit_Drill_is_Inch, int format, * these other vaules share the same mark
const wxPoint& auxoffset ) */
bool EXCELLON_WRITER::GenDrillMapFile( const wxString& aFullFileName,
const PAGE_INFO& aSheet,
PlotFormat aFormat )
{ {
double scale = 1.0; double scale = 1.0;
wxPoint offset; wxPoint offset;
PLOTTER* plotter = NULL; PLOTTER* plotter = NULL;
PCB_PLOT_PARAMS plot_opts; // starts plotting with default options PCB_PLOT_PARAMS plot_opts; // starts plotting with default options
LOCALE_IO toggle; // use standard C notation for float numbers LOCALE_IO toggle; // use standard C notation for float numbers
// Calculate dimensions and center of PCB // Calculate dimensions and center of PCB
EDA_RECT bbbox = aPcb->ComputeBoundingBox(true); EDA_RECT bbbox = m_pcb->ComputeBoundingBox( true );
// Calculate the scale for the format type, scale 1 in HPGL, drawing on // Calculate the scale for the format type, scale 1 in HPGL, drawing on
// an A4 sheet in PS, + text description of symbols // an A4 sheet in PS, + text description of symbols
switch( format ) switch( aFormat )
{ {
case PLOT_FORMAT_GERBER: case PLOT_FORMAT_GERBER:
offset = auxoffset; offset = GetOffset();
plotter = new GERBER_PLOTTER(); plotter = new GERBER_PLOTTER();
plotter->SetViewport( offset, IU_PER_DECIMILS, scale, false ); plotter->SetViewport( offset, IU_PER_DECIMILS, scale, false );
break; break;
case PLOT_FORMAT_HPGL: // Scale for HPGL format. case PLOT_FORMAT_HPGL: // Scale for HPGL format.
{ {
HPGL_PLOTTER* hpgl_plotter = new HPGL_PLOTTER; HPGL_PLOTTER* hpgl_plotter = new HPGL_PLOTTER;
plotter = hpgl_plotter; plotter = hpgl_plotter;
...@@ -76,15 +103,15 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName, ...@@ -76,15 +103,15 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
wxSize pageSizeIU = pageA4.GetSizeIU(); wxSize pageSizeIU = pageA4.GetSizeIU();
// Reserve a margin around the page. // Reserve a margin around the page.
int margin = (int)(20 * IU_PER_MM ); int margin = (int) (20 * IU_PER_MM );
// Calculate a scaling factor to print the board on the sheet // Calculate a scaling factor to print the board on the sheet
double Xscale = (double)( pageSizeIU.x - ( 2 * margin ) ) / bbbox.GetWidth(); double Xscale = (double) ( pageSizeIU.x - ( 2 * margin ) ) / bbbox.GetWidth();
// We should print the list of drill sizes, so reserve room for it // We should print the list of drill sizes, so reserve room for it
// 60% height for board 40% height for list // 60% height for board 40% height for list
int ypagesize_for_board = (int) (pageSizeIU.y * 0.6); int ypagesize_for_board = (int) (pageSizeIU.y * 0.6);
double Yscale = (double)( ypagesize_for_board - margin ) / bbbox.GetHeight(); double Yscale = (double) ( ypagesize_for_board - margin ) / bbbox.GetHeight();
scale = std::min( Xscale, Yscale ); scale = std::min( Xscale, Yscale );
...@@ -93,9 +120,9 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName, ...@@ -93,9 +120,9 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
// So the scale is clipped at 3.0; // So the scale is clipped at 3.0;
scale = std::min( scale, 3.0 ); scale = std::min( scale, 3.0 );
offset.x = (int) ( (double) bbbox.Centre().x - ( pageSizeIU.x / 2.0 ) / scale ); offset.x = (int) ( (double) bbbox.Centre().x - ( pageSizeIU.x / 2.0 ) / scale );
offset.y = (int) ( (double) bbbox.Centre().y - offset.y = (int) ( (double) bbbox.Centre().y -
( ypagesize_for_board / 2.0 ) / scale ); ( ypagesize_for_board / 2.0 ) / scale );
PS_PLOTTER* ps_plotter = new PS_PLOTTER; PS_PLOTTER* ps_plotter = new PS_PLOTTER;
plotter = ps_plotter; plotter = ps_plotter;
...@@ -126,16 +153,24 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName, ...@@ -126,16 +153,24 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
wxASSERT( false ); wxASSERT( false );
} }
FILE* plotfile = wxFopen( aFullFileName, wxT( "wt" ) );
if( plotfile == NULL )
{
delete plotter;
return false;
}
plotter->SetCreator( wxT( "PCBNEW" ) ); plotter->SetCreator( wxT( "PCBNEW" ) );
plotter->SetFilename( aFullFileName ); plotter->SetFilename( aFullFileName );
plotter->SetDefaultLineWidth( 10 * IU_PER_DECIMILS ); plotter->SetDefaultLineWidth( 10 * IU_PER_DECIMILS );
plotter->StartPlot( aFile ); plotter->StartPlot( plotfile );
// Draw items on edge layer (not all, only items useful for drill map // Draw items on edge layer (not all, only items useful for drill map
BRDITEMS_PLOTTER itemplotter( plotter, aPcb, plot_opts ); BRDITEMS_PLOTTER itemplotter( plotter, m_pcb, plot_opts );
itemplotter.SetLayerMask( EDGE_LAYER ); itemplotter.SetLayerMask( EDGE_LAYER );
for( EDA_ITEM* PtStruct = aPcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) for( EDA_ITEM* PtStruct = m_pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
{ {
switch( PtStruct->Type() ) switch( PtStruct->Type() )
{ {
...@@ -160,25 +195,25 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName, ...@@ -160,25 +195,25 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
int intervalle = 0; int intervalle = 0;
char line[1024]; char line[1024];
wxString msg; wxString msg;
int textmarginaftersymbol = (int) (2 * IU_PER_MM); int textmarginaftersymbol = (int) (2 * IU_PER_MM);
// Set Drill Symbols width // Set Drill Symbols width
plotter->SetDefaultLineWidth( 0.2 * IU_PER_MM / scale ); plotter->SetDefaultLineWidth( 0.2 * IU_PER_MM / scale );
plotter->SetCurrentLineWidth( -1 ); plotter->SetCurrentLineWidth( -1 );
// Plot board outlines and drill map // Plot board outlines and drill map
Gen_Drill_PcbMap( aPcb, plotter, aHoleListBuffer, aToolListBuffer ); PlotDrillMarks( plotter );
// Print a list of symbols used. // Print a list of symbols used.
int charSize = 3 * IU_PER_MM; // text size in IUs int charSize = 3 * IU_PER_MM; // text size in IUs
double charScale = 1.0/scale; // real scale will be 1/scale, double charScale = 1.0 / scale; // real scale will be 1/scale,
//because the global plot scale is scale // because the global plot scale is scale
TextWidth = (int) ( (charSize * charScale) / 10 ); // Set text width (thickness) TextWidth = (int) ( (charSize * charScale) / 10 ); // Set text width (thickness)
intervalle = (int) ( charSize * charScale ) + TextWidth; intervalle = (int) ( charSize * charScale ) + TextWidth;
// Trace information. // Trace information.
plotX = (int) ( (double) bbbox.GetX() + textmarginaftersymbol * charScale ); plotX = (int) ( (double) bbbox.GetX() + textmarginaftersymbol * charScale );
plotY = bbbox.GetBottom() + intervalle; plotY = bbbox.GetBottom() + intervalle;
// Plot title "Info" // Plot title "Info"
wxString Text = wxT( "Drill Map:" ); wxString Text = wxT( "Drill Map:" );
...@@ -188,139 +223,128 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName, ...@@ -188,139 +223,128 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER, GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER,
TextWidth, false, false ); TextWidth, false, false );
for( unsigned ii = 0; ii < aToolListBuffer.size(); ii++ ) for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
{ {
int plot_diam; int plot_diam;
if( aToolListBuffer[ii].m_TotalCount == 0 ) if( m_toolListBuffer[ii].m_TotalCount == 0 )
continue; continue;
plotY += intervalle; plotY += intervalle;
plot_diam = (int) aToolListBuffer[ii].m_Diameter; plot_diam = (int) m_toolListBuffer[ii].m_Diameter;
x = (int) ( (double) plotX - textmarginaftersymbol * charScale x = (int) ( (double) plotX - textmarginaftersymbol * charScale
- (double)plot_diam / 2.0 ); - (double) plot_diam / 2.0 );
y = (int) ( (double) plotY + (double) charSize * charScale ); y = (int) ( (double) plotY + (double) charSize * charScale );
plotter->Marker( wxPoint( x, y ), plot_diam, ii ); plotter->Marker( wxPoint( x, y ), plot_diam, ii );
// Trace the legends. // List the diameter of each drill in mm and inches.
sprintf( line, "%2.2fmm / %2.3f\" ",
// List the diameter of each drill in the selected Drill Unit, diameter_in_mm( m_toolListBuffer[ii].m_Diameter ),
// and then its diameter in the other Drill Unit. diameter_in_inches( m_toolListBuffer[ii].m_Diameter ) );
if( aUnit_Drill_is_Inch )
sprintf( line, "%2.3f\" / %2.2fmm ",
diameter_in_inches( aToolListBuffer[ii].m_Diameter ),
diameter_in_mm( aToolListBuffer[ii].m_Diameter ) );
else
sprintf( line, "%2.2fmm / %2.3f\" ",
diameter_in_mm( aToolListBuffer[ii].m_Diameter ),
diameter_in_inches( aToolListBuffer[ii].m_Diameter ) );
msg = FROM_UTF8( line ); msg = FROM_UTF8( line );
// Now list how many holes and ovals are associated with each drill. // Now list how many holes and ovals are associated with each drill.
if( ( aToolListBuffer[ii].m_TotalCount == 1 ) if( ( m_toolListBuffer[ii].m_TotalCount == 1 )
&& ( aToolListBuffer[ii].m_OvalCount == 0 ) ) && ( m_toolListBuffer[ii].m_OvalCount == 0 ) )
sprintf( line, "(1 hole)" ); sprintf( line, "(1 hole)" );
else if( aToolListBuffer[ii].m_TotalCount == 1 ) // && ( aToolListBuffer[ii]m_OvalCount == 1 ) else if( m_toolListBuffer[ii].m_TotalCount == 1 ) // && ( m_toolListBuffer[ii]m_OvalCount == 1 )
sprintf( line, "(1 slot)" ); sprintf( line, "(1 slot)" );
else if( aToolListBuffer[ii].m_OvalCount == 0 ) else if( m_toolListBuffer[ii].m_OvalCount == 0 )
sprintf( line, "(%d holes)", aToolListBuffer[ii].m_TotalCount ); sprintf( line, "(%d holes)", m_toolListBuffer[ii].m_TotalCount );
else if( aToolListBuffer[ii].m_OvalCount == 1 ) else if( m_toolListBuffer[ii].m_OvalCount == 1 )
sprintf( line, "(%d holes + 1 slot)", aToolListBuffer[ii].m_TotalCount - 1 ); sprintf( line, "(%d holes + 1 slot)", m_toolListBuffer[ii].m_TotalCount - 1 );
else // if ( aToolListBuffer[ii]m_OvalCount > 1 ) else // if ( m_toolListBuffer[ii]m_OvalCount > 1 )
sprintf( line, "(%d holes + %d slots)", sprintf( line, "(%d holes + %d slots)",
aToolListBuffer[ii].m_TotalCount - aToolListBuffer[ii].m_OvalCount, m_toolListBuffer[ii].m_TotalCount - m_toolListBuffer[ii].m_OvalCount,
aToolListBuffer[ii].m_OvalCount ); m_toolListBuffer[ii].m_OvalCount );
msg += FROM_UTF8( line ); msg += FROM_UTF8( line );
plotter->Text( wxPoint( plotX, y ), UNSPECIFIED_COLOR, plotter->Text( wxPoint( plotX, y ), UNSPECIFIED_COLOR,
msg, msg,
0, wxSize( (int) ( charSize * charScale ), 0, wxSize( (int) ( charSize * charScale ),
(int) ( charSize * charScale ) ), (int) ( charSize * charScale ) ),
GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER, GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER,
TextWidth, false, false ); TextWidth, false, false );
intervalle = (int) ( charSize * charScale ) + TextWidth; intervalle = (int) ( charSize * charScale ) + TextWidth;
intervalle = (int) ( intervalle * 1.2 ); intervalle = (int) ( intervalle * 1.2 );
if( intervalle < (plot_diam + (1*IU_PER_MM/scale) + TextWidth) ) if( intervalle < (plot_diam + (1 * IU_PER_MM / scale) + TextWidth) )
intervalle = plot_diam + (1*IU_PER_MM/scale) + TextWidth; intervalle = plot_diam + (1 * IU_PER_MM / scale) + TextWidth;
} }
plotter->EndPlot(); plotter->EndPlot();
delete plotter; delete plotter;
}
return true;
/** Creates the drill map aFile in HPGL or POSTSCRIPT format
* @param aPcb = the BOARD
* @param aPlotter = a PLOTTER instance (HPGL or POSTSCRIPT plotter).
* @param aHoleListBuffer = std::vector<HOLE_INFO> list of holes descriptors
* @param aToolListBuffer = std::vector<DRILL_TOOL> drill list buffer
*/
void Gen_Drill_PcbMap( BOARD* aPcb, PLOTTER* aPlotter,
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& aToolListBuffer )
{
wxPoint pos;
// create the drill list
if( aToolListBuffer.size() > PLOTTER::MARKER_COUNT )
{
DisplayInfoMessage( NULL,
_( " Drill map: Too many diameter values to draw one symbol per drill value\n"
"Plot will use circle shape for some drill values" ),
10 );
}
// Plot the drill map:
for( unsigned ii = 0; ii < aHoleListBuffer.size(); ii++ )
{
pos = aHoleListBuffer[ii].m_Hole_Pos;
/* Always plot the drill symbol (for slots identifies the needed
* cutter!) */
aPlotter->Marker( pos, aHoleListBuffer[ii].m_Hole_Diameter,
aHoleListBuffer[ii].m_Tool_Reference - 1 );
if( aHoleListBuffer[ii].m_Hole_Shape != 0 )
{
wxSize oblong_size;
oblong_size = aHoleListBuffer[ii].m_Hole_Size;
aPlotter->FlashPadOval( pos, oblong_size,
aHoleListBuffer[ii].m_Hole_Orient, LINE );
}
}
} }
/* /*
* Create a list of drill values and drill count * Create a plain text report file giving a list of drill values and drill count
* for through holes, oblong holes, and for buried vias,
* drill values and drill count per layer pair
*/
/* Here is a sample created by this function:
* Drill report for F:/tmp/interf_u/interf_u.brd
* Created on 04/10/2012 20:48:38
* Selected Drill Unit: Imperial (inches)
*
* Drill report for plated through holes :
* T1 0,025" 0,64mm (88 holes)
* T2 0,031" 0,79mm (120 holes)
* T3 0,032" 0,81mm (151 holes) (with 1 slot)
* T4 0,040" 1,02mm (43 holes)
* T5 0,079" 2,00mm (1 hole) (with 1 slot)
* T6 0,120" 3,05mm (1 hole) (with 1 slot)
*
* Total plated holes count 404
*
*
* Drill report for buried and blind vias :
*
* Drill report for holes from layer Soudure to layer Interne1 :
*
* Total plated holes count 0
*
*
* Drill report for holes from layer Interne1 to layer Interne2 :
* T1 0,025" 0,64mm (3 holes)
*
* Total plated holes count 3
*
*
* Drill report for holes from layer Interne2 to layer Composant :
* T1 0,025" 0,64mm (1 hole)
*
* Total plated holes count 1
*
*
* Drill report for unplated through holes :
* T1 0,120" 3,05mm (1 hole) (with 1 slot)
*
* Total unplated holes count 1
*
*/ */
void GenDrillReportFile( FILE* aFile, BOARD* aPcb, bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
const wxString& aBoardFilename,
bool aUnit_Drill_is_Inch,
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& aToolListBuffer )
{ {
unsigned TotalHoleCount; unsigned totalHoleCount;
char line[1024]; char line[1024];
int layer1 = LAYER_N_BACK; int layer1 = LAYER_N_BACK;
int layer2 = LAYER_N_FRONT; int layer2 = LAYER_N_FRONT;
bool gen_through_holes = true; bool gen_through_holes = true;
bool gen_NPTH_holes = false; bool gen_NPTH_holes = false;
m_file = wxFopen( aFullFileName, wxT( "w" ) );
fprintf( aFile, "Drill report for %s\n", TO_UTF8( aBoardFilename ) ); if( m_file == NULL )
fprintf( aFile, "Created on %s\n", TO_UTF8( DateAndTime() ) ); return false;
// List which Drill Unit option had been selected for the associated wxString brdFilename = m_pcb->GetFileName();
// drill aFile. fprintf( m_file, "Drill report for %s\n", TO_UTF8( brdFilename ) );
if( aUnit_Drill_is_Inch ) fprintf( m_file, "Created on %s\n", TO_UTF8( DateAndTime() ) );
fputs( "Selected Drill Unit: Imperial (inches)\n\n", aFile );
else
fputs( "Selected Drill Unit: Metric (mm)\n\n", aFile );
/* build hole lists: /* build hole lists:
* 1 - through holes * 1 - through holes
...@@ -330,87 +354,66 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb, ...@@ -330,87 +354,66 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb,
for( ; ; ) for( ; ; )
{ {
Build_Holes_List( aPcb, BuildHolesList( layer1, layer2,
aHoleListBuffer,
aToolListBuffer,
layer1,
layer2,
gen_through_holes ? false : true, gen_NPTH_holes ); gen_through_holes ? false : true, gen_NPTH_holes );
TotalHoleCount = 0; totalHoleCount = 0;
if( gen_NPTH_holes ) if( gen_NPTH_holes )
{
sprintf( line, "Drill report for unplated through holes :\n" ); sprintf( line, "Drill report for unplated through holes :\n" );
}
else if( gen_through_holes ) else if( gen_through_holes )
{
sprintf( line, "Drill report for plated through holes :\n" ); sprintf( line, "Drill report for plated through holes :\n" );
}
else else
{ {
if( layer1 == LAYER_N_BACK ) // First partial hole list // If this is the first partial hole list: print a title
{ if( layer1 == LAYER_N_BACK )
sprintf( line, "Drill report for buried and blind vias :\n\n" ); fputs( "Drill report for buried and blind vias :\n\n", m_file );
fputs( line, aFile );
}
sprintf( line, "Drill report for holes from layer %s to layer %s :\n", sprintf( line, "Drill report for holes from layer %s to layer %s :\n",
TO_UTF8( aPcb->GetLayerName( layer1 ) ), TO_UTF8( m_pcb->GetLayerName( layer1 ) ),
TO_UTF8( aPcb->GetLayerName( layer2 ) ) ); TO_UTF8( m_pcb->GetLayerName( layer2 ) ) );
} }
fputs( line, aFile ); fputs( line, m_file );
for( unsigned ii = 0; ii < aToolListBuffer.size(); ii++ ) for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
{ {
// List the tool number assigned to each drill, // List the tool number assigned to each drill,
// then its diameter in the selected Drill Unit, // in mm then in inches.
// and then its diameter in the other Drill Unit. sprintf( line, "T%d %2.2fmm %2.3f\" ",
if( aUnit_Drill_is_Inch ) ii + 1,
{ diameter_in_mm( m_toolListBuffer[ii].m_Diameter ),
sprintf( line, "T%d %2.3f\" %2.2fmm ", diameter_in_inches( m_toolListBuffer[ii].m_Diameter ) );
ii + 1,
diameter_in_inches( aToolListBuffer[ii].m_Diameter ),
diameter_in_mm( aToolListBuffer[ii].m_Diameter ) );
}
else
{
sprintf( line, "T%d %2.2fmm %2.3f\" ",
ii + 1,
diameter_in_mm( aToolListBuffer[ii].m_Diameter ),
diameter_in_inches( aToolListBuffer[ii].m_Diameter ) );
}
fputs( line, aFile ); fputs( line, m_file );
// Now list how many holes and ovals are associated with each drill. // Now list how many holes and ovals are associated with each drill.
if( ( aToolListBuffer[ii].m_TotalCount == 1 ) if( ( m_toolListBuffer[ii].m_TotalCount == 1 )
&& ( aToolListBuffer[ii].m_OvalCount == 0 ) ) && ( m_toolListBuffer[ii].m_OvalCount == 0 ) )
sprintf( line, "(1 hole)\n" ); sprintf( line, "(1 hole)\n" );
else if( aToolListBuffer[ii].m_TotalCount == 1 ) else if( m_toolListBuffer[ii].m_TotalCount == 1 )
sprintf( line, "(1 hole) (with 1 slot)\n" ); sprintf( line, "(1 hole) (with 1 slot)\n" );
else if( aToolListBuffer[ii].m_OvalCount == 0 ) else if( m_toolListBuffer[ii].m_OvalCount == 0 )
sprintf( line, "(%d holes)\n", aToolListBuffer[ii].m_TotalCount ); sprintf( line, "(%d holes)\n", m_toolListBuffer[ii].m_TotalCount );
else if( aToolListBuffer[ii].m_OvalCount == 1 ) else if( m_toolListBuffer[ii].m_OvalCount == 1 )
sprintf( line, "(%d holes) (with 1 slot)\n", aToolListBuffer[ii].m_TotalCount ); sprintf( line, "(%d holes) (with 1 slot)\n",
else // if ( buffer[ii]m_OvalCount > 1 ) m_toolListBuffer[ii].m_TotalCount );
else // if ( buffer[ii]m_OvalCount > 1 )
sprintf( line, "(%d holes) (with %d slots)\n", sprintf( line, "(%d holes) (with %d slots)\n",
aToolListBuffer[ii].m_TotalCount, m_toolListBuffer[ii].m_TotalCount,
aToolListBuffer[ii].m_OvalCount ); m_toolListBuffer[ii].m_OvalCount );
fputs( line, aFile ); fputs( line, m_file );
TotalHoleCount += aToolListBuffer[ii].m_TotalCount; totalHoleCount += m_toolListBuffer[ii].m_TotalCount;
} }
if( gen_NPTH_holes ) if( gen_NPTH_holes )
sprintf( line, "\nTotal unplated holes count %d\n\n\n", TotalHoleCount ); sprintf( line, "\nTotal unplated holes count %d\n\n\n", totalHoleCount );
else else
sprintf( line, "\nTotal plated holes count %d\n\n\n", TotalHoleCount ); sprintf( line, "\nTotal plated holes count %d\n\n\n", totalHoleCount );
fputs( line, aFile ); fputs( line, m_file );
if( gen_NPTH_holes ) if( gen_NPTH_holes )
{ {
...@@ -418,7 +421,7 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb, ...@@ -418,7 +421,7 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb,
} }
else else
{ {
if( aPcb->GetCopperLayerCount() <= 2 ) if( m_pcb->GetCopperLayerCount() <= 2 )
{ {
gen_NPTH_holes = true; gen_NPTH_holes = true;
continue; continue;
...@@ -438,13 +441,43 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb, ...@@ -438,13 +441,43 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb,
layer1++; layer2++; // use next layer pair layer1++; layer2++; // use next layer pair
if( layer2 == aPcb->GetCopperLayerCount() - 1 ) if( layer2 == m_pcb->GetCopperLayerCount() - 1 )
layer2 = LAYER_N_FRONT; // the last layer is always the layer2 = LAYER_N_FRONT; // the last layer is always the
// component layer
// component layer
} }
gen_through_holes = false; gen_through_holes = false;
} }
} }
fclose( aFile ); fclose( m_file );
return true;
}
// Helper function to plot drill marks:
bool EXCELLON_WRITER::PlotDrillMarks( PLOTTER* aPlotter )
{
// Plot the drill map:
wxPoint pos;
for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
{
pos = m_holeListBuffer[ii].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 );
if( m_holeListBuffer[ii].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, LINE );
}
}
return true;
} }
/** /**
* @file gendrill.cpp * @file gendrill_Excellon_writer.cpp
* @brief Functions to create EXCELLON drill files and report files. * @brief Functions to create EXCELLON drill files and report files.
*/ */
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2010 Jean_Pierre Charras <jp.charras@ujf-grenoble.fr> * Copyright (C) 1992-2012 Jean_Pierre Charras <jp.charras at wanadoo.fr>
* Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -39,19 +39,18 @@ ...@@ -39,19 +39,18 @@
#include <plot_common.h> #include <plot_common.h>
#include <trigo.h> #include <trigo.h>
#include <confirm.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <gestfich.h>
#include <wxPcbStruct.h> #include <wxPcbStruct.h>
#include <macros.h>
#include <appl_wxstruct.h> #include <appl_wxstruct.h>
#include <build_version.h> #include <build_version.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h>
#include <class_track.h>
#include <pcbplot.h> #include <pcbplot.h>
#include <pcbnew.h> #include <pcbnew.h>
#include <gendrill.h> #include <gendrill_Excellon_writer.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <dialog_gendrill.h> // Dialog box for drill file generation #include <dialog_gendrill.h> // Dialog box for drill file generation
...@@ -66,199 +65,17 @@ ...@@ -66,199 +65,17 @@
* Units * Units
* - Decimal * - Decimal
* - Metric * - Metric
*
* The drill maps can be created in HPGL or PS format
*
* dialog_gendrill.cpp is the file which handles
* the Dialog box for drill file generation
*/
static std::vector<DRILL_TOOL> s_ToolListBuffer;
static std::vector<HOLE_INFO> s_HoleListBuffer;
/* This function displays the dialog frame for drill tools
*/
void PCB_EDIT_FRAME::InstallDrillFrame( wxCommandEvent& event )
{
DIALOG_GENDRILL dlg( this );
dlg.ShowModal();
}
/**
* Function GenDrillAndReportFiles
* Calls the functions to create EXCELLON drill files and/or drill map files
* >When all holes are through, only one excellon file is created.
* >When there are some partial holes (some blind or buried vias),
* one excellon file is created, for all plated through holes,
* and one file per layer pair, which have one or more holes, excluding
* through holes, already in the first file.
* one file for all Not Plated through holes
*/ */
void DIALOG_GENDRILL::GenDrillAndReportFiles()
{
wxFileName fn;
wxString layer_extend; /* added to the Board FileName to
* create FullFileName (= Board
* FileName + layer pair names) */
wxString msg;
bool hasBuriedVias = false; /* If true, drill files are created
* layer pair by layer pair for
* buried vias */
int layer1 = LAYER_N_BACK;
int layer2 = LAYER_N_FRONT;
bool gen_through_holes = true;
bool gen_NPTH_holes = false;
wxString currentWD = ::wxGetCwd();
UpdateConfig(); // set params and Save drill options
m_parent->ClearMsgPanel();
if( m_microViasCount || m_blindOrBuriedViasCount )
hasBuriedVias = true;
for( ; ; )
{
Build_Holes_List( m_parent->GetBoard(), s_HoleListBuffer,
s_ToolListBuffer, layer1, layer2,
gen_through_holes ? false : true, gen_NPTH_holes );
if( s_ToolListBuffer.size() > 0 ) // holes?
{
fn = m_parent->GetBoard()->GetFileName();
layer_extend.Empty();
if( gen_NPTH_holes )
{
layer_extend << wxT( "-NPTH" );
}
else if( !gen_through_holes )
{
if( layer1 == LAYER_N_BACK )
layer_extend << wxT( "-copper" );
else
layer_extend << wxT( "-inner" ) << layer1;
if( layer2 == LAYER_N_FRONT )
layer_extend << wxT( "-cmp" );
else
layer_extend << wxT( "-inner" ) << layer2;
}
fn.SetName( fn.GetName() + layer_extend );
fn.SetExt( DrillFileExtension );
wxString defaultPath = m_plotDefaultpath;
if( defaultPath.IsEmpty() )
defaultPath = ::wxGetCwd();
wxFileDialog dlg( this, _( "Save Drill File" ), defaultPath,
fn.GetFullName(), wxGetTranslation( DrillFileWildcard ),
wxFD_SAVE | wxFD_CHANGE_DIR );
if( dlg.ShowModal() == wxID_CANCEL )
break;
FILE* aFile = wxFopen( dlg.GetPath(), wxT( "w" ) );
if( aFile == 0 )
{
msg.Printf( _( "Unable to create drill file %s" ), GetChars( dlg.GetPath() ) );
wxMessageBox( msg );
::wxSetWorkingDirectory( currentWD );
EndModal( 0 );
return;
}
EXCELLON_WRITER excellonWriter( m_parent->GetBoard(),
aFile, m_FileDrillOffset,
&s_HoleListBuffer, &s_ToolListBuffer );
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.CreateDrillFile();
switch( m_Choice_Drill_Map->GetSelection() )
{
case 0:
break;
case 1:
GenDrillMap( dlg.GetPath(), s_HoleListBuffer, s_ToolListBuffer,
PLOT_FORMAT_HPGL );
break;
case 2:
GenDrillMap( dlg.GetPath(), s_HoleListBuffer, s_ToolListBuffer,
PLOT_FORMAT_POST );
break;
case 3:
GenDrillMap( dlg.GetPath(), s_HoleListBuffer, s_ToolListBuffer,
PLOT_FORMAT_GERBER );
break;
case 4:
GenDrillMap( dlg.GetPath(), s_HoleListBuffer, s_ToolListBuffer,
PLOT_FORMAT_DXF );
break;
case 5:
GenDrillMap( dlg.GetPath(), s_HoleListBuffer, s_ToolListBuffer,
PLOT_FORMAT_SVG );
break;
}
}
if( gen_NPTH_holes ) // The last drill file was created
break;
if( !hasBuriedVias )
gen_NPTH_holes = true;
else
{
if( gen_through_holes )
layer2 = layer1 + 1; // prepare generation of first layer pair
else
{
if( layer2 >= LAYER_N_FRONT ) // no more layer pair to consider
{
layer1 = LAYER_N_BACK;
layer2 = LAYER_N_FRONT;
gen_NPTH_holes = true;
continue;
}
layer1++;
layer2++; // use next layer pair
if( layer2 == m_parent->GetBoard()->GetCopperLayerCount() - 1 )
layer2 = LAYER_N_FRONT; // the last layer is always the
// component layer
}
gen_through_holes = false;
}
}
if( m_Choice_Drill_Report->GetSelection() > 0 )
{
fn = m_parent->GetBoard()->GetFileName();
GenDrillReport( fn.GetFullName() );
}
::wxSetWorkingDirectory( currentWD );
}
/*
/**
* Create the drill file in EXCELLON format * Create the drill file in EXCELLON format
* @return hole count * return hole count
*/ */
int EXCELLON_WRITER::CreateDrillFile() int EXCELLON_WRITER::CreateDrillFile( FILE * aFile )
{ {
m_file = aFile;
int diam, holes_count; int diam, holes_count;
int x0, y0, xf, yf, xc, yc; int x0, y0, xf, yf, xc, yc;
double xt, yt; double xt, yt;
...@@ -266,14 +83,14 @@ int EXCELLON_WRITER::CreateDrillFile() ...@@ -266,14 +83,14 @@ int EXCELLON_WRITER::CreateDrillFile()
SetLocaleTo_C_standard(); // Use the standard notation for double numbers SetLocaleTo_C_standard(); // Use the standard notation for double numbers
WriteHeader(); WriteEXCELLONHeader();
holes_count = 0; holes_count = 0;
/* Write the tool list */ /* Write the tool list */
for( unsigned ii = 0; ii < m_toolListBuffer->size(); ii++ ) for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
{ {
DRILL_TOOL& tool_descr = (*m_toolListBuffer)[ii]; DRILL_TOOL& tool_descr = m_toolListBuffer[ii];
fprintf( m_file, "T%dC%.3f\n", ii + 1, fprintf( m_file, "T%dC%.3f\n", ii + 1,
tool_descr.m_Diameter * m_conversionUnits ); tool_descr.m_Diameter * m_conversionUnits );
} }
...@@ -294,9 +111,9 @@ int EXCELLON_WRITER::CreateDrillFile() ...@@ -294,9 +111,9 @@ int EXCELLON_WRITER::CreateDrillFile()
/* Read the hole file and generate lines for normal holes (oblong /* Read the hole file and generate lines for normal holes (oblong
* holes will be created later) */ * holes will be created later) */
int tool_reference = -2; int tool_reference = -2;
for( unsigned ii = 0; ii < m_holeListBuffer->size(); ii++ ) for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
{ {
HOLE_INFO& hole_descr = (*m_holeListBuffer)[ii]; HOLE_INFO& hole_descr = m_holeListBuffer[ii];
if( hole_descr.m_Hole_Shape ) if( hole_descr.m_Hole_Shape )
continue; // oblong holes will be created later continue; // oblong holes will be created later
...@@ -323,10 +140,10 @@ int EXCELLON_WRITER::CreateDrillFile() ...@@ -323,10 +140,10 @@ int EXCELLON_WRITER::CreateDrillFile()
/* Read the hole file and generate lines for normal holes (oblong holes /* Read the hole file and generate lines for normal holes (oblong holes
* will be created later) */ * will be created later) */
tool_reference = -2; // set to a value not used for tool_reference = -2; // set to a value not used for
// aHoleListBuffer[ii].m_Tool_Reference // m_holeListBuffer[ii].m_Tool_Reference
for( unsigned ii = 0; ii < m_holeListBuffer->size(); ii++ ) for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
{ {
HOLE_INFO& hole_descr = (*m_holeListBuffer)[ii]; HOLE_INFO& hole_descr = m_holeListBuffer[ii];
if( hole_descr.m_Hole_Shape == 0 ) if( hole_descr.m_Hole_Shape == 0 )
continue; // wait for oblong holes continue; // wait for oblong holes
if( tool_reference != hole_descr.m_Tool_Reference ) if( tool_reference != hole_descr.m_Tool_Reference )
...@@ -387,7 +204,7 @@ int EXCELLON_WRITER::CreateDrillFile() ...@@ -387,7 +204,7 @@ int EXCELLON_WRITER::CreateDrillFile()
holes_count++; holes_count++;
} }
WriteEndOfFile(); WriteEXCELLONEndOfFile();
SetLocaleTo_Default(); // Revert to locale double notation SetLocaleTo_Default(); // Revert to locale double notation
...@@ -432,7 +249,7 @@ void EXCELLON_WRITER::WriteCoordinates( char* aLine, double aCoordX, double aCoo ...@@ -432,7 +249,7 @@ void EXCELLON_WRITER::WriteCoordinates( char* aLine, double aCoordX, double aCoo
int xpad = m_precision.m_lhs + m_precision.m_rhs; int xpad = m_precision.m_lhs + m_precision.m_rhs;
int ypad = xpad; int ypad = xpad;
switch( DIALOG_GENDRILL::m_ZerosFormat ) switch( m_zeroFormat )
{ {
default: default:
case DECIMAL_FORMAT: case DECIMAL_FORMAT:
...@@ -526,7 +343,7 @@ void EXCELLON_WRITER::WriteCoordinates( char* aLine, double aCoordX, double aCoo ...@@ -526,7 +343,7 @@ void EXCELLON_WRITER::WriteCoordinates( char* aLine, double aCoordX, double aCoo
* FMAT,2 * FMAT,2
* INCH,TZ * INCH,TZ
*/ */
void EXCELLON_WRITER::WriteHeader() void EXCELLON_WRITER::WriteEXCELLONHeader()
{ {
fputs( "M48\n", m_file ); // The beginning of a header fputs( "M48\n", m_file ); // The beginning of a header
...@@ -589,7 +406,7 @@ void EXCELLON_WRITER::WriteHeader() ...@@ -589,7 +406,7 @@ void EXCELLON_WRITER::WriteHeader()
} }
void EXCELLON_WRITER::WriteEndOfFile() void EXCELLON_WRITER::WriteEXCELLONEndOfFile()
{ {
//add if minimal here //add if minimal here
fputs( "T0\nM30\n", m_file ); fputs( "T0\nM30\n", m_file );
...@@ -597,114 +414,154 @@ void EXCELLON_WRITER::WriteEndOfFile() ...@@ -597,114 +414,154 @@ void EXCELLON_WRITER::WriteEndOfFile()
} }
/* Generate the drill plan (Drill map) format HPGL or POSTSCRIPT
/* Helper function for sorting hole list.
* Compare function used for sorting holes by increasing diameter value
* and X value
*/ */
void DIALOG_GENDRILL::GenDrillMap( const wxString aFileName, static bool CmpHoleDiameterValue( const HOLE_INFO& a, const HOLE_INFO& b )
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& buffer,
int format )
{ {
wxFileName fn; if( a.m_Hole_Diameter != b.m_Hole_Diameter )
wxString ext, wildcard; return a.m_Hole_Diameter < b.m_Hole_Diameter;
wxString msg;
/* Init extension */ if( a.m_Hole_Pos.x != b.m_Hole_Pos.x )
switch( format ) return a.m_Hole_Pos.x < b.m_Hole_Pos.x;
{
case PLOT_FORMAT_HPGL:
ext = HPGL_PLOTTER::GetDefaultFileExtension();
wildcard = _( "HPGL plot files (.plt)|*.plt" );
break;
case PLOT_FORMAT_POST: return a.m_Hole_Pos.y < b.m_Hole_Pos.y;
ext = PS_PLOTTER::GetDefaultFileExtension(); }
wildcard = _( "PostScript files (.ps)|*.ps" );
break;
case PLOT_FORMAT_GERBER:
ext = GERBER_PLOTTER::GetDefaultFileExtension();
wildcard = _( "Gerber files (.pho)|*.pho" );
break;
case PLOT_FORMAT_DXF: /*
ext = DXF_PLOTTER::GetDefaultFileExtension(); * Create the list of holes and tools for a given board
wildcard = _( "DXF files (.dxf)|*.dxf" ); * The list is sorted by increasing drill values
break; * Only holes from aFirstLayer to aLastLayer copper layers are listed (for vias, because pad holes are always through holes)
* param aFirstLayer = first layer to consider. if < 0 aFirstLayer is ignored (used to creates report file)
* param aLastLayer = last layer to consider. if < 0 aLastLayer is ignored
* param aExcludeThroughHoles : if true, exclude through holes ( pads and vias through )
* param aGenerateNPTH_list :
* true to create NPTH only list (with no plated holes)
* false to created plated holes list (with no NPTH )
*/
void EXCELLON_WRITER::BuildHolesList( int aFirstLayer,
int aLastLayer,
bool aExcludeThroughHoles,
bool aGenerateNPTH_list )
{
HOLE_INFO new_hole;
int hole_value;
case PLOT_FORMAT_SVG: m_holeListBuffer.clear();
ext = SVG_PLOTTER::GetDefaultFileExtension(); m_toolListBuffer.clear();
wildcard = SVGFileWildcard;
break;
default: if( (aFirstLayer >= 0) && (aLastLayer >= 0) )
DisplayError( this, wxT( "DIALOG_GENDRILL::GenDrillMap() error" ) ); {
return; if( aFirstLayer > aLastLayer )
EXCHG( aFirstLayer, aLastLayer );
} }
/* Init file name */ /* build hole list for vias
fn = aFileName; */
fn.SetName( fn.GetName() + wxT( "-drl" ) ); if( ! aGenerateNPTH_list ) // vias are always plated !
fn.SetExt( ext ); {
for( TRACK* track = m_pcb->m_Track; track; track = track->Next() )
{
if( track->Type() != PCB_VIA_T )
continue;
SEGVIA* via = (SEGVIA*) track;
hole_value = via->GetDrillValue();
wxFileDialog dlg( this, _( "Save Drill Plot File" ), fn.GetPath(), if( hole_value == 0 )
fn.GetFullName(), wildcard, continue;
wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL ) new_hole.m_Tool_Reference = -1; // Flag value for Not initialized
return; new_hole.m_Hole_Orient = 0;
new_hole.m_Hole_Diameter = hole_value;
new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
FILE* plotfile = wxFopen( dlg.GetPath(), wxT( "wt" ) ); new_hole.m_Hole_Shape = 0; // hole shape: round
new_hole.m_Hole_Pos = via->m_Start;
via->ReturnLayerPair( &new_hole.m_Hole_Top_Layer, &new_hole.m_Hole_Bottom_Layer );
if( plotfile == 0 ) // ReturnLayerPair return params with m_Hole_Bottom_Layer < m_Hole_Top_Layer
if( (new_hole.m_Hole_Bottom_Layer > aFirstLayer) && (aFirstLayer >= 0) )
continue;
if( (new_hole.m_Hole_Top_Layer < aLastLayer) && (aLastLayer >= 0) )
continue;
if( aExcludeThroughHoles && (new_hole.m_Hole_Bottom_Layer == LAYER_N_BACK)
&& (new_hole.m_Hole_Top_Layer == LAYER_N_FRONT) )
continue;
m_holeListBuffer.push_back( new_hole );
}
}
// build hole list for pads (assumed always through holes)
if( !aExcludeThroughHoles || aGenerateNPTH_list )
{ {
msg = _( "Unable to create file" ); for( MODULE* module = m_pcb->m_Modules; module; module = module->Next() )
msg << wxT( " <" ) << dlg.GetPath() << wxT( ">" ); {
wxMessageBox( msg ); // Read and analyse pads
return; for( D_PAD* pad = module->m_Pads; pad; pad = pad->Next() )
{
if( ! aGenerateNPTH_list && pad->GetAttribute() == PAD_HOLE_NOT_PLATED )
continue;
if( aGenerateNPTH_list && pad->GetAttribute() != PAD_HOLE_NOT_PLATED )
continue;
if( pad->GetDrillSize().x == 0 )
continue;
new_hole.m_Hole_NotPlated = (pad->GetAttribute() == PAD_HOLE_NOT_PLATED);
new_hole.m_Tool_Reference = -1; // Flag is: Not initialized
new_hole.m_Hole_Orient = pad->GetOrientation();
new_hole.m_Hole_Shape = 0; // hole shape: round
new_hole.m_Hole_Diameter = std::min( pad->GetDrillSize().x, pad->GetDrillSize().y );
new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
if( pad->GetDrillShape() != PAD_CIRCLE )
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_Bottom_Layer = LAYER_N_BACK;
new_hole.m_Hole_Top_Layer = LAYER_N_FRONT;// pad holes are through holes
m_holeListBuffer.push_back( new_hole );
}
}
} }
GenDrillMapFile( m_parent->GetBoard(), // Sort holes per increasing diameter value
plotfile, sort( m_holeListBuffer.begin(), m_holeListBuffer.end(), CmpHoleDiameterValue );
dlg.GetPath(),
m_parent->GetPageSettings(),
s_HoleListBuffer,
s_ToolListBuffer,
m_UnitDrillIsInch,
format, m_FileDrillOffset );
}
// build the tool list
int LastHole = -1; /* Set to not initialised (this is a value not used
* for m_holeListBuffer[ii].m_Hole_Diameter) */
DRILL_TOOL new_tool( 0 );
unsigned jj;
/* for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
* Create a list of drill values and drill count {
*/ if( m_holeListBuffer[ii].m_Hole_Diameter != LastHole )
void DIALOG_GENDRILL::GenDrillReport( const wxString aFileName ) {
{ new_tool.m_Diameter = ( m_holeListBuffer[ii].m_Hole_Diameter );
wxFileName fn; m_toolListBuffer.push_back( new_tool );
wxString msg; LastHole = new_tool.m_Diameter;
}
fn = aFileName; jj = m_toolListBuffer.size();
fn.SetName( fn.GetName() + wxT( "-drl" ) );
fn.SetExt( ReportFileExtension );
wxFileDialog dlg( this, _( "Save Drill Report File" ), fn.GetPath(), if( jj == 0 )
fn.GetFullName(), wxGetTranslation( ReportFileWildcard ), continue; // Should not occurs
wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL ) m_holeListBuffer[ii].m_Tool_Reference = jj; // Tool value Initialized (value >= 1)
return;
FILE* report_dest = wxFopen( dlg.GetPath(), wxT( "w" ) ); m_toolListBuffer.back().m_TotalCount++;
if( report_dest == 0 ) if( m_holeListBuffer[ii].m_Hole_Shape )
{ m_toolListBuffer.back().m_OvalCount++;
msg = _( "Unable to create file " ) + dlg.GetPath();
wxMessageBox( msg );
return;
} }
GenDrillReportFile( report_dest, m_parent->GetBoard(),
m_parent->GetBoard()->GetFileName(),
m_UnitDrillIsInch,
s_HoleListBuffer,
s_ToolListBuffer );
} }
/** /**
* @file gendrill.h * @file gendrill_Excellon_writer.h
* @brief Classes and functions declaration used in drill file and report generation. * @brief Classes used in drill files, map files and report files generation.
*/ */
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2010 Jean_Pierre Charras <jp.charras@ujf-grenoble.fr> * Copyright (C) 1992-2012 Jean_Pierre Charras <jp.charras at wanadoo.fr>
* Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#ifndef _GENDRILL_H_ #ifndef _GENDRILL_EXCELLON_WRITER_
#define _GENDRILL_H_ #define _GENDRILL_EXCELLON_WRITER_
#include <vector> #include <vector>
...@@ -44,7 +44,9 @@ public: ...@@ -44,7 +44,9 @@ public:
int m_Diameter; // the diameter of the used tool (for oblong, the smaller size) 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_TotalCount; // how many times it is used (round and oblong)
int m_OvalCount; // oblong count int m_OvalCount; // oblong count
public: DRILL_TOOL( int diametre )
public:
DRILL_TOOL( int diametre )
{ {
m_TotalCount = 0; m_TotalCount = 0;
m_OvalCount = 0; m_OvalCount = 0;
...@@ -104,7 +106,10 @@ public: DRILL_PRECISION( int l = 2, int r = 4 ) ...@@ -104,7 +106,10 @@ public: DRILL_PRECISION( int l = 2, int r = 4 )
}; };
// A helper class to create Excellon drill files /**
* EXCELLON_WRITER is a class mainly used to create Excellon drill files
* However, this class is also used to create drill maps and drill report
*/
class EXCELLON_WRITER class EXCELLON_WRITER
{ {
public: public:
...@@ -130,19 +135,14 @@ private: ...@@ -130,19 +135,14 @@ private:
// (i.e inches or mm) // (i.e inches or mm)
bool m_mirror; bool m_mirror;
wxPoint m_offset; // Drill offset ooordinates wxPoint m_offset; // Drill offset ooordinates
std::vector<HOLE_INFO>* m_holeListBuffer; // Buffer containing holes std::vector<HOLE_INFO> m_holeListBuffer; // Buffer containing holes
std::vector<DRILL_TOOL>* m_toolListBuffer; // Buffer containing tools std::vector<DRILL_TOOL> m_toolListBuffer; // Buffer containing tools
public: EXCELLON_WRITER( BOARD* aPcb, FILE* aFile, public: EXCELLON_WRITER( BOARD* aPcb, wxPoint aOffset )
wxPoint aOffset,
std::vector<HOLE_INFO>* aHoleListBuffer,
std::vector<DRILL_TOOL>* aToolListBuffer )
{ {
m_file = aFile; m_file = NULL;
m_pcb = aPcb; m_pcb = aPcb;
m_zeroFormat = DECIMAL_FORMAT; m_zeroFormat = DECIMAL_FORMAT;
m_holeListBuffer = aHoleListBuffer;
m_toolListBuffer = aToolListBuffer;
m_conversionUnits = 0.0001; m_conversionUnits = 0.0001;
m_unitsDecimal = false; m_unitsDecimal = false;
m_mirror = false; m_mirror = false;
...@@ -154,6 +154,11 @@ public: EXCELLON_WRITER( BOARD* aPcb, FILE* aFile, ...@@ -154,6 +154,11 @@ public: EXCELLON_WRITER( BOARD* aPcb, FILE* aFile,
{ {
} }
/**
* Return the plot offset (usually the position
* of the auxiliaty axis
*/
const wxPoint GetOffset() { return m_offset; }
/** /**
* Function SetFormat * Function SetFormat
...@@ -179,62 +184,74 @@ public: EXCELLON_WRITER( BOARD* aPcb, FILE* aFile, ...@@ -179,62 +184,74 @@ public: EXCELLON_WRITER( BOARD* aPcb, FILE* aFile,
m_minimalHeader = aMinimalHeader; m_minimalHeader = aMinimalHeader;
} }
/**
* Function BuildHolesList
* Create the list of holes and tools for a given board
* The list is sorted by increasing drill values
* Only holes from aFirstLayer to aLastLayer copper layers are listed (for vias, because
* pad holes are always through holes)
* @param aFirstLayer = first layer to consider. if < 0 aFirstLayer is ignored
* @param aLastLayer = last layer to consider. if < 0 aLastLayer is ignored
* @param aExcludeThroughHoles Exclude through holes if true.
* @param aGenerateNPTH_list :
* true to create NPTH only list (with no plated holes)
* false to created plated holes list (with no NPTH )
*/
void BuildHolesList( int aFirstLayer, int aLastLayer,
bool aExcludeThroughHoles,
bool aGenerateNPTH_list );
int GetHolesCount() const { return m_holeListBuffer.size(); }
/** /**
* Function CreateDrillFile * Function CreateDrillFile
* Creates an Excellon drill file * Creates an Excellon drill file
* @param aFile = an opened file to write to
* will be closed by CreateDrillFile
* @return hole count * @return hole count
*/ */
int CreateDrillFile(); int CreateDrillFile( FILE * aFile );
/**
* Function GenDrillReportFile
* Create a plain text report file giving a list of drill values and drill count
* for through holes, oblong holes, and for buried vias,
* drill values and drill count per layer pair
* there is only one report for all drill files even when buried or blinds vias exist
* @param aFullFileName : the name of the file to create
* m_unitsDecimal = false tu use inches, true to use mm in report file
*
* @return success if the file is created
*/
bool GenDrillReportFile( const wxString& aFullFileName );
/**
* Function GenDrillMapFile
* Plot a map of drill marks for holes.
* @param aFullFileName : the name of this file (to plot it)
* @param aSheet : the paper sheet touse for plot
* @param aFormat : one of the supported plot formats (see enum PlotFormat )
*/
bool GenDrillMapFile( const wxString& aFullFileName,
const PAGE_INFO& aSheet,
PlotFormat aFormat );
private: private:
void WriteHeader(); void WriteEXCELLONHeader();
void WriteEndOfFile(); void WriteEXCELLONEndOfFile();
void WriteCoordinates( char* aLine, double aCoordX, double aCoordY ); void WriteCoordinates( char* aLine, double aCoordX, double aCoordY );
};
/** /** Helper function.
* Function BuildHolesList * Writes the drill marks in HPGL, POSTSCRIPT or other supported formats
* Create the list of holes and tools for a given board * Each hole size has a symbol (circle, cross X, cross + ...) up to
* The list is sorted by increasing drill values * PLOTTER::MARKER_COUNT different values.
* Only holes from aFirstLayer to aLastLayer copper layers are listed (for vias, because * If more than PLOTTER::MARKER_COUNT different values,
* pad holes are always through holes) * these other values share the same mark shape
* @param aPcb : the given board * @param aPlotter = a PLOTTER instance (HPGL, POSTSCRIPT ... plotter).
* @param aHoleListBuffer : the std::vector<HOLE_INFO> to fill with pcb holes info */
* @param aToolListBuffer : the std::vector<DRILL_TOOL> to fill with tools to use bool PlotDrillMarks( PLOTTER* plotter );
* @param aFirstLayer = first layer to consider. if < 0 aFirstLayer is ignored };
* @param aLastLayer = last layer to consider. if < 0 aLastLayer is ignored
* @param aExcludeThroughHoles Exclude through holes if true.
* @param aGenerateNPTH_list :
* true to create NPTH only list (with no plated holes)
* false to created plated holes list (with no NPTH )
*/
void Build_Holes_List( BOARD* aPcb, std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& aToolListBuffer,
int aFirstLayer, int aLastLayer, bool aExcludeThroughHoles,
bool aGenerateNPTH_list );
void GenDrillMapFile( BOARD* aPcb,
FILE* aFile,
const wxString& aFullFileName,
const PAGE_INFO& aSheet,
std::vector<HOLE_INFO> aHoleListBuffer,
std::vector<DRILL_TOOL> aToolListBuffer,
bool aUnit_Drill_is_Inch,
int format, const wxPoint& auxoffset );
void Gen_Drill_PcbMap( BOARD* aPcb, PLOTTER* plotter,
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& aToolListBuffer );
/*
* Create a list of drill values and drill count
* there is only one report for all drill files even when buried or blinds vias exist
*/
void GenDrillReportFile( FILE* aFile, BOARD* aPcb, const wxString& aBoardFilename,
bool aUnit_Drill_is_Inch,
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& aToolListBuffer
);
#endif // #ifndef _GENDRILL_H_ #endif // #ifndef _GENDRILL_EXCELLON_WRITER_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment