Better approximation for pads in Export Gerber to Pcbnew
We can't get all the way there because we can't create pads outside of modules and the Gerbers don't store any grouping/footprint info. This change moves us from outputing a via for every flashed item (some of which don't even have holes) to synthesizing pads from flashed items using a via (when they have holes) and a copper polygon. This is much better for SMD pads, perhaps better for regular pads, and no worse for vias.
This commit is contained in:
parent
40250c427a
commit
39d4e422ea
|
@ -1,8 +1,8 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Aug 4 2017)
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dialog_layers_select_to_pcb_base.h"
|
||||
|
@ -20,25 +20,25 @@ END_EVENT_TABLE()
|
|||
LAYERS_MAP_DIALOG_BASE::LAYERS_MAP_DIALOG_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
|
||||
|
||||
|
||||
wxBoxSizer* bSizerMain;
|
||||
bSizerMain = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
wxBoxSizer* sbUpperSizer;
|
||||
sbUpperSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
wxBoxSizer* bSizerLayerSelection;
|
||||
bSizerLayerSelection = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
m_staticTextLayerSel = new wxStaticText( this, wxID_ANY, _("Layer selection:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextLayerSel->Wrap( -1 );
|
||||
bSizerLayerSelection->Add( m_staticTextLayerSel, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_bSizerLayerList = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
|
||||
|
||||
m_bSizerLayerList->Add( 0, 0, 0, wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
m_flexLeftColumnBoxSizer = new wxFlexGridSizer( 16, 4, 0, 0 );
|
||||
m_flexLeftColumnBoxSizer->AddGrowableCol( 0 );
|
||||
m_flexLeftColumnBoxSizer->AddGrowableCol( 1 );
|
||||
|
@ -46,13 +46,13 @@ LAYERS_MAP_DIALOG_BASE::LAYERS_MAP_DIALOG_BASE( wxWindow* parent, wxWindowID id,
|
|||
m_flexLeftColumnBoxSizer->AddGrowableCol( 3 );
|
||||
m_flexLeftColumnBoxSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_flexLeftColumnBoxSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
|
||||
|
||||
m_bSizerLayerList->Add( m_flexLeftColumnBoxSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticlineSep = new wxStaticLine( this, ID_M_STATICLINESEP, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
m_bSizerLayerList->Add( m_staticlineSep, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
m_flexRightColumnBoxSizer = new wxFlexGridSizer( 16, 4, 0, 0 );
|
||||
m_flexRightColumnBoxSizer->AddGrowableCol( 0 );
|
||||
m_flexRightColumnBoxSizer->AddGrowableCol( 1 );
|
||||
|
@ -60,26 +60,26 @@ LAYERS_MAP_DIALOG_BASE::LAYERS_MAP_DIALOG_BASE( wxWindow* parent, wxWindowID id,
|
|||
m_flexRightColumnBoxSizer->AddGrowableCol( 3 );
|
||||
m_flexRightColumnBoxSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_flexRightColumnBoxSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
|
||||
|
||||
m_bSizerLayerList->Add( m_flexRightColumnBoxSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bSizerLayerSelection->Add( m_bSizerLayerList, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
sbUpperSizer->Add( bSizerLayerSelection, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
wxBoxSizer* bRightSizer;
|
||||
bRightSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
wxBoxSizer* bSizerLyrCnt;
|
||||
bSizerLyrCnt = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
m_staticTextCopperlayerCount = new wxStaticText( this, ID_M_STATICTEXTCOPPERLAYERCOUNT, _("Copper layers count:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextCopperlayerCount->Wrap( -1 );
|
||||
bSizerLyrCnt->Add( m_staticTextCopperlayerCount, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
m_comboCopperLayersCount = new wxComboBox( this, ID_M_COMBOCOPPERLAYERSCOUNT, _("2 Layers"), wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
|
||||
m_comboCopperLayersCount->Append( _("2 Layers") );
|
||||
m_comboCopperLayersCount->Append( _("4 Layers") );
|
||||
|
@ -90,50 +90,51 @@ LAYERS_MAP_DIALOG_BASE::LAYERS_MAP_DIALOG_BASE( wxWindow* parent, wxWindowID id,
|
|||
m_comboCopperLayersCount->Append( _("14 Layers") );
|
||||
m_comboCopperLayersCount->Append( _("16 Layers") );
|
||||
bSizerLyrCnt->Add( m_comboCopperLayersCount, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bRightSizer->Add( bSizerLyrCnt, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bRightSizer->Add( 5, 15, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
wxBoxSizer* bSizerButtons;
|
||||
bSizerButtons = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
m_buttonStore = new wxButton( this, ID_STORE_CHOICE, _("Store Choice"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_buttonStore, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_buttonRetrieve = new wxButton( this, ID_GET_PREVIOUS_CHOICE, _("Get Stored Choice"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_buttonRetrieve, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_buttonReset = new wxButton( this, ID_RESET_CHOICE, _("Reset"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_buttonReset, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bRightSizer->Add( bSizerButtons, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
sbUpperSizer->Add( bRightSizer, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( sbUpperSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
bSizerMain->Add( sbUpperSizer, 1, wxEXPAND|wxALL, 5 );
|
||||
|
||||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizerMain->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
m_sdbSizerButtons = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerButtonsOK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizerButtons->AddButton( m_sdbSizerButtonsOK );
|
||||
m_sdbSizerButtonsCancel = new wxButton( this, wxID_CANCEL );
|
||||
m_sdbSizerButtons->AddButton( m_sdbSizerButtonsCancel );
|
||||
m_sdbSizerButtons->Realize();
|
||||
|
||||
|
||||
bSizerMain->Add( m_sdbSizerButtons, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
this->SetSizer( bSizerMain );
|
||||
this->Layout();
|
||||
|
||||
bSizerMain->Fit( this );
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +1,15 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Aug 4 2017)
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __DIALOG_LAYERS_SELECT_TO_PCB_BASE_H__
|
||||
#define __DIALOG_LAYERS_SELECT_TO_PCB_BASE_H__
|
||||
#pragma once
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
class DIALOG_SHIM;
|
||||
|
||||
#include "dialog_shim.h"
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
|
@ -23,6 +20,9 @@ class DIALOG_SHIM;
|
|||
#include <wx/sizer.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
|
@ -43,15 +43,15 @@ class LAYERS_MAP_DIALOG_BASE : public DIALOG_SHIM
|
|||
{
|
||||
DECLARE_EVENT_TABLE()
|
||||
private:
|
||||
|
||||
|
||||
// Private event handlers
|
||||
void _wxFB_OnBrdLayersCountSelection( wxCommandEvent& event ){ OnBrdLayersCountSelection( event ); }
|
||||
void _wxFB_OnStoreSetup( wxCommandEvent& event ){ OnStoreSetup( event ); }
|
||||
void _wxFB_OnGetSetup( wxCommandEvent& event ){ OnGetSetup( event ); }
|
||||
void _wxFB_OnResetClick( wxCommandEvent& event ){ OnResetClick( event ); }
|
||||
void _wxFB_OnOkClick( wxCommandEvent& event ){ OnOkClick( event ); }
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
wxStaticText* m_staticTextLayerSel;
|
||||
wxBoxSizer* m_bSizerLayerList;
|
||||
|
@ -67,20 +67,19 @@ class LAYERS_MAP_DIALOG_BASE : public DIALOG_SHIM
|
|||
wxStdDialogButtonSizer* m_sdbSizerButtons;
|
||||
wxButton* m_sdbSizerButtonsOK;
|
||||
wxButton* m_sdbSizerButtonsCancel;
|
||||
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnBrdLayersCountSelection( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnStoreSetup( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnGetSetup( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnResetClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
LAYERS_MAP_DIALOG_BASE( wxWindow* parent, wxWindowID id = ID_LAYERS_MAP_DIALOG_BASE, const wxString& title = _("Layer Selection"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 386,333 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
|
||||
LAYERS_MAP_DIALOG_BASE( wxWindow* parent, wxWindowID id = ID_LAYERS_MAP_DIALOG_BASE, const wxString& title = _("Layer Selection"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~LAYERS_MAP_DIALOG_BASE();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //__DIALOG_LAYERS_SELECT_TO_PCB_BASE_H__
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012-2014 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 1992-2020 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
|
||||
|
@ -46,16 +46,15 @@ enum layer_sel_id {
|
|||
};
|
||||
|
||||
|
||||
class SELECT_LAYER_DIALOG : public wxDialog
|
||||
class SELECT_LAYER_DIALOG : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
wxRadioBox* m_layerList;
|
||||
wxRadioBox* m_layerRadioBox;
|
||||
std::vector <int> m_layerId;
|
||||
|
||||
public:
|
||||
// Constructor and destructor
|
||||
SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent, int aDefaultLayer,
|
||||
int aCopperLayerCount, bool aShowDeselectOption );
|
||||
SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent, int aDefaultLayer, int aCopperLayerCount );
|
||||
~SELECT_LAYER_DIALOG() { };
|
||||
|
||||
private:
|
||||
|
@ -88,12 +87,9 @@ END_EVENT_TABLE()
|
|||
* different radiobutton is clicked on) prior to then clicking on the "Deselect"
|
||||
* button provided within the "Layer selection:" dialog box).
|
||||
*/
|
||||
int GERBVIEW_FRAME::SelectPCBLayer( int aDefaultLayer, int aCopperLayerCount,
|
||||
bool aShowDeselectOption )
|
||||
int GERBVIEW_FRAME::SelectPCBLayer( int aDefaultLayer, int aCopperLayerCount )
|
||||
{
|
||||
SELECT_LAYER_DIALOG* frame = new SELECT_LAYER_DIALOG( this, aDefaultLayer,
|
||||
aCopperLayerCount,
|
||||
aShowDeselectOption );
|
||||
SELECT_LAYER_DIALOG* frame = new SELECT_LAYER_DIALOG( this, aDefaultLayer, aCopperLayerCount );
|
||||
|
||||
int layer = frame->ShowModal();
|
||||
frame->Destroy();
|
||||
|
@ -107,17 +103,15 @@ int GERBVIEW_FRAME::SelectPCBLayer( int aDefaultLayer, int aCopperLayerCount,
|
|||
* radiobuttons, in which case they are positioned (in a vertical line)
|
||||
* to the right of that radiobox.
|
||||
*/
|
||||
SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent,
|
||||
int aDefaultLayer, int aCopperLayerCount,
|
||||
bool aShowDeselectOption ) :
|
||||
wxDialog( parent, -1, _( "Select Layer:" ), wxPoint( -1, -1 ),
|
||||
wxSize( 470, 250 ),
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
|
||||
SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent, int aDefaultLayer,
|
||||
int aCopperLayerCount ) :
|
||||
DIALOG_SHIM( parent, -1, _( "Select Layer:" ), wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
|
||||
{
|
||||
wxButton* button;
|
||||
int ii;
|
||||
wxArrayString layerList;
|
||||
int layerSelect = -1;
|
||||
int selected = -1;
|
||||
|
||||
// Build the layer list; first build copper layers list
|
||||
int layerCount = 0;
|
||||
|
@ -128,8 +122,8 @@ SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent,
|
|||
{
|
||||
layerList.Add( GetPCBDefaultLayerName( ii ) );
|
||||
|
||||
if( ii == aDefaultLayer )
|
||||
layerSelect = layerCount;
|
||||
if( aDefaultLayer == ii )
|
||||
selected = layerCount;
|
||||
|
||||
m_layerId.push_back( ii );
|
||||
layerCount++;
|
||||
|
@ -144,46 +138,54 @@ SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent,
|
|||
|
||||
layerList.Add( GetPCBDefaultLayerName( ii ) );
|
||||
|
||||
if( ii == aDefaultLayer )
|
||||
layerSelect = layerCount;
|
||||
if( aDefaultLayer == ii )
|
||||
selected = layerCount;
|
||||
|
||||
m_layerId.push_back( ii );
|
||||
layerCount++;
|
||||
}
|
||||
|
||||
// When appropriate, also provide a "(Deselect)" radiobutton
|
||||
if( aShowDeselectOption )
|
||||
{
|
||||
layerList.Add( _( "Do not export" ) );
|
||||
layerList.Add( _( "Hole data" ) );
|
||||
|
||||
if( UNSELECTED_LAYER == aDefaultLayer )
|
||||
layerSelect = layerCount;
|
||||
if( aDefaultLayer == UNDEFINED_LAYER )
|
||||
selected = layerCount;
|
||||
|
||||
m_layerId.push_back( UNSELECTED_LAYER );
|
||||
layerCount++;
|
||||
}
|
||||
m_layerId.push_back( UNDEFINED_LAYER );
|
||||
layerCount++;
|
||||
|
||||
m_layerList = new wxRadioBox( this, ID_LAYER_SELECT, _( "Layer" ),
|
||||
wxPoint( -1, -1 ), wxSize( -1, -1 ),
|
||||
layerList,
|
||||
(layerCount < 8) ? layerCount : 8,
|
||||
wxRA_SPECIFY_ROWS );
|
||||
layerList.Add( _( "Do not export" ) );
|
||||
|
||||
if( layerSelect >= 0 )
|
||||
m_layerList->SetSelection( layerSelect );
|
||||
if( aDefaultLayer == UNSELECTED_LAYER )
|
||||
selected = layerCount;
|
||||
|
||||
wxBoxSizer* FrameBoxSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
SetSizer( FrameBoxSizer );
|
||||
FrameBoxSizer->Add( m_layerList, 0, wxALIGN_TOP | wxALL, 5 );
|
||||
wxBoxSizer* ButtonBoxSizer = new wxBoxSizer( wxVERTICAL );
|
||||
FrameBoxSizer->Add( ButtonBoxSizer, 0, wxALIGN_BOTTOM | wxALL, 0 );
|
||||
m_layerId.push_back( UNSELECTED_LAYER );
|
||||
layerCount++;
|
||||
|
||||
m_layerRadioBox = new wxRadioBox( this, ID_LAYER_SELECT, _( "Layer" ), wxDefaultPosition,
|
||||
wxDefaultSize, layerList, std::min( layerCount, 12 ),
|
||||
wxRA_SPECIFY_ROWS );
|
||||
|
||||
if( selected >= 0 )
|
||||
m_layerRadioBox->SetSelection( selected );
|
||||
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
SetSizer( mainSizer );
|
||||
mainSizer->Add( m_layerRadioBox, 1, wxEXPAND | wxALIGN_TOP | wxALL, 5 );
|
||||
wxBoxSizer* buttonsSizer = new wxBoxSizer( wxVERTICAL );
|
||||
mainSizer->Add( buttonsSizer, 0, wxALIGN_BOTTOM | wxALL, 5 );
|
||||
|
||||
button = new wxButton( this, wxID_OK, _( "OK" ) );
|
||||
button->SetDefault();
|
||||
ButtonBoxSizer->Add( button, 0, wxGROW | wxALL, 5 );
|
||||
buttonsSizer->Add( button, 0, wxGROW | wxALL, 5 );
|
||||
|
||||
button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
|
||||
ButtonBoxSizer->Add( button, 0, wxGROW | wxALL, 5 );
|
||||
buttonsSizer->Add( button, 0, wxGROW | wxALL, 5 );
|
||||
|
||||
#ifdef __WXOSX__
|
||||
// Hack to fix clipped radio buttons on OSX
|
||||
wxSize size = m_layerRadioBox->GetBestSize() + wxSize( 20, 0 );
|
||||
m_layerRadioBox->SetMinSize( size );
|
||||
#endif
|
||||
|
||||
GetSizer()->SetSizeHints( this );
|
||||
|
||||
|
@ -193,7 +195,7 @@ SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent,
|
|||
|
||||
void SELECT_LAYER_DIALOG::OnLayerSelected( wxCommandEvent& event )
|
||||
{
|
||||
int ii = m_layerId[m_layerList->GetSelection()];
|
||||
int ii = m_layerId[m_layerRadioBox->GetSelection()];
|
||||
|
||||
EndModal( ii );
|
||||
}
|
||||
|
|
|
@ -34,19 +34,32 @@
|
|||
#include <confirm.h>
|
||||
#include <macros.h>
|
||||
#include <trigo.h>
|
||||
#include <gerbview.h>
|
||||
#include <gerbview_frame.h>
|
||||
#include <gerber_file_image.h>
|
||||
#include <gerber_file_image_list.h>
|
||||
#include <select_layers_to_pcb.h>
|
||||
#include <build_version.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
||||
#include "excellon_image.h"
|
||||
|
||||
// Imported function
|
||||
extern const wxString GetPCBDefaultLayerName( LAYER_NUM aLayerNumber );
|
||||
|
||||
|
||||
struct EXPORT_VIA
|
||||
{
|
||||
EXPORT_VIA( const wxPoint& aPos, int aSize, int aDrill ) :
|
||||
m_Pos( aPos ),
|
||||
m_Size( aSize ),
|
||||
m_Drill( aDrill )
|
||||
{ }
|
||||
|
||||
wxPoint m_Pos;
|
||||
int m_Size;
|
||||
int m_Drill;
|
||||
};
|
||||
|
||||
|
||||
/* A helper class to export a Gerber set of files to Pcbnew
|
||||
*/
|
||||
class GBR_TO_PCB_EXPORTER
|
||||
|
@ -56,9 +69,7 @@ private:
|
|||
wxString m_pcb_file_name; // BOARD file to write to
|
||||
FILE* m_fp; // the board file
|
||||
int m_pcbCopperLayersCount;
|
||||
std::vector<wxPoint> m_vias_coordinates; // list of already generated vias,
|
||||
// used to export only once a via
|
||||
// having a given coordinate
|
||||
std::vector<EXPORT_VIA> m_vias;
|
||||
public:
|
||||
GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME* aFrame, const wxString& aFileName );
|
||||
~GBR_TO_PCB_EXPORTER();
|
||||
|
@ -70,6 +81,22 @@ public:
|
|||
bool ExportPcb( LAYER_NUM* aLayerLookUpTable, int aCopperLayers );
|
||||
|
||||
private:
|
||||
/**
|
||||
* collect holes from a drill layer.
|
||||
* We'll use these later when writing pads & vias.
|
||||
* @param aGbrItem
|
||||
*/
|
||||
void collect_hole( GERBER_DRAW_ITEM* aGbrItem );
|
||||
|
||||
/**
|
||||
* write a via to the board file.
|
||||
* Some of these will represent actual vias while others are used to represent
|
||||
* holes in pads. (We can't generate actual pads because the Gerbers don't contain
|
||||
* info on how to group them into modules.)
|
||||
* @param aVia
|
||||
*/
|
||||
void export_via( const EXPORT_VIA& aVia );
|
||||
|
||||
/**
|
||||
* write a non copper line or arc to the board file.
|
||||
* @param aGbrItem = the Gerber item (line, arc) to export
|
||||
|
@ -93,7 +120,7 @@ private:
|
|||
void writePcbZoneItem( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer );
|
||||
|
||||
/**
|
||||
* write a track or via) to the board file.
|
||||
* write a track (or via) to the board file.
|
||||
* @param aGbrItem = the Gerber item (line, arc, flashed) to export
|
||||
* @param aLayer = the copper layer to use
|
||||
*/
|
||||
|
@ -101,10 +128,13 @@ private:
|
|||
|
||||
/**
|
||||
* Function export_flashed_copper_item
|
||||
* write a via to the board file (always uses a via through).
|
||||
* write a synthetic pad to the board file.
|
||||
* We can't create real pads because the Gerbers don't store grouping/footprint info.
|
||||
* So we synthesize a pad with a via for the hole (if present) and a copper polygon for
|
||||
* the pad.
|
||||
* @param aGbrItem = the flashed Gerber item to export
|
||||
*/
|
||||
void export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem );
|
||||
void export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer );
|
||||
|
||||
/**
|
||||
* Function export_segline_copper_item
|
||||
|
@ -237,10 +267,22 @@ bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* aLayerLookUpTable, int aCopperLa
|
|||
writePcbHeader( aLayerLookUpTable );
|
||||
|
||||
// create an image of gerber data
|
||||
// First: non copper layers:
|
||||
const int pcbCopperLayerMax = 31;
|
||||
GERBER_FILE_IMAGE_LIST* images = m_gerbview_frame->GetGerberLayout()->GetImagesList();
|
||||
|
||||
// First collect all the holes. We'll use these to generate pads, vias, etc.
|
||||
for( unsigned layer = 0; layer < images->ImagesMaxCount(); ++layer )
|
||||
{
|
||||
EXCELLON_IMAGE* excellon = dynamic_cast<EXCELLON_IMAGE*>( images->GetGbrImage( layer ) );
|
||||
|
||||
if( excellon == NULL ) // Layer not yet used or not a drill image
|
||||
continue;
|
||||
|
||||
for( GERBER_DRAW_ITEM* gerb_item : excellon->GetItems() )
|
||||
collect_hole( gerb_item );
|
||||
}
|
||||
|
||||
// Next: non copper layers:
|
||||
for( unsigned layer = 0; layer < images->ImagesMaxCount(); ++layer )
|
||||
{
|
||||
GERBER_FILE_IMAGE* gerber = images->GetGbrImage( layer );
|
||||
|
@ -277,6 +319,10 @@ bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* aLayerLookUpTable, int aCopperLa
|
|||
export_copper_item( gerb_item, pcb_layer_number );
|
||||
}
|
||||
|
||||
// Now write out the holes we collected earlier as vias
|
||||
for( const EXPORT_VIA& via : m_vias )
|
||||
export_via( via );
|
||||
|
||||
fprintf( m_fp, ")\n" );
|
||||
|
||||
fclose( m_fp );
|
||||
|
@ -388,6 +434,44 @@ void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, LA
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Many holes will be pads, but we have no way to create those without modules, and creating
|
||||
* a module per pad is not really viable.
|
||||
*
|
||||
* So we use vias to mimic holes, with the loss of any hole shape (as we only have round holes
|
||||
* in vias at present).
|
||||
*
|
||||
* We start out with a via size minimally larger than the hole. We'll leave it this way if
|
||||
* the pad gets drawn as a copper polygon, or increase it to the proper size if it has a
|
||||
* circular, concentric copper flashing.
|
||||
*/
|
||||
void GBR_TO_PCB_EXPORTER::collect_hole( GERBER_DRAW_ITEM* aGbrItem )
|
||||
{
|
||||
int size = std::min( aGbrItem->m_Size.x, aGbrItem->m_Size.y );
|
||||
m_vias.emplace_back( aGbrItem->m_Start, size + 1, size );
|
||||
}
|
||||
|
||||
|
||||
void GBR_TO_PCB_EXPORTER::export_via( const EXPORT_VIA& aVia )
|
||||
{
|
||||
wxPoint via_pos = aVia.m_Pos;
|
||||
|
||||
// Reverse Y axis:
|
||||
via_pos.y = -via_pos.y;
|
||||
|
||||
// Layers are Front to Back
|
||||
fprintf( m_fp, " (via (at %s %s) (size %s) (drill %s)",
|
||||
Double2Str( MapToPcbUnits( via_pos.x ) ).c_str(),
|
||||
Double2Str( MapToPcbUnits( via_pos.y ) ).c_str(),
|
||||
Double2Str( MapToPcbUnits( aVia.m_Size ) ).c_str(),
|
||||
Double2Str( MapToPcbUnits( aVia.m_Drill ) ).c_str() );
|
||||
|
||||
fprintf( m_fp, " (layers %s %s))\n",
|
||||
TO_UTF8( GetPCBDefaultLayerName( F_Cu ) ),
|
||||
TO_UTF8( GetPCBDefaultLayerName( B_Cu ) ) );
|
||||
}
|
||||
|
||||
|
||||
void GBR_TO_PCB_EXPORTER::export_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer )
|
||||
{
|
||||
switch( aGbrItem->m_Shape )
|
||||
|
@ -395,8 +479,7 @@ void GBR_TO_PCB_EXPORTER::export_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_
|
|||
case GBR_SPOT_CIRCLE:
|
||||
case GBR_SPOT_RECT:
|
||||
case GBR_SPOT_OVAL:
|
||||
// replace spots with vias when possible
|
||||
export_flashed_copper_item( aGbrItem );
|
||||
export_flashed_copper_item( aGbrItem, aLayer );
|
||||
break;
|
||||
|
||||
case GBR_ARC:
|
||||
|
@ -505,37 +588,44 @@ void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem,
|
|||
|
||||
|
||||
/*
|
||||
* creates a via from a flashed gerber item.
|
||||
* Flashed items are usually pads or vias, so we try to export all of them
|
||||
* using vias
|
||||
* Flashed items are usually pads or vias. Pads are problematic because we have no way to
|
||||
* represent one in Pcbnew outside of a module (and creating a module per pad isn't really
|
||||
* viable).
|
||||
* If we've already created a via from a hole, and the flashed copper item is a simple circle
|
||||
* then we'll enlarge the via to the proper size. Otherwise we create a copper polygon to
|
||||
* represent the flashed item (which is presumably a pad).
|
||||
*/
|
||||
void GBR_TO_PCB_EXPORTER::export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem )
|
||||
void GBR_TO_PCB_EXPORTER::export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem,
|
||||
LAYER_NUM aLayer )
|
||||
{
|
||||
// First, explore already created vias, before creating a new via
|
||||
for( unsigned ii = 0; ii < m_vias_coordinates.size(); ii++ )
|
||||
static D_CODE flashed_item_D_CODE( 0 );
|
||||
|
||||
D_CODE* d_codeDescr = aGbrItem->GetDcodeDescr();
|
||||
SHAPE_POLY_SET polygon;
|
||||
|
||||
if( d_codeDescr == NULL )
|
||||
d_codeDescr = &flashed_item_D_CODE;
|
||||
|
||||
if( aGbrItem->m_Shape == GBR_SPOT_CIRCLE )
|
||||
{
|
||||
if( m_vias_coordinates[ii] == aGbrItem->m_Start ) // Already created
|
||||
return;
|
||||
// See if there's a via that we can enlarge to fit this flashed item
|
||||
for( EXPORT_VIA& via : m_vias )
|
||||
{
|
||||
if( via.m_Pos == aGbrItem->m_Start )
|
||||
{
|
||||
via.m_Size = std::max( via.m_Size, aGbrItem->m_Size.x );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_vias_coordinates.push_back( aGbrItem->m_Start );
|
||||
d_codeDescr->ConvertShapeToPolygon();
|
||||
wxPoint offset = aGbrItem->GetABPosition( aGbrItem->m_Start );
|
||||
|
||||
wxPoint via_pos = aGbrItem->m_Start;
|
||||
int width = (aGbrItem->m_Size.x + aGbrItem->m_Size.y) / 2;
|
||||
// Reverse Y axis:
|
||||
via_pos.y = -via_pos.y;
|
||||
|
||||
// Layers are Front to Back
|
||||
fprintf( m_fp, " (via (at %s %s) (size %s)",
|
||||
Double2Str( MapToPcbUnits(via_pos.x) ).c_str(),
|
||||
Double2Str( MapToPcbUnits(via_pos.y) ).c_str(),
|
||||
Double2Str( MapToPcbUnits( width ) ).c_str() );
|
||||
|
||||
fprintf( m_fp, " (layers %s %s))\n",
|
||||
TO_UTF8( GetPCBDefaultLayerName( F_Cu ) ),
|
||||
TO_UTF8( GetPCBDefaultLayerName( B_Cu ) ) );
|
||||
writePcbPolygon( d_codeDescr->m_Polygon, aLayer, offset );
|
||||
}
|
||||
|
||||
|
||||
void GBR_TO_PCB_EXPORTER::writePcbHeader( LAYER_NUM* aLayerLookUpTable )
|
||||
{
|
||||
fprintf( m_fp, "(kicad_pcb (version 4) (host Gerbview \"%s\")\n\n",
|
||||
|
|
|
@ -122,7 +122,6 @@ public:
|
|||
/** Install the dialog box for layer selection
|
||||
* @param aDefaultLayer = Preselection (NB_PCB_LAYERS for "(Deselect)" layer)
|
||||
* @param aCopperLayerCount = number of copper layers
|
||||
* @param aShowDeselectOption = display a "(Deselect)" radiobutton (when set to true)
|
||||
* @return new layer value (NB_PCB_LAYERS when "(Deselect)" radiobutton selected),
|
||||
* or -1 if canceled
|
||||
*
|
||||
|
@ -134,7 +133,7 @@ public:
|
|||
* different radiobutton is clicked on) prior to then clicking on the "Deselect"
|
||||
* button provided within the "Layer selection:" dialog box).
|
||||
*/
|
||||
int SelectPCBLayer( int aDefaultLayer, int aOpperLayerCount, bool aNullLayer = false );
|
||||
int SelectPCBLayer( int aDefaultLayer, int aCopperLayerCount );
|
||||
|
||||
///> @copydoc EDA_DRAW_FRAME::SetGridColor()
|
||||
virtual void SetGridColor( COLOR4D aColor ) override;
|
||||
|
|
|
@ -158,24 +158,18 @@ void LAYERS_MAP_DIALOG::initDialog()
|
|||
// Provide a text string to identify the Gerber layer
|
||||
msg.Printf( _( "Layer %d" ), m_buttonTable[ii] + 1 );
|
||||
|
||||
label = new wxStaticText( this,
|
||||
wxID_STATIC, msg, wxDefaultPosition,
|
||||
wxDefaultSize, 0 );
|
||||
label = new wxStaticText( this, wxID_STATIC, msg );
|
||||
flexColumnBoxSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
|
||||
|
||||
/* Add file name and extension without path. */
|
||||
wxFileName fn( images->GetGbrImage( ii )->m_FileName );
|
||||
label = new wxStaticText( this,
|
||||
wxID_STATIC, fn.GetFullName(),
|
||||
wxDefaultPosition, wxDefaultSize );
|
||||
flexColumnBoxSizer->Add( label, 0,
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5 );
|
||||
label = new wxStaticText( this, wxID_STATIC, fn.GetFullName() );
|
||||
flexColumnBoxSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
|
||||
|
||||
// Provide a button for this layer (which will invoke a child dialog box)
|
||||
item_ID = ID_BUTTON_0 + ii;
|
||||
wxButton * Button = new wxButton( this,
|
||||
item_ID, wxT( "..." ),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
|
||||
wxButton * Button = new wxButton( this, item_ID, wxT( "..." ), wxDefaultPosition,
|
||||
wxDefaultSize, wxBU_EXACTFIT );
|
||||
|
||||
flexColumnBoxSizer->Add( Button, 0, wxALIGN_CENTER_VERTICAL | wxALL );
|
||||
|
||||
|
@ -195,14 +189,13 @@ void LAYERS_MAP_DIALOG::initDialog()
|
|||
if( ii == 0 )
|
||||
{
|
||||
msg = _( "Do not export" );
|
||||
text = new wxStaticText( this,
|
||||
item_ID, msg, wxDefaultPosition,
|
||||
wxDefaultSize, 0 );
|
||||
text = new wxStaticText( this, item_ID, msg );
|
||||
goodSize = text->GetSize();
|
||||
|
||||
for( LAYER_NUM jj = 0; jj < GERBER_DRAWLAYERS_COUNT; ++jj )
|
||||
{
|
||||
text->SetLabel( GetPCBDefaultLayerName( jj ) );
|
||||
|
||||
if( goodSize.x < text->GetSize().x )
|
||||
goodSize.x = text->GetSize().x;
|
||||
}
|
||||
|
@ -213,13 +206,10 @@ void LAYERS_MAP_DIALOG::initDialog()
|
|||
else
|
||||
{
|
||||
msg = GetPCBDefaultLayerName( m_layersLookUpTable[m_buttonTable[ii]] );
|
||||
text = new wxStaticText( this,
|
||||
item_ID, msg, wxDefaultPosition,
|
||||
wxDefaultSize, 0 );
|
||||
text = new wxStaticText( this, item_ID, msg );
|
||||
}
|
||||
text->SetMinSize( goodSize );
|
||||
flexColumnBoxSizer->Add( text, 1, wxALIGN_CENTER_VERTICAL | wxALL,
|
||||
5 );
|
||||
flexColumnBoxSizer->Add( text, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
|
||||
|
||||
m_layersList[ii] = text;
|
||||
}
|
||||
|
@ -310,6 +300,11 @@ void LAYERS_MAP_DIALOG::OnGetSetup( wxCommandEvent& event )
|
|||
m_layersList[ii]->SetLabel( _( "Do not export" ) );
|
||||
m_layersList[ii]->SetForegroundColour( *wxBLUE );
|
||||
}
|
||||
else if( layer == UNDEFINED_LAYER )
|
||||
{
|
||||
m_layersList[ii]->SetLabel( _( "Hole data" ) );
|
||||
m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( layer ) );
|
||||
|
@ -332,12 +327,12 @@ void LAYERS_MAP_DIALOG::OnSelectLayer( wxCommandEvent& event )
|
|||
|
||||
LAYER_NUM jj = m_layersLookUpTable[m_buttonTable[ii]];
|
||||
|
||||
if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) )
|
||||
if( jj != UNSELECTED_LAYER && jj != UNDEFINED_LAYER && !IsValidLayer( jj ) )
|
||||
jj = B_Cu; // (Defaults to "Copper" layer.)
|
||||
|
||||
jj = m_Parent->SelectPCBLayer( jj, m_exportBoardCopperLayersCount, true );
|
||||
jj = m_Parent->SelectPCBLayer( jj, m_exportBoardCopperLayersCount );
|
||||
|
||||
if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) )
|
||||
if( jj != UNSELECTED_LAYER && jj != UNDEFINED_LAYER && !IsValidLayer( jj ) )
|
||||
return;
|
||||
|
||||
if( jj != m_layersLookUpTable[m_buttonTable[ii]] )
|
||||
|
@ -352,6 +347,14 @@ void LAYERS_MAP_DIALOG::OnSelectLayer( wxCommandEvent& event )
|
|||
// that this layer is *not* being exported)
|
||||
m_layersList[ii]->SetForegroundColour( *wxBLUE );
|
||||
}
|
||||
else if( jj == UNDEFINED_LAYER )
|
||||
{
|
||||
m_layersList[ii]->SetLabel( _( "Hole data" ) );
|
||||
|
||||
// Change the text color to fuchsia (to highlight
|
||||
// that this layer *is* being exported)
|
||||
m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( jj ) );
|
||||
|
@ -387,7 +390,7 @@ void LAYERS_MAP_DIALOG::OnOkClick( wxCommandEvent& event )
|
|||
if( inner_layer_max > m_exportBoardCopperLayersCount-2 )
|
||||
{
|
||||
wxMessageBox(
|
||||
_("The exported board has not enough copper layers to handle selected inner layers") );
|
||||
_("Exported board does not have enough copper layers to handle selected inner layers") );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue