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 (*)|*" ) );
// Wildcard for cvpcb component to footprint link file
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 SVGFileWildcard( _( "SVG files (*.svg)|*.svg;*.SVG" ) );
const wxString ReportFileWildcard = _( "Report files (*.rpt)|*.rpt" );
......
......@@ -151,9 +151,8 @@ set(PCBNEW_CLASS_SRCS
export_vrml.cpp
files.cpp
gen_drill_report_files.cpp
gen_holes_and_tools_lists_for_drill.cpp
gen_modules_placefile.cpp
gendrill.cpp
gendrill_Excellon_writer.cpp
globaleditpad.cpp
gpcb_exchange.cpp
highlight.cpp
......
......@@ -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->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 );
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 );
wxString m_ModeColorOptionChoices[] = { _("Color"), _("Black and white") };
......@@ -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 );
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 );
......
......@@ -207,7 +207,7 @@
<property name="style"></property>
<property name="subclass"></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_name"></property>
<property name="window_style"></property>
......@@ -290,7 +290,7 @@
<property name="style"></property>
<property name="subclass"></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_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
......@@ -629,7 +629,7 @@
<property name="gripper">0</property>
<property name="hidden">0</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="maximize_button">0</property>
<property name="maximum_size"></property>
......
......@@ -5,8 +5,8 @@
/*
* 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-2010 KiCad Developers, see change_log.txt for contributors.
* 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
......@@ -31,13 +31,14 @@
#include <pcbnew.h>
#include <wxPcbStruct.h>
#include <pcbplot.h>
#include <gendrill.h>
#include <gendrill_Excellon_writer.h>
#include <class_board.h>
#include <class_track.h>
#include <class_module.h>
#include <dialog_gendrill.h>
#include <wildcards_and_files_ext.h>
// Keywords for read and write config
......@@ -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_BASE( parent )
{
m_parent = parent;
m_board = parent->GetBoard();
m_config = wxGetApp().GetSettings();
m_plotOpts = m_parent->GetPlotSettings();
SetReturnCode( 1 );
initDialog();
......@@ -75,14 +91,13 @@ DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* parent ) :
// Static members of DIALOG_GENDRILL
int DIALOG_GENDRILL:: m_UnitDrillIsInch = true;
int DIALOG_GENDRILL:: m_ZerosFormat = EXCELLON_WRITER::DECIMAL_FORMAT;
int DIALOG_GENDRILL::m_UnitDrillIsInch = true;
int DIALOG_GENDRILL::m_ZerosFormat = EXCELLON_WRITER::DECIMAL_FORMAT;
bool DIALOG_GENDRILL::m_MinimalHeader = false;
bool DIALOG_GENDRILL::m_Mirror = false;
bool DIALOG_GENDRILL::m_DrillOriginIsAuxAxis = false;
int DIALOG_GENDRILL:: m_PrecisionFormat = 1;
bool DIALOG_GENDRILL::m_createRpt = false;
int DIALOG_GENDRILL::m_createMap = 0;
int DIALOG_GENDRILL::m_PrecisionFormat = 1;
int DIALOG_GENDRILL::m_mapFileType = 1;
DIALOG_GENDRILL::~DIALOG_GENDRILL()
......@@ -93,17 +108,12 @@ DIALOG_GENDRILL::~DIALOG_GENDRILL()
void DIALOG_GENDRILL::initDialog()
{
wxConfig* Config = wxGetApp().GetSettings();
if( Config )
{
Config->Read( ZerosFormatKey, &DIALOG_GENDRILL::m_ZerosFormat );
Config->Read( PrecisionKey, &DIALOG_GENDRILL::m_PrecisionFormat );
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 );
}
m_config->Read( ZerosFormatKey, &DIALOG_GENDRILL::m_ZerosFormat );
m_config->Read( PrecisionKey, &DIALOG_GENDRILL::m_PrecisionFormat );
m_config->Read( MirrorKey, &DIALOG_GENDRILL::m_Mirror );
m_config->Read( MinimalHeaderKey, &DIALOG_GENDRILL::m_MinimalHeader );
m_config->Read( UnitDrillInchKey, &DIALOG_GENDRILL::m_UnitDrillIsInch );
m_config->Read( DrillOriginIsAuxAxisKey, &DIALOG_GENDRILL::m_DrillOriginIsAuxAxis );
InitDisplayParams();
}
......@@ -129,8 +139,7 @@ void DIALOG_GENDRILL::InitDisplayParams()
m_Check_Mirror->SetValue( m_Mirror );
m_Choice_Drill_Map->SetSelection( m_createMap );
m_Choice_Drill_Report->SetSelection( m_createRpt );
m_Choice_Drill_Map->SetSelection( m_mapFileType );
m_ViaDrillValue->SetLabel( _( "Use Netclasses values" ) );
......@@ -208,6 +217,9 @@ void DIALOG_GENDRILL::InitDisplayParams()
msg = m_BuriedViasInfoMsg->GetLabel();
msg << wxT( " " ) << m_blindOrBuriedViasCount;
m_BuriedViasInfoMsg->SetLabel( msg );
// Output directory
m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
}
......@@ -215,17 +227,12 @@ void DIALOG_GENDRILL::UpdateConfig()
{
SetParams();
wxConfig* config = wxGetApp().GetSettings();
if( config )
{
config->Write( ZerosFormatKey, m_ZerosFormat );
config->Write( PrecisionKey, m_PrecisionFormat );
config->Write( MirrorKey, m_Mirror );
config->Write( MinimalHeaderKey, m_MinimalHeader );
config->Write( UnitDrillInchKey, m_UnitDrillIsInch );
config->Write( DrillOriginIsAuxAxisKey, m_DrillOriginIsAuxAxis );
}
m_config->Write( ZerosFormatKey, m_ZerosFormat );
m_config->Write( PrecisionKey, m_PrecisionFormat );
m_config->Write( MirrorKey, m_Mirror );
m_config->Write( MinimalHeaderKey, m_MinimalHeader );
m_config->Write( UnitDrillInchKey, m_UnitDrillIsInch );
m_config->Write( DrillOriginIsAuxAxisKey, m_DrillOriginIsAuxAxis );
}
......@@ -234,11 +241,14 @@ void DIALOG_GENDRILL::OnSelDrillUnitsSelected( wxCommandEvent& event )
UpdatePrecisionOptions();
}
void DIALOG_GENDRILL::OnGenMapFile( wxCommandEvent& event )
{
GenDrillAndMapFiles( false, true);
}
void DIALOG_GENDRILL::OnOkClick( wxCommandEvent& event )
void DIALOG_GENDRILL::OnGenDrillFile( wxCommandEvent& event )
{
GenDrillAndReportFiles();
EndModal( wxID_OK );
GenDrillAndMapFiles(true, false);
}
......@@ -276,17 +286,53 @@ void DIALOG_GENDRILL::UpdatePrecisionOptions()
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()
{
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_createMap = m_Choice_Drill_Map->GetSelection();
m_createRpt = m_Choice_Drill_Report->GetSelection();
m_mapFileType = m_Choice_Drill_Map->GetSelection();
m_UnitDrillIsInch = (m_Choice_Unit->GetSelection() == 0) ? false : true;
m_MinimalHeader = m_Check_Minimal->IsChecked();
......@@ -295,8 +341,6 @@ void DIALOG_GENDRILL::SetParams()
m_DrillOriginIsAuxAxis = m_Choice_Drill_Offset->GetSelection();
m_PrecisionFormat = m_Choice_Precision->GetSelection();
plot_opts.SetHPGLPenNum( 1 );
if( m_Choice_Drill_Offset->GetSelection() == 0 )
m_FileDrillOffset = wxPoint( 0, 0 );
else
......@@ -310,5 +354,271 @@ void DIALOG_GENDRILL::SetParams()
else
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:
private:
PCB_EDIT_FRAME* m_parent;
wxConfig* m_config;
BOARD* m_board;
wxString m_plotDefaultpath; // Current default plot dircetory.
PCB_PLOT_PARAMS m_plotOpts;
int m_platedPadsHoleCount;
int m_notplatedPadsHoleCount;
......@@ -60,8 +61,7 @@ private:
int m_microViasCount;
int m_blindOrBuriedViasCount;
static bool m_createRpt; // true to create a drill file report
static int m_createMap; // > 0 to create a map file report
static int m_mapFileType; // HPGL, PS ...
void initDialog();
......@@ -70,24 +70,25 @@ private:
// event functions
void OnSelDrillUnitsSelected( 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 OnOutputDirectoryBrowseClicked( wxCommandEvent& event );
// Specific functions:
void SetParams( void );
void GenDrillAndReportFiles();
void GenDrillMap( const wxString aFileName,
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& aToolListBuffer,
int format );
void GenDrillAndMapFiles(bool aGenDrill, bool aGenMap);
void GenDrillMap( const wxString aFileName,
EXCELLON_WRITER& aExcellonWriter,
PlotFormat format );
void UpdatePrecisionOptions();
void UpdateConfig();
void GenDrillReport( const wxString aFileName );
int Create_Drill_File_EXCELLON( FILE* aFile,
wxPoint aOffset,
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& aToolListBuffer );
int Gen_Liste_Tools( std::vector<DRILL_TOOL>& buffer, bool print_header );
int Create_Drill_File_EXCELLON( FILE* aFile,
wxPoint aOffset );
int Gen_Liste_Tools( std::vector<DRILL_TOOL>& buffer,
bool print_header );
/**
* Return the selected format for coordinates, if not decimal
......
......@@ -14,7 +14,28 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
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;
m_LeftBoxSizer = new wxBoxSizer( wxVERTICAL );
......@@ -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 );
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 );
bMainSizer->Add( m_LeftBoxSizer, 1, wxEXPAND, 5 );
bmiddlerSizer->Add( m_LeftBoxSizer, 0, wxEXPAND, 5 );
wxBoxSizer* bMiddleBoxSizer;
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 );
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") );
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;
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
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;
bRightBoxSizer = new wxBoxSizer( wxVERTICAL );
......@@ -108,7 +121,7 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
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;
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
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( 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_OkButton->SetDefault();
bRightBoxSizer->Add( m_OkButton, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
m_messagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
m_messagesBox->SetMinSize( wxSize( -1,90 ) );
m_CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
bRightBoxSizer->Add( m_CancelButton, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
bmsgSizer->Add( m_messagesBox, 1, wxALL|wxEXPAND, 5 );
bMainSizer->Add( bRightBoxSizer, 1, wxEXPAND, 5 );
bMainSizer->Add( bmsgSizer, 1, wxEXPAND, 5 );
this->SetSizer( bMainSizer );
......@@ -159,18 +198,24 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
this->Centre( wxBOTH );
// 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_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 );
}
DIALOG_GENDRILL_BASE::~DIALOG_GENDRILL_BASE()
{
// 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_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 );
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -13,20 +13,22 @@
#include <wx/intl.h>
#include "dialog_shim.h"
#include <wx/string.h>
#include <wx/radiobox.h>
#include <wx/textctrl.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/checkbox.h>
#include <wx/statbox.h>
#include <wx/radiobox.h>
#include <wx/checkbox.h>
#include <wx/stattext.h>
#include <wx/button.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
#define ID_GEN_DRILL_FILE 1000
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_GENDRILL_BASE
......@@ -36,14 +38,15 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
private:
protected:
wxTextCtrl* m_outputDirectoryName;
wxButton* m_buttonBrowse;
wxRadioBox* m_Choice_Unit;
wxRadioBox* m_Choice_Zeros_Format;
wxRadioBox* m_Choice_Precision;
wxRadioBox* m_Choice_Drill_Offset;
wxRadioBox* m_Choice_Drill_Map;
wxRadioBox* m_Choice_Drill_Report;
wxCheckBox* m_Check_Mirror;
wxCheckBox* m_Check_Minimal;
wxRadioBox* m_Choice_Drill_Offset;
wxStaticBoxSizer* m_DefaultViasDrillSizer;
wxStaticText* m_ViaDrillValue;
wxStaticBoxSizer* m_MicroViasDrillSizer;
......@@ -53,19 +56,25 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
wxStaticText* m_ThroughViasInfoMsg;
wxStaticText* m_MicroViasInfoMsg;
wxStaticText* m_BuriedViasInfoMsg;
wxButton* m_OkButton;
wxButton* m_buttonDrill;
wxButton* m_buttonMap;
wxButton* m_buttonReport;
wxButton* m_CancelButton;
wxTextCtrl* m_messagesBox;
// 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 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(); }
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();
};
......
/************************************************************************/
/* 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 <common.h>
#include <plot_common.h>
#include <base_struct.h>
#include <colors.h>
#include <drawtxt.h>
#include <confirm.h>
#include <kicad_string.h>
#include <macros.h>
#include <class_board.h>
#include <pcbnew.h>
#include <pcbplot.h>
#include <gendrill.h>
#include <gendrill_Excellon_writer.h>
/* 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;
}
static double diameter_in_mm(double ius)
inline double diameter_in_mm( double ius )
{
return ius / IU_PER_MM;
}
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 )
/* Creates a hole map of the board in HPGL, POSTSCRIPT or other supported formats
* Each hole size has a the drill mark symbol (circle, cross X, cross + ...) up to
* PLOTTER::MARKER_COUNT different values.
* If more than PLOTTER::MARKER_COUNT different values,
* these other vaules share the same mark
*/
bool EXCELLON_WRITER::GenDrillMapFile( const wxString& aFullFileName,
const PAGE_INFO& aSheet,
PlotFormat aFormat )
{
double scale = 1.0;
wxPoint offset;
PLOTTER* plotter = NULL;
double scale = 1.0;
wxPoint offset;
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
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
// an A4 sheet in PS, + text description of symbols
switch( format )
switch( aFormat )
{
case PLOT_FORMAT_GERBER:
offset = auxoffset;
offset = GetOffset();
plotter = new GERBER_PLOTTER();
plotter->SetViewport( offset, IU_PER_DECIMILS, scale, false );
break;
case PLOT_FORMAT_HPGL: // Scale for HPGL format.
case PLOT_FORMAT_HPGL: // Scale for HPGL format.
{
HPGL_PLOTTER* hpgl_plotter = new HPGL_PLOTTER;
plotter = hpgl_plotter;
......@@ -76,15 +103,15 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
wxSize pageSizeIU = pageA4.GetSizeIU();
// 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
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
// 60% height for board 40% height for list
int ypagesize_for_board = (int) (pageSizeIU.y * 0.6);
double Yscale = (double)( ypagesize_for_board - margin ) / bbbox.GetHeight();
int ypagesize_for_board = (int) (pageSizeIU.y * 0.6);
double Yscale = (double) ( ypagesize_for_board - margin ) / bbbox.GetHeight();
scale = std::min( Xscale, Yscale );
......@@ -93,9 +120,9 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
// So the scale is clipped at 3.0;
scale = std::min( scale, 3.0 );
offset.x = (int) ( (double) bbbox.Centre().x - ( pageSizeIU.x / 2.0 ) / scale );
offset.y = (int) ( (double) bbbox.Centre().y -
( ypagesize_for_board / 2.0 ) / scale );
offset.x = (int) ( (double) bbbox.Centre().x - ( pageSizeIU.x / 2.0 ) / scale );
offset.y = (int) ( (double) bbbox.Centre().y -
( ypagesize_for_board / 2.0 ) / scale );
PS_PLOTTER* ps_plotter = new PS_PLOTTER;
plotter = ps_plotter;
......@@ -126,16 +153,24 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
wxASSERT( false );
}
FILE* plotfile = wxFopen( aFullFileName, wxT( "wt" ) );
if( plotfile == NULL )
{
delete plotter;
return false;
}
plotter->SetCreator( wxT( "PCBNEW" ) );
plotter->SetFilename( aFullFileName );
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
BRDITEMS_PLOTTER itemplotter( plotter, aPcb, plot_opts );
BRDITEMS_PLOTTER itemplotter( plotter, m_pcb, plot_opts );
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() )
{
......@@ -160,25 +195,25 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
int intervalle = 0;
char line[1024];
wxString msg;
int textmarginaftersymbol = (int) (2 * IU_PER_MM);
int textmarginaftersymbol = (int) (2 * IU_PER_MM);
// Set Drill Symbols width
plotter->SetDefaultLineWidth( 0.2 * IU_PER_MM / scale );
plotter->SetCurrentLineWidth( -1 );
// Plot board outlines and drill map
Gen_Drill_PcbMap( aPcb, plotter, aHoleListBuffer, aToolListBuffer );
PlotDrillMarks( plotter );
// Print a list of symbols used.
int charSize = 3 * IU_PER_MM; // text size in IUs
double charScale = 1.0/scale; // real scale will be 1/scale,
//because the global plot scale is scale
TextWidth = (int) ( (charSize * charScale) / 10 ); // Set text width (thickness)
intervalle = (int) ( charSize * charScale ) + TextWidth;
int charSize = 3 * IU_PER_MM; // text size in IUs
double charScale = 1.0 / scale; // real scale will be 1/scale,
// because the global plot scale is scale
TextWidth = (int) ( (charSize * charScale) / 10 ); // Set text width (thickness)
intervalle = (int) ( charSize * charScale ) + TextWidth;
// Trace information.
plotX = (int) ( (double) bbbox.GetX() + textmarginaftersymbol * charScale );
plotY = bbbox.GetBottom() + intervalle;
plotX = (int) ( (double) bbbox.GetX() + textmarginaftersymbol * charScale );
plotY = bbbox.GetBottom() + intervalle;
// Plot title "Info"
wxString Text = wxT( "Drill Map:" );
......@@ -188,139 +223,128 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER,
TextWidth, false, false );
for( unsigned ii = 0; ii < aToolListBuffer.size(); ii++ )
for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
{
int plot_diam;
if( aToolListBuffer[ii].m_TotalCount == 0 )
if( m_toolListBuffer[ii].m_TotalCount == 0 )
continue;
plotY += intervalle;
plot_diam = (int) aToolListBuffer[ii].m_Diameter;
plot_diam = (int) m_toolListBuffer[ii].m_Diameter;
x = (int) ( (double) plotX - textmarginaftersymbol * charScale
- (double)plot_diam / 2.0 );
- (double) plot_diam / 2.0 );
y = (int) ( (double) plotY + (double) charSize * charScale );
plotter->Marker( wxPoint( x, y ), plot_diam, ii );
// Trace the legends.
// List the diameter of each drill in the selected Drill Unit,
// and then its diameter in the other Drill Unit.
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 ) );
// 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 ) );
msg = FROM_UTF8( line );
// Now list how many holes and ovals are associated with each drill.
if( ( aToolListBuffer[ii].m_TotalCount == 1 )
&& ( aToolListBuffer[ii].m_OvalCount == 0 ) )
if( ( m_toolListBuffer[ii].m_TotalCount == 1 )
&& ( m_toolListBuffer[ii].m_OvalCount == 0 ) )
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)" );
else if( aToolListBuffer[ii].m_OvalCount == 0 )
sprintf( line, "(%d holes)", aToolListBuffer[ii].m_TotalCount );
else if( aToolListBuffer[ii].m_OvalCount == 1 )
sprintf( line, "(%d holes + 1 slot)", aToolListBuffer[ii].m_TotalCount - 1 );
else // if ( aToolListBuffer[ii]m_OvalCount > 1 )
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 )
sprintf( line, "(%d holes + %d slots)",
aToolListBuffer[ii].m_TotalCount - aToolListBuffer[ii].m_OvalCount,
aToolListBuffer[ii].m_OvalCount );
m_toolListBuffer[ii].m_TotalCount - m_toolListBuffer[ii].m_OvalCount,
m_toolListBuffer[ii].m_OvalCount );
msg += FROM_UTF8( line );
plotter->Text( wxPoint( plotX, y ), UNSPECIFIED_COLOR,
msg,
0, wxSize( (int) ( charSize * charScale ),
(int) ( charSize * charScale ) ),
(int) ( charSize * charScale ) ),
GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER,
TextWidth, false, false );
intervalle = (int) ( charSize * charScale ) + TextWidth;
intervalle = (int) ( intervalle * 1.2 );
intervalle = (int) ( charSize * charScale ) + TextWidth;
intervalle = (int) ( intervalle * 1.2 );
if( intervalle < (plot_diam + (1*IU_PER_MM/scale) + TextWidth) )
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;
}
plotter->EndPlot();
delete plotter;
}
/** 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 );
}
}
return true;
}
/*
* 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,
const wxString& aBoardFilename,
bool aUnit_Drill_is_Inch,
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& aToolListBuffer )
bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
{
unsigned TotalHoleCount;
char line[1024];
int layer1 = LAYER_N_BACK;
int layer2 = LAYER_N_FRONT;
bool gen_through_holes = true;
bool gen_NPTH_holes = false;
unsigned totalHoleCount;
char line[1024];
int layer1 = LAYER_N_BACK;
int layer2 = LAYER_N_FRONT;
bool gen_through_holes = true;
bool gen_NPTH_holes = false;
m_file = wxFopen( aFullFileName, wxT( "w" ) );
fprintf( aFile, "Drill report for %s\n", TO_UTF8( aBoardFilename ) );
fprintf( aFile, "Created on %s\n", TO_UTF8( DateAndTime() ) );
if( m_file == NULL )
return false;
// List which Drill Unit option had been selected for the associated
// drill aFile.
if( aUnit_Drill_is_Inch )
fputs( "Selected Drill Unit: Imperial (inches)\n\n", aFile );
else
fputs( "Selected Drill Unit: Metric (mm)\n\n", aFile );
wxString brdFilename = m_pcb->GetFileName();
fprintf( m_file, "Drill report for %s\n", TO_UTF8( brdFilename ) );
fprintf( m_file, "Created on %s\n", TO_UTF8( DateAndTime() ) );
/* build hole lists:
* 1 - through holes
......@@ -330,87 +354,66 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb,
for( ; ; )
{
Build_Holes_List( aPcb,
aHoleListBuffer,
aToolListBuffer,
layer1,
layer2,
BuildHolesList( layer1, layer2,
gen_through_holes ? false : true, gen_NPTH_holes );
TotalHoleCount = 0;
totalHoleCount = 0;
if( gen_NPTH_holes )
{
sprintf( line, "Drill report for unplated through holes :\n" );
}
else if( gen_through_holes )
{
sprintf( line, "Drill report for plated through holes :\n" );
}
else
{
if( layer1 == LAYER_N_BACK ) // First partial hole list
{
sprintf( line, "Drill report for buried and blind vias :\n\n" );
fputs( line, aFile );
}
// If this is the first partial hole list: print a title
if( layer1 == LAYER_N_BACK )
fputs( "Drill report for buried and blind vias :\n\n", m_file );
sprintf( line, "Drill report for holes from layer %s to layer %s :\n",
TO_UTF8( aPcb->GetLayerName( layer1 ) ),
TO_UTF8( aPcb->GetLayerName( layer2 ) ) );
TO_UTF8( m_pcb->GetLayerName( layer1 ) ),
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,
// then its diameter in the selected Drill Unit,
// and then its diameter in the other Drill Unit.
if( aUnit_Drill_is_Inch )
{
sprintf( line, "T%d %2.3f\" %2.2fmm ",
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 ) );
}
// in mm then in inches.
sprintf( line, "T%d %2.2fmm %2.3f\" ",
ii + 1,
diameter_in_mm( m_toolListBuffer[ii].m_Diameter ),
diameter_in_inches( m_toolListBuffer[ii].m_Diameter ) );
fputs( line, aFile );
fputs( line, m_file );
// Now list how many holes and ovals are associated with each drill.
if( ( aToolListBuffer[ii].m_TotalCount == 1 )
&& ( aToolListBuffer[ii].m_OvalCount == 0 ) )
if( ( m_toolListBuffer[ii].m_TotalCount == 1 )
&& ( m_toolListBuffer[ii].m_OvalCount == 0 ) )
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" );
else if( aToolListBuffer[ii].m_OvalCount == 0 )
sprintf( line, "(%d holes)\n", aToolListBuffer[ii].m_TotalCount );
else if( aToolListBuffer[ii].m_OvalCount == 1 )
sprintf( line, "(%d holes) (with 1 slot)\n", aToolListBuffer[ii].m_TotalCount );
else // if ( buffer[ii]m_OvalCount > 1 )
else if( m_toolListBuffer[ii].m_OvalCount == 0 )
sprintf( line, "(%d holes)\n", m_toolListBuffer[ii].m_TotalCount );
else if( m_toolListBuffer[ii].m_OvalCount == 1 )
sprintf( line, "(%d holes) (with 1 slot)\n",
m_toolListBuffer[ii].m_TotalCount );
else // if ( buffer[ii]m_OvalCount > 1 )
sprintf( line, "(%d holes) (with %d slots)\n",
aToolListBuffer[ii].m_TotalCount,
aToolListBuffer[ii].m_OvalCount );
m_toolListBuffer[ii].m_TotalCount,
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 )
sprintf( line, "\nTotal unplated holes count %d\n\n\n", TotalHoleCount );
sprintf( line, "\nTotal unplated holes count %d\n\n\n", totalHoleCount );
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 )
{
......@@ -418,7 +421,7 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb,
}
else
{
if( aPcb->GetCopperLayerCount() <= 2 )
if( m_pcb->GetCopperLayerCount() <= 2 )
{
gen_NPTH_holes = true;
continue;
......@@ -438,13 +441,43 @@ void GenDrillReportFile( FILE* aFile, BOARD* aPcb,
layer1++; layer2++; // use next layer pair
if( layer2 == aPcb->GetCopperLayerCount() - 1 )
layer2 = LAYER_N_FRONT; // the last layer is always the
// component layer
if( layer2 == m_pcb->GetCopperLayerCount() - 1 )
layer2 = LAYER_N_FRONT; // the last layer is always the
// component layer
}
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.
*/
/*
* 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-2010 KiCad Developers, see change_log.txt for contributors.
* 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
......@@ -39,19 +39,18 @@
#include <plot_common.h>
#include <trigo.h>
#include <confirm.h>
#include <kicad_string.h>
#include <gestfich.h>
#include <wxPcbStruct.h>
#include <macros.h>
#include <appl_wxstruct.h>
#include <build_version.h>
#include <class_board.h>
#include <class_module.h>
#include <class_track.h>
#include <pcbplot.h>
#include <pcbnew.h>
#include <gendrill.h>
#include <gendrill_Excellon_writer.h>
#include <wildcards_and_files_ext.h>
#include <dialog_gendrill.h> // Dialog box for drill file generation
......@@ -66,199 +65,17 @@
* Units
* - Decimal
* - 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
* @return hole count
* return hole count
*/
int EXCELLON_WRITER::CreateDrillFile()
int EXCELLON_WRITER::CreateDrillFile( FILE * aFile )
{
m_file = aFile;
int diam, holes_count;
int x0, y0, xf, yf, xc, yc;
double xt, yt;
......@@ -266,14 +83,14 @@ int EXCELLON_WRITER::CreateDrillFile()
SetLocaleTo_C_standard(); // Use the standard notation for double numbers
WriteHeader();
WriteEXCELLONHeader();
holes_count = 0;
/* 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,
tool_descr.m_Diameter * m_conversionUnits );
}
......@@ -294,9 +111,9 @@ int EXCELLON_WRITER::CreateDrillFile()
/* Read the hole file and generate lines for normal holes (oblong
* holes will be created later) */
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 )
continue; // oblong holes will be created later
......@@ -323,10 +140,10 @@ int EXCELLON_WRITER::CreateDrillFile()
/* Read the hole file and generate lines for normal holes (oblong holes
* will be created later) */
tool_reference = -2; // set to a value not used for
// aHoleListBuffer[ii].m_Tool_Reference
for( unsigned ii = 0; ii < m_holeListBuffer->size(); ii++ )
// m_holeListBuffer[ii].m_Tool_Reference
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 )
continue; // wait for oblong holes
if( tool_reference != hole_descr.m_Tool_Reference )
......@@ -387,7 +204,7 @@ int EXCELLON_WRITER::CreateDrillFile()
holes_count++;
}
WriteEndOfFile();
WriteEXCELLONEndOfFile();
SetLocaleTo_Default(); // Revert to locale double notation
......@@ -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 ypad = xpad;
switch( DIALOG_GENDRILL::m_ZerosFormat )
switch( m_zeroFormat )
{
default:
case DECIMAL_FORMAT:
......@@ -526,7 +343,7 @@ void EXCELLON_WRITER::WriteCoordinates( char* aLine, double aCoordX, double aCoo
* FMAT,2
* INCH,TZ
*/
void EXCELLON_WRITER::WriteHeader()
void EXCELLON_WRITER::WriteEXCELLONHeader()
{
fputs( "M48\n", m_file ); // The beginning of a header
......@@ -589,7 +406,7 @@ void EXCELLON_WRITER::WriteHeader()
}
void EXCELLON_WRITER::WriteEndOfFile()
void EXCELLON_WRITER::WriteEXCELLONEndOfFile()
{
//add if minimal here
fputs( "T0\nM30\n", m_file );
......@@ -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,
std::vector<HOLE_INFO>& aHoleListBuffer,
std::vector<DRILL_TOOL>& buffer,
int format )
static bool CmpHoleDiameterValue( const HOLE_INFO& a, const HOLE_INFO& b )
{
wxFileName fn;
wxString ext, wildcard;
wxString msg;
if( a.m_Hole_Diameter != b.m_Hole_Diameter )
return a.m_Hole_Diameter < b.m_Hole_Diameter;
/* Init extension */
switch( format )
{
case PLOT_FORMAT_HPGL:
ext = HPGL_PLOTTER::GetDefaultFileExtension();
wildcard = _( "HPGL plot files (.plt)|*.plt" );
break;
if( a.m_Hole_Pos.x != b.m_Hole_Pos.x )
return a.m_Hole_Pos.x < b.m_Hole_Pos.x;
case PLOT_FORMAT_POST:
ext = PS_PLOTTER::GetDefaultFileExtension();
wildcard = _( "PostScript files (.ps)|*.ps" );
break;
return a.m_Hole_Pos.y < b.m_Hole_Pos.y;
}
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;
/*
* 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 (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:
ext = SVG_PLOTTER::GetDefaultFileExtension();
wildcard = SVGFileWildcard;
break;
m_holeListBuffer.clear();
m_toolListBuffer.clear();
default:
DisplayError( this, wxT( "DIALOG_GENDRILL::GenDrillMap() error" ) );
return;
if( (aFirstLayer >= 0) && (aLastLayer >= 0) )
{
if( aFirstLayer > aLastLayer )
EXCHG( aFirstLayer, aLastLayer );
}
/* Init file name */
fn = aFileName;
fn.SetName( fn.GetName() + wxT( "-drl" ) );
fn.SetExt( ext );
/* build hole list for vias
*/
if( ! aGenerateNPTH_list ) // vias are always plated !
{
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(),
fn.GetFullName(), wildcard,
wxFD_SAVE );
if( hole_value == 0 )
continue;
if( dlg.ShowModal() == wxID_CANCEL )
return;
new_hole.m_Tool_Reference = -1; // Flag value for Not initialized
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" );
msg << wxT( " <" ) << dlg.GetPath() << wxT( ">" );
wxMessageBox( msg );
return;
for( MODULE* module = m_pcb->m_Modules; module; module = module->Next() )
{
// Read and analyse pads
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(),
plotfile,
dlg.GetPath(),
m_parent->GetPageSettings(),
s_HoleListBuffer,
s_ToolListBuffer,
m_UnitDrillIsInch,
format, m_FileDrillOffset );
}
// Sort holes per increasing diameter value
sort( m_holeListBuffer.begin(), m_holeListBuffer.end(), CmpHoleDiameterValue );
// 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;
/*
* Create a list of drill values and drill count
*/
void DIALOG_GENDRILL::GenDrillReport( const wxString aFileName )
{
wxFileName fn;
wxString msg;
for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
{
if( m_holeListBuffer[ii].m_Hole_Diameter != LastHole )
{
new_tool.m_Diameter = ( m_holeListBuffer[ii].m_Hole_Diameter );
m_toolListBuffer.push_back( new_tool );
LastHole = new_tool.m_Diameter;
}
fn = aFileName;
fn.SetName( fn.GetName() + wxT( "-drl" ) );
fn.SetExt( ReportFileExtension );
jj = m_toolListBuffer.size();
wxFileDialog dlg( this, _( "Save Drill Report File" ), fn.GetPath(),
fn.GetFullName(), wxGetTranslation( ReportFileWildcard ),
wxFD_SAVE );
if( jj == 0 )
continue; // Should not occurs
if( dlg.ShowModal() == wxID_CANCEL )
return;
m_holeListBuffer[ii].m_Tool_Reference = jj; // Tool value Initialized (value >= 1)
FILE* report_dest = wxFopen( dlg.GetPath(), wxT( "w" ) );
m_toolListBuffer.back().m_TotalCount++;
if( report_dest == 0 )
{
msg = _( "Unable to create file " ) + dlg.GetPath();
wxMessageBox( msg );
return;
if( m_holeListBuffer[ii].m_Hole_Shape )
m_toolListBuffer.back().m_OvalCount++;
}
GenDrillReportFile( report_dest, m_parent->GetBoard(),
m_parent->GetBoard()->GetFileName(),
m_UnitDrillIsInch,
s_HoleListBuffer,
s_ToolListBuffer );
}
/**
* @file gendrill.h
* @brief Classes and functions declaration used in drill file and report generation.
* @file gendrill_Excellon_writer.h
* @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.
*
* Copyright (C) 1992-2010 Jean_Pierre Charras <jp.charras@ujf-grenoble.fr>
* Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors.
* 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
......@@ -27,8 +27,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _GENDRILL_H_
#define _GENDRILL_H_
#ifndef _GENDRILL_EXCELLON_WRITER_
#define _GENDRILL_EXCELLON_WRITER_
#include <vector>
......@@ -44,7 +44,9 @@ 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
public: DRILL_TOOL( int diametre )
public:
DRILL_TOOL( int diametre )
{
m_TotalCount = 0;
m_OvalCount = 0;
......@@ -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
{
public:
......@@ -130,19 +135,14 @@ private:
// (i.e inches or mm)
bool m_mirror;
wxPoint m_offset; // Drill offset ooordinates
std::vector<HOLE_INFO>* m_holeListBuffer; // Buffer containing holes
std::vector<DRILL_TOOL>* m_toolListBuffer; // Buffer containing tools
std::vector<HOLE_INFO> m_holeListBuffer; // Buffer containing holes
std::vector<DRILL_TOOL> m_toolListBuffer; // Buffer containing tools
public: EXCELLON_WRITER( BOARD* aPcb, FILE* aFile,
wxPoint aOffset,
std::vector<HOLE_INFO>* aHoleListBuffer,
std::vector<DRILL_TOOL>* aToolListBuffer )
public: EXCELLON_WRITER( BOARD* aPcb, wxPoint aOffset )
{
m_file = aFile;
m_file = NULL;
m_pcb = aPcb;
m_zeroFormat = DECIMAL_FORMAT;
m_holeListBuffer = aHoleListBuffer;
m_toolListBuffer = aToolListBuffer;
m_conversionUnits = 0.0001;
m_unitsDecimal = false;
m_mirror = false;
......@@ -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
......@@ -179,62 +184,74 @@ public: EXCELLON_WRITER( BOARD* aPcb, FILE* aFile,
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
* Creates an Excellon drill file
* @param aFile = an opened file to write to
* will be closed by CreateDrillFile
* @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:
void WriteHeader();
void WriteEndOfFile();
void WriteEXCELLONHeader();
void WriteEXCELLONEndOfFile();
void WriteCoordinates( char* aLine, double aCoordX, double aCoordY );
};
/**
* 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 aPcb : the given board
* @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
* @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 );
/** Helper function.
* Writes the drill marks in HPGL, POSTSCRIPT or other supported formats
* Each hole size has a symbol (circle, cross X, cross + ...) up to
* PLOTTER::MARKER_COUNT different values.
* If more than PLOTTER::MARKER_COUNT different values,
* these other values share the same mark shape
* @param aPlotter = a PLOTTER instance (HPGL, POSTSCRIPT ... plotter).
*/
bool PlotDrillMarks( PLOTTER* plotter );
};
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