Pcbnew: Add creation of Drill Files in Gerber X2 format.
Gerbview: add support of drill files in Gerber format. Fix also an issue in drill dialog: Axis choice is now common to plot a drill files.
This commit is contained in:
parent
a92ea8c75b
commit
afe92c7bfc
|
@ -99,9 +99,23 @@ std::string GBR_APERTURE_METADATA::FormatAttribute( GBR_APERTURE_ATTRIB aAttribu
|
|||
attribute_string = "%TA.AperFunction,WasherPad*%\n";
|
||||
break;
|
||||
|
||||
case GBR_APERTURE_ATTRIB_HEATSINKPAD: // print info associated to a flashed heat sink pad (typically for SMDs)
|
||||
case GBR_APERTURE_ATTRIB_HEATSINKPAD: // print info associated to a flashed heat sink pad
|
||||
// (typically for SMDs)
|
||||
attribute_string = "%TA.AperFunction,HeatsinkPad*%\n";
|
||||
break;
|
||||
|
||||
case GBR_APERTURE_ATTRIB_VIADRILL: // print info associated to a via hole in drill files
|
||||
attribute_string = "%TA.AperFunction,ViaDrill*%\n";
|
||||
break;
|
||||
|
||||
case GBR_APERTURE_ATTRIB_COMPONENTDRILL: // print info associated to a component
|
||||
// round hole in drill files
|
||||
attribute_string = "%TA.AperFunction,ComponentDrill*%\n";
|
||||
break;
|
||||
|
||||
case GBR_APERTURE_ATTRIB_SLOTDRILL: // print info associated to a oblong hole in drill files
|
||||
attribute_string = "%TA.AperFunction,Slot*%\n";
|
||||
break;
|
||||
}
|
||||
|
||||
return attribute_string;
|
||||
|
|
|
@ -174,8 +174,8 @@ X2_ATTRIBUTE_FILEFUNCTION::X2_ATTRIBUTE_FILEFUNCTION( X2_ATTRIBUTE& aAttributeBa
|
|||
m_Prms = aAttributeBase.GetPrms();
|
||||
m_z_order = 0;
|
||||
|
||||
//ensure at least 5 parameters
|
||||
while( GetPrmCount() < 5 )
|
||||
// ensure at least 7 parameters exist.
|
||||
while( GetPrmCount() < 7 )
|
||||
m_Prms.Add( wxEmptyString );
|
||||
|
||||
set_Z_Order();
|
||||
|
@ -183,7 +183,7 @@ X2_ATTRIBUTE_FILEFUNCTION::X2_ATTRIBUTE_FILEFUNCTION( X2_ATTRIBUTE& aAttributeBa
|
|||
|
||||
const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetFileType()
|
||||
{
|
||||
// the type of layer (Copper , Soldermask ... )
|
||||
// the type of layer (Copper, Soldermask ... )
|
||||
return m_Prms.Item( 1 );
|
||||
}
|
||||
|
||||
|
@ -193,6 +193,14 @@ const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetBrdLayerId()
|
|||
return m_Prms.Item( 2 );
|
||||
}
|
||||
|
||||
const wxString X2_ATTRIBUTE_FILEFUNCTION::GetDrillLayerPair()
|
||||
{
|
||||
// the layer pair identifiers, for drill files, i.e.
|
||||
// with m_Prms.Item( 1 ) = "Plated" or "NonPlated"
|
||||
wxString lpair = m_Prms.Item( 2 ) + ',' + m_Prms.Item( 3 );
|
||||
return lpair;
|
||||
}
|
||||
|
||||
const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetBrdLayerSide()
|
||||
{
|
||||
if( IsCopper() )
|
||||
|
@ -203,6 +211,7 @@ const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetBrdLayerSide()
|
|||
return m_Prms.Item( 2 );
|
||||
}
|
||||
|
||||
|
||||
const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetLabel()
|
||||
{
|
||||
if( IsCopper() )
|
||||
|
@ -212,12 +221,35 @@ const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetLabel()
|
|||
}
|
||||
|
||||
|
||||
const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetLPType()
|
||||
{
|
||||
// Only for drill files: the Layer Pair type (PTH, NPTH, Blind or Buried)
|
||||
return m_Prms.Item( 4 );
|
||||
}
|
||||
|
||||
|
||||
const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetRouteType()
|
||||
{
|
||||
// Only for drill files: the drill/routing type(Drill, Route, Mixed)
|
||||
return m_Prms.Item( 5 );
|
||||
}
|
||||
|
||||
|
||||
bool X2_ATTRIBUTE_FILEFUNCTION::IsCopper()
|
||||
{
|
||||
// the filefunction label, if any
|
||||
return GetFileType().IsSameAs( wxT( "Copper" ), false );
|
||||
}
|
||||
|
||||
|
||||
bool X2_ATTRIBUTE_FILEFUNCTION::IsDrillFile()
|
||||
{
|
||||
// the filefunction label, if any
|
||||
return GetFileType().IsSameAs( wxT( "Plated" ), false )
|
||||
|| GetFileType().IsSameAs( wxT( "NonPlated" ), false );
|
||||
}
|
||||
|
||||
|
||||
// Initialize the z order priority of the current file, from its attributes
|
||||
// this priority is the order of layers from top to bottom to draw/display gerber images
|
||||
// Stack up is( from external copper layer to external)
|
||||
|
|
|
@ -156,9 +156,33 @@ public:
|
|||
|
||||
bool IsCopper(); ///< return true if the filefunction type is "Copper"
|
||||
|
||||
/**
|
||||
* @return true if the filefunction type is "Plated" or "NotPlated"
|
||||
* therefore a drill file
|
||||
*/
|
||||
bool IsDrillFile();
|
||||
|
||||
const wxString& GetFileType(); ///< the type of layer (Copper, Soldermask ... )
|
||||
const wxString& GetBrdLayerId(); ///< the brd layer identifier: Ln, only for Copper type
|
||||
///< or Top, Bot for other types
|
||||
/**
|
||||
* @return the brd layer pair identifier: n,m for drill files
|
||||
* (files with m_Prms.Item( 1 ) = "Plated" or "NotPlated")
|
||||
*/
|
||||
const wxString GetDrillLayerPair();
|
||||
|
||||
/**
|
||||
* @return the Layer Pair type for drill files
|
||||
* (PTH, NPTH, Blind or Buried)
|
||||
*/
|
||||
const wxString& GetLPType();
|
||||
|
||||
/**
|
||||
* @return the drill/routing type for drill files
|
||||
* (Drill, Route, Mixed)
|
||||
*/
|
||||
const wxString& GetRouteType();
|
||||
|
||||
const wxString& GetBrdLayerSide(); ///< the brd layer Pos: Top, Bot, Inr
|
||||
///< same as GetBrdLayerId() for non copper type
|
||||
const wxString& GetLabel(); ///< the filefunction label, if any
|
||||
|
|
|
@ -157,6 +157,15 @@ const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx, bool aNameOnly
|
|||
GetChars( gerber->m_FileFunction->GetBrdLayerId() ),
|
||||
GetChars( gerber->m_FileFunction->GetBrdLayerSide() ) );
|
||||
}
|
||||
if( gerber->m_FileFunction->IsDrillFile() )
|
||||
{
|
||||
name.Printf( "%s (%s,%s,%s,%s)",
|
||||
filename.GetData(),
|
||||
GetChars( gerber->m_FileFunction->GetFileType() ),
|
||||
GetChars( gerber->m_FileFunction->GetDrillLayerPair() ),
|
||||
GetChars( gerber->m_FileFunction->GetLPType() ),
|
||||
GetChars( gerber->m_FileFunction->GetRouteType() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
name.Printf( "%s (%s, %s)",
|
||||
|
|
|
@ -60,6 +60,9 @@ public:
|
|||
GBR_APERTURE_ATTRIB_CONNECTORPAD, ///< aperture used for edge connecto pad (outer layers)
|
||||
GBR_APERTURE_ATTRIB_WASHERPAD, ///< aperture used for mechanical pads (NPTH)
|
||||
GBR_APERTURE_ATTRIB_HEATSINKPAD, ///< aperture used for heat sink pad (typically for SMDs)
|
||||
GBR_APERTURE_ATTRIB_VIADRILL, ///< aperture used for via holes in drill files
|
||||
GBR_APERTURE_ATTRIB_COMPONENTDRILL, ///< aperture used for pad holes in drill files
|
||||
GBR_APERTURE_ATTRIB_SLOTDRILL, ///< aperture used for oblong holes in drill files
|
||||
GBR_APERTURE_ATTRIB_END ///< sentinel: max value
|
||||
};
|
||||
|
||||
|
|
|
@ -178,6 +178,8 @@ set( PCBNEW_EXPORTERS
|
|||
exporters/gen_drill_report_files.cpp
|
||||
exporters/gen_modules_placefile.cpp
|
||||
exporters/gendrill_Excellon_writer.cpp
|
||||
exporters/gendrill_file_writer_base.cpp
|
||||
exporters/gendrill_gerber_writer.cpp
|
||||
)
|
||||
|
||||
set( PCBNEW_AUTOROUTER_SRCS
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
/*
|
||||
* 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-2016 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 1992-2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 1992-2017 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
|
||||
|
@ -32,7 +32,8 @@
|
|||
#include <wxPcbStruct.h>
|
||||
#include <pcbplot.h>
|
||||
#include <gendrill_Excellon_writer.h>
|
||||
#include <macros.h>
|
||||
#include <gendrill_gerber_writer.h>
|
||||
//#include <macros.h>
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_track.h>
|
||||
|
@ -54,6 +55,7 @@
|
|||
#define UnitDrillInchKey wxT( "DrillUnit" )
|
||||
#define DrillOriginIsAuxAxisKey wxT( "DrillAuxAxis" )
|
||||
#define DrillMapFileTypeKey wxT( "DrillMapFileType" )
|
||||
#define DrillFileFormatKey wxT( "DrillFileType" )
|
||||
|
||||
// list of allowed precision for EXCELLON files, for integer format:
|
||||
// Due to difference between inches and mm,
|
||||
|
@ -87,13 +89,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;
|
||||
bool DIALOG_GENDRILL::m_MinimalHeader = false;
|
||||
bool DIALOG_GENDRILL::m_Mirror = false;
|
||||
bool DIALOG_GENDRILL::m_Merge_PTH_NPTH = false;
|
||||
bool DIALOG_GENDRILL::m_DrillOriginIsAuxAxis = false;
|
||||
int DIALOG_GENDRILL::m_mapFileType = 1;
|
||||
int DIALOG_GENDRILL::m_UnitDrillIsInch = true; // Only for Excellon format
|
||||
int DIALOG_GENDRILL::m_ZerosFormat = EXCELLON_WRITER::DECIMAL_FORMAT;
|
||||
bool DIALOG_GENDRILL::m_MinimalHeader = false; // Only for Excellon format
|
||||
bool DIALOG_GENDRILL::m_Mirror = false; // Only for Excellon format
|
||||
bool DIALOG_GENDRILL::m_Merge_PTH_NPTH = false; // Only for Excellon format
|
||||
int DIALOG_GENDRILL::m_mapFileType = 1;
|
||||
int DIALOG_GENDRILL::m_drillFileType = 0;
|
||||
|
||||
|
||||
DIALOG_GENDRILL::~DIALOG_GENDRILL()
|
||||
|
@ -109,8 +111,9 @@ void DIALOG_GENDRILL::initDialog()
|
|||
m_config->Read( MergePTHNPTHKey, &m_Merge_PTH_NPTH );
|
||||
m_config->Read( MinimalHeaderKey, &m_MinimalHeader );
|
||||
m_config->Read( UnitDrillInchKey, &m_UnitDrillIsInch );
|
||||
m_config->Read( DrillOriginIsAuxAxisKey, &m_DrillOriginIsAuxAxis );
|
||||
m_drillOriginIsAuxAxis = m_plotOpts.GetUseAuxOrigin();
|
||||
m_config->Read( DrillMapFileTypeKey, &m_mapFileType );
|
||||
m_config->Read( DrillFileFormatKey, &m_drillFileType );
|
||||
|
||||
InitDisplayParams();
|
||||
}
|
||||
|
@ -120,12 +123,13 @@ void DIALOG_GENDRILL::InitDisplayParams()
|
|||
{
|
||||
wxString msg;
|
||||
|
||||
m_rbFileFormat->SetSelection( m_drillFileType );
|
||||
m_Choice_Unit->SetSelection( m_UnitDrillIsInch ? 1 : 0 );
|
||||
m_Choice_Zeros_Format->SetSelection( m_ZerosFormat );
|
||||
UpdatePrecisionOptions();
|
||||
m_Check_Minimal->SetValue( m_MinimalHeader );
|
||||
|
||||
if( m_DrillOriginIsAuxAxis )
|
||||
if( m_drillOriginIsAuxAxis )
|
||||
m_Choice_Drill_Offset->SetSelection( 1 );
|
||||
|
||||
m_Check_Mirror->SetValue( m_Mirror );
|
||||
|
@ -221,6 +225,30 @@ void DIALOG_GENDRILL::InitDisplayParams()
|
|||
|
||||
// Output directory
|
||||
m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
|
||||
|
||||
wxCommandEvent dummy;
|
||||
onFileFormatSelection( dummy );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_GENDRILL::onFileFormatSelection( wxCommandEvent& event )
|
||||
{
|
||||
m_drillFileType = m_rbFileFormat->GetSelection();
|
||||
bool enbl_Excellon = m_drillFileType == 0;
|
||||
|
||||
m_Choice_Unit->Enable( enbl_Excellon );
|
||||
m_Choice_Zeros_Format->Enable( enbl_Excellon );
|
||||
m_Check_Mirror->Enable( enbl_Excellon );
|
||||
m_Check_Minimal->Enable( enbl_Excellon );
|
||||
m_Check_Merge_PTH_NPTH->Enable( enbl_Excellon );
|
||||
|
||||
if( enbl_Excellon )
|
||||
UpdatePrecisionOptions();
|
||||
else
|
||||
{
|
||||
m_staticTextPrecision->Enable( true );
|
||||
m_staticTextPrecision->SetLabel( m_plotOpts.GetGerberPrecision() == 6 ? "4.6" : "4.5" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -233,8 +261,8 @@ void DIALOG_GENDRILL::UpdateConfig()
|
|||
m_config->Write( MergePTHNPTHKey, m_Merge_PTH_NPTH );
|
||||
m_config->Write( MinimalHeaderKey, m_MinimalHeader );
|
||||
m_config->Write( UnitDrillInchKey, m_UnitDrillIsInch );
|
||||
m_config->Write( DrillOriginIsAuxAxisKey, m_DrillOriginIsAuxAxis );
|
||||
m_config->Write( DrillMapFileTypeKey, m_mapFileType );
|
||||
m_config->Write( DrillFileFormatKey, m_drillFileType );
|
||||
}
|
||||
|
||||
|
||||
|
@ -328,6 +356,8 @@ void DIALOG_GENDRILL::SetParams()
|
|||
dirStr = m_outputDirectoryName->GetValue();
|
||||
dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
|
||||
m_plotOpts.SetOutputDirectory( dirStr );
|
||||
m_drillOriginIsAuxAxis = m_Choice_Drill_Offset->GetSelection();
|
||||
m_plotOpts.SetUseAuxOrigin( m_drillOriginIsAuxAxis );
|
||||
|
||||
m_mapFileType = m_Choice_Drill_Map->GetSelection();
|
||||
|
||||
|
@ -336,7 +366,6 @@ void DIALOG_GENDRILL::SetParams()
|
|||
m_Mirror = m_Check_Mirror->IsChecked();
|
||||
m_Merge_PTH_NPTH = m_Check_Merge_PTH_NPTH->IsChecked();
|
||||
m_ZerosFormat = m_Choice_Zeros_Format->GetSelection();
|
||||
m_DrillOriginIsAuxAxis = m_Choice_Drill_Offset->GetSelection();
|
||||
|
||||
if( m_Choice_Drill_Offset->GetSelection() == 0 )
|
||||
m_FileDrillOffset = wxPoint( 0, 0 );
|
||||
|
@ -371,13 +400,28 @@ void DIALOG_GENDRILL::GenDrillAndMapFiles( bool aGenDrill, bool aGenMap )
|
|||
if( choice >= DIM( filefmt ) )
|
||||
choice = 1;
|
||||
|
||||
EXCELLON_WRITER excellonWriter( m_parent->GetBoard() );
|
||||
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, m_Merge_PTH_NPTH );
|
||||
excellonWriter.SetMapFileFormat( filefmt[choice] );
|
||||
if( m_drillFileType == 0 )
|
||||
{
|
||||
EXCELLON_WRITER excellonWriter( m_parent->GetBoard() );
|
||||
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, m_Merge_PTH_NPTH );
|
||||
excellonWriter.SetMapFileFormat( filefmt[choice] );
|
||||
|
||||
excellonWriter.CreateDrillandMapFilesSet( defaultPath, aGenDrill, aGenMap, &reporter );
|
||||
excellonWriter.CreateDrillandMapFilesSet( defaultPath, aGenDrill, aGenMap, &reporter );
|
||||
}
|
||||
else
|
||||
{
|
||||
GERBER_WRITER gerberWriter( m_parent->GetBoard() );
|
||||
// Set gerber precision: only 5 or 6 digits for mantissa are allowed
|
||||
// (SetFormat() accept 5 or 6, and any other value set the precision to 5)
|
||||
// the integer part precision is always 4, and units always mm
|
||||
gerberWriter.SetFormat( m_plotOpts.GetGerberPrecision() );
|
||||
gerberWriter.SetOptions( m_FileDrillOffset );
|
||||
gerberWriter.SetMapFileFormat( filefmt[choice] );
|
||||
|
||||
gerberWriter.CreateDrillandMapFilesSet( defaultPath, aGenDrill, aGenMap, &reporter );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -401,12 +445,21 @@ void DIALOG_GENDRILL::OnGenReportFile( wxCommandEvent& event )
|
|||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
EXCELLON_WRITER excellonWriter( m_parent->GetBoard() );
|
||||
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, m_Merge_PTH_NPTH );
|
||||
bool success;
|
||||
|
||||
bool success = excellonWriter.GenDrillReportFile( dlg.GetPath() );
|
||||
// Info is slightly different between Excellon and Gerber
|
||||
// (file ext, Merge PTH/NPTH option)
|
||||
if( m_drillFileType == 0 )
|
||||
{
|
||||
EXCELLON_WRITER excellonWriter( m_parent->GetBoard() );
|
||||
excellonWriter.SetMergeOption( m_Merge_PTH_NPTH );
|
||||
success = excellonWriter.GenDrillReportFile( dlg.GetPath() );
|
||||
}
|
||||
else
|
||||
{
|
||||
GERBER_WRITER gerberWriter( m_parent->GetBoard() );
|
||||
success = gerberWriter.GenDrillReportFile( dlg.GetPath() );
|
||||
}
|
||||
|
||||
wxString msg;
|
||||
|
||||
|
|
|
@ -42,8 +42,6 @@ public:
|
|||
static bool m_MinimalHeader;
|
||||
static bool m_Mirror;
|
||||
static bool m_Merge_PTH_NPTH;
|
||||
static bool m_DrillOriginIsAuxAxis; /* Axis selection (main / auxiliary)
|
||||
* for drill origin coordinates */
|
||||
DRILL_PRECISION m_Precision; // Selected precision for drill files
|
||||
wxPoint m_FileDrillOffset; // Drill offset: 0,0 for absolute coordinates,
|
||||
// or origin of the auxiliary axis
|
||||
|
@ -51,10 +49,11 @@ public:
|
|||
|
||||
private:
|
||||
PCB_EDIT_FRAME* m_parent;
|
||||
wxConfigBase* m_config;
|
||||
wxConfigBase* m_config;
|
||||
BOARD* m_board;
|
||||
PCB_PLOT_PARAMS m_plotOpts;
|
||||
|
||||
bool m_drillOriginIsAuxAxis; // Axis selection (main / auxiliary)
|
||||
// for drill origin coordinates
|
||||
int m_platedPadsHoleCount;
|
||||
int m_notplatedPadsHoleCount;
|
||||
int m_throughViasCount;
|
||||
|
@ -62,6 +61,7 @@ private:
|
|||
int m_blindOrBuriedViasCount;
|
||||
|
||||
static int m_mapFileType; // HPGL, PS ...
|
||||
static int m_drillFileType; // Excellon, Gerber
|
||||
|
||||
|
||||
void initDialog();
|
||||
|
@ -72,6 +72,7 @@ private:
|
|||
void OnSelZerosFmtSelected( wxCommandEvent& event ) override;
|
||||
void OnGenDrillFile( wxCommandEvent& event ) override;
|
||||
void OnGenMapFile( wxCommandEvent& event ) override;
|
||||
void onFileFormatSelection( wxCommandEvent& event ) override;
|
||||
|
||||
/*
|
||||
* Create a plain text report file giving a list of drill values and drill count
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jun 17 2015)
|
||||
// C++ code generated with wxFormBuilder (version Feb 19 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
|
@ -23,7 +23,6 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
|
|||
bdirnameSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Output directory:") ), wxHORIZONTAL );
|
||||
|
||||
m_outputDirectoryName = new wxTextCtrl( bdirnameSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_outputDirectoryName->SetMaxLength( 0 );
|
||||
bdirnameSizer->Add( m_outputDirectoryName, 1, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_buttonBrowse = new wxButton( bdirnameSizer->GetStaticBox(), wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
@ -41,6 +40,12 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
|
|||
wxBoxSizer* m_LeftBoxSizer;
|
||||
m_LeftBoxSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxString m_rbFileFormatChoices[] = { _("Excellon"), _("Gerber X2 (experimental)") };
|
||||
int m_rbFileFormatNChoices = sizeof( m_rbFileFormatChoices ) / sizeof( wxString );
|
||||
m_rbFileFormat = new wxRadioBox( this, wxID_ANY, _("File Format:"), wxDefaultPosition, wxDefaultSize, m_rbFileFormatNChoices, m_rbFileFormatChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_rbFileFormat->SetSelection( 0 );
|
||||
m_LeftBoxSizer->Add( m_rbFileFormat, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
wxString m_Choice_UnitChoices[] = { _("Millimeters"), _("Inches") };
|
||||
int m_Choice_UnitNChoices = sizeof( m_Choice_UnitChoices ) / sizeof( wxString );
|
||||
m_Choice_Unit = new wxRadioBox( this, wxID_ANY, _("Drill Units:"), wxDefaultPosition, wxDefaultSize, m_Choice_UnitNChoices, m_Choice_UnitChoices, 1, wxRA_SPECIFY_COLS );
|
||||
|
@ -55,15 +60,22 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
|
|||
|
||||
m_LeftBoxSizer->Add( m_Choice_Zeros_Format, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizerPrecision;
|
||||
sbSizerPrecision = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Precision") ), wxVERTICAL );
|
||||
wxFlexGridSizer* fgSizer1;
|
||||
fgSizer1 = new wxFlexGridSizer( 0, 2, 0, 0 );
|
||||
fgSizer1->AddGrowableCol( 1 );
|
||||
fgSizer1->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticTextPrecision = new wxStaticText( sbSizerPrecision->GetStaticBox(), wxID_ANY, _("Precision"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextTitle = new wxStaticText( this, wxID_ANY, _("Precision"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextTitle->Wrap( -1 );
|
||||
fgSizer1->Add( m_staticTextTitle, 0, wxALL, 5 );
|
||||
|
||||
m_staticTextPrecision = new wxStaticText( this, wxID_ANY, _("Precision"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextPrecision->Wrap( -1 );
|
||||
sbSizerPrecision->Add( m_staticTextPrecision, 0, wxALL, 5 );
|
||||
fgSizer1->Add( m_staticTextPrecision, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_LeftBoxSizer->Add( sbSizerPrecision, 0, wxEXPAND, 5 );
|
||||
m_LeftBoxSizer->Add( fgSizer1, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bmiddlerSizer->Add( m_LeftBoxSizer, 0, wxEXPAND, 5 );
|
||||
|
@ -79,26 +91,26 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
|
|||
|
||||
bMiddleBoxSizer->Add( m_Choice_Drill_Map, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbOptSizer;
|
||||
sbOptSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Drill File Options:") ), wxVERTICAL );
|
||||
wxStaticBoxSizer* sbExcellonOptSizer;
|
||||
sbExcellonOptSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Excellon Drill File Options:") ), wxVERTICAL );
|
||||
|
||||
m_Check_Mirror = new wxCheckBox( sbOptSizer->GetStaticBox(), wxID_ANY, _("Mirror y axis"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_Check_Mirror = new wxCheckBox( sbExcellonOptSizer->GetStaticBox(), wxID_ANY, _("Mirror y axis"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_Check_Mirror->SetToolTip( _("Not recommended.\nUsed mostly by users who make the boards themselves.") );
|
||||
|
||||
sbOptSizer->Add( m_Check_Mirror, 0, wxRIGHT|wxLEFT, 5 );
|
||||
sbExcellonOptSizer->Add( m_Check_Mirror, 0, wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_Check_Minimal = new wxCheckBox( sbOptSizer->GetStaticBox(), wxID_ANY, _("Minimal header"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_Check_Minimal->SetToolTip( _("Not recommended.\nOnly use for board houses which do not accept fully featured headers.") );
|
||||
m_Check_Minimal = new wxCheckBox( sbExcellonOptSizer->GetStaticBox(), wxID_ANY, _("Minimal header"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_Check_Minimal->SetToolTip( _("Not recommended.\nOnly use it for board houses which do not accept fully featured headers.") );
|
||||
|
||||
sbOptSizer->Add( m_Check_Minimal, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
sbExcellonOptSizer->Add( m_Check_Minimal, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_Check_Merge_PTH_NPTH = new wxCheckBox( sbOptSizer->GetStaticBox(), wxID_ANY, _("Merge PTH and NPTH holes into one file"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_Check_Merge_PTH_NPTH->SetToolTip( _("Not recommended.\nOnly use for board houses which ask for merged PTH and NPTH into a single file.") );
|
||||
m_Check_Merge_PTH_NPTH = new wxCheckBox( sbExcellonOptSizer->GetStaticBox(), wxID_ANY, _("Merge PTH and NPTH holes into one file"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_Check_Merge_PTH_NPTH->SetToolTip( _("Not recommended.\nOnly use for board houses which ask for merged PTH and NTPH into a single file.") );
|
||||
|
||||
sbOptSizer->Add( m_Check_Merge_PTH_NPTH, 0, wxALL, 5 );
|
||||
sbExcellonOptSizer->Add( m_Check_Merge_PTH_NPTH, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bMiddleBoxSizer->Add( sbOptSizer, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
|
||||
bMiddleBoxSizer->Add( sbExcellonOptSizer, 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 );
|
||||
|
@ -211,6 +223,7 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
|
|||
|
||||
// Connect Events
|
||||
m_buttonBrowse->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnOutputDirectoryBrowseClicked ), NULL, this );
|
||||
m_rbFileFormat->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::onFileFormatSelection ), 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_buttonDrill->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnGenDrillFile ), NULL, this );
|
||||
|
@ -223,6 +236,7 @@ DIALOG_GENDRILL_BASE::~DIALOG_GENDRILL_BASE()
|
|||
{
|
||||
// Disconnect Events
|
||||
m_buttonBrowse->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnOutputDirectoryBrowseClicked ), NULL, this );
|
||||
m_rbFileFormat->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::onFileFormatSelection ), 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_buttonDrill->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GENDRILL_BASE::OnGenDrillFile ), NULL, this );
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">DIALOG_GENDRILL_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">506,518</property>
|
||||
<property name="size">661,518</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||
<property name="title">Drill Files Generation</property>
|
||||
|
@ -112,6 +112,7 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">bdirnameSizer</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="1">
|
||||
|
@ -315,6 +316,96 @@
|
|||
<property name="name">m_LeftBoxSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxRadioBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="choices">"Excellon" "Gerber X2 (experimental)"</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">File Format:</property>
|
||||
<property name="majorDimension">1</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_rbFileFormat</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="selection">0</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxRA_SPECIFY_COLS</property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRadioBox">onFileFormatSelection</event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
|
@ -499,14 +590,101 @@
|
|||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticBoxSizer" expanded="1">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Precision</property>
|
||||
<object class="wxFlexGridSizer" expanded="1">
|
||||
<property name="cols">2</property>
|
||||
<property name="flexible_direction">wxBOTH</property>
|
||||
<property name="growablecols">1</property>
|
||||
<property name="growablerows"></property>
|
||||
<property name="hgap">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizerPrecision</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="name">fgSizer1</property>
|
||||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<property name="rows">0</property>
|
||||
<property name="vgap">0</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Precision</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_staticTextTitle</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
|
@ -699,10 +877,11 @@
|
|||
<property name="proportion">0</property>
|
||||
<object class="wxStaticBoxSizer" expanded="1">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Drill File Options:</property>
|
||||
<property name="label">Excellon Drill File Options:</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbOptSizer</property>
|
||||
<property name="name">sbExcellonOptSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="1">
|
||||
|
@ -1082,6 +1261,7 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizerInfo</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="1">
|
||||
|
@ -1094,6 +1274,7 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">m_DefaultViasDrillSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="1">
|
||||
|
@ -1191,6 +1372,7 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">m_MicroViasDrillSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="1">
|
||||
|
@ -1288,6 +1470,7 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizerHoles</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="1">
|
||||
|
@ -2096,6 +2279,7 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">bmsgSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="1">
|
||||
|
@ -2133,7 +2317,7 @@
|
|||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="maxlength"></property>
|
||||
<property name="maxlength">0</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">-1,90</property>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jun 17 2015)
|
||||
// C++ code generated with wxFormBuilder (version Feb 19 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
|
@ -42,8 +42,10 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
|
|||
protected:
|
||||
wxTextCtrl* m_outputDirectoryName;
|
||||
wxButton* m_buttonBrowse;
|
||||
wxRadioBox* m_rbFileFormat;
|
||||
wxRadioBox* m_Choice_Unit;
|
||||
wxRadioBox* m_Choice_Zeros_Format;
|
||||
wxStaticText* m_staticTextTitle;
|
||||
wxStaticText* m_staticTextPrecision;
|
||||
wxRadioBox* m_Choice_Drill_Map;
|
||||
wxCheckBox* m_Check_Mirror;
|
||||
|
@ -67,6 +69,7 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
|
|||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onFileFormatSelection( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSelDrillUnitsSelected( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSelZerosFmtSelected( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnGenDrillFile( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
@ -77,7 +80,7 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
|
|||
|
||||
public:
|
||||
|
||||
DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Drill Files Generation"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 506,473 ), 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( 661,518 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~DIALOG_GENDRILL_BASE();
|
||||
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.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
|
||||
|
@ -40,15 +40,12 @@
|
|||
#include <dialog_plot.h>
|
||||
#include <wx_html_report_panel.h>
|
||||
|
||||
// Uncomment this line to allow experimetal net attributes in Gerber files:
|
||||
#define KICAD_USE_GBR_NETATTRIBUTES
|
||||
|
||||
DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aParent ) :
|
||||
DIALOG_PLOT_BASE( aParent ), m_parent( aParent ),
|
||||
m_board( aParent->GetBoard() ),
|
||||
m_plotOpts( aParent->GetPlotSettings() )
|
||||
m_board( aParent->GetBoard() )
|
||||
{
|
||||
m_config = Kiface().KifaceSettings();
|
||||
m_plotOpts = aParent->GetPlotSettings();
|
||||
Init_Dialog();
|
||||
|
||||
GetSizer()->Fit( this );
|
||||
|
@ -164,15 +161,11 @@ void DIALOG_PLOT::Init_Dialog()
|
|||
m_useGerberX2Attributes->SetValue( m_plotOpts.GetUseGerberAttributes() );
|
||||
|
||||
// Option for including Gerber netlist info (from Gerber X2 format) in the output
|
||||
#ifdef KICAD_USE_GBR_NETATTRIBUTES
|
||||
m_useGerberNetAttributes->SetValue( m_plotOpts.GetIncludeGerberNetlistInfo() );
|
||||
|
||||
// Grey out if m_useGerberX2Attributes is not checked
|
||||
m_useGerberNetAttributes->Enable( m_useGerberX2Attributes->GetValue() );
|
||||
#else
|
||||
m_plotOpts.SetIncludeGerberNetlistInfo( false );
|
||||
m_useGerberNetAttributes->SetValue( false );
|
||||
#endif
|
||||
|
||||
// Gerber precision for coordinates
|
||||
m_rbGerberFormat->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 );
|
||||
|
||||
|
@ -244,7 +237,7 @@ void DIALOG_PLOT::OnRightClick( wxMouseEvent& event )
|
|||
#include <layers_id_colors_and_visibility.h>
|
||||
void DIALOG_PLOT::OnPopUpLayers( wxCommandEvent& event )
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int i;
|
||||
|
||||
switch( event.GetId() )
|
||||
{
|
||||
|
@ -294,7 +287,14 @@ void DIALOG_PLOT::OnPopUpLayers( wxCommandEvent& event )
|
|||
|
||||
void DIALOG_PLOT::CreateDrillFile( wxCommandEvent& event )
|
||||
{
|
||||
// Be sure drill file use the same settings (axis option, plot directory)
|
||||
// than plot files:
|
||||
applyPlotSettings();
|
||||
m_parent->InstallDrillFrame( event );
|
||||
|
||||
// a few plot settings can be modified: take them in account
|
||||
m_plotOpts = m_parent->GetPlotSettings();
|
||||
Init_Dialog();
|
||||
}
|
||||
|
||||
|
||||
|
@ -443,9 +443,6 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
|
|||
m_PlotOptionsSizer->Show( m_GerberOptionsSizer );
|
||||
m_PlotOptionsSizer->Hide( m_HPGLOptionsSizer );
|
||||
m_PlotOptionsSizer->Hide( m_PSOptionsSizer );
|
||||
#ifndef KICAD_USE_GBR_NETATTRIBUTES
|
||||
m_useGerberNetAttributes->Show( false );
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PLOT_FORMAT_HPGL:
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2015 Jean_Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 1992-2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 1992-2017 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
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
#include <pcbnew.h>
|
||||
#include <pcbplot.h>
|
||||
#include <gendrill_Excellon_writer.h>
|
||||
#include <gendrill_file_writer_base.h>
|
||||
|
||||
/* Conversion utilities - these will be used often in there... */
|
||||
inline double diameter_in_inches( double ius )
|
||||
|
@ -55,9 +55,13 @@ inline double diameter_in_mm( double ius )
|
|||
}
|
||||
|
||||
|
||||
bool EXCELLON_WRITER::GenDrillMapFile( const wxString& aFullFileName,
|
||||
PlotFormat aFormat )
|
||||
bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName,
|
||||
PlotFormat aFormat )
|
||||
{
|
||||
// Remark:
|
||||
// Hole list must be created before calling this function, by buildHolesList(),
|
||||
// for the right holes set (PTH, NPTH, buried/blind vias ...)
|
||||
|
||||
double scale = 1.0;
|
||||
wxPoint offset;
|
||||
PLOTTER* plotter = NULL;
|
||||
|
@ -285,7 +289,7 @@ bool EXCELLON_WRITER::GenDrillMapFile( const wxString& aFullFileName,
|
|||
}
|
||||
|
||||
|
||||
bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
|
||||
bool GENDRILL_WRITER_BASE::GenDrillReportFile( const wxString& aFullFileName )
|
||||
{
|
||||
FILE_OUTPUTFORMATTER out( aFullFileName );
|
||||
|
||||
|
@ -309,6 +313,7 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
|
|||
LSET cu = m_pcb->GetEnabledLayers() & LSET::AllCuMask();
|
||||
|
||||
int conventional_layer_num = 1;
|
||||
|
||||
for( LSEQ seq = cu.Seq(); seq; ++seq, ++conventional_layer_num )
|
||||
{
|
||||
out.Print( 0, " L%-2d: %-25s %s\n",
|
||||
|
@ -326,10 +331,10 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
|
|||
* 3 - Non Plated through holes
|
||||
*/
|
||||
|
||||
bool buildNPTHlist = false;
|
||||
bool buildNPTHlist = false; // First pass: build PTH list only
|
||||
|
||||
// in this loop are plated only:
|
||||
for( unsigned pair_ndx = 0; pair_ndx < hole_sets.size(); ++pair_ndx )
|
||||
for( unsigned pair_ndx = 0; pair_ndx < hole_sets.size(); ++pair_ndx )
|
||||
{
|
||||
DRILL_LAYER_PAIR pair = hole_sets[pair_ndx];
|
||||
|
||||
|
@ -338,7 +343,7 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
|
|||
if( pair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
|
||||
{
|
||||
out.Print( 0, "Drill file '%s' contains\n",
|
||||
TO_UTF8( drillFileName( pair, false, m_merge_PTH_NPTH ) ) );
|
||||
TO_UTF8( getDrillFileName( pair, false, m_merge_PTH_NPTH ) ) );
|
||||
|
||||
out.Print( 0, " plated through holes:\n" );
|
||||
out.Print( 0, separator );
|
||||
|
@ -348,7 +353,7 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
|
|||
else // blind/buried
|
||||
{
|
||||
out.Print( 0, "Drill file '%s' contains\n",
|
||||
TO_UTF8( drillFileName( pair, false, m_merge_PTH_NPTH ) ) );
|
||||
TO_UTF8( getDrillFileName( pair, false, m_merge_PTH_NPTH ) ) );
|
||||
|
||||
out.Print( 0, " holes connecting layer pair: '%s and %s' (%s vias):\n",
|
||||
TO_UTF8( m_pcb->GetLayerName( ToLAYER_ID( pair.first ) ) ),
|
||||
|
@ -376,7 +381,7 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
|
|||
out.Print( 0, "Not plated through holes are merged with plated holes\n" );
|
||||
else
|
||||
out.Print( 0, "Drill file '%s' contains\n",
|
||||
TO_UTF8( drillFileName( DRILL_LAYER_PAIR( F_Cu, B_Cu ),
|
||||
TO_UTF8( getDrillFileName( DRILL_LAYER_PAIR( F_Cu, B_Cu ),
|
||||
true, m_merge_PTH_NPTH ) ) );
|
||||
|
||||
out.Print( 0, " unplated through holes:\n" );
|
||||
|
@ -388,7 +393,7 @@ bool EXCELLON_WRITER::GenDrillReportFile( const wxString& aFullFileName )
|
|||
}
|
||||
|
||||
|
||||
bool EXCELLON_WRITER::plotDrillMarks( PLOTTER* aPlotter )
|
||||
bool GENDRILL_WRITER_BASE::plotDrillMarks( PLOTTER* aPlotter )
|
||||
{
|
||||
// Plot the drill map:
|
||||
wxPoint pos;
|
||||
|
@ -412,7 +417,7 @@ bool EXCELLON_WRITER::plotDrillMarks( PLOTTER* aPlotter )
|
|||
}
|
||||
|
||||
|
||||
unsigned EXCELLON_WRITER::printToolSummary( OUTPUTFORMATTER& out, bool aSummaryNPTH ) const
|
||||
unsigned GENDRILL_WRITER_BASE::printToolSummary( OUTPUTFORMATTER& out, bool aSummaryNPTH ) const
|
||||
{
|
||||
unsigned totalHoleCount = 0;
|
||||
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
/**
|
||||
* @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.
|
||||
*
|
||||
|
@ -28,6 +23,12 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gendrill_Excellon_writer.cpp
|
||||
* @brief Functions to create EXCELLON drill files and report files.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see for EXCELLON format, see:
|
||||
* http://www.excellon.com/manuals/program.htm
|
||||
|
@ -36,26 +37,17 @@
|
|||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <plot_common.h>
|
||||
#include <trigo.h>
|
||||
#include <macros.h>
|
||||
#include <kicad_string.h>
|
||||
#include <wxPcbStruct.h>
|
||||
#include <pgm_base.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_Excellon_writer.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <reporter.h>
|
||||
#include <collectors.h>
|
||||
|
||||
// Comment/uncomment this to write or not a comment
|
||||
// in drill file when PTH and NPTH are merged to flag
|
||||
|
@ -64,18 +56,15 @@
|
|||
|
||||
|
||||
EXCELLON_WRITER::EXCELLON_WRITER( BOARD* aPcb )
|
||||
: GENDRILL_WRITER_BASE( aPcb )
|
||||
{
|
||||
m_file = NULL;
|
||||
m_pcb = aPcb;
|
||||
m_zeroFormat = DECIMAL_FORMAT;
|
||||
m_conversionUnits = 0.0001;
|
||||
m_unitsDecimal = true;
|
||||
m_mirror = false;
|
||||
m_merge_PTH_NPTH = false;
|
||||
m_minimalHeader = false;
|
||||
m_ShortHeader = false;
|
||||
m_mapFileFmt = PLOT_FORMAT_PDF;
|
||||
m_pageInfo = NULL;
|
||||
m_drillFileExtension = DrillFileExtension;
|
||||
}
|
||||
|
||||
|
||||
|
@ -105,7 +94,7 @@ void EXCELLON_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
|||
// to be sure the NPTH file is up to date in separate files mode.
|
||||
if( getHolesCount() > 0 || doing_npth )
|
||||
{
|
||||
fn = drillFileName( pair, doing_npth, m_merge_PTH_NPTH );
|
||||
fn = getDrillFileName( pair, doing_npth, m_merge_PTH_NPTH );
|
||||
fn.SetPath( aPlotDirectory );
|
||||
|
||||
if( aGenDrill )
|
||||
|
@ -134,36 +123,11 @@ void EXCELLON_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
|||
|
||||
createDrillFile( file );
|
||||
}
|
||||
|
||||
if( aGenMap )
|
||||
{
|
||||
fn.SetExt( wxEmptyString ); // Will be added by GenDrillMap
|
||||
wxString fullfilename = fn.GetFullPath() + wxT( "-drl_map" );
|
||||
fullfilename << wxT(".") << GetDefaultPlotExtension( m_mapFileFmt );
|
||||
|
||||
bool success = GenDrillMapFile( fullfilename, m_mapFileFmt );
|
||||
|
||||
if( ! success )
|
||||
{
|
||||
if( aReporter )
|
||||
{
|
||||
msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fullfilename ) );
|
||||
aReporter->Report( msg );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aReporter )
|
||||
{
|
||||
msg.Printf( _( "Create file %s\n" ), GetChars( fullfilename ) );
|
||||
aReporter->Report( msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( aGenMap )
|
||||
CreateMapFilesSet( aPlotDirectory, aReporter );
|
||||
}
|
||||
|
||||
|
||||
|
@ -532,240 +496,3 @@ void EXCELLON_WRITER::writeEXCELLONEndOfFile()
|
|||
fputs( "T0\nM30\n", m_file );
|
||||
fclose( m_file );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Helper function for sorting hole list.
|
||||
* Compare function used for sorting holes type type (plated then not plated)
|
||||
* then by increasing diameter value and X value
|
||||
*/
|
||||
static bool CmpHoleSettings( const HOLE_INFO& a, const HOLE_INFO& b )
|
||||
{
|
||||
if( a.m_Hole_NotPlated != b.m_Hole_NotPlated )
|
||||
return b.m_Hole_NotPlated;
|
||||
|
||||
if( a.m_Hole_Diameter != b.m_Hole_Diameter )
|
||||
return a.m_Hole_Diameter < b.m_Hole_Diameter;
|
||||
|
||||
if( a.m_Hole_Pos.x != b.m_Hole_Pos.x )
|
||||
return a.m_Hole_Pos.x < b.m_Hole_Pos.x;
|
||||
|
||||
return a.m_Hole_Pos.y < b.m_Hole_Pos.y;
|
||||
}
|
||||
|
||||
|
||||
void EXCELLON_WRITER::buildHolesList( DRILL_LAYER_PAIR aLayerPair,
|
||||
bool aGenerateNPTH_list )
|
||||
{
|
||||
HOLE_INFO new_hole;
|
||||
|
||||
m_holeListBuffer.clear();
|
||||
m_toolListBuffer.clear();
|
||||
|
||||
wxASSERT( aLayerPair.first < aLayerPair.second ); // fix the caller
|
||||
|
||||
// build hole list for vias
|
||||
if( ! aGenerateNPTH_list ) // vias are always plated !
|
||||
{
|
||||
for( VIA* via = GetFirstVia( m_pcb->m_Track ); via; via = GetFirstVia( via->Next() ) )
|
||||
{
|
||||
int hole_sz = via->GetDrillValue();
|
||||
|
||||
if( hole_sz == 0 ) // Should not occur.
|
||||
continue;
|
||||
|
||||
new_hole.m_Tool_Reference = -1; // Flag value for Not initialized
|
||||
new_hole.m_Hole_Orient = 0;
|
||||
new_hole.m_Hole_Diameter = hole_sz;
|
||||
new_hole.m_Hole_NotPlated = false;
|
||||
new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
|
||||
|
||||
new_hole.m_Hole_Shape = 0; // hole shape: round
|
||||
new_hole.m_Hole_Pos = via->GetStart();
|
||||
|
||||
via->LayerPair( &new_hole.m_Hole_Top_Layer, &new_hole.m_Hole_Bottom_Layer );
|
||||
|
||||
// LayerPair() returns params with m_Hole_Bottom_Layer > m_Hole_Top_Layer
|
||||
// Remember: top layer = 0 and bottom layer = 31 for through hole vias
|
||||
// Any captured via should be from aLayerPair.first to aLayerPair.second exactly.
|
||||
if( new_hole.m_Hole_Top_Layer != aLayerPair.first ||
|
||||
new_hole.m_Hole_Bottom_Layer != aLayerPair.second )
|
||||
continue;
|
||||
|
||||
m_holeListBuffer.push_back( new_hole );
|
||||
}
|
||||
}
|
||||
|
||||
if( aLayerPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
|
||||
{
|
||||
// add holes for thru hole pads
|
||||
for( MODULE* module = m_pcb->m_Modules; module; module = module->Next() )
|
||||
{
|
||||
for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
|
||||
{
|
||||
if( !m_merge_PTH_NPTH )
|
||||
{
|
||||
if( !aGenerateNPTH_list && pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
continue;
|
||||
|
||||
if( aGenerateNPTH_list && pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
continue;
|
||||
}
|
||||
|
||||
if( pad->GetDrillSize().x == 0 )
|
||||
continue;
|
||||
|
||||
new_hole.m_Hole_NotPlated = (pad->GetAttribute() == PAD_ATTRIB_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_DRILL_SHAPE_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 = B_Cu;
|
||||
new_hole.m_Hole_Top_Layer = F_Cu; // pad holes are through holes
|
||||
m_holeListBuffer.push_back( new_hole );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort holes per increasing diameter value
|
||||
sort( m_holeListBuffer.begin(), m_holeListBuffer.end(), CmpHoleSettings );
|
||||
|
||||
// build the tool list
|
||||
int last_hole = -1; // Set to not initialized (this is a value not used
|
||||
// for m_holeListBuffer[ii].m_Hole_Diameter)
|
||||
bool last_notplated_opt = false;
|
||||
|
||||
DRILL_TOOL new_tool( 0, false );
|
||||
unsigned jj;
|
||||
|
||||
for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
|
||||
{
|
||||
if( m_holeListBuffer[ii].m_Hole_Diameter != last_hole ||
|
||||
m_holeListBuffer[ii].m_Hole_NotPlated != last_notplated_opt )
|
||||
{
|
||||
new_tool.m_Diameter = m_holeListBuffer[ii].m_Hole_Diameter;
|
||||
new_tool.m_Hole_NotPlated = m_holeListBuffer[ii].m_Hole_NotPlated;
|
||||
m_toolListBuffer.push_back( new_tool );
|
||||
last_hole = new_tool.m_Diameter;
|
||||
last_notplated_opt = new_tool.m_Hole_NotPlated;
|
||||
}
|
||||
|
||||
jj = m_toolListBuffer.size();
|
||||
|
||||
if( jj == 0 )
|
||||
continue; // Should not occurs
|
||||
|
||||
m_holeListBuffer[ii].m_Tool_Reference = jj; // Tool value Initialized (value >= 1)
|
||||
|
||||
m_toolListBuffer.back().m_TotalCount++;
|
||||
|
||||
if( m_holeListBuffer[ii].m_Hole_Shape )
|
||||
m_toolListBuffer.back().m_OvalCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<DRILL_LAYER_PAIR> EXCELLON_WRITER::getUniqueLayerPairs() const
|
||||
{
|
||||
wxASSERT( m_pcb );
|
||||
|
||||
static const KICAD_T interesting_stuff_to_collect[] = {
|
||||
PCB_VIA_T,
|
||||
EOT
|
||||
};
|
||||
|
||||
PCB_TYPE_COLLECTOR vias;
|
||||
|
||||
vias.Collect( m_pcb, interesting_stuff_to_collect );
|
||||
|
||||
std::set< DRILL_LAYER_PAIR > unique;
|
||||
|
||||
DRILL_LAYER_PAIR layer_pair;
|
||||
|
||||
for( int i = 0; i < vias.GetCount(); ++i )
|
||||
{
|
||||
VIA* v = (VIA*) vias[i];
|
||||
|
||||
v->LayerPair( &layer_pair.first, &layer_pair.second );
|
||||
|
||||
// only make note of blind buried.
|
||||
// thru hole is placed unconditionally as first in fetched list.
|
||||
if( layer_pair != DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
|
||||
{
|
||||
unique.insert( layer_pair );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DRILL_LAYER_PAIR> ret;
|
||||
|
||||
ret.push_back( DRILL_LAYER_PAIR( F_Cu, B_Cu ) ); // always first in returned list
|
||||
|
||||
for( std::set< DRILL_LAYER_PAIR >::const_iterator it = unique.begin(); it != unique.end(); ++it )
|
||||
ret.push_back( *it );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const std::string EXCELLON_WRITER::layerName( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
// Generic names here.
|
||||
switch( aLayer )
|
||||
{
|
||||
case F_Cu:
|
||||
return "front";
|
||||
case B_Cu:
|
||||
return "back";
|
||||
default:
|
||||
return StrPrintf( "inner%d", aLayer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::string EXCELLON_WRITER::layerPairName( DRILL_LAYER_PAIR aPair ) const
|
||||
{
|
||||
std::string ret = layerName( aPair.first );
|
||||
ret += '-';
|
||||
ret += layerName( aPair.second );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const wxString EXCELLON_WRITER::drillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH,
|
||||
bool aMerge_PTH_NPTH ) const
|
||||
{
|
||||
wxASSERT( m_pcb );
|
||||
|
||||
wxString extend;
|
||||
|
||||
if( aNPTH )
|
||||
extend = "-NPTH";
|
||||
else if( aPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
|
||||
{
|
||||
if( !aMerge_PTH_NPTH )
|
||||
extend = "-PTH";
|
||||
// if merged, extend with nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
extend += '-';
|
||||
extend += layerPairName( aPair );
|
||||
}
|
||||
|
||||
wxFileName fn = m_pcb->GetFileName();
|
||||
|
||||
fn.SetName( fn.GetName() + extend );
|
||||
fn.SetExt( DrillFileExtension );
|
||||
|
||||
wxString ret = fn.GetFullName(); // show me in debugger
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
/**
|
||||
* @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.
|
||||
*
|
||||
|
@ -27,135 +22,31 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gendrill_Excellon_writer.h
|
||||
* @brief Classes used in drill files, map files and report files generation.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GENDRILL_EXCELLON_WRITER_
|
||||
#define _GENDRILL_EXCELLON_WRITER_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gendrill_file_writer_base.h>
|
||||
|
||||
class BOARD;
|
||||
class PLOTTER;
|
||||
|
||||
|
||||
// the DRILL_TOOL class handles tools used in the excellon drill file:
|
||||
class DRILL_TOOL
|
||||
{
|
||||
public:
|
||||
int m_Diameter; // the diameter of the used tool (for oblong, the smaller size)
|
||||
int m_TotalCount; // how many times it is used (round and oblong)
|
||||
int m_OvalCount; // oblong count
|
||||
bool m_Hole_NotPlated; // Is the hole plated or not plated
|
||||
|
||||
public:
|
||||
DRILL_TOOL( int aDiameter, bool a_NotPlated )
|
||||
{
|
||||
m_TotalCount = 0;
|
||||
m_OvalCount = 0;
|
||||
m_Diameter = aDiameter;
|
||||
m_Hole_NotPlated = a_NotPlated;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* the HOLE_INFO class handle hole which must be drilled (diameter, position and layers)
|
||||
* For buried or micro vias, the hole is not on all layers.
|
||||
* So we must generate a drill file for each layer pair (adjacent layers)
|
||||
* Not plated holes are always through holes, and must be output on a specific drill file
|
||||
* because they are drilled after the Pcb process is finished.
|
||||
*/
|
||||
class HOLE_INFO
|
||||
{
|
||||
public:
|
||||
int m_Hole_Diameter; // hole value, and for oblong: min(hole size x, hole size y)
|
||||
int m_Tool_Reference; // Tool reference for this hole = 1 ... n (values <=0 must not be used)
|
||||
wxSize m_Hole_Size; // hole size for oblong holes
|
||||
double m_Hole_Orient; // Hole rotation (= pad rotation) for oblong holes
|
||||
int m_Hole_Shape; // hole shape: round (0) or oval (1)
|
||||
wxPoint m_Hole_Pos; // hole position
|
||||
PCB_LAYER_ID m_Hole_Bottom_Layer; // hole ending layer (usually back layer)
|
||||
PCB_LAYER_ID m_Hole_Top_Layer; // hole starting layer (usually front layer):
|
||||
// m_Hole_Top_Layer < m_Hole_Bottom_Layer
|
||||
bool m_Hole_NotPlated; // hole not plated. Must be in a specific drill file or section
|
||||
|
||||
public:
|
||||
HOLE_INFO()
|
||||
{
|
||||
m_Hole_NotPlated = false;
|
||||
m_Hole_Diameter = 0;
|
||||
m_Tool_Reference = 0;
|
||||
m_Hole_Orient = 0.0;
|
||||
m_Hole_Shape = 0;
|
||||
m_Hole_Bottom_Layer = B_Cu;
|
||||
m_Hole_Top_Layer = F_Cu;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* the DRILL_PRECISION helper class to handle drill precision format in excellon files
|
||||
*/
|
||||
class DRILL_PRECISION
|
||||
{
|
||||
public:
|
||||
int m_lhs; // Left digit number (integer value of coordinates)
|
||||
int m_rhs; // Right digit number (decimal value of coordinates)
|
||||
|
||||
public:
|
||||
DRILL_PRECISION( int l = 2, int r = 4 )
|
||||
{
|
||||
m_lhs = l; m_rhs = r;
|
||||
}
|
||||
|
||||
|
||||
wxString GetPrecisionString()
|
||||
{
|
||||
wxString text;
|
||||
|
||||
text << m_lhs << wxT( ":" ) << m_rhs;
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::pair<PCB_LAYER_ID, PCB_LAYER_ID> DRILL_LAYER_PAIR;
|
||||
class OUTPUTFORMATTER;
|
||||
|
||||
/**
|
||||
* 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 GENDRILL_WRITER_BASE
|
||||
{
|
||||
public:
|
||||
enum ZEROS_FMT { // Zero format in coordinates
|
||||
DECIMAL_FORMAT, // Floating point coordinates
|
||||
SUPPRESS_LEADING, // Suppress leading zeros
|
||||
SUPPRESS_TRAILING, // Suppress trainling zeros
|
||||
KEEP_ZEROS // keep zeros
|
||||
};
|
||||
|
||||
wxPoint m_Offset; // offset coordinates
|
||||
bool m_ShortHeader; // true to generate the smallest header (strip comments)
|
||||
|
||||
private:
|
||||
FILE* m_file; // The output file
|
||||
BOARD* m_pcb;
|
||||
bool m_minimalHeader; // True to use minimal header
|
||||
// in excellon file (strip comments)
|
||||
bool m_unitsDecimal; // true = decimal, false = inches
|
||||
ZEROS_FMT m_zeroFormat; // the zero format option for output file
|
||||
DRILL_PRECISION m_precision; // The current coordinate precision (not used in decimal format)
|
||||
double m_conversionUnits; // scaling factor to convert the board unites to Excellon units
|
||||
// (i.e inches or mm)
|
||||
bool m_mirror;
|
||||
wxPoint m_offset; // Drill offset coordinates
|
||||
bool m_merge_PTH_NPTH; // True to generate only one drill file
|
||||
std::vector<HOLE_INFO> m_holeListBuffer; // Buffer containing holes
|
||||
std::vector<DRILL_TOOL> m_toolListBuffer; // Buffer containing tools
|
||||
|
||||
PlotFormat m_mapFileFmt; // the format of the map drill file,
|
||||
// if this map is needed
|
||||
const PAGE_INFO* m_pageInfo; // the page info used to plot drill maps
|
||||
// If NULL, use a A4 page format
|
||||
|
||||
public:
|
||||
EXCELLON_WRITER( BOARD* aPcb );
|
||||
|
@ -183,22 +74,6 @@ public:
|
|||
void SetFormat( bool aMetric, ZEROS_FMT aZerosFmt = DECIMAL_FORMAT,
|
||||
int aLeftDigits = 0, int aRightDigits = 0 );
|
||||
|
||||
/**
|
||||
* Sets the page info used to plot drill maps
|
||||
* If NULL, a A4 page format will be used
|
||||
* @param aPageInfo = a reference to the page info, usually used to plot/display the board
|
||||
*/
|
||||
void SetPageInfo( const PAGE_INFO* aPageInfo ) { m_pageInfo = aPageInfo; }
|
||||
|
||||
/**
|
||||
* Function SetMapFileFormat
|
||||
* Initialize the format for the drill map file
|
||||
* @param SetMapFileFormat = a PlotFormat value (one of
|
||||
* PLOT_FORMAT_HPGL, PLOT_FORMAT_POST, PLOT_FORMAT_GERBER,
|
||||
* PLOT_FORMAT_DXF, PLOT_FORMAT_SVG, PLOT_FORMAT_PDF
|
||||
* the most useful are PLOT_FORMAT_PDF and PLOT_FORMAT_POST
|
||||
*/
|
||||
void SetMapFileFormat( PlotFormat aMapFmt ) { m_mapFileFmt = aMapFmt; }
|
||||
|
||||
|
||||
/**
|
||||
|
@ -229,70 +104,6 @@ public:
|
|||
bool aGenDrill, bool aGenMap,
|
||||
REPORTER * aReporter = NULL );
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* @param aFullFileName : the name of the file to create
|
||||
* m_unitsDecimal = false to 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.
|
||||
* the paper sheet to use to plot the map is set in m_pageInfo
|
||||
* ( calls SetPageInfo() to set it )
|
||||
* if NULL, A4 format will be used
|
||||
* @param aFullFileName : the full filename of the map file to create,
|
||||
* @param aFormat : one of the supported plot formats (see enum PlotFormat )
|
||||
*/
|
||||
bool GenDrillMapFile( const wxString& aFullFileName, PlotFormat aFormat );
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -303,23 +114,6 @@ private:
|
|||
*/
|
||||
int createDrillFile( FILE * aFile );
|
||||
|
||||
/**
|
||||
* Function BuildHolesList
|
||||
* Create the list of holes and tools for a given board
|
||||
* The list is sorted by increasing drill size.
|
||||
* Only holes included within aLayerPair are listed.
|
||||
* If aLayerPair identifies with [F_Cu, B_Cu], then
|
||||
* pad holes are always included also.
|
||||
*
|
||||
* @param aLayerPair is an inclusive range of layers.
|
||||
* @param aGenerateNPTH_list :
|
||||
* true to create NPTH only list (with no plated holes)
|
||||
* false to created plated holes list (with no NPTH )
|
||||
*/
|
||||
void buildHolesList( DRILL_LAYER_PAIR aLayerPair,
|
||||
bool aGenerateNPTH_list );
|
||||
|
||||
int getHolesCount() const { return m_holeListBuffer.size(); }
|
||||
|
||||
/* Print the DRILL file header. The full header is:
|
||||
* M48
|
||||
|
@ -337,43 +131,6 @@ private:
|
|||
* According to the selected format
|
||||
*/
|
||||
void writeCoordinates( char* aLine, double aCoordX, double aCoordY );
|
||||
|
||||
/** 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* aPlotter );
|
||||
|
||||
/// Get unique layer pairs by examining the micro and blind_buried vias.
|
||||
std::vector<DRILL_LAYER_PAIR> getUniqueLayerPairs() const;
|
||||
|
||||
/**
|
||||
* Function printToolSummary
|
||||
* prints m_toolListBuffer[] tools to aOut and returns total hole count.
|
||||
* @param aOut = the current OUTPUTFORMATTER to print summary
|
||||
* @param aSummaryNPTH = true to print summary for NPTH, false for PTH
|
||||
*/
|
||||
unsigned printToolSummary( OUTPUTFORMATTER& aOut, bool aSummaryNPTH ) const;
|
||||
|
||||
const std::string layerPairName( DRILL_LAYER_PAIR aPair ) const;
|
||||
|
||||
const std::string layerName( PCB_LAYER_ID aLayer ) const;
|
||||
|
||||
/**
|
||||
* @return a filename which identify the drill file function.
|
||||
* it is the board name with the layer pair names added, and for separate
|
||||
* (PTH and NPTH) files, "-NPH" or "-NPTH" added
|
||||
* @param aPair = the layer pair
|
||||
* @param aNPTH = true to generate the filename of NPTH holes
|
||||
* @param aMerge_PTH_NPTH = true to generate the filename of a file which containd both
|
||||
* NPH and NPTH holes
|
||||
*/
|
||||
const wxString drillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH,
|
||||
bool aMerge_PTH_NPTH ) const;
|
||||
};
|
||||
|
||||
#endif // #ifndef _GENDRILL_EXCELLON_WRITER_
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2017 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 <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <collectors.h>
|
||||
#include <reporter.h>
|
||||
|
||||
#include <gendrill_file_writer_base.h>
|
||||
|
||||
|
||||
/* Helper function for sorting hole list.
|
||||
* Compare function used for sorting holes type type (plated then not plated)
|
||||
* then by increasing diameter value and X value
|
||||
*/
|
||||
static bool CmpHoleSorting( const HOLE_INFO& a, const HOLE_INFO& b )
|
||||
{
|
||||
if( a.m_Hole_NotPlated != b.m_Hole_NotPlated )
|
||||
return b.m_Hole_NotPlated;
|
||||
|
||||
if( a.m_Hole_Diameter != b.m_Hole_Diameter )
|
||||
return a.m_Hole_Diameter < b.m_Hole_Diameter;
|
||||
|
||||
// group by components when possible
|
||||
const D_PAD* pada = dyn_cast<const D_PAD*>( a.m_ItemParent );
|
||||
const D_PAD* padb = dyn_cast<const D_PAD*>( b.m_ItemParent );
|
||||
|
||||
if( pada && padb )
|
||||
{
|
||||
if( pada->GetParent()->GetReference().Cmp( padb->GetParent()->GetReference() ) != 0 )
|
||||
return pada->GetParent()->GetReference().Cmp( padb->GetParent()->GetReference() ) < 0;
|
||||
}
|
||||
else if( pada || padb )
|
||||
return true;
|
||||
|
||||
// At this point, holes are via holes: sort by position
|
||||
|
||||
if( a.m_Hole_Pos.x != b.m_Hole_Pos.x )
|
||||
return a.m_Hole_Pos.x < b.m_Hole_Pos.x;
|
||||
|
||||
return a.m_Hole_Pos.y < b.m_Hole_Pos.y;
|
||||
}
|
||||
|
||||
|
||||
void GENDRILL_WRITER_BASE::buildHolesList( DRILL_LAYER_PAIR aLayerPair,
|
||||
bool aGenerateNPTH_list )
|
||||
{
|
||||
HOLE_INFO new_hole;
|
||||
|
||||
m_holeListBuffer.clear();
|
||||
m_toolListBuffer.clear();
|
||||
|
||||
wxASSERT( aLayerPair.first < aLayerPair.second ); // fix the caller
|
||||
|
||||
// build hole list for vias
|
||||
if( ! aGenerateNPTH_list ) // vias are always plated !
|
||||
{
|
||||
for( VIA* via = GetFirstVia( m_pcb->m_Track ); via; via = GetFirstVia( via->Next() ) )
|
||||
{
|
||||
int hole_sz = via->GetDrillValue();
|
||||
|
||||
if( hole_sz == 0 ) // Should not occur.
|
||||
continue;
|
||||
|
||||
new_hole.m_ItemParent = via;
|
||||
new_hole.m_Tool_Reference = -1; // Flag value for Not initialized
|
||||
new_hole.m_Hole_Orient = 0;
|
||||
new_hole.m_Hole_Diameter = hole_sz;
|
||||
new_hole.m_Hole_NotPlated = false;
|
||||
new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
|
||||
|
||||
new_hole.m_Hole_Shape = 0; // hole shape: round
|
||||
new_hole.m_Hole_Pos = via->GetStart();
|
||||
|
||||
via->LayerPair( &new_hole.m_Hole_Top_Layer, &new_hole.m_Hole_Bottom_Layer );
|
||||
|
||||
// LayerPair() returns params with m_Hole_Bottom_Layer > m_Hole_Top_Layer
|
||||
// Remember: top layer = 0 and bottom layer = 31 for through hole vias
|
||||
// Any captured via should be from aLayerPair.first to aLayerPair.second exactly.
|
||||
if( new_hole.m_Hole_Top_Layer != aLayerPair.first ||
|
||||
new_hole.m_Hole_Bottom_Layer != aLayerPair.second )
|
||||
continue;
|
||||
|
||||
m_holeListBuffer.push_back( new_hole );
|
||||
}
|
||||
}
|
||||
|
||||
if( aLayerPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
|
||||
{
|
||||
// add holes for thru hole pads
|
||||
for( MODULE* module = m_pcb->m_Modules; module; module = module->Next() )
|
||||
{
|
||||
for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
|
||||
{
|
||||
if( !m_merge_PTH_NPTH )
|
||||
{
|
||||
if( !aGenerateNPTH_list && pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
continue;
|
||||
|
||||
if( aGenerateNPTH_list && pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
continue;
|
||||
}
|
||||
|
||||
if( pad->GetDrillSize().x == 0 )
|
||||
continue;
|
||||
|
||||
new_hole.m_ItemParent = pad;
|
||||
new_hole.m_Hole_NotPlated = (pad->GetAttribute() == PAD_ATTRIB_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_DRILL_SHAPE_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 = B_Cu;
|
||||
new_hole.m_Hole_Top_Layer = F_Cu; // pad holes are through holes
|
||||
m_holeListBuffer.push_back( new_hole );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort holes per increasing diameter value
|
||||
sort( m_holeListBuffer.begin(), m_holeListBuffer.end(), CmpHoleSorting );
|
||||
|
||||
// build the tool list
|
||||
int last_hole = -1; // Set to not initialized (this is a value not used
|
||||
// for m_holeListBuffer[ii].m_Hole_Diameter)
|
||||
bool last_notplated_opt = false;
|
||||
|
||||
DRILL_TOOL new_tool( 0, false );
|
||||
unsigned jj;
|
||||
|
||||
for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
|
||||
{
|
||||
if( m_holeListBuffer[ii].m_Hole_Diameter != last_hole ||
|
||||
m_holeListBuffer[ii].m_Hole_NotPlated != last_notplated_opt )
|
||||
{
|
||||
new_tool.m_Diameter = m_holeListBuffer[ii].m_Hole_Diameter;
|
||||
new_tool.m_Hole_NotPlated = m_holeListBuffer[ii].m_Hole_NotPlated;
|
||||
m_toolListBuffer.push_back( new_tool );
|
||||
last_hole = new_tool.m_Diameter;
|
||||
last_notplated_opt = new_tool.m_Hole_NotPlated;
|
||||
}
|
||||
|
||||
jj = m_toolListBuffer.size();
|
||||
|
||||
if( jj == 0 )
|
||||
continue; // Should not occurs
|
||||
|
||||
m_holeListBuffer[ii].m_Tool_Reference = jj; // Tool value Initialized (value >= 1)
|
||||
|
||||
m_toolListBuffer.back().m_TotalCount++;
|
||||
|
||||
if( m_holeListBuffer[ii].m_Hole_Shape )
|
||||
m_toolListBuffer.back().m_OvalCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<DRILL_LAYER_PAIR> GENDRILL_WRITER_BASE::getUniqueLayerPairs() const
|
||||
{
|
||||
wxASSERT( m_pcb );
|
||||
|
||||
static const KICAD_T interesting_stuff_to_collect[] = {
|
||||
PCB_VIA_T,
|
||||
EOT
|
||||
};
|
||||
|
||||
PCB_TYPE_COLLECTOR vias;
|
||||
|
||||
vias.Collect( m_pcb, interesting_stuff_to_collect );
|
||||
|
||||
std::set< DRILL_LAYER_PAIR > unique;
|
||||
|
||||
DRILL_LAYER_PAIR layer_pair;
|
||||
|
||||
for( int i = 0; i < vias.GetCount(); ++i )
|
||||
{
|
||||
VIA* v = (VIA*) vias[i];
|
||||
|
||||
v->LayerPair( &layer_pair.first, &layer_pair.second );
|
||||
|
||||
// only make note of blind buried.
|
||||
// thru hole is placed unconditionally as first in fetched list.
|
||||
if( layer_pair != DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
|
||||
{
|
||||
unique.insert( layer_pair );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DRILL_LAYER_PAIR> ret;
|
||||
|
||||
ret.push_back( DRILL_LAYER_PAIR( F_Cu, B_Cu ) ); // always first in returned list
|
||||
|
||||
for( std::set< DRILL_LAYER_PAIR >::const_iterator it = unique.begin(); it != unique.end(); ++it )
|
||||
ret.push_back( *it );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const std::string GENDRILL_WRITER_BASE::layerName( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
// Generic names here.
|
||||
switch( aLayer )
|
||||
{
|
||||
case F_Cu:
|
||||
return "front";
|
||||
case B_Cu:
|
||||
return "back";
|
||||
default:
|
||||
return StrPrintf( "in%d", aLayer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::string GENDRILL_WRITER_BASE::layerPairName( DRILL_LAYER_PAIR aPair ) const
|
||||
{
|
||||
std::string ret = layerName( aPair.first );
|
||||
ret += '-';
|
||||
ret += layerName( aPair.second );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const wxString GENDRILL_WRITER_BASE::getDrillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH,
|
||||
bool aMerge_PTH_NPTH ) const
|
||||
{
|
||||
wxASSERT( m_pcb );
|
||||
|
||||
wxString extend;
|
||||
|
||||
if( aNPTH )
|
||||
extend = "-NPTH";
|
||||
else if( aPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
|
||||
{
|
||||
if( !aMerge_PTH_NPTH )
|
||||
extend = "-PTH";
|
||||
// if merged, extend with nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
extend += '-';
|
||||
extend += layerPairName( aPair );
|
||||
}
|
||||
|
||||
wxFileName fn = m_pcb->GetFileName();
|
||||
|
||||
fn.SetName( fn.GetName() + extend );
|
||||
fn.SetExt( m_drillFileExtension );
|
||||
|
||||
wxString ret = fn.GetFullName();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GENDRILL_WRITER_BASE::CreateMapFilesSet( const wxString& aPlotDirectory,
|
||||
REPORTER * aReporter )
|
||||
{
|
||||
wxFileName fn;
|
||||
wxString msg;
|
||||
|
||||
std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
|
||||
|
||||
// append a pair representing the NPTH set of holes, for separate drill files.
|
||||
if( !m_merge_PTH_NPTH )
|
||||
hole_sets.push_back( DRILL_LAYER_PAIR( F_Cu, B_Cu ) );
|
||||
|
||||
for( std::vector<DRILL_LAYER_PAIR>::const_iterator it = hole_sets.begin();
|
||||
it != hole_sets.end(); ++it )
|
||||
{
|
||||
DRILL_LAYER_PAIR pair = *it;
|
||||
// For separate drill files, the last layer pair is the NPTH drill file.
|
||||
bool doing_npth = m_merge_PTH_NPTH ? false : ( it == hole_sets.end() - 1 );
|
||||
|
||||
buildHolesList( pair, doing_npth );
|
||||
|
||||
// The file is created if it has holes, or if it is the non plated drill file
|
||||
// to be sure the NPTH file is up to date in separate files mode.
|
||||
if( getHolesCount() > 0 || doing_npth )
|
||||
{
|
||||
fn = getDrillFileName( pair, doing_npth, m_merge_PTH_NPTH );
|
||||
fn.SetPath( aPlotDirectory );
|
||||
|
||||
fn.SetExt( wxEmptyString ); // Will be added by GenDrillMap
|
||||
wxString fullfilename = fn.GetFullPath() + wxT( "-drl_map" );
|
||||
fullfilename << wxT(".") << GetDefaultPlotExtension( m_mapFileFmt );
|
||||
|
||||
bool success = genDrillMapFile( fullfilename, m_mapFileFmt );
|
||||
|
||||
if( ! success )
|
||||
{
|
||||
if( aReporter )
|
||||
{
|
||||
msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fullfilename ) );
|
||||
aReporter->Report( msg );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aReporter )
|
||||
{
|
||||
msg.Printf( _( "Create file %s\n" ), GetChars( fullfilename ) );
|
||||
aReporter->Report( msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 1992-2017 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gendrill_file_writer_base.h
|
||||
* @brief helper classes to handle hole info for drill files generators.
|
||||
*/
|
||||
#ifndef GENDRILL_FILE_WRITER_BASE_H
|
||||
#define GENDRILL_FILE_WRITER_BASE_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
class BOARD_ITEM;
|
||||
|
||||
|
||||
// the DRILL_TOOL class handles tools used in the excellon drill file:
|
||||
class DRILL_TOOL
|
||||
{
|
||||
public:
|
||||
int m_Diameter; // the diameter of the used tool (for oblong, the smaller size)
|
||||
int m_TotalCount; // how many times it is used (round and oblong)
|
||||
int m_OvalCount; // oblong count
|
||||
bool m_Hole_NotPlated; // Is the hole plated or not plated
|
||||
|
||||
public:
|
||||
DRILL_TOOL( int aDiameter, bool a_NotPlated )
|
||||
{
|
||||
m_TotalCount = 0;
|
||||
m_OvalCount = 0;
|
||||
m_Diameter = aDiameter;
|
||||
m_Hole_NotPlated = a_NotPlated;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* the HOLE_INFO class handle hole which must be drilled (diameter, position and layers)
|
||||
* For buried or micro vias, the hole is not on all layers.
|
||||
* So we must generate a drill file for each layer pair (adjacent layers)
|
||||
* Not plated holes are always through holes, and must be output on a specific drill file
|
||||
* because they are drilled after the Pcb process is finished.
|
||||
*/
|
||||
class HOLE_INFO
|
||||
{
|
||||
public:
|
||||
BOARD_ITEM* m_ItemParent; // The pad or via parent of this hole
|
||||
int m_Hole_Diameter; // hole value, and for oblong: min(hole size x, hole size y)
|
||||
int m_Tool_Reference; // Tool reference for this hole = 1 ... n (values <=0 must not be used)
|
||||
wxSize m_Hole_Size; // hole size for oblong holes
|
||||
double m_Hole_Orient; // Hole rotation (= pad rotation) for oblong holes
|
||||
int m_Hole_Shape; // hole shape: round (0) or oval (1)
|
||||
wxPoint m_Hole_Pos; // hole position
|
||||
PCB_LAYER_ID m_Hole_Bottom_Layer; // hole ending layer (usually back layer)
|
||||
PCB_LAYER_ID m_Hole_Top_Layer; // hole starting layer (usually front layer):
|
||||
// m_Hole_Top_Layer < m_Hole_Bottom_Layer
|
||||
bool m_Hole_NotPlated; // hole not plated. Must be in a specific drill file or section
|
||||
|
||||
public:
|
||||
HOLE_INFO()
|
||||
{
|
||||
m_ItemParent = nullptr;
|
||||
m_Hole_NotPlated = false;
|
||||
m_Hole_Diameter = 0;
|
||||
m_Tool_Reference = 0;
|
||||
m_Hole_Orient = 0.0;
|
||||
m_Hole_Shape = 0;
|
||||
m_Hole_Bottom_Layer = B_Cu;
|
||||
m_Hole_Top_Layer = F_Cu;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* the DRILL_PRECISION helper class to handle drill precision format in excellon files
|
||||
*/
|
||||
class DRILL_PRECISION
|
||||
{
|
||||
public:
|
||||
int m_lhs; // Left digit number (integer value of coordinates)
|
||||
int m_rhs; // Right digit number (decimal value of coordinates)
|
||||
|
||||
public:
|
||||
DRILL_PRECISION( int l = 2, int r = 4 )
|
||||
{
|
||||
m_lhs = l; m_rhs = r;
|
||||
}
|
||||
|
||||
|
||||
wxString GetPrecisionString()
|
||||
{
|
||||
wxString text;
|
||||
|
||||
text << m_lhs << wxT( ":" ) << m_rhs;
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::pair<PCB_LAYER_ID, PCB_LAYER_ID> DRILL_LAYER_PAIR;
|
||||
|
||||
/**
|
||||
* GENDRILL_WRITER_BASE is a class to create drill maps and drill report,
|
||||
* and a helper class to created drill files.
|
||||
* drill files are created by specialized derived classes, depenfing on the
|
||||
* file format.
|
||||
*/
|
||||
class GENDRILL_WRITER_BASE
|
||||
{
|
||||
public:
|
||||
enum ZEROS_FMT { // Zero format in coordinates
|
||||
DECIMAL_FORMAT, // Floating point coordinates
|
||||
SUPPRESS_LEADING, // Suppress leading zeros
|
||||
SUPPRESS_TRAILING, // Suppress trainling zeros
|
||||
KEEP_ZEROS // keep zeros
|
||||
};
|
||||
|
||||
protected:
|
||||
BOARD* m_pcb;
|
||||
wxString m_drillFileExtension; // .drl or .gbr, depending on format
|
||||
bool m_unitsDecimal; // true = decimal, false = inches
|
||||
ZEROS_FMT m_zeroFormat; // the zero format option for output file
|
||||
DRILL_PRECISION m_precision; // The current coordinate precision (not used in decimal format)
|
||||
double m_conversionUnits; // scaling factor to convert the board unites to
|
||||
// Excellon/Gerber units (i.e inches or mm)
|
||||
wxPoint m_offset; // Drill offset coordinates
|
||||
bool m_merge_PTH_NPTH; // True to generate only one drill file
|
||||
std::vector<HOLE_INFO> m_holeListBuffer; // Buffer containing holes
|
||||
std::vector<DRILL_TOOL> m_toolListBuffer; // Buffer containing tools
|
||||
|
||||
PlotFormat m_mapFileFmt; // the format of the map drill file,
|
||||
// if this map is needed
|
||||
const PAGE_INFO* m_pageInfo; // the page info used to plot drill maps
|
||||
// If NULL, use a A4 page format
|
||||
// This Ctor is protected.
|
||||
// Use derived classes to build a fully initialized GENDRILL_WRITER_BASE class.
|
||||
GENDRILL_WRITER_BASE( BOARD* aPcb )
|
||||
{
|
||||
m_pcb = aPcb;
|
||||
m_conversionUnits = 1.0;
|
||||
m_unitsDecimal = true;
|
||||
m_mapFileFmt = PLOT_FORMAT_PDF;
|
||||
m_pageInfo = NULL;
|
||||
m_merge_PTH_NPTH = false;
|
||||
}
|
||||
|
||||
public:
|
||||
~GENDRILL_WRITER_BASE()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* set the option to make separate drill files for PTH and NPTH
|
||||
* @param aMerge = true to make only one file containing PTH and NPTH
|
||||
* = false to create 2 separate files
|
||||
*/
|
||||
void SetMergeOption( bool aMerge ) { m_merge_PTH_NPTH = aMerge; }
|
||||
|
||||
/**
|
||||
* Return the plot offset (usually the position
|
||||
* of the auxiliary axis
|
||||
*/
|
||||
const wxPoint GetOffset() { return m_offset; }
|
||||
|
||||
/**
|
||||
* Sets the page info used to plot drill maps
|
||||
* If NULL, a A4 page format will be used
|
||||
* @param aPageInfo = a reference to the page info, usually used to plot/display the board
|
||||
*/
|
||||
void SetPageInfo( const PAGE_INFO* aPageInfo ) { m_pageInfo = aPageInfo; }
|
||||
|
||||
/**
|
||||
* Function SetMapFileFormat
|
||||
* Initialize the format for the drill map file
|
||||
* @param SetMapFileFormat = a PlotFormat value (one of
|
||||
* PLOT_FORMAT_HPGL, PLOT_FORMAT_POST, PLOT_FORMAT_GERBER,
|
||||
* PLOT_FORMAT_DXF, PLOT_FORMAT_SVG, PLOT_FORMAT_PDF
|
||||
* the most useful are PLOT_FORMAT_PDF and PLOT_FORMAT_POST
|
||||
*/
|
||||
void SetMapFileFormat( PlotFormat aMapFmt ) { m_mapFileFmt = aMapFmt; }
|
||||
|
||||
/**
|
||||
* Function CreateMapFilesSet
|
||||
* Creates the full set of map files for the board, in PS, PDF ... format
|
||||
* (use SetMapFileFormat() to select the format)
|
||||
* filenames are computed from the board name, and layers id
|
||||
* @param aPlotDirectory = the output folder
|
||||
* @param aReporter = a REPORTER to return activity or any message (can be NULL)
|
||||
*/
|
||||
void CreateMapFilesSet( const wxString& aPlotDirectory,
|
||||
REPORTER* aReporter = NULL );
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* @param aFullFileName : the name of the file to create
|
||||
*
|
||||
* @return true if the file is created
|
||||
*/
|
||||
bool GenDrillReportFile( const wxString& aFullFileName );
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Function GenDrillMapFile
|
||||
* Plot a map of drill marks for holes.
|
||||
* Hole list must be created before calling this function, by buildHolesList()
|
||||
* for the right holes set (PTH, NPTH, buried/blind vias ...)
|
||||
* the paper sheet to use to plot the map is set in m_pageInfo
|
||||
* ( calls SetPageInfo() to set it )
|
||||
* if NULL, A4 format will be used
|
||||
* @param aFullFileName : the full filename of the map file to create,
|
||||
* @param aFormat : one of the supported plot formats (see enum PlotFormat )
|
||||
*/
|
||||
bool genDrillMapFile( const wxString& aFullFileName, PlotFormat aFormat );
|
||||
|
||||
/**
|
||||
* Function BuildHolesList
|
||||
* Create the list of holes and tools for a given board
|
||||
* The list is sorted by increasing drill size.
|
||||
* Only holes included within aLayerPair are listed.
|
||||
* If aLayerPair identifies with [F_Cu, B_Cu], then
|
||||
* pad holes are always included also.
|
||||
*
|
||||
* @param aLayerPair is an inclusive range of layers.
|
||||
* @param aGenerateNPTH_list :
|
||||
* true to create NPTH only list (with no plated holes)
|
||||
* false to created plated holes list (with no NPTH )
|
||||
*/
|
||||
void buildHolesList( DRILL_LAYER_PAIR aLayerPair,
|
||||
bool aGenerateNPTH_list );
|
||||
|
||||
int getHolesCount() const { return m_holeListBuffer.size(); }
|
||||
|
||||
/** 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* aPlotter );
|
||||
|
||||
/// Get unique layer pairs by examining the micro and blind_buried vias.
|
||||
std::vector<DRILL_LAYER_PAIR> getUniqueLayerPairs() const;
|
||||
|
||||
/**
|
||||
* Function printToolSummary
|
||||
* prints m_toolListBuffer[] tools to aOut and returns total hole count.
|
||||
* @param aOut = the current OUTPUTFORMATTER to print summary
|
||||
* @param aSummaryNPTH = true to print summary for NPTH, false for PTH
|
||||
*/
|
||||
unsigned printToolSummary( OUTPUTFORMATTER& aOut, bool aSummaryNPTH ) const;
|
||||
|
||||
/**
|
||||
* minor helper function.
|
||||
* @return a string from aPair to identify the layer layer pair.
|
||||
* string is "<layer1Name>"-"<layer2Name>"
|
||||
* used to generate a filename for drill files and drill maps
|
||||
*/
|
||||
const std::string layerPairName( DRILL_LAYER_PAIR aPair ) const;
|
||||
|
||||
/**
|
||||
* minor helper function.
|
||||
* @return a string from aLayer to identify the layer.
|
||||
* string are "front" "back" or "in<aLayer>"
|
||||
*/
|
||||
const std::string layerName( PCB_LAYER_ID aLayer ) const;
|
||||
|
||||
/**
|
||||
* @return a filename which identify the drill file function.
|
||||
* it is the board name with the layer pair names added, and for separate
|
||||
* (PTH and NPTH) files, "-NPH" or "-NPTH" added
|
||||
* @param aPair = the layer pair
|
||||
* @param aNPTH = true to generate the filename of NPTH holes
|
||||
* @param aMerge_PTH_NPTH = true to generate the filename of a file which containd both
|
||||
* NPH and NPTH holes
|
||||
*/
|
||||
virtual const wxString getDrillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH,
|
||||
bool aMerge_PTH_NPTH ) const;
|
||||
};
|
||||
|
||||
#endif // #define GENDRILL_FILE_WRITER_BASE_H
|
||||
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 1992-2017 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gendrill_gerber_writer.cpp
|
||||
* @brief Functions to create drill files in gerber X2 format.
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <plot_common.h>
|
||||
#include <kicad_string.h>
|
||||
#include <wxPcbStruct.h>
|
||||
#include <pgm_base.h>
|
||||
#include <build_version.h>
|
||||
|
||||
#include <class_board.h>
|
||||
|
||||
#include <pcbplot.h>
|
||||
#include <pcbnew.h>
|
||||
#include <gendrill_gerber_writer.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <reporter.h>
|
||||
#include <plot_auxiliary_data.h>
|
||||
#include <class_module.h>
|
||||
|
||||
|
||||
GERBER_WRITER::GERBER_WRITER( BOARD* aPcb )
|
||||
: GENDRILL_WRITER_BASE( aPcb )
|
||||
{
|
||||
m_zeroFormat = SUPPRESS_LEADING;
|
||||
m_conversionUnits = 1.0;
|
||||
m_unitsDecimal = true;
|
||||
m_drillFileExtension = "gbr";
|
||||
m_merge_PTH_NPTH = false;
|
||||
}
|
||||
|
||||
|
||||
void GERBER_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
||||
bool aGenDrill, bool aGenMap,
|
||||
REPORTER * aReporter )
|
||||
{
|
||||
// Note: In Gerber drill files, NPTH and PTH are always separate files
|
||||
m_merge_PTH_NPTH = false;
|
||||
|
||||
wxFileName fn;
|
||||
wxString msg;
|
||||
|
||||
std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
|
||||
|
||||
// append a pair representing the NPTH set of holes, for separate drill files.
|
||||
// (Gerber drill files are separate files for PTH and NPTH)
|
||||
hole_sets.push_back( DRILL_LAYER_PAIR( F_Cu, B_Cu ) );
|
||||
|
||||
for( std::vector<DRILL_LAYER_PAIR>::const_iterator it = hole_sets.begin();
|
||||
it != hole_sets.end(); ++it )
|
||||
{
|
||||
DRILL_LAYER_PAIR pair = *it;
|
||||
// For separate drill files, the last layer pair is the NPTH drill file.
|
||||
bool doing_npth = ( it == hole_sets.end() - 1 );
|
||||
|
||||
buildHolesList( pair, doing_npth );
|
||||
|
||||
// The file is created if it has holes, or if it is the non plated drill file
|
||||
// to be sure the NPTH file is up to date in separate files mode.
|
||||
if( getHolesCount() > 0 || doing_npth )
|
||||
{
|
||||
fn = getDrillFileName( pair, doing_npth, false );
|
||||
fn.SetPath( aPlotDirectory );
|
||||
|
||||
if( aGenDrill )
|
||||
{
|
||||
wxString fullFilename = fn.GetFullPath();
|
||||
|
||||
int result = createDrillFile( fullFilename, doing_npth, pair.first, pair.second );
|
||||
|
||||
if( result < 0 )
|
||||
{
|
||||
if( aReporter )
|
||||
{
|
||||
msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fullFilename ) );
|
||||
aReporter->Report( msg );
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aReporter )
|
||||
{
|
||||
msg.Printf( _( "Create file %s\n" ), GetChars( fullFilename ) );
|
||||
aReporter->Report( msg );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( aGenMap )
|
||||
CreateMapFilesSet( aPlotDirectory, aReporter );
|
||||
}
|
||||
|
||||
// A helper class to transform an oblong hole to a segment
|
||||
static void convertOblong2Segment( wxSize aSize, double aOrient, wxPoint& aStart, wxPoint& aEnd );
|
||||
|
||||
int GERBER_WRITER::createDrillFile( wxString& aFullFilename, bool aIsNpth,
|
||||
int aLayer1, int aLayer2 )
|
||||
{
|
||||
int holes_count;
|
||||
|
||||
LOCALE_IO dummy; // Use the standard notation for double numbers
|
||||
|
||||
GERBER_PLOTTER plotter;
|
||||
|
||||
// Gerber drill file imply X2 format:
|
||||
plotter.UseX2Attributes( true );
|
||||
plotter.UseX2NetAttributes( true );
|
||||
|
||||
// Add the standard X2 header, without FileFunction
|
||||
AddGerberX2Header( &plotter, m_pcb );
|
||||
plotter.SetViewport( m_offset, IU_PER_MILS/10, /* scale */ 1.0, /* mirror */false );
|
||||
// has meaning only for gerber plotter. Must be called only after SetViewport
|
||||
plotter.SetGerberCoordinatesFormat( 6 );
|
||||
plotter.SetCreator( wxT( "PCBNEW" ) );
|
||||
|
||||
// Add the standard X2 FileFunction for drill files
|
||||
// %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Route][Mixed]*%
|
||||
wxString text( "%TF.FileFunction," );
|
||||
|
||||
if( aIsNpth )
|
||||
text << "NonPlated,";
|
||||
else
|
||||
text << "Plated,";
|
||||
|
||||
// In Gerber files, layers num are 1 to copper layer count instead of F_Cu to B_Cu
|
||||
// (0 to copper layer count-1)
|
||||
// Note also for a n copper layers board, gerber layers num are 1 ... n
|
||||
aLayer1 += 1;
|
||||
|
||||
if( aLayer2 == B_Cu )
|
||||
aLayer2 = m_pcb->GetCopperLayerCount();
|
||||
else
|
||||
aLayer2 += 1;
|
||||
|
||||
text << aLayer1 << ",";
|
||||
text << aLayer2 << ",";
|
||||
|
||||
// Now add PTH or NPTH or Blind or Buried attribute
|
||||
int toplayer = 1;
|
||||
int bottomlayer = m_pcb->GetCopperLayerCount();
|
||||
|
||||
if( aIsNpth )
|
||||
text << "NPTH";
|
||||
else if( aLayer1 == toplayer && aLayer2 == bottomlayer )
|
||||
text << "PTH";
|
||||
else if( aLayer1 == toplayer || aLayer2 == bottomlayer )
|
||||
text << "Blind";
|
||||
else
|
||||
text << "Buried";
|
||||
|
||||
// Now add Drill or Route or Mixed:
|
||||
// file containing only round holes have Drill attribute
|
||||
// file containing only oblong holes have Routed attribute
|
||||
// file containing both holes have Mixed attribute
|
||||
bool hasOblong = false;
|
||||
bool hasDrill = false;
|
||||
|
||||
for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
|
||||
{
|
||||
HOLE_INFO& hole_descr = m_holeListBuffer[ii];
|
||||
|
||||
if( hole_descr.m_Hole_Shape ) // m_Hole_Shape not 0 is an oblong hole)
|
||||
hasOblong = true;
|
||||
else
|
||||
hasDrill = true;
|
||||
}
|
||||
|
||||
if( hasOblong && hasDrill )
|
||||
text << ",Mixed";
|
||||
else if( hasDrill )
|
||||
text << ",Drill";
|
||||
else if( hasOblong )
|
||||
text << ",Route";
|
||||
|
||||
// else: empty file.
|
||||
|
||||
// End of attribute:
|
||||
text << "*%";
|
||||
|
||||
plotter.AddLineToHeader( text );
|
||||
|
||||
if( !plotter.OpenFile( aFullFilename ) )
|
||||
return -1;
|
||||
|
||||
plotter.StartPlot();
|
||||
|
||||
holes_count = 0;
|
||||
|
||||
wxPoint hole_pos;
|
||||
|
||||
for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
|
||||
{
|
||||
HOLE_INFO& hole_descr = m_holeListBuffer[ii];
|
||||
hole_pos = hole_descr.m_Hole_Pos;
|
||||
|
||||
// Manage the aperture attributes: in drill files 3 attributes can be used:
|
||||
// "ViaDrill", only for vias, not pads
|
||||
// "ComponentDrill", only for Through Holes pads
|
||||
// "Slot" for oblong holes;
|
||||
GBR_METADATA gbr_metadata;
|
||||
|
||||
if( dyn_cast<const VIA*>(hole_descr.m_ItemParent ) )
|
||||
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_VIADRILL );
|
||||
else if( dyn_cast<const D_PAD*>( hole_descr.m_ItemParent ) )
|
||||
{
|
||||
if( hole_descr.m_Hole_Shape )
|
||||
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_SLOTDRILL );
|
||||
else
|
||||
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_COMPONENTDRILL );
|
||||
|
||||
// Add object attribute: component reference to pads (mainly usefull for users)
|
||||
const D_PAD* pad = dyn_cast<const D_PAD*>( hole_descr.m_ItemParent );
|
||||
gbr_metadata.SetCmpReference( pad->GetParent()->GetReference() );
|
||||
gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP );
|
||||
}
|
||||
|
||||
if( hole_descr.m_Hole_Shape )
|
||||
{
|
||||
#if 0 // set to 1 to use flashed oblong holes.
|
||||
// Currently not possible for hole orient != 0 or 90 deg
|
||||
// Use flashed oblong hole
|
||||
plotter.FlashPadOval( hole_pos, hole_descr.m_Hole_Size,
|
||||
hole_descr.m_Hole_Orient, FILLED, &gbr_metadata );
|
||||
#else
|
||||
// Use routing for oblong hole (Slots)
|
||||
wxPoint start, end;
|
||||
convertOblong2Segment( hole_descr.m_Hole_Size,
|
||||
hole_descr.m_Hole_Orient, start, end );
|
||||
int width = std::min( hole_descr.m_Hole_Size.x, hole_descr.m_Hole_Size.y );
|
||||
plotter.ThickSegment( start+hole_pos, end+hole_pos,
|
||||
width, FILLED, &gbr_metadata );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
int diam = std::min( hole_descr.m_Hole_Size.x, hole_descr.m_Hole_Size.y );
|
||||
plotter.FlashPadCircle( hole_pos, diam, FILLED, &gbr_metadata );
|
||||
}
|
||||
|
||||
holes_count++;
|
||||
}
|
||||
|
||||
plotter.EndPlot();
|
||||
|
||||
return holes_count;
|
||||
}
|
||||
|
||||
|
||||
void convertOblong2Segment( wxSize aSize, double aOrient, wxPoint& aStart, wxPoint& aEnd )
|
||||
{
|
||||
wxSize size( aSize );
|
||||
double orient = aOrient;
|
||||
|
||||
/* The pad will be drawn as an oblong shape with size.y > size.x
|
||||
* (Oval vertical orientation 0)
|
||||
*/
|
||||
if( size.x > size.y )
|
||||
{
|
||||
std::swap( size.x, size.y );
|
||||
orient = AddAngles( orient, 900 );
|
||||
}
|
||||
|
||||
int deltaxy = size.y - size.x; // distance between centers of the oval
|
||||
|
||||
int cx = 0;
|
||||
int cy = deltaxy / 2;
|
||||
RotatePoint( &cx, &cy, orient );
|
||||
aStart = wxPoint( cx, cy );
|
||||
cx = 0; cy = -deltaxy / 2;
|
||||
RotatePoint( &cx, &cy, orient );
|
||||
aEnd = wxPoint( cx, cy );
|
||||
}
|
||||
|
||||
|
||||
void GERBER_WRITER::SetFormat( int aRightDigits )
|
||||
{
|
||||
/* Set conversion scale depending on drill file units */
|
||||
m_conversionUnits = 1.0 / IU_PER_MM; // Gerber units = mm
|
||||
|
||||
// Set precison (unit is mm).
|
||||
m_precision.m_lhs = 4;
|
||||
m_precision.m_rhs = aRightDigits == 6 ? 6 : 5;
|
||||
}
|
||||
|
||||
|
||||
const wxString GERBER_WRITER::getDrillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH,
|
||||
bool aMerge_PTH_NPTH ) const
|
||||
{
|
||||
// Gerber files extension is always .gbr.
|
||||
// Therefore, to mark drill files, add "-drl" to the filename.
|
||||
wxFileName fname( GENDRILL_WRITER_BASE::getDrillFileName( aPair, aNPTH, aMerge_PTH_NPTH ) );
|
||||
fname.SetName( fname.GetName() + "-drl" );
|
||||
|
||||
return fname.GetFullPath();
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* @file gendrill_gerber_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-2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 1992-2017 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
|
||||
*/
|
||||
|
||||
#ifndef _GENDRILL_GERBER_WRITER_
|
||||
#define _GENDRILL_GERBER_WRITER_
|
||||
|
||||
#include <gendrill_file_writer_base.h>
|
||||
|
||||
class BOARD;
|
||||
|
||||
/**
|
||||
* GERBER_WRITER is a class mainly used to create Gerber drill files
|
||||
*/
|
||||
class GERBER_WRITER: public GENDRILL_WRITER_BASE
|
||||
{
|
||||
public:
|
||||
GERBER_WRITER( BOARD* aPcb );
|
||||
|
||||
~GERBER_WRITER()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Function SetFormat
|
||||
* Initialize internal parameters to match the given format
|
||||
* @param aRightDigits = number of digits for mantissa part of coordinates (5 or 6)
|
||||
*/
|
||||
void SetFormat( int aRightDigits = 6 );
|
||||
|
||||
/**
|
||||
* Function SetOptions
|
||||
* Initialize internal parameters to match drill options
|
||||
* note: PTH and NPTH are always separate files in Gerber format
|
||||
* @param aOffset = drill coordinates offset
|
||||
*/
|
||||
void SetOptions( wxPoint aOffset )
|
||||
{
|
||||
m_offset = aOffset;
|
||||
m_merge_PTH_NPTH = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function CreateDrillandMapFilesSet
|
||||
* Creates the full set of Excellon drill file for the board
|
||||
* filenames are computed from the board name, and layers id
|
||||
* @param aPlotDirectory = the output folder
|
||||
* @param aGenDrill = true to generate the EXCELLON drill file
|
||||
* @param aGenMap = true to generate a drill map file
|
||||
* @param aReporter = a REPORTER to return activity or any message (can be NULL)
|
||||
*/
|
||||
void CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
||||
bool aGenDrill, bool aGenMap,
|
||||
REPORTER * aReporter = NULL );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Function createDrillFile
|
||||
* Creates an Excellon drill file
|
||||
* @param aFullFilename = the full filename
|
||||
* @param aIsNpth = true for a NPTH file, false for a PTH file
|
||||
* @param aLayer1 = the first board layer
|
||||
* @param aLayer2 = the last board layer
|
||||
* for blind buried vias, they are not always top and bottom layers
|
||||
* @return hole count, or -1 if the file cannot be created
|
||||
*/
|
||||
int createDrillFile( wxString& aFullFilename, bool aIsNpth, int aLayer1, int aLayer2 );
|
||||
|
||||
/**
|
||||
* @return a filename which identify the drill file function.
|
||||
* it is the board name with the layer pair names added, and for separate
|
||||
* (PTH and NPTH) files, "-NPH" or "-NPTH" added
|
||||
* @param aPair = the layer pair
|
||||
* @param aNPTH = true to generate the filename of NPTH holes
|
||||
* @param aMerge_PTH_NPTH = true to generate the filename of a file which containd both
|
||||
* NPH and NPTH holes
|
||||
*/
|
||||
virtual const wxString getDrillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH,
|
||||
bool aMerge_PTH_NPTH ) const override;
|
||||
};
|
||||
|
||||
#endif // #ifndef _GENDRILL_GERBER_WRITER_
|
|
@ -269,8 +269,9 @@ static wxString& makeStringCompatX1( wxString& aText, bool aUseX1CompatibilityMo
|
|||
return aText;
|
||||
}
|
||||
|
||||
void AddGerberX2Attribute( PLOTTER * aPlotter,
|
||||
const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode )
|
||||
|
||||
void AddGerberX2Header( PLOTTER * aPlotter,
|
||||
const BOARD *aBoard, bool aUseX1CompatibilityMode )
|
||||
{
|
||||
wxString text;
|
||||
|
||||
|
@ -339,6 +340,15 @@ void AddGerberX2Attribute( PLOTTER * aPlotter,
|
|||
|
||||
text.Printf( wxT( "%%TF.ProjectId,%s,%s,%s*%%" ), msg.ToAscii(), GetChars( guid ), rev.ToAscii() );
|
||||
aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
|
||||
}
|
||||
|
||||
|
||||
void AddGerberX2Attribute( PLOTTER * aPlotter,
|
||||
const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode )
|
||||
{
|
||||
AddGerberX2Header( aPlotter, aBoard, aUseX1CompatibilityMode );
|
||||
|
||||
wxString text;
|
||||
|
||||
// Add the TF.FileFunction
|
||||
text = GetGerberFileFunctionAttribute( aBoard, aLayer );
|
||||
|
|
|
@ -268,11 +268,35 @@ const wxString GetGerberProtelExtension( LAYER_NUM aLayer );
|
|||
*/
|
||||
const wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, LAYER_NUM aLayer );
|
||||
|
||||
/**
|
||||
* Function AddGerberX2Header
|
||||
* Calculates some X2 attributes, as defined in the
|
||||
* Gerber file format specification J4 (chapter 5) and add them
|
||||
* the to the gerber file header:
|
||||
* TF.GenerationSoftware
|
||||
* TF.CreationDate
|
||||
* TF.ProjectId
|
||||
* file format attribute is not added
|
||||
* @param aPlotter, the current plotter.
|
||||
* @param aBoard = the board, needed to extract some info
|
||||
* @param aUseX1CompatibilityMode = false to generate X2 attributes, true to
|
||||
* use X1 compatibility (X2 attributes added as structured comments,
|
||||
* starting by "G04 #@! " followed by the X2 attribute
|
||||
*/
|
||||
void AddGerberX2Header( PLOTTER * aPlotter,
|
||||
const BOARD *aBoard, bool aUseX1CompatibilityMode = false );
|
||||
|
||||
/**
|
||||
* Function AddGerberX2Attribute
|
||||
* Calculates some X2 attributes, as defined in the
|
||||
* Gerber file format specification J4 (chapter 5) and add them
|
||||
* the to the gerber file header
|
||||
* TF.GenerationSoftware
|
||||
* TF.CreationDate
|
||||
* TF.ProjectId
|
||||
* TF.FileFunction
|
||||
* TF.FilePolarity
|
||||
*
|
||||
* @param aPlotter, the current plotter.
|
||||
* @param aBoard = the board, needed to extract some info
|
||||
* @param aLayer = the layer number to create the attribute for
|
||||
|
@ -280,7 +304,7 @@ const wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, LAYER_NUM aL
|
|||
* use X1 compatibility (X2 attributes added as structured comments,
|
||||
* starting by "G04 #@! " followed by the X2 attribute
|
||||
*/
|
||||
extern void AddGerberX2Attribute( PLOTTER * aPlotter, const BOARD *aBoard,
|
||||
LAYER_NUM aLayer, bool aUseX1CompatibilityMode );
|
||||
void AddGerberX2Attribute( PLOTTER * aPlotter, const BOARD *aBoard,
|
||||
LAYER_NUM aLayer, bool aUseX1CompatibilityMode );
|
||||
|
||||
#endif // PCBPLOT_H_
|
||||
|
|
Loading…
Reference in New Issue