Implement ODB++ export
ADDED: Add support in Pcbnew for exporting ODB++ files under Fabrication Outputs, base on ODB++Design Format Specification (Release v8.1 Update 3 February 2021). Note: There is still a lot of work to do if we will make the feature as complete as the ODB++ spec. However, the current functionality's completeness is already sufficient to cover general production scenarios. I have compared the output results with Gerber files by DFM tool and the accuracy at the graphic level should be able to cover most usage scenarios. Additionally, I am very grateful to the great open-source project Horizon EDA for giving me a lot of inspiration in terms of ideas. The feature can be enabled by adding "EnableODB=1" to the kicad_advanced configuration file. Fixes https://gitlab.com/kicad/code/kicad/-/issues/2019jobs
-
4common/advanced_config.cpp
-
10common/bitmap_info.cpp
-
9include/advanced_config.h
-
1include/bitmaps/bitmaps_list.h
-
1include/project/project_file.h
-
5pcbnew/CMakeLists.txt
-
112pcbnew/dialogs/dialog_export_odbpp.cpp
-
671pcbnew/dialogs/dialog_export_odbpp.fbp
-
56pcbnew/dialogs/dialog_export_odbpp.h
-
117pcbnew/dialogs/dialog_export_odbpp_base.cpp
-
72pcbnew/dialogs/dialog_export_odbpp_base.h
-
143pcbnew/files.cpp
-
4pcbnew/menubar_pcb_editor.cpp
-
5pcbnew/pcb_edit_frame.h
-
38pcbnew/pcb_io/odbpp/CMakeLists.txt
-
101pcbnew/pcb_io/odbpp/odb_attribute.cpp
-
352pcbnew/pcb_io/odbpp/odb_attribute.h
-
94pcbnew/pcb_io/odbpp/odb_component.cpp
-
99pcbnew/pcb_io/odbpp/odb_component.h
-
34pcbnew/pcb_io/odbpp/odb_defines.h
-
420pcbnew/pcb_io/odbpp/odb_eda_data.cpp
-
340pcbnew/pcb_io/odbpp/odb_eda_data.h
-
975pcbnew/pcb_io/odbpp/odb_entity.cpp
-
273pcbnew/pcb_io/odbpp/odb_entity.h
-
1002pcbnew/pcb_io/odbpp/odb_feature.cpp
-
349pcbnew/pcb_io/odbpp/odb_feature.h
-
671pcbnew/pcb_io/odbpp/odb_fonts.cpp
-
285pcbnew/pcb_io/odbpp/odb_netlist.cpp
-
77pcbnew/pcb_io/odbpp/odb_netlist.h
-
352pcbnew/pcb_io/odbpp/odb_util.cpp
-
355pcbnew/pcb_io/odbpp/odb_util.h
-
170pcbnew/pcb_io/odbpp/pcb_io_odbpp.cpp
-
182pcbnew/pcb_io/odbpp/pcb_io_odbpp.h
-
8pcbnew/pcb_io/pcb_io_mgr.cpp
-
1pcbnew/pcb_io/pcb_io_mgr.h
-
9pcbnew/pcbnew_settings.h
-
3pcbnew/tools/board_editor_control.cpp
-
7pcbnew/tools/pcb_actions.cpp
-
1pcbnew/tools/pcb_actions.h
-
1resources/bitmaps_png/CMakeLists.txt
-
BINresources/bitmaps_png/png/post_odb_16.png
-
BINresources/bitmaps_png/png/post_odb_24.png
-
BINresources/bitmaps_png/png/post_odb_32.png
-
BINresources/bitmaps_png/png/post_odb_48.png
-
BINresources/bitmaps_png/png/post_odb_64.png
-
BINresources/bitmaps_png/png/post_odb_dark_16.png
-
BINresources/bitmaps_png/png/post_odb_dark_24.png
-
BINresources/bitmaps_png/png/post_odb_dark_32.png
-
BINresources/bitmaps_png/png/post_odb_dark_48.png
-
BINresources/bitmaps_png/png/post_odb_dark_64.png
-
147resources/bitmaps_png/sources/dark/post_odb.svg
-
145resources/bitmaps_png/sources/light/post_odb.svg
@ -0,0 +1,112 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 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 as published by the |
|||
* Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <dialogs/dialog_export_odbpp.h>
|
|||
|
|||
#include <board.h>
|
|||
#include <footprint.h>
|
|||
#include <kiway_holder.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <pcbnew_settings.h>
|
|||
#include <pgm_base.h>
|
|||
#include <project.h>
|
|||
#include <project/board_project_settings.h>
|
|||
#include <project/project_file.h>
|
|||
#include <settings/settings_manager.h>
|
|||
#include <widgets/std_bitmap_button.h>
|
|||
|
|||
#include <set>
|
|||
#include <vector>
|
|||
#include <wx/dirdlg.h>
|
|||
|
|||
static wxString s_oemColumn = wxEmptyString; |
|||
|
|||
DIALOG_EXPORT_ODBPP::DIALOG_EXPORT_ODBPP( PCB_EDIT_FRAME* aParent ) : |
|||
DIALOG_EXPORT_ODBPP_BASE( aParent ), m_parent( aParent ) |
|||
{ |
|||
m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) ); |
|||
|
|||
SetupStandardButtons( { { wxID_OK, _( "Export" ) }, { wxID_CANCEL, _( "Close" ) } } ); |
|||
|
|||
wxString path = m_parent->GetLastPath( LAST_PATH_ODBPP ); |
|||
|
|||
if( path.IsEmpty() ) |
|||
{ |
|||
wxFileName brdFile( m_parent->GetBoard()->GetFileName() ); |
|||
path = brdFile.GetPath(); |
|||
} |
|||
|
|||
m_outputFileName->SetValue( path ); |
|||
|
|||
// Fill wxChoice (and others) items with data before calling finishDialogSettings()
|
|||
// to calculate suitable widgets sizes
|
|||
Init(); |
|||
|
|||
// Now all widgets have the size fixed, call FinishDialogSettings
|
|||
finishDialogSettings(); |
|||
} |
|||
|
|||
|
|||
void DIALOG_EXPORT_ODBPP::onBrowseClicked( wxCommandEvent& event ) |
|||
{ |
|||
// Build the absolute path of current output directory to preselect it in the file browser.
|
|||
wxString path = ExpandEnvVarSubstitutions( m_outputFileName->GetValue(), &Prj() ); |
|||
wxFileName fn( Prj().AbsolutePath( path ) ); |
|||
|
|||
wxDirDialog dlg( this, _( "Export ODB++ File" ), fn.GetPath() ); |
|||
|
|||
if( dlg.ShowModal() == wxID_CANCEL ) |
|||
return; |
|||
|
|||
m_outputFileName->SetValue( dlg.GetPath() ); |
|||
} |
|||
|
|||
|
|||
void DIALOG_EXPORT_ODBPP::onOKClick( wxCommandEvent& event ) |
|||
{ |
|||
m_parent->SetLastPath( LAST_PATH_ODBPP, m_outputFileName->GetValue() ); |
|||
|
|||
event.Skip(); |
|||
} |
|||
|
|||
|
|||
bool DIALOG_EXPORT_ODBPP::Init() |
|||
{ |
|||
PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>(); |
|||
|
|||
BOARD* board = m_parent->GetBoard(); |
|||
|
|||
m_choiceUnits->SetSelection( cfg->m_ExportODBPP.units ); |
|||
m_precision->SetValue( cfg->m_ExportODBPP.precision ); |
|||
m_cbCompress->SetValue( cfg->m_ExportODBPP.compress ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
bool DIALOG_EXPORT_ODBPP::TransferDataFromWindow() |
|||
{ |
|||
PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>(); |
|||
|
|||
cfg->m_ExportODBPP.units = m_choiceUnits->GetSelection(); |
|||
cfg->m_ExportODBPP.precision = m_precision->GetValue(); |
|||
cfg->m_ExportODBPP.compress = m_cbCompress->GetValue(); |
|||
|
|||
return true; |
|||
} |
@ -0,0 +1,671 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
|||
<wxFormBuilder_Project> |
|||
<FileVersion major="1" minor="17"/> |
|||
<object class="Project" expanded="true"> |
|||
<property name="class_decoration"></property> |
|||
<property name="code_generation">C++</property> |
|||
<property name="disconnect_events">1</property> |
|||
<property name="disconnect_mode">source_name</property> |
|||
<property name="disconnect_php_events">0</property> |
|||
<property name="disconnect_python_events">0</property> |
|||
<property name="embedded_files_path">res</property> |
|||
<property name="encoding">UTF-8</property> |
|||
<property name="event_generation">connect</property> |
|||
<property name="file">dialog_export_odbpp_base</property> |
|||
<property name="first_id">1000</property> |
|||
<property name="help_provider">none</property> |
|||
<property name="image_path_wrapper_function_name"></property> |
|||
<property name="indent_with_spaces"></property> |
|||
<property name="internationalize">1</property> |
|||
<property name="name">DIALOG_EXPORT_ODBPP_BASE</property> |
|||
<property name="namespace"></property> |
|||
<property name="path">.</property> |
|||
<property name="precompiled_header"></property> |
|||
<property name="relative_path">1</property> |
|||
<property name="skip_lua_events">1</property> |
|||
<property name="skip_php_events">1</property> |
|||
<property name="skip_python_events">1</property> |
|||
<property name="ui_table">UI</property> |
|||
<property name="use_array_enum">0</property> |
|||
<property name="use_enum">0</property> |
|||
<property name="use_microsoft_bom">0</property> |
|||
<object class="Dialog" expanded="true"> |
|||
<property name="aui_managed">0</property> |
|||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> |
|||
<property name="bg"></property> |
|||
<property name="center">wxBOTH</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="event_handler">impl_virtual</property> |
|||
<property name="extra_style"></property> |
|||
<property name="fg"></property> |
|||
<property name="font"></property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">DIALOG_EXPORT_ODBPP_BASE</property> |
|||
<property name="pos"></property> |
|||
<property name="size">380,300</property> |
|||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> |
|||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property> |
|||
<property name="title">Export ODB++</property> |
|||
<property name="tooltip"></property> |
|||
<property name="two_step_creation">0</property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<object class="wxBoxSizer" expanded="true"> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">bMainSizer</property> |
|||
<property name="orient">wxVERTICAL</property> |
|||
<property name="permission">none</property> |
|||
<object class="sizeritem" expanded="true"> |
|||
<property name="border">15</property> |
|||
<property name="flag">wxBOTTOM|wxEXPAND|wxTOP</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxBoxSizer" expanded="true"> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">bSizerTop</property> |
|||
<property name="orient">wxHORIZONTAL</property> |
|||
<property name="permission">protected</property> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStaticText" expanded="false"> |
|||
<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="drag_accept_files">0</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:</property> |
|||
<property name="markup">0</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_lblBrdFile</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> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALIGN_CENTER_VERTICAL</property> |
|||
<property name="proportion">1</property> |
|||
<object class="wxTextCtrl" expanded="false"> |
|||
<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="drag_accept_files">0</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="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="maxlength">0</property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size">350,-1</property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_outputFileName</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">Enter a filename if you do not want to use default file names
Can be used only when printing the current sheet</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="value"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxBitmapButton" expanded="false"> |
|||
<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="auth_needed">0</property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="bitmap"></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="current"></property> |
|||
<property name="default">0</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="disabled"></property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="focus"></property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">MyButton</property> |
|||
<property name="margins"></property> |
|||
<property name="markup">0</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">-1,-1</property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_browseButton</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="position"></property> |
|||
<property name="pressed"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size">-1,-1</property> |
|||
<property name="style"></property> |
|||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</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="OnButtonClick">onBrowseClicked</event> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="true"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxEXPAND</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxBoxSizer" expanded="true"> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">bSizer3</property> |
|||
<property name="orient">wxHORIZONTAL</property> |
|||
<property name="permission">none</property> |
|||
<object class="sizeritem" expanded="true"> |
|||
<property name="border">10</property> |
|||
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property> |
|||
<property name="proportion">1</property> |
|||
<object class="wxStaticBoxSizer" expanded="true"> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">File Format</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">sbSizer1</property> |
|||
<property name="orient">wxVERTICAL</property> |
|||
<property name="parent">1</property> |
|||
<property name="permission">none</property> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxEXPAND|wxALL</property> |
|||
<property name="proportion">3</property> |
|||
<object class="wxFlexGridSizer" expanded="false"> |
|||
<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">fgSizer</property> |
|||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property> |
|||
<property name="permission">none</property> |
|||
<property name="rows">0</property> |
|||
<property name="vgap">0</property> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStaticText" expanded="false"> |
|||
<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="drag_accept_files">0</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">Units:</property> |
|||
<property name="markup">0</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_lblUnits</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> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALIGN_RIGHT|wxALL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxChoice" expanded="false"> |
|||
<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">"Millimeters" "Inches"</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="drag_accept_files">0</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="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_choiceUnits</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">130,30</property> |
|||
<property name="style"></property> |
|||
<property name="subclass">; ; forward_declare</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> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStaticText" expanded="false"> |
|||
<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="drag_accept_files">0</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="markup">0</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_lblPrecision</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">The number of values following the decimal separator</property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<property name="wrap">-1</property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALIGN_RIGHT|wxALL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxSpinCtrl" expanded="false"> |
|||
<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="drag_accept_files">0</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="initial">7</property> |
|||
<property name="max">16</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min">2</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_precision</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">130,30</property> |
|||
<property name="style">wxSP_ARROW_KEYS</property> |
|||
<property name="subclass"></property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip">The number of values following the decimal separator</property> |
|||
<property name="value"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxCheckBox" expanded="false"> |
|||
<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="checked">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="drag_accept_files">0</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">Compress output</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_cbCompress</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">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip">Compress output into 'zip' file</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="OnCheckBox">onCompressCheck</event> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxEXPAND</property> |
|||
<property name="proportion">1</property> |
|||
<object class="spacer" expanded="false"> |
|||
<property name="height">0</property> |
|||
<property name="permission">protected</property> |
|||
<property name="width">0</property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="false"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL|wxEXPAND</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStdDialogButtonSizer" expanded="false"> |
|||
<property name="Apply">0</property> |
|||
<property name="Cancel">1</property> |
|||
<property name="ContextHelp">0</property> |
|||
<property name="Help">0</property> |
|||
<property name="No">0</property> |
|||
<property name="OK">1</property> |
|||
<property name="Save">0</property> |
|||
<property name="Yes">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">m_stdButtons</property> |
|||
<property name="permission">protected</property> |
|||
<event name="OnOKButtonClick">onOKClick</event> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</wxFormBuilder_Project> |
@ -0,0 +1,56 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 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 as published by the |
|||
* Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
#ifndef ODBPP_EXPORT_DIALOG_H |
|||
#define ODBPP_EXPORT_DIALOG_H |
|||
#include "dialog_export_odbpp_base.h" |
|||
|
|||
class PCB_EDIT_FRAME; |
|||
|
|||
class DIALOG_EXPORT_ODBPP : public DIALOG_EXPORT_ODBPP_BASE |
|||
{ |
|||
public: |
|||
DIALOG_EXPORT_ODBPP( PCB_EDIT_FRAME* aParent ); |
|||
|
|||
wxString GetOutputPath() const { return m_outputFileName->GetValue(); } |
|||
|
|||
wxString GetUnitsString() const |
|||
{ |
|||
if( m_choiceUnits->GetSelection() == 0 ) |
|||
return wxT( "mm" ); |
|||
else |
|||
return wxT( "inch" ); |
|||
} |
|||
|
|||
wxString GetPrecision() const { return wxString::Format( "%d", m_precision->GetValue() ); } |
|||
|
|||
|
|||
bool GetCompress() const { return m_cbCompress->GetValue(); } |
|||
|
|||
private: |
|||
void onBrowseClicked( wxCommandEvent& event ) override; |
|||
void onOKClick( wxCommandEvent& event ) override; |
|||
|
|||
bool Init(); |
|||
bool TransferDataFromWindow() override; |
|||
|
|||
PCB_EDIT_FRAME* m_parent; |
|||
}; |
|||
|
|||
#endif // ODBPP_EXPORT_DIALOG_H |
@ -0,0 +1,117 @@ |
|||
///////////////////////////////////////////////////////////////////////////
|
|||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
|||
// http://www.wxformbuilder.org/
|
|||
//
|
|||
// PLEASE DO *NOT* EDIT THIS FILE!
|
|||
///////////////////////////////////////////////////////////////////////////
|
|||
|
|||
#include "widgets/std_bitmap_button.h"
|
|||
|
|||
#include "dialog_export_odbpp_base.h"
|
|||
|
|||
///////////////////////////////////////////////////////////////////////////
|
|||
|
|||
DIALOG_EXPORT_ODBPP_BASE::DIALOG_EXPORT_ODBPP_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* bMainSizer; |
|||
bMainSizer = new wxBoxSizer( wxVERTICAL ); |
|||
|
|||
bSizerTop = new wxBoxSizer( wxHORIZONTAL ); |
|||
|
|||
m_lblBrdFile = new wxStaticText( this, wxID_ANY, _("File:"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_lblBrdFile->Wrap( -1 ); |
|||
bSizerTop->Add( m_lblBrdFile, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); |
|||
|
|||
m_outputFileName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_outputFileName->SetToolTip( _("Enter a filename if you do not want to use default file names\nCan be used only when printing the current sheet") ); |
|||
m_outputFileName->SetMinSize( wxSize( 350,-1 ) ); |
|||
|
|||
bSizerTop->Add( m_outputFileName, 1, wxALIGN_CENTER_VERTICAL, 5 ); |
|||
|
|||
m_browseButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); |
|||
bSizerTop->Add( m_browseButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); |
|||
|
|||
|
|||
bMainSizer->Add( bSizerTop, 0, wxBOTTOM|wxEXPAND|wxTOP, 15 ); |
|||
|
|||
wxBoxSizer* bSizer3; |
|||
bSizer3 = new wxBoxSizer( wxHORIZONTAL ); |
|||
|
|||
wxStaticBoxSizer* sbSizer1; |
|||
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("File Format") ), wxVERTICAL ); |
|||
|
|||
wxFlexGridSizer* fgSizer; |
|||
fgSizer = new wxFlexGridSizer( 0, 2, 0, 0 ); |
|||
fgSizer->AddGrowableCol( 1 ); |
|||
fgSizer->SetFlexibleDirection( wxBOTH ); |
|||
fgSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); |
|||
|
|||
m_lblUnits = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Units:"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_lblUnits->Wrap( -1 ); |
|||
fgSizer->Add( m_lblUnits, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); |
|||
|
|||
wxString m_choiceUnitsChoices[] = { _("Millimeters"), _("Inches") }; |
|||
int m_choiceUnitsNChoices = sizeof( m_choiceUnitsChoices ) / sizeof( wxString ); |
|||
m_choiceUnits = new wxChoice( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( 130,30 ), m_choiceUnitsNChoices, m_choiceUnitsChoices, 0 ); |
|||
m_choiceUnits->SetSelection( 0 ); |
|||
fgSizer->Add( m_choiceUnits, 0, wxALIGN_RIGHT|wxALL, 5 ); |
|||
|
|||
m_lblPrecision = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Precision:"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_lblPrecision->Wrap( -1 ); |
|||
m_lblPrecision->SetToolTip( _("The number of values following the decimal separator") ); |
|||
|
|||
fgSizer->Add( m_lblPrecision, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); |
|||
|
|||
m_precision = new wxSpinCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 130,30 ), wxSP_ARROW_KEYS, 2, 16, 3 ); |
|||
m_precision->SetToolTip( _("The number of values following the decimal separator") ); |
|||
|
|||
fgSizer->Add( m_precision, 0, wxALIGN_RIGHT|wxALL, 5 ); |
|||
|
|||
m_cbCompress = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Compress output"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_cbCompress->SetToolTip( _("Compress output into 'zip' file") ); |
|||
|
|||
fgSizer->Add( m_cbCompress, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 ); |
|||
|
|||
|
|||
sbSizer1->Add( fgSizer, 3, wxEXPAND|wxALL, 5 ); |
|||
|
|||
|
|||
bSizer3->Add( sbSizer1, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 10 ); |
|||
|
|||
|
|||
bMainSizer->Add( bSizer3, 0, wxEXPAND, 5 ); |
|||
|
|||
|
|||
bMainSizer->Add( 0, 0, 1, wxEXPAND, 5 ); |
|||
|
|||
m_stdButtons = new wxStdDialogButtonSizer(); |
|||
m_stdButtonsOK = new wxButton( this, wxID_OK ); |
|||
m_stdButtons->AddButton( m_stdButtonsOK ); |
|||
m_stdButtonsCancel = new wxButton( this, wxID_CANCEL ); |
|||
m_stdButtons->AddButton( m_stdButtonsCancel ); |
|||
m_stdButtons->Realize(); |
|||
|
|||
bMainSizer->Add( m_stdButtons, 0, wxALL|wxEXPAND, 5 ); |
|||
|
|||
|
|||
this->SetSizer( bMainSizer ); |
|||
this->Layout(); |
|||
|
|||
this->Centre( wxBOTH ); |
|||
|
|||
// Connect Events
|
|||
m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onBrowseClicked ), NULL, this ); |
|||
m_cbCompress->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onCompressCheck ), NULL, this ); |
|||
m_stdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onOKClick ), NULL, this ); |
|||
} |
|||
|
|||
DIALOG_EXPORT_ODBPP_BASE::~DIALOG_EXPORT_ODBPP_BASE() |
|||
{ |
|||
// Disconnect Events
|
|||
m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onBrowseClicked ), NULL, this ); |
|||
m_cbCompress->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onCompressCheck ), NULL, this ); |
|||
m_stdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onOKClick ), NULL, this ); |
|||
|
|||
} |
@ -0,0 +1,72 @@ |
|||
/////////////////////////////////////////////////////////////////////////// |
|||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf) |
|||
// http://www.wxformbuilder.org/ |
|||
// |
|||
// PLEASE DO *NOT* EDIT THIS FILE! |
|||
/////////////////////////////////////////////////////////////////////////// |
|||
|
|||
#pragma once |
|||
|
|||
#include <wx/artprov.h> |
|||
#include <wx/xrc/xmlres.h> |
|||
#include <wx/intl.h> |
|||
class STD_BITMAP_BUTTON; |
|||
|
|||
#include "dialog_shim.h" |
|||
#include <wx/string.h> |
|||
#include <wx/stattext.h> |
|||
#include <wx/gdicmn.h> |
|||
#include <wx/font.h> |
|||
#include <wx/colour.h> |
|||
#include <wx/settings.h> |
|||
#include <wx/textctrl.h> |
|||
#include <wx/bmpbuttn.h> |
|||
#include <wx/bitmap.h> |
|||
#include <wx/image.h> |
|||
#include <wx/icon.h> |
|||
#include <wx/button.h> |
|||
#include <wx/sizer.h> |
|||
#include <wx/choice.h> |
|||
#include <wx/spinctrl.h> |
|||
#include <wx/checkbox.h> |
|||
#include <wx/statbox.h> |
|||
#include <wx/dialog.h> |
|||
|
|||
/////////////////////////////////////////////////////////////////////////// |
|||
|
|||
|
|||
/////////////////////////////////////////////////////////////////////////////// |
|||
/// Class DIALOG_EXPORT_ODBPP_BASE |
|||
/////////////////////////////////////////////////////////////////////////////// |
|||
class DIALOG_EXPORT_ODBPP_BASE : public DIALOG_SHIM |
|||
{ |
|||
private: |
|||
|
|||
protected: |
|||
wxBoxSizer* bSizerTop; |
|||
wxStaticText* m_lblBrdFile; |
|||
wxTextCtrl* m_outputFileName; |
|||
STD_BITMAP_BUTTON* m_browseButton; |
|||
wxStaticText* m_lblUnits; |
|||
wxChoice* m_choiceUnits; |
|||
wxStaticText* m_lblPrecision; |
|||
wxSpinCtrl* m_precision; |
|||
wxCheckBox* m_cbCompress; |
|||
wxStdDialogButtonSizer* m_stdButtons; |
|||
wxButton* m_stdButtonsOK; |
|||
wxButton* m_stdButtonsCancel; |
|||
|
|||
// Virtual event handlers, override them in your derived class |
|||
virtual void onBrowseClicked( wxCommandEvent& event ) { event.Skip(); } |
|||
virtual void onCompressCheck( wxCommandEvent& event ) { event.Skip(); } |
|||
virtual void onOKClick( wxCommandEvent& event ) { event.Skip(); } |
|||
|
|||
|
|||
public: |
|||
|
|||
DIALOG_EXPORT_ODBPP_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Export ODB++"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 380,300 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); |
|||
|
|||
~DIALOG_EXPORT_ODBPP_BASE(); |
|||
|
|||
}; |
|||
|
@ -0,0 +1,38 @@ |
|||
# This program source code file is part of KiCad, a free EDA CAD application. |
|||
# |
|||
# Copyright (C) 2024 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
# Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
# |
|||
# 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
|
|||
# Sources for the pcbnew pcb_io called ODB++ |
|||
|
|||
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) |
|||
|
|||
|
|||
set( ODBPP_SRCS |
|||
odb_util.cpp |
|||
odb_attribute.cpp |
|||
odb_feature.cpp |
|||
odb_component.cpp |
|||
odb_netlist.cpp |
|||
odb_eda_data.cpp |
|||
odb_fonts.cpp |
|||
odb_entity.cpp |
|||
pcb_io_odbpp.cpp |
|||
) |
|||
|
|||
add_library( odbpp STATIC ${ODBPP_SRCS} ) |
|||
|
|||
target_link_libraries( odbpp pcbcommon ) |
@ -0,0 +1,101 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include "odb_attribute.h"
|
|||
#include <sstream>
|
|||
#include <iomanip>
|
|||
|
|||
|
|||
size_t ATTR_MANAGER::GetTextIndex( std::unordered_map<std::string, size_t>& aMap, |
|||
std::vector<std::pair<size_t, std::string>>& aVec, |
|||
const std::string& aText ) |
|||
{ |
|||
if( aMap.count( aText ) ) |
|||
{ |
|||
return aMap.at( aText ); |
|||
} |
|||
else |
|||
{ |
|||
auto index = aMap.size(); |
|||
aMap.emplace( aText, index ); |
|||
aVec.emplace_back( index, aText ); |
|||
|
|||
return index; |
|||
} |
|||
} |
|||
|
|||
|
|||
size_t ATTR_MANAGER::GetAttrNameNumber( const wxString& aName ) |
|||
{ |
|||
return GetTextIndex( m_attrNames, m_attrNameVec, aName.Lower().ToStdString() ); |
|||
} |
|||
|
|||
|
|||
size_t ATTR_MANAGER::GetAttrTextNumber( const wxString& aText ) |
|||
{ |
|||
return GetTextIndex( m_attrTexts, m_attrTextVec, aText.Upper().ToStdString() ); |
|||
} |
|||
|
|||
|
|||
void ATTR_RECORD_WRITER::WriteAttributes( std::ostream& ost ) const |
|||
{ |
|||
ODB::CHECK_ONCE once; |
|||
|
|||
for( const auto& attr : attributes ) |
|||
{ |
|||
if( once() ) |
|||
ost << ";"; |
|||
else |
|||
ost << ","; |
|||
ost << attr.first; |
|||
if( attr.second.size() ) |
|||
ost << "=" << attr.second; |
|||
} |
|||
|
|||
ost << ";"; |
|||
} |
|||
|
|||
|
|||
void ATTR_MANAGER::WriteAttributesName( std::ostream& ost, const std::string& prefix ) const |
|||
{ |
|||
for( const auto& [n, name] : m_attrNameVec ) |
|||
{ |
|||
ost << prefix << "@" << n << " " << name << std::endl; |
|||
} |
|||
} |
|||
|
|||
|
|||
void ATTR_MANAGER::WriteAttributesText( std::ostream& ost, const std::string& prefix ) const |
|||
{ |
|||
for( const auto& [n, name] : m_attrTextVec ) |
|||
{ |
|||
ost << prefix << "&" << n << " " << name << std::endl; |
|||
} |
|||
} |
|||
|
|||
|
|||
void ATTR_MANAGER::WriteAttributes( std::ostream& ost, const std::string& prefix ) const |
|||
{ |
|||
ost << std::endl << "#\n#Feature attribute names\n#" << std::endl; |
|||
WriteAttributesName( ost ); |
|||
|
|||
ost << std::endl << "#\n#Feature attribute text strings\n#" << std::endl; |
|||
WriteAttributesText( ost ); |
|||
} |
@ -0,0 +1,352 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
#ifndef _ATTRIBUTE_PROVIDER_H_ |
|||
#define _ATTRIBUTE_PROVIDER_H_ |
|||
|
|||
#include "odb_util.h" |
|||
#include "stroke_params.h" |
|||
#include <wx/string.h> |
|||
#include <string> |
|||
#include <type_traits> |
|||
|
|||
|
|||
namespace ODB_ATTR |
|||
{ |
|||
|
|||
enum class TYPE |
|||
{ |
|||
FLOAT, |
|||
BOOLEAN, |
|||
TEXT, |
|||
OPTION, |
|||
INTEGER |
|||
}; |
|||
|
|||
// Base class template for attributes |
|||
template <typename T, TYPE AttrType> |
|||
struct AttributeBase |
|||
{ |
|||
using ValueType = T; |
|||
static constexpr TYPE type = AttrType; |
|||
constexpr AttributeBase( T v ) : value( v ) {} |
|||
T value; |
|||
}; |
|||
|
|||
// Specialized attribute types |
|||
template <typename T, unsigned int N> |
|||
struct FloatAttribute : AttributeBase<double, TYPE::FLOAT> |
|||
{ |
|||
static constexpr unsigned int digits = N; |
|||
using AttributeBase<double, TYPE::FLOAT>::AttributeBase; |
|||
}; |
|||
|
|||
template <typename T> |
|||
struct BooleanAttribute : AttributeBase<bool, TYPE::BOOLEAN> |
|||
{ |
|||
using AttributeBase<bool, TYPE::BOOLEAN>::AttributeBase; |
|||
}; |
|||
|
|||
template <typename T> |
|||
struct TextAttribute : AttributeBase<std::string, TYPE::TEXT> |
|||
{ |
|||
constexpr TextAttribute( const std::string& t ) : |
|||
AttributeBase<std::string, TYPE::TEXT>( ODB::GenLegalEntityName( t ).ToStdString() ) |
|||
{ |
|||
} |
|||
}; |
|||
|
|||
template <typename T> |
|||
struct OPTION_Attribute : AttributeBase<int, TYPE::OPTION> |
|||
{ |
|||
using AttributeBase<int, TYPE::OPTION>::AttributeBase; |
|||
}; |
|||
|
|||
|
|||
template <typename T> |
|||
struct AttributeName |
|||
{ |
|||
}; |
|||
|
|||
// Attribute name and type definitions |
|||
template <typename Tag, template <typename, unsigned int> class Attr, TYPE AttrType, unsigned int N> |
|||
struct Attribute |
|||
{ |
|||
using TYPE = Attr<Tag, N>; |
|||
}; |
|||
|
|||
template <typename Tag, template <typename> class Attr, TYPE AttrType> |
|||
struct AttributeSimple |
|||
{ |
|||
using TYPE = Attr<Tag>; |
|||
}; |
|||
|
|||
// TYPE traits for attributes |
|||
template <typename T> |
|||
struct IsFeature : std::false_type |
|||
{ |
|||
}; |
|||
template <typename T> |
|||
struct IsNet : std::false_type |
|||
{ |
|||
}; |
|||
template <typename T> |
|||
struct IsPkg : std::false_type |
|||
{ |
|||
}; |
|||
template <typename T> |
|||
struct IsLayer : std::false_type |
|||
{ |
|||
}; |
|||
template <typename T> |
|||
struct IsStep : std::false_type |
|||
{ |
|||
}; |
|||
template <typename T> |
|||
struct IsComp : std::false_type |
|||
{ |
|||
}; |
|||
template <typename T> |
|||
struct IsProductModel : std::false_type |
|||
{ |
|||
}; |
|||
template <typename T> |
|||
struct IsSymbol : std::false_type |
|||
{ |
|||
}; |
|||
|
|||
|
|||
#define DEFINE_ATTR( Tag, Attr, AttrType, AttrName, ... ) \ |
|||
struct Tag##_t \ |
|||
{ \ |
|||
}; \ |
|||
constexpr const char Tag##_name[] = AttrName; \ |
|||
using Tag = Attribute<Tag##_t, Attr, AttrType, __VA_ARGS__>::TYPE; \ |
|||
template <> \ |
|||
struct AttributeName<Tag> \ |
|||
{ \ |
|||
static constexpr const char* name = Tag##_name; \ |
|||
}; |
|||
|
|||
#define DEFINE_ATTR_SIMPLE( Tag, Attr, AttrType, AttrName ) \ |
|||
struct Tag##_t \ |
|||
{ \ |
|||
}; \ |
|||
constexpr const char Tag##_name[] = AttrName; \ |
|||
using Tag = AttributeSimple<Tag##_t, Attr, AttrType>::TYPE; \ |
|||
template <> \ |
|||
struct AttributeName<Tag> \ |
|||
{ \ |
|||
static constexpr const char* name = Tag##_name; \ |
|||
}; |
|||
|
|||
|
|||
#define DEFINE_FLOAT_ATTR( NAME, N ) DEFINE_ATTR( NAME, FloatAttribute, TYPE::FLOAT, #NAME, N ) |
|||
|
|||
#define DEFINE_BOOLEAN_ATTR( NAME ) \ |
|||
DEFINE_ATTR_SIMPLE( NAME, BooleanAttribute, TYPE::BOOLEAN, #NAME ) |
|||
|
|||
#define DEFINE_TEXT_ATTR( NAME ) DEFINE_ATTR_SIMPLE( NAME, TextAttribute, TYPE::TEXT, #NAME ) |
|||
|
|||
#define DEFINE_OPTION_ATTR( NAME ) \ |
|||
struct NAME##_t \ |
|||
{ \ |
|||
}; \ |
|||
template <> \ |
|||
struct AttributeSimple<NAME##_t, OPTION_Attribute, TYPE::OPTION>; \ |
|||
template <> \ |
|||
struct AttributeName<NAME> \ |
|||
{ \ |
|||
static constexpr const char* name = #NAME; \ |
|||
}; |
|||
|
|||
|
|||
// used by which entity |
|||
#define USED_BY_FEATURE_ENTITY( NAME ) \ |
|||
template <> \ |
|||
struct IsFeature<NAME> : std::true_type \ |
|||
{ \ |
|||
}; |
|||
|
|||
#define USED_BY_NET_ENTITY( NAME ) \ |
|||
template <> \ |
|||
struct IsNet<NAME> : std::true_type \ |
|||
{ \ |
|||
}; |
|||
|
|||
#define USED_BY_PKG_ENTITY( NAME ) \ |
|||
template <> \ |
|||
struct IsPkg<NAME> : std::true_type \ |
|||
{ \ |
|||
}; |
|||
|
|||
// Attribute definitions |
|||
// BOOLEAN ATTRIBUTES |
|||
DEFINE_BOOLEAN_ATTR( SMD ) |
|||
USED_BY_FEATURE_ENTITY( SMD ) |
|||
|
|||
DEFINE_BOOLEAN_ATTR( NET_POINT ) |
|||
USED_BY_FEATURE_ENTITY( NET_POINT ) |
|||
|
|||
DEFINE_BOOLEAN_ATTR( ROUT_PLATED ) |
|||
USED_BY_FEATURE_ENTITY( ROUT_PLATED ) |
|||
|
|||
DEFINE_BOOLEAN_ATTR( MECHANICAL ) |
|||
|
|||
DEFINE_BOOLEAN_ATTR( MOUNT_HOLE ) |
|||
USED_BY_FEATURE_ENTITY( MOUNT_HOLE ) |
|||
|
|||
DEFINE_BOOLEAN_ATTR( TEAR_DROP ) |
|||
USED_BY_FEATURE_ENTITY( TEAR_DROP ) |
|||
|
|||
DEFINE_BOOLEAN_ATTR( TEST_POINT ) |
|||
USED_BY_FEATURE_ENTITY( TEST_POINT ) |
|||
|
|||
// TEXT ATTRIBUTES |
|||
DEFINE_TEXT_ATTR( STRING ) |
|||
USED_BY_FEATURE_ENTITY( STRING ) |
|||
|
|||
DEFINE_TEXT_ATTR( GEOMETRY ) |
|||
USED_BY_FEATURE_ENTITY( GEOMETRY ) |
|||
|
|||
DEFINE_TEXT_ATTR( NET_NAME ) |
|||
USED_BY_FEATURE_ENTITY( NET_NAME ) |
|||
|
|||
|
|||
// FLOAT ATTRIBUTES |
|||
DEFINE_FLOAT_ATTR( BOARD_THICKNESS, 1 ) // 0.0~10.0 |
|||
|
|||
DEFINE_FLOAT_ATTR( STRING_ANGLE, 1 ) // 0.0~360.0 |
|||
USED_BY_FEATURE_ENTITY( STRING_ANGLE ) |
|||
|
|||
|
|||
// OPTION ATTRIBUTES |
|||
enum class DRILL |
|||
{ |
|||
PLATED, |
|||
NON_PLATED, |
|||
VIA |
|||
}; |
|||
DEFINE_OPTION_ATTR( DRILL ) |
|||
USED_BY_FEATURE_ENTITY( DRILL ) |
|||
|
|||
enum class PAD_USAGE |
|||
{ |
|||
TOEPRINT, |
|||
VIA, |
|||
G_FIDUCIAL, |
|||
L_FIDUCIAL, |
|||
TOOLING_HOLE, |
|||
BOND_FINGER |
|||
}; |
|||
DEFINE_OPTION_ATTR( PAD_USAGE ) |
|||
USED_BY_FEATURE_ENTITY( PAD_USAGE ) |
|||
|
|||
enum class PLATED_TYPE |
|||
{ |
|||
STANDARD, |
|||
PRESS_FIT |
|||
}; |
|||
DEFINE_OPTION_ATTR( PLATED_TYPE ) |
|||
USED_BY_FEATURE_ENTITY( PLATED_TYPE ) |
|||
|
|||
enum class VIA_TYPE |
|||
{ |
|||
DRILLED, |
|||
LASER, |
|||
PHOTO |
|||
}; |
|||
DEFINE_OPTION_ATTR( VIA_TYPE ) |
|||
USED_BY_FEATURE_ENTITY( VIA_TYPE ) |
|||
|
|||
} // namespace ODB_ATTR |
|||
|
|||
|
|||
class ATTR_MANAGER |
|||
{ |
|||
public: |
|||
ATTR_MANAGER() = default; |
|||
virtual ~ATTR_MANAGER() = default; |
|||
|
|||
template <typename Tr, typename Ta> |
|||
void AddFeatureAttribute( Tr& r, Ta v ) |
|||
{ |
|||
const auto id = GetAttrNameNumber( ODB_ATTR::AttributeName<Ta>::name ); |
|||
|
|||
if constexpr( std::is_enum_v<Ta> ) |
|||
r.attributes.emplace( id, std::to_string( static_cast<int>( v ) ) ); |
|||
else |
|||
r.attributes.emplace( id, AttrValue2String( v ) ); |
|||
} |
|||
|
|||
protected: |
|||
size_t GetAttrNameNumber( const wxString& name ); |
|||
|
|||
void WriteAttributes( std::ostream& ost, const std::string& prefix = "" ) const; |
|||
void WriteAttributesName( std::ostream& ost, const std::string& prefix = "" ) const; |
|||
void WriteAttributesText( std::ostream& ost, const std::string& prefix = "" ) const; |
|||
|
|||
|
|||
private: |
|||
size_t GetAttrTextNumber( const wxString& aName ); |
|||
size_t GetTextIndex( std::unordered_map<std::string, size_t>& aMap, |
|||
std::vector<std::pair<size_t, std::string>>& aVec, |
|||
const std::string& aText ); |
|||
|
|||
template <typename T, unsigned int n> |
|||
std::string AttrValue2String( ODB_ATTR::FloatAttribute<T, n> a ) |
|||
{ |
|||
return ODB::Double2String( a.value, a.digits ); |
|||
} |
|||
|
|||
template <typename T> |
|||
std::string AttrValue2String( ODB_ATTR::BooleanAttribute<T> a ) |
|||
{ |
|||
return ""; |
|||
} |
|||
|
|||
template <typename T> |
|||
std::string AttrValue2String( ODB_ATTR::TextAttribute<T> a ) |
|||
{ |
|||
return std::to_string( GetAttrTextNumber( a.value ) ); |
|||
} |
|||
|
|||
|
|||
std::unordered_map<std::string, size_t> m_attrNames; |
|||
std::vector<std::pair<size_t, std::string>> m_attrNameVec; |
|||
|
|||
std::unordered_map<std::string, size_t> m_attrTexts; |
|||
std::vector<std::pair<size_t, std::string>> m_attrTextVec; |
|||
}; |
|||
|
|||
class ATTR_RECORD_WRITER |
|||
{ |
|||
public: |
|||
ATTR_RECORD_WRITER() = default; |
|||
virtual ~ATTR_RECORD_WRITER() = default; |
|||
|
|||
void WriteAttributes( std::ostream& ost ) const; |
|||
|
|||
public: |
|||
std::map<unsigned int, std::string> attributes; |
|||
}; |
|||
|
|||
|
|||
#endif // ATTRIBUTE_PROVIDER_H_ |
@ -0,0 +1,94 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include "odb_component.h"
|
|||
#include "odb_util.h"
|
|||
#include "hash_eda.h"
|
|||
#include "pcb_io_odbpp.h"
|
|||
|
|||
|
|||
ODB_COMPONENT& COMPONENTS_MANAGER::AddComponent( const FOOTPRINT* aFp, |
|||
const EDA_DATA::PACKAGE& aPkg ) |
|||
{ |
|||
auto& comp = m_compList.emplace_back( m_compList.size(), aPkg.m_index ); |
|||
|
|||
comp.m_center = ODB::AddXY( aFp->GetPosition() ); |
|||
|
|||
if( aFp->GetOrientation() != ANGLE_0 ) |
|||
{ |
|||
// odb Rotation is expressed in degrees and is always clockwise.
|
|||
// while kicad EDA_ANGLE is anticlockwise.
|
|||
|
|||
comp.m_rot = |
|||
ODB::Double2String( ( ANGLE_360 - aFp->GetOrientation() ).Normalize().AsDegrees() ); |
|||
} |
|||
|
|||
if( aFp->GetLayer() != F_Cu ) |
|||
{ |
|||
comp.m_mirror = wxT( "M" ); |
|||
} |
|||
|
|||
comp.m_comp_name = aFp->GetReference().ToAscii(); |
|||
comp.m_part_name = |
|||
wxString::Format( "%s_%s_%s", aFp->GetFPID().GetFullLibraryName(), |
|||
aFp->GetFPID().GetLibItemName().wx_str(), aFp->GetValue() ); |
|||
|
|||
return comp; |
|||
} |
|||
|
|||
|
|||
void COMPONENTS_MANAGER::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl; |
|||
|
|||
WriteAttributes( ost ); |
|||
|
|||
for( const auto& comp : m_compList ) |
|||
{ |
|||
comp.Write( ost ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_COMPONENT::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "# CMP " << m_index << std::endl; |
|||
ost << "CMP " << m_pkg_ref << " " << m_center.first << " " << m_center.second << " " << m_rot |
|||
<< " " << m_mirror << " " << m_comp_name << " " << m_part_name; |
|||
|
|||
WriteAttributes( ost ); |
|||
|
|||
ost << std::endl; |
|||
|
|||
for( const auto& toep : m_toeprints ) |
|||
{ |
|||
toep.Write( ost ); |
|||
} |
|||
|
|||
ost << "#" << std::endl; |
|||
} |
|||
|
|||
|
|||
void ODB_COMPONENT::TOEPRINT::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "TOP " << m_pin_num << " " << m_center.first << " " << m_center.second << " " << m_rot |
|||
<< " " << m_mirror << " " << m_net_num << " " << m_subnet_num << " " << m_toeprint_name |
|||
<< std::endl; |
|||
} |
@ -0,0 +1,99 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
|
|||
#ifndef _ODB_COMPONENT_H_ |
|||
#define _ODB_COMPONENT_H_ |
|||
|
|||
#include "odb_util.h" |
|||
#include <list> |
|||
#include <wx/string.h> |
|||
#include "odb_attribute.h" |
|||
#include "odb_eda_data.h" |
|||
|
|||
class ODB_COMPONENT; |
|||
class COMPONENTS_MANAGER : public ATTR_MANAGER |
|||
{ |
|||
public: |
|||
COMPONENTS_MANAGER() = default; |
|||
|
|||
virtual ~COMPONENTS_MANAGER() { m_compList.clear(); } |
|||
|
|||
ODB_COMPONENT& AddComponent( const FOOTPRINT* aFp, const EDA_DATA::PACKAGE& aPkg ); |
|||
|
|||
void Write( std::ostream& ost ) const; |
|||
|
|||
private: |
|||
std::list<ODB_COMPONENT> m_compList; |
|||
}; |
|||
|
|||
|
|||
class ODB_COMPONENT : public ATTR_RECORD_WRITER |
|||
{ |
|||
public: |
|||
ODB_COMPONENT( size_t aIndex, size_t r ) : m_index( aIndex ), m_pkg_ref( r ) {} |
|||
|
|||
const size_t m_index; ///<! CMP index number on board to be used in SNT(TOP), 0~n-1 |
|||
size_t m_pkg_ref; ///<! package ref number from PKG in eda/data file, 0~n-1 |
|||
std::pair<wxString, wxString> m_center; |
|||
wxString m_rot = wxT( "0" ); |
|||
wxString m_mirror = wxT( "N" ); |
|||
|
|||
wxString m_comp_name; ///<! Unique reference designator (component name) |
|||
|
|||
wxString |
|||
m_part_name; ///<! Part identification is a single string of ASCII characters without spaces |
|||
|
|||
std::vector<std::pair<wxString, wxString>> m_prp; // !< Component Property Record |
|||
|
|||
struct TOEPRINT |
|||
{ |
|||
public: |
|||
TOEPRINT( const EDA_DATA::PIN& pin ) : |
|||
m_pin_num( pin.m_index ), m_toeprint_name( pin.m_name ) |
|||
{ |
|||
} |
|||
|
|||
const size_t m_pin_num; ///<! index of PIN record in the eda/data file, 0~n-1. |
|||
|
|||
std::pair<wxString, wxString> m_center; ///<! Board location of the pin. |
|||
|
|||
wxString m_rot; ///<! Rotation, clockwise, it equals to the actual PAD rotation, |
|||
///<! not CMP m_rot. |
|||
|
|||
wxString m_mirror; ///<! equal to CMP m_mirror. |
|||
|
|||
size_t m_net_num = 0; ///<! Number of NET record in the eda/data file. |
|||
|
|||
size_t m_subnet_num = 0; ///<! Number of subnet (SNT record TOP) in the referenced net |
|||
|
|||
wxString m_toeprint_name; ///<! Name of the pad in PIN record |
|||
|
|||
void Write( std::ostream& ost ) const; |
|||
}; |
|||
|
|||
|
|||
std::list<TOEPRINT> m_toeprints; |
|||
|
|||
void Write( std::ostream& ost ) const; |
|||
}; |
|||
|
|||
|
|||
#endif // _ODB_COMPONENT_H_ |
@ -0,0 +1,34 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
|
|||
#ifndef _ODB_DEFINES_H_ |
|||
#define _ODB_DEFINES_H_ |
|||
|
|||
#include <string> |
|||
|
|||
#define ODB_JOB_NAME "JOB_NAME" |
|||
#define ODB_UNITS "UNITS" |
|||
#define ODB_DIM_X "x" |
|||
#define ODB_DIM_R "r" |
|||
#define ODB_DIM_C "c" |
|||
#define ODB_NONE "NONE" |
|||
|
|||
#endif // _ODB_DEFINES_H_ |
@ -0,0 +1,420 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include "odb_eda_data.h"
|
|||
#include "hash_eda.h"
|
|||
#include "netinfo.h"
|
|||
#include "odb_feature.h"
|
|||
#include "base_units.h"
|
|||
#include "pcb_io_odbpp.h"
|
|||
|
|||
|
|||
EDA_DATA::EDA_DATA() |
|||
{ |
|||
auto& x = nets_map.emplace( std::piecewise_construct, std::forward_as_tuple( 0 ), |
|||
std::forward_as_tuple( nets.size(), "$NONE$" ) ) |
|||
.first->second; |
|||
|
|||
nets.push_back( &x ); |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::NET::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "NET " << m_name; |
|||
|
|||
WriteAttributes( ost ); |
|||
|
|||
ost << std::endl; |
|||
|
|||
for( const auto& subnet : subnets ) |
|||
{ |
|||
subnet->Write( ost ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::AddNET( const NETINFO_ITEM* aNet ) |
|||
{ |
|||
if( nets_map.end() == nets_map.find( aNet->GetNetCode() ) ) |
|||
{ |
|||
auto& net = nets_map.emplace( std::piecewise_construct, |
|||
std::forward_as_tuple( aNet->GetNetCode() ), |
|||
std::forward_as_tuple( nets.size(), aNet->GetNetname() ) ) |
|||
.first->second; |
|||
|
|||
nets.push_back( &net ); |
|||
|
|||
//TODO: netname check
|
|||
} |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::SUB_NET::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "SNT "; |
|||
|
|||
WriteSubnet( ost ); |
|||
|
|||
ost << std::endl; |
|||
|
|||
for( const auto& fid : feature_ids ) |
|||
{ |
|||
fid.Write( ost ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::FEATURE_ID::Write( std::ostream& ost ) const |
|||
{ |
|||
static const std::map<TYPE, std::string> type_map = { |
|||
{ TYPE::COPPER, "C" }, |
|||
{ TYPE::HOLE, "H" }, |
|||
}; |
|||
|
|||
ost << "FID " << type_map.at( type ) << " " << layer << " " << feature_id << std::endl; |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::SUB_NET_VIA::WriteSubnet( std::ostream& ost ) const |
|||
{ |
|||
ost << "VIA"; |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::SUB_NET_TRACE::WriteSubnet( std::ostream& ost ) const |
|||
{ |
|||
ost << "TRC"; |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::SUB_NET_PLANE::WriteSubnet( std::ostream& ost ) const |
|||
{ |
|||
static const std::map<FILL_TYPE, std::string> fill_type_map = { { FILL_TYPE::SOLID, "S" }, |
|||
{ FILL_TYPE::OUTLINE, "O" } }; |
|||
|
|||
static const std::map<CUTOUT_TYPE, std::string> cutout_type_map = { |
|||
{ CUTOUT_TYPE::CIRCLE, "C" }, |
|||
{ CUTOUT_TYPE::RECT, "R" }, |
|||
{ CUTOUT_TYPE::OCTAGON, "O" }, |
|||
{ CUTOUT_TYPE::EXACT, "E" } |
|||
}; |
|||
|
|||
ost << "PLN " << fill_type_map.at( fill_type ) << " " << cutout_type_map.at( cutout_type ) |
|||
<< " " << fill_size; |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::SUB_NET_TOEPRINT::WriteSubnet( std::ostream& ost ) const |
|||
{ |
|||
static const std::map<SIDE, std::string> side_map = { |
|||
{ SIDE::BOTTOM, "B" }, |
|||
{ SIDE::TOP, "T" }, |
|||
}; |
|||
ost << "TOP " << side_map.at( side ) << " " << comp_num << " " << toep_num; |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::SUB_NET::AddFeatureID( FEATURE_ID::TYPE type, const wxString& layer, |
|||
size_t feature_id ) |
|||
{ |
|||
feature_ids.emplace_back( type, m_edadata->GetLyrIdx( layer ), feature_id ); |
|||
} |
|||
|
|||
|
|||
size_t EDA_DATA::GetLyrIdx( const wxString& aLayer ) |
|||
{ |
|||
if( layers_map.count( aLayer ) ) |
|||
{ |
|||
return layers_map.at( aLayer ); |
|||
} |
|||
else |
|||
{ |
|||
auto idx = layers_map.size(); |
|||
layers_map.emplace( aLayer, idx ); |
|||
layers.push_back( aLayer ); |
|||
return idx; |
|||
} |
|||
} |
|||
|
|||
|
|||
void OUTLINE_SQUARE::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "SQ " << ODB::Data2String( m_center.x ) << " " << ODB::Data2String( m_center.y ) << " " |
|||
<< ODB::Data2String( m_halfSide ) << std::endl; |
|||
} |
|||
|
|||
|
|||
void OUTLINE_CIRCLE::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "CR " << ODB::Data2String( m_center.x ) << " " << ODB::Data2String( m_center.y ) << " " |
|||
<< ODB::Data2String( m_radius ) << std::endl; |
|||
} |
|||
|
|||
|
|||
void OUTLINE_RECT::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "RC " << ODB::Data2String( m_lower_left.x ) << " " << ODB::Data2String( m_lower_left.y ) |
|||
<< " " << ODB::Data2String( m_width ) << " " << ODB::Data2String( m_height ) << std::endl; |
|||
} |
|||
|
|||
|
|||
void OUTLINE_CONTOUR::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "CT" << std::endl; |
|||
m_surfaces->WriteData( ost ); |
|||
ost << "CE" << std::endl; |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::AddPackage( const FOOTPRINT* aFp ) |
|||
{ |
|||
// ODBPP only need unique PACKAGE in PKG record in eda/data file.
|
|||
// the PKG index can repeat to be ref in CMP record in component file.
|
|||
|
|||
std::shared_ptr<FOOTPRINT> fp( static_cast<FOOTPRINT*>( aFp->Clone() ) ); |
|||
m_eda_footprints.emplace_back( fp ); |
|||
fp->SetParentGroup( nullptr ); |
|||
fp->SetPosition( { 0, 0 } ); |
|||
|
|||
if( fp->GetLayer() != F_Cu ) |
|||
fp->Flip( fp->GetPosition(), false ); |
|||
|
|||
fp->SetOrientation( ANGLE_0 ); |
|||
|
|||
size_t hash = hash_fp_item( fp.get(), HASH_POS | REL_COORD ); |
|||
size_t pkg_index = packages_map.size(); |
|||
wxString fp_name = fp->GetFPID().GetLibItemName().wx_str(); |
|||
|
|||
auto [iter, success] = packages_map.emplace( hash, PACKAGE( pkg_index, fp_name ) ); |
|||
|
|||
if( !success ) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
PACKAGE* pkg = &( iter->second ); |
|||
|
|||
packages.push_back( pkg ); |
|||
|
|||
BOX2I bbox = fp->GetBoundingBox(); |
|||
pkg->m_xmin = bbox.GetPosition().x; |
|||
pkg->m_ymin = bbox.GetPosition().y; |
|||
pkg->m_xmax = bbox.GetEnd().x; |
|||
pkg->m_ymax = bbox.GetEnd().y; |
|||
pkg->m_pitch = UINT64_MAX; |
|||
|
|||
if( fp->Pads().size() < 2 ) |
|||
pkg->m_pitch = pcbIUScale.mmToIU( 1.0 ); // placeholder value
|
|||
|
|||
for( size_t i = 0; i < fp->Pads().size(); ++i ) |
|||
{ |
|||
const PAD* pad1 = fp->Pads()[i]; |
|||
for( size_t j = i + 1; j < fp->Pads().size(); ++j ) |
|||
{ |
|||
const PAD* pad2 = fp->Pads()[j]; |
|||
const uint64_t pin_dist = ( pad1->GetCenter() - pad2->GetCenter() ).EuclideanNorm(); |
|||
pkg->m_pitch = std::min( pkg->m_pitch, pin_dist ); |
|||
} |
|||
} |
|||
|
|||
const SHAPE_POLY_SET& courtyard = fp->GetCourtyard( F_CrtYd ); |
|||
const SHAPE_POLY_SET& courtyard_back = fp->GetCourtyard( B_CrtYd ); |
|||
SHAPE_POLY_SET pkg_outline; |
|||
|
|||
if( courtyard.OutlineCount() > 0 ) |
|||
pkg_outline = courtyard; |
|||
|
|||
if( courtyard_back.OutlineCount() > 0 ) |
|||
{ |
|||
pkg_outline = courtyard_back; |
|||
} |
|||
|
|||
if( !courtyard.OutlineCount() && !courtyard_back.OutlineCount() ) |
|||
{ |
|||
pkg_outline = fp->GetBoundingHull(); |
|||
} |
|||
|
|||
// TODO: Here we put rect, square, and circle, all as polygon
|
|||
|
|||
if( pkg_outline.OutlineCount() > 0 ) |
|||
{ |
|||
for( int ii = 0; ii < pkg_outline.OutlineCount(); ++ii ) |
|||
{ |
|||
pkg->m_pkgOutlines.push_back( |
|||
std::make_unique<OUTLINE_CONTOUR>( pkg_outline.Polygon( ii ) ) ); |
|||
} |
|||
} |
|||
|
|||
for( size_t i = 0; i < fp->Pads().size(); ++i ) |
|||
{ |
|||
const PAD* pad = fp->Pads()[i]; |
|||
pkg->AddPin( pad, i ); |
|||
} |
|||
|
|||
return; |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::PACKAGE::AddPin( const PAD* aPad, size_t aPinNum ) |
|||
{ |
|||
wxString name = aPad->GetNumber(); |
|||
|
|||
// Pins are required to have names, so if our pad doesn't have a name, we need to
|
|||
// generate one that is unique
|
|||
|
|||
if( aPad->GetAttribute() == PAD_ATTRIB::NPTH ) |
|||
name = wxString::Format( "NPTH%zu", aPinNum ); |
|||
else if( name.empty() ) |
|||
name = wxString::Format( "PAD%zu", aPinNum ); |
|||
|
|||
// // for SNT record, pad, net, pin
|
|||
std::shared_ptr<PIN> pin = std::make_shared<PIN>( m_pinsVec.size(), name ); |
|||
m_pinsVec.push_back( pin ); |
|||
|
|||
VECTOR2D relpos = aPad->GetFPRelativePosition(); |
|||
|
|||
// TODO: is odb pkg pin center means center of pad hole or center of pad shape?
|
|||
|
|||
if( aPad->GetOffset().x != 0 || aPad->GetOffset().y != 0 ) |
|||
relpos += aPad->GetOffset(); |
|||
|
|||
pin->m_center = ODB::AddXY( relpos ); |
|||
|
|||
if( aPad->HasHole() ) |
|||
{ |
|||
pin->type = PIN::TYPE::THROUGH_HOLE; |
|||
} |
|||
else |
|||
{ |
|||
pin->type = PIN::TYPE::SURFACE; |
|||
} |
|||
|
|||
if( aPad->GetAttribute() == PAD_ATTRIB::NPTH ) |
|||
pin->etype = PIN::ELECTRICAL_TYPE::MECHANICAL; |
|||
else if( aPad->IsOnCopperLayer() ) |
|||
pin->etype = PIN::ELECTRICAL_TYPE::ELECTRICAL; |
|||
else |
|||
pin->etype = PIN::ELECTRICAL_TYPE::UNDEFINED; |
|||
|
|||
|
|||
if( ( aPad->HasHole() && aPad->IsOnCopperLayer() ) || aPad->GetAttribute() == PAD_ATTRIB::PTH ) |
|||
{ |
|||
pin->mtype = PIN::MOUNT_TYPE::THROUGH_HOLE; |
|||
} |
|||
else if( aPad->HasHole() && aPad->GetAttribute() == PAD_ATTRIB::NPTH ) |
|||
{ |
|||
pin->mtype = PIN::MOUNT_TYPE::HOLE; |
|||
} |
|||
else if( aPad->GetAttribute() == PAD_ATTRIB::SMD ) |
|||
{ |
|||
pin->mtype = PIN::MOUNT_TYPE::SMT; |
|||
} |
|||
else |
|||
{ |
|||
pin->mtype = PIN::MOUNT_TYPE::UNDEFINED; |
|||
} |
|||
|
|||
const std::shared_ptr<SHAPE_POLY_SET>& polygons = aPad->GetEffectivePolygon( ERROR_INSIDE ); |
|||
|
|||
// TODO: Here we put all pad shapes as polygonl, we should switch by pad shape
|
|||
// Note:pad only use polygons->Polygon(0),
|
|||
if( polygons->OutlineCount() > 0 ) |
|||
{ |
|||
pin->m_pinOutlines.push_back( std::make_unique<OUTLINE_CONTOUR>( polygons->Polygon( 0 ) ) ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::PIN::Write( std::ostream& ost ) const |
|||
{ |
|||
static const std::map<TYPE, std::string> type_map = { { TYPE::SURFACE, "S" }, |
|||
{ TYPE::THROUGH_HOLE, "T" }, |
|||
{ TYPE::BLIND, "B" } }; |
|||
|
|||
static const std::map<ELECTRICAL_TYPE, std::string> etype_map = { |
|||
{ ELECTRICAL_TYPE::ELECTRICAL, "E" }, |
|||
{ ELECTRICAL_TYPE::MECHANICAL, "M" }, |
|||
{ ELECTRICAL_TYPE::UNDEFINED, "U" } |
|||
}; |
|||
static const std::map<MOUNT_TYPE, std::string> mtype_map = { { MOUNT_TYPE::THROUGH_HOLE, "T" }, |
|||
{ MOUNT_TYPE::HOLE, "H" }, |
|||
{ MOUNT_TYPE::SMT, "S" }, |
|||
{ MOUNT_TYPE::UNDEFINED, "U" } }; |
|||
|
|||
ost << "PIN " << m_name << " " << type_map.at( type ) << " " << m_center.first << " " |
|||
<< m_center.second << " 0 " << etype_map.at( etype ) << " " << mtype_map.at( mtype ) |
|||
<< std::endl; |
|||
|
|||
for( const auto& outline : m_pinOutlines ) |
|||
{ |
|||
outline->Write( ost ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::PACKAGE::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "PKG " << m_name << " " << ODB::Data2String( m_pitch ) << " " |
|||
<< ODB::Data2String( m_xmin ) << " " << ODB::Data2String( m_ymin ) << " " |
|||
<< ODB::Data2String( m_xmax ) << " " << ODB::Data2String( m_ymax ) << std::endl; |
|||
|
|||
for( const auto& outline : m_pkgOutlines ) |
|||
{ |
|||
outline->Write( ost ); |
|||
} |
|||
|
|||
for( const auto& pin : m_pinsVec ) |
|||
{ |
|||
pin->Write( ost ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void EDA_DATA::Write( std::ostream& ost ) const |
|||
{ |
|||
ost << "# " << wxDateTime::Now().FormatISOCombined() << std::endl; |
|||
ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl; |
|||
ost << "LYR"; |
|||
|
|||
for( const auto& layer : layers ) |
|||
{ |
|||
ost << " " << layer; |
|||
} |
|||
|
|||
ost << std::endl; |
|||
|
|||
WriteAttributes( ost, "#" ); |
|||
|
|||
for( const auto& net : nets ) |
|||
{ |
|||
ost << "#NET " << net->m_index << std::endl; |
|||
net->Write( ost ); |
|||
} |
|||
|
|||
size_t i = 0; |
|||
for( const auto* pkg : packages ) |
|||
{ |
|||
ost << "# PKG " << i << std::endl; |
|||
i++; |
|||
pkg->Write( ost ); |
|||
ost << "#" << std::endl; |
|||
} |
|||
} |
@ -0,0 +1,340 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
#ifndef _ODB_EDA_DATA_H_ |
|||
#define _ODB_EDA_DATA_H_ |
|||
|
|||
|
|||
#include <list> |
|||
#include <memory> |
|||
|
|||
#include "odb_attribute.h" |
|||
#include "odb_feature.h" |
|||
|
|||
|
|||
class PKG_OUTLINE; |
|||
class EDA_DATA : public ATTR_MANAGER |
|||
{ |
|||
public: |
|||
EDA_DATA(); |
|||
|
|||
void Write( std::ostream& ost ) const; |
|||
size_t GetLyrIdx( const wxString& aLayerName ); |
|||
std::vector<std::shared_ptr<FOOTPRINT>> GetEdaFootprints() const { return m_eda_footprints; } |
|||
|
|||
class FEATURE_ID |
|||
{ |
|||
friend EDA_DATA; |
|||
|
|||
public: |
|||
enum class TYPE |
|||
{ |
|||
COPPER, |
|||
LAMINATE, |
|||
HOLE |
|||
}; |
|||
|
|||
FEATURE_ID( TYPE t, size_t l, size_t fid ) : type( t ), layer( l ), feature_id( fid ) {} |
|||
|
|||
TYPE type; |
|||
size_t layer; |
|||
size_t feature_id; |
|||
|
|||
void Write( std::ostream& ost ) const; |
|||
}; |
|||
|
|||
class SUB_NET |
|||
{ |
|||
public: |
|||
SUB_NET( size_t aIndex, EDA_DATA* aEda ) : m_index( aIndex ), m_edadata( aEda ) {} |
|||
const size_t m_index; |
|||
void Write( std::ostream& ost ) const; |
|||
|
|||
std::list<FEATURE_ID> feature_ids; |
|||
void AddFeatureID( FEATURE_ID::TYPE type, const wxString& layer, size_t feature_id ); |
|||
|
|||
virtual ~SUB_NET() {} |
|||
|
|||
protected: |
|||
virtual void WriteSubnet( std::ostream& ost ) const = 0; |
|||
EDA_DATA* m_edadata; |
|||
}; |
|||
|
|||
class SUB_NET_VIA : public SUB_NET |
|||
{ |
|||
public: |
|||
SUB_NET_VIA( size_t aIndex, EDA_DATA* aEda ) : SUB_NET( aIndex, aEda ) {} |
|||
void WriteSubnet( std::ostream& ost ) const override; |
|||
}; |
|||
|
|||
class SUB_NET_TRACE : public SUB_NET |
|||
{ |
|||
public: |
|||
SUB_NET_TRACE( size_t aIndex, EDA_DATA* aEda ) : SUB_NET( aIndex, aEda ) {} |
|||
void WriteSubnet( std::ostream& ost ) const override; |
|||
}; |
|||
|
|||
class SUB_NET_PLANE : public SUB_NET |
|||
{ |
|||
public: |
|||
enum class FILL_TYPE |
|||
{ |
|||
SOLID, |
|||
OUTLINE |
|||
}; |
|||
|
|||
enum class CUTOUT_TYPE |
|||
{ |
|||
CIRCLE, |
|||
RECT, |
|||
OCTAGON, |
|||
EXACT |
|||
}; |
|||
|
|||
SUB_NET_PLANE( size_t aIndex, EDA_DATA* aEda, FILL_TYPE aFill, CUTOUT_TYPE aCutout, |
|||
size_t aFillSize ) : |
|||
SUB_NET( aIndex, aEda ), fill_type( aFill ), cutout_type( aCutout ), |
|||
fill_size( aFillSize ) |
|||
{ |
|||
} |
|||
|
|||
FILL_TYPE fill_type; |
|||
CUTOUT_TYPE cutout_type; |
|||
size_t fill_size; |
|||
|
|||
void WriteSubnet( std::ostream& ost ) const override; |
|||
}; |
|||
|
|||
class SUB_NET_TOEPRINT : public SUB_NET |
|||
{ |
|||
public: |
|||
enum class SIDE |
|||
{ |
|||
TOP, |
|||
BOTTOM |
|||
}; |
|||
|
|||
SUB_NET_TOEPRINT( size_t aIndex, EDA_DATA* aEda, SIDE aSide, size_t aCompNum, |
|||
size_t aToepNum ) : |
|||
SUB_NET( aIndex, aEda ), side( aSide ), comp_num( aCompNum ), toep_num( aToepNum ) |
|||
{ |
|||
} |
|||
|
|||
~SUB_NET_TOEPRINT() {} |
|||
|
|||
SIDE side; |
|||
|
|||
size_t comp_num; |
|||
size_t toep_num; |
|||
|
|||
void WriteSubnet( std::ostream& ost ) const override; |
|||
}; |
|||
|
|||
class NET : public ATTR_RECORD_WRITER |
|||
{ |
|||
public: |
|||
NET( size_t aIndex, const wxString& aName ) : m_index( aIndex ), m_name( aName ) {} |
|||
|
|||
const size_t m_index; |
|||
wxString m_name; |
|||
std::list<std::unique_ptr<SUB_NET>> subnets; |
|||
|
|||
template <typename T, typename... Args> |
|||
T& AddSubnet( Args&&... args ) |
|||
{ |
|||
auto f = std::make_unique<T>( subnets.size(), std::forward<Args>( args )... ); |
|||
auto& r = *f; |
|||
subnets.push_back( std::move( f ) ); |
|||
return r; |
|||
} |
|||
|
|||
void Write( std::ostream& ost ) const; |
|||
}; |
|||
|
|||
void AddNET( const NETINFO_ITEM* aNet ); |
|||
NET& GetNet( size_t aNetcode ) { return nets_map.at( aNetcode ); } |
|||
|
|||
class PIN |
|||
{ |
|||
public: |
|||
PIN( const size_t aIndex, const wxString& aName ) : m_index( aIndex ), m_name( aName ) {} |
|||
|
|||
const size_t m_index; |
|||
wxString m_name; |
|||
|
|||
std::pair<wxString, wxString> m_center; |
|||
|
|||
enum class TYPE |
|||
{ |
|||
THROUGH_HOLE, |
|||
BLIND, |
|||
SURFACE |
|||
}; |
|||
|
|||
TYPE type = TYPE::SURFACE; |
|||
|
|||
enum class ELECTRICAL_TYPE |
|||
{ |
|||
ELECTRICAL, |
|||
MECHANICAL, |
|||
UNDEFINED |
|||
}; |
|||
|
|||
ELECTRICAL_TYPE etype = ELECTRICAL_TYPE::UNDEFINED; |
|||
|
|||
enum class MOUNT_TYPE |
|||
{ |
|||
SMT, |
|||
SMT_RECOMMENDED, |
|||
THROUGH_HOLE, |
|||
THROUGH_RECOMMENDED, |
|||
PRESSFIT, |
|||
NON_BOARD, |
|||
HOLE, |
|||
UNDEFINED |
|||
}; |
|||
MOUNT_TYPE mtype = MOUNT_TYPE::UNDEFINED; |
|||
|
|||
std::list<std::unique_ptr<PKG_OUTLINE>> m_pinOutlines; |
|||
|
|||
void Write( std::ostream& ost ) const; |
|||
}; |
|||
|
|||
class PACKAGE : public ATTR_RECORD_WRITER |
|||
{ |
|||
public: |
|||
PACKAGE( const size_t aIndex, const wxString& afpName ) : |
|||
m_index( aIndex ), m_name( afpName ) |
|||
{ |
|||
} |
|||
|
|||
const size_t m_index; /// <! Reference number of the package to be used in CMP. |
|||
wxString m_name; |
|||
|
|||
size_t m_pitch; |
|||
int64_t m_xmin, m_ymin, m_xmax, m_ymax; // Box points: leftlow, rightup |
|||
|
|||
std::list<std::unique_ptr<PKG_OUTLINE>> m_pkgOutlines; |
|||
|
|||
void AddPin( const PAD* aPad, size_t aPinNum ); |
|||
const std::shared_ptr<PIN> GetEdaPkgPin( size_t aPadIndex ) const |
|||
{ |
|||
return m_pinsVec.at( aPadIndex ); |
|||
} |
|||
|
|||
void Write( std::ostream& ost ) const; |
|||
|
|||
private: |
|||
std::vector<std::shared_ptr<PIN>> m_pinsVec; |
|||
}; |
|||
|
|||
void AddPackage( const FOOTPRINT* aFp ); |
|||
const PACKAGE& GetPackage( size_t aHash ) const { return packages_map.at( aHash ); } |
|||
|
|||
private: |
|||
std::map<size_t, NET> nets_map; |
|||
std::list<const NET*> nets; |
|||
|
|||
std::map<size_t, PACKAGE> packages_map; //hash value, package |
|||
std::list<const PACKAGE*> packages; |
|||
|
|||
std::map<wxString, size_t> layers_map; |
|||
std::vector<wxString> layers; |
|||
std::vector<std::shared_ptr<FOOTPRINT>> m_eda_footprints; |
|||
}; |
|||
|
|||
class PKG_OUTLINE |
|||
{ |
|||
public: |
|||
virtual void Write( std::ostream& ost ) const = 0; |
|||
|
|||
virtual ~PKG_OUTLINE() = default; |
|||
}; |
|||
|
|||
class OUTLINE_RECT : public PKG_OUTLINE |
|||
{ |
|||
public: |
|||
OUTLINE_RECT( const VECTOR2I& aLowerLeft, size_t aWidth, size_t aHeight ) : |
|||
m_lower_left( aLowerLeft ), m_width( aWidth ), m_height( aHeight ) |
|||
{ |
|||
} |
|||
|
|||
OUTLINE_RECT( const BOX2I& aBox ) : |
|||
OUTLINE_RECT( aBox.GetPosition(), aBox.GetWidth(), aBox.GetHeight() ) |
|||
{ |
|||
} |
|||
|
|||
VECTOR2I m_lower_left; |
|||
size_t m_width; |
|||
size_t m_height; |
|||
|
|||
void Write( std::ostream& ost ) const override; |
|||
}; |
|||
|
|||
class ODB_SURFACE_DATA; |
|||
class OUTLINE_CONTOUR : public PKG_OUTLINE |
|||
{ |
|||
public: |
|||
OUTLINE_CONTOUR( const SHAPE_POLY_SET::POLYGON& aPolygon, |
|||
FILL_T aFillType = FILL_T::FILLED_SHAPE ) |
|||
{ |
|||
if( !aPolygon.empty() && aPolygon[0].PointCount() >= 3 ) |
|||
{ |
|||
m_surfaces = std::make_unique<ODB_SURFACE_DATA>( aPolygon ); |
|||
if( aFillType != FILL_T::NO_FILL ) |
|||
{ |
|||
m_surfaces->AddPolygonHoles( aPolygon ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
std::unique_ptr<ODB_SURFACE_DATA> m_surfaces; |
|||
|
|||
void Write( std::ostream& ost ) const override; |
|||
}; |
|||
|
|||
class OUTLINE_SQUARE : public PKG_OUTLINE |
|||
{ |
|||
public: |
|||
OUTLINE_SQUARE( const VECTOR2I& aCenter, size_t aHalfSide ) : |
|||
m_center( aCenter ), m_halfSide( aHalfSide ) |
|||
{ |
|||
} |
|||
VECTOR2I m_center; |
|||
size_t m_halfSide; |
|||
|
|||
void Write( std::ostream& ost ) const override; |
|||
}; |
|||
|
|||
class OUTLINE_CIRCLE : public PKG_OUTLINE |
|||
{ |
|||
public: |
|||
OUTLINE_CIRCLE( const VECTOR2I& aCenter, size_t aRadius ) : |
|||
m_center( aCenter ), m_radius( aRadius ) |
|||
{ |
|||
} |
|||
VECTOR2I m_center; |
|||
size_t m_radius; |
|||
|
|||
void Write( std::ostream& ost ) const override; |
|||
}; |
|||
|
|||
|
|||
#endif // _ODB_EDA_DATA_H_ |
@ -0,0 +1,975 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
|
|||
#include <base_units.h>
|
|||
#include <board_stackup_manager/stackup_predefined_prms.h>
|
|||
#include <build_version.h>
|
|||
#include <callback_gal.h>
|
|||
#include <connectivity/connectivity_data.h>
|
|||
#include <connectivity/connectivity_algo.h>
|
|||
#include <convert_basic_shapes_to_polygon.h>
|
|||
#include <font/font.h>
|
|||
#include <footprint.h>
|
|||
#include <hash_eda.h>
|
|||
#include <pad.h>
|
|||
#include <pcb_dimension.h>
|
|||
#include <pcb_shape.h>
|
|||
#include <pcb_text.h>
|
|||
#include <pcb_textbox.h>
|
|||
#include <pcb_track.h>
|
|||
#include <pcbnew_settings.h>
|
|||
#include <board_design_settings.h>
|
|||
#include <pgm_base.h>
|
|||
#include <progress_reporter.h>
|
|||
#include <settings/settings_manager.h>
|
|||
#include <wx_fstream_progress.h>
|
|||
|
|||
#include <geometry/shape_circle.h>
|
|||
#include <geometry/shape_line_chain.h>
|
|||
#include <geometry/shape_poly_set.h>
|
|||
#include <geometry/shape_segment.h>
|
|||
|
|||
#include <wx/log.h>
|
|||
#include <wx/numformatter.h>
|
|||
#include <wx/mstream.h>
|
|||
|
|||
#include "odb_attribute.h"
|
|||
#include "odb_entity.h"
|
|||
#include "odb_defines.h"
|
|||
#include "odb_feature.h"
|
|||
#include "odb_util.h"
|
|||
#include "pcb_io_odbpp.h"
|
|||
|
|||
|
|||
bool ODB_ENTITY_BASE::CreateDirectiryTree( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
try |
|||
{ |
|||
writer.CreateEntityDirectory( writer.GetRootPath(), GetEntityName() ); |
|||
return true; |
|||
} |
|||
catch( const std::exception& e ) |
|||
{ |
|||
std::cerr << e.what() << std::endl; |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
|
|||
ODB_MISC_ENTITY::ODB_MISC_ENTITY() |
|||
{ |
|||
m_info = { { wxS( ODB_JOB_NAME ), wxS( "job" ) }, |
|||
{ wxS( ODB_UNITS ), PCB_IO_ODBPP::m_unitsStr }, |
|||
{ wxS( "ODB_VERSION_MAJOR" ), wxS( "8" ) }, |
|||
{ wxS( "ODB_VERSION_MINOR" ), wxS( "1" ) }, |
|||
{ wxS( "ODB_SOURCE" ), wxS( "KiCad EDA" + GetMajorMinorPatchVersion() ) }, |
|||
{ wxS( "CREATION_DATE" ), wxDateTime::Now().FormatISOCombined() }, |
|||
{ wxS( "SAVE_DATE" ), wxDateTime::Now().FormatISOCombined() }, |
|||
{ wxS( "SAVE_APP" ), wxS( "Pcbnew" ) }, |
|||
{ wxS( "SAVE_USER" ), wxS( "" ) }, |
|||
{ wxS( "MAX_UID" ), wxS( "" ) } }; |
|||
} |
|||
|
|||
|
|||
void ODB_MISC_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "info" ); |
|||
|
|||
ODB_TEXT_WRITER twriter( fileproxy.GetStream() ); |
|||
|
|||
for( auto& info : m_info ) |
|||
{ |
|||
twriter.WriteEquationLine( info.first, info.second ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_MATRIX_ENTITY::AddStep( const wxString& aStepName ) |
|||
{ |
|||
m_matrixSteps.emplace( aStepName.Upper(), m_col++ ); |
|||
} |
|||
|
|||
|
|||
void ODB_MATRIX_ENTITY::InitEntityData() |
|||
{ |
|||
AddStep( "PCB" ); |
|||
|
|||
InitMatrixLayerData(); |
|||
} |
|||
|
|||
|
|||
void ODB_MATRIX_ENTITY::InitMatrixLayerData() |
|||
{ |
|||
BOARD_DESIGN_SETTINGS& dsnSettings = m_board->GetDesignSettings(); |
|||
BOARD_STACKUP& stackup = dsnSettings.GetStackupDescriptor(); |
|||
stackup.SynchronizeWithBoard( &dsnSettings ); |
|||
|
|||
std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList(); |
|||
std::set<PCB_LAYER_ID> added_layers; |
|||
|
|||
for( int i = 0; i < stackup.GetCount(); i++ ) |
|||
{ |
|||
BOARD_STACKUP_ITEM* stackup_item = layers.at( i ); |
|||
|
|||
for( int sublayer_id = 0; sublayer_id < stackup_item->GetSublayersCount(); sublayer_id++ ) |
|||
{ |
|||
wxString ly_name = stackup_item->GetLayerName(); |
|||
|
|||
if( ly_name.IsEmpty() ) |
|||
{ |
|||
if( IsValidLayer( stackup_item->GetBrdLayerId() ) ) |
|||
ly_name = m_board->GetLayerName( stackup_item->GetBrdLayerId() ); |
|||
|
|||
if( ly_name.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC ) |
|||
ly_name = wxString::Format( "DIELECTRIC_%d", |
|||
stackup_item->GetDielectricLayerId() ); |
|||
} |
|||
|
|||
MATRIX_LAYER matrix( m_row++, ly_name ); |
|||
|
|||
if( stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC ) |
|||
{ |
|||
if( stackup_item->GetTypeName() == KEY_CORE ) |
|||
matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::CORE ); |
|||
else |
|||
matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::PREPREG ); |
|||
|
|||
matrix.m_type = ODB_TYPE::DIELECTRIC; |
|||
matrix.m_context = ODB_CONTEXT::BOARD; |
|||
matrix.m_polarity = ODB_POLARITY::POSITIVE; |
|||
m_matrixLayers.push_back( matrix ); |
|||
m_plugin->GetLayerNameList().emplace_back( |
|||
std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) ); |
|||
|
|||
continue; |
|||
} |
|||
else |
|||
{ |
|||
added_layers.insert( stackup_item->GetBrdLayerId() ); |
|||
AddMatrixLayerField( matrix, stackup_item->GetBrdLayerId() ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
LSEQ layer_seq = m_board->GetEnabledLayers().Seq(); |
|||
|
|||
for( PCB_LAYER_ID layer : layer_seq ) |
|||
{ |
|||
if( added_layers.find( layer ) != added_layers.end() ) |
|||
continue; |
|||
|
|||
MATRIX_LAYER matrix( m_row++, m_board->GetLayerName( layer ) ); |
|||
added_layers.insert( layer ); |
|||
AddMatrixLayerField( matrix, layer ); |
|||
} |
|||
|
|||
AddDrillMatrixLayer(); |
|||
|
|||
AddCOMPMatrixLayer(); |
|||
} |
|||
|
|||
|
|||
void ODB_MATRIX_ENTITY::AddMatrixLayerField( MATRIX_LAYER& aMLayer, PCB_LAYER_ID aLayer ) |
|||
{ |
|||
aMLayer.m_polarity = ODB_POLARITY::POSITIVE; |
|||
aMLayer.m_context = ODB_CONTEXT::BOARD; |
|||
switch( aLayer ) |
|||
{ |
|||
case F_Paste: |
|||
case B_Paste: aMLayer.m_type = ODB_TYPE::SOLDER_PASTE; break; |
|||
case F_SilkS: |
|||
case B_SilkS: aMLayer.m_type = ODB_TYPE::SILK_SCREEN; break; |
|||
case F_Mask: |
|||
case B_Mask: aMLayer.m_type = ODB_TYPE::SOLDER_MASK; break; |
|||
case B_CrtYd: |
|||
case F_CrtYd: |
|||
case Edge_Cuts: |
|||
case B_Fab: |
|||
case F_Fab: |
|||
case F_Adhes: |
|||
case B_Adhes: |
|||
case Dwgs_User: |
|||
case Cmts_User: |
|||
case Eco1_User: |
|||
case Eco2_User: |
|||
case Margin: |
|||
case User_1: |
|||
case User_2: |
|||
case User_3: |
|||
case User_4: |
|||
case User_5: |
|||
case User_6: |
|||
case User_7: |
|||
case User_8: |
|||
case User_9: |
|||
aMLayer.m_context = ODB_CONTEXT::MISC; |
|||
aMLayer.m_type = ODB_TYPE::DOCUMENT; |
|||
break; |
|||
|
|||
default: |
|||
if( IsCopperLayer( aLayer ) ) |
|||
{ |
|||
aMLayer.m_type = ODB_TYPE::SIGNAL; |
|||
} |
|||
else |
|||
{ |
|||
// Do not handle other layers :
|
|||
aMLayer.m_type = ODB_TYPE::UNDEFINED; |
|||
m_row--; |
|||
} |
|||
|
|||
break; |
|||
} |
|||
|
|||
if( aMLayer.m_type != ODB_TYPE::UNDEFINED ) |
|||
{ |
|||
m_matrixLayers.push_back( aMLayer ); |
|||
m_plugin->GetLayerNameList().emplace_back( std::make_pair( aLayer, aMLayer.m_layerName ) ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_MATRIX_ENTITY::AddDrillMatrixLayer() |
|||
{ |
|||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& drill_layers = |
|||
m_plugin->GetDrillLayerItemsMap(); |
|||
|
|||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes = |
|||
m_plugin->GetSlotHolesMap(); |
|||
|
|||
bool has_pth_layer = false; |
|||
bool has_npth_layer = false; |
|||
|
|||
for( BOARD_ITEM* item : m_board->Tracks() ) |
|||
{ |
|||
if( item->Type() == PCB_VIA_T ) |
|||
{ |
|||
PCB_VIA* via = static_cast<PCB_VIA*>( item ); |
|||
drill_layers[std::make_pair( via->TopLayer(), via->BottomLayer() )].push_back( via ); |
|||
} |
|||
} |
|||
|
|||
for( FOOTPRINT* fp : m_board->Footprints() ) |
|||
{ |
|||
// std::shared_ptr<FOOTPRINT> fp( static_cast<FOOTPRINT*>( it_fp->Clone() ) );
|
|||
|
|||
if( fp->IsFlipped() ) |
|||
{ |
|||
m_hasBotComp = true; |
|||
} |
|||
|
|||
for( PAD* pad : fp->Pads() ) |
|||
{ |
|||
if( !has_pth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH ) |
|||
has_pth_layer = true; |
|||
if( !has_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) |
|||
has_npth_layer = true; |
|||
|
|||
if( pad->HasHole() && pad->GetDrillSizeX() != pad->GetDrillSizeY() ) |
|||
slot_holes[std::make_pair( F_Cu, B_Cu )].push_back( pad ); |
|||
else if( pad->HasHole() ) |
|||
drill_layers[std::make_pair( F_Cu, B_Cu )].push_back( pad ); |
|||
} |
|||
|
|||
// m_plugin->GetLoadedFootprintList().push_back( std::move( fp ) );
|
|||
} |
|||
|
|||
auto InitDrillMatrix = |
|||
[&]( const wxString& aHasPlated, std::pair<PCB_LAYER_ID, PCB_LAYER_ID> aLayerPair ) |
|||
{ |
|||
wxString dLayerName = wxString::Format( "drill_%s_%s-%s", aHasPlated, |
|||
m_board->GetLayerName( aLayerPair.first ), |
|||
m_board->GetLayerName( aLayerPair.second ) ); |
|||
MATRIX_LAYER matrix( m_row++, dLayerName ); |
|||
|
|||
matrix.m_type = ODB_TYPE::DRILL; |
|||
matrix.m_context = ODB_CONTEXT::BOARD; |
|||
matrix.m_polarity = ODB_POLARITY::POSITIVE; |
|||
matrix.m_span.emplace( std::make_pair( |
|||
ODB::GenLegalEntityName( m_board->GetLayerName( aLayerPair.first ) ), |
|||
ODB::GenLegalEntityName( m_board->GetLayerName( aLayerPair.second ) ) ) ); |
|||
m_matrixLayers.push_back( matrix ); |
|||
m_plugin->GetLayerNameList().emplace_back( |
|||
std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) ); |
|||
}; |
|||
|
|||
if( drill_layers.find( std::make_pair( F_Cu, B_Cu ) ) != drill_layers.end() |
|||
|| !slot_holes.empty() ) |
|||
{ |
|||
// for pad has hole
|
|||
if( has_pth_layer ) |
|||
InitDrillMatrix( "plated", std::make_pair( F_Cu, B_Cu ) ); |
|||
if( has_npth_layer ) |
|||
InitDrillMatrix( "non-plated", std::make_pair( F_Cu, B_Cu ) ); |
|||
} |
|||
|
|||
for( const auto& [layer_pair, vec] : drill_layers ) |
|||
{ |
|||
if( layer_pair != std::make_pair( F_Cu, B_Cu ) ) // pad has initialized above
|
|||
InitDrillMatrix( "plated", layer_pair ); // for via
|
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_MATRIX_ENTITY::AddCOMPMatrixLayer() |
|||
{ |
|||
MATRIX_LAYER matrix( m_row++, "COMP_+_TOP" ); |
|||
matrix.m_type = ODB_TYPE::COMPONENT; |
|||
matrix.m_context = ODB_CONTEXT::BOARD; |
|||
|
|||
m_matrixLayers.push_back( matrix ); |
|||
m_plugin->GetLayerNameList().emplace_back( |
|||
std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) ); |
|||
|
|||
if( m_hasBotComp ) |
|||
{ |
|||
matrix.m_layerName = ODB::GenLegalEntityName( "COMP_+_BOT" ); |
|||
matrix.m_rowNumber = m_row++; |
|||
m_matrixLayers.push_back( matrix ); |
|||
m_plugin->GetLayerNameList().emplace_back( |
|||
std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_MATRIX_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "matrix" ); |
|||
|
|||
ODB_TEXT_WRITER twriter( fileproxy.GetStream() ); |
|||
|
|||
for( const auto& [step_name, column] : m_matrixSteps ) |
|||
{ |
|||
const auto array_proxy = twriter.MakeArrayProxy( "STEP" ); |
|||
twriter.WriteEquationLine( "COL", column ); |
|||
twriter.WriteEquationLine( "NAME", step_name ); |
|||
} |
|||
|
|||
for( const auto& layer : m_matrixLayers ) |
|||
{ |
|||
const auto array_proxy = twriter.MakeArrayProxy( "LAYER" ); |
|||
twriter.WriteEquationLine( "ROW", layer.m_rowNumber ); |
|||
twriter.write_line_enum( "CONTEXT", layer.m_context ); |
|||
twriter.write_line_enum( "TYPE", layer.m_type ); |
|||
|
|||
if( layer.m_addType.has_value() ) |
|||
{ |
|||
twriter.write_line_enum( "ADD_TYPE", layer.m_addType.value() ); |
|||
} |
|||
|
|||
twriter.WriteEquationLine( "NAME", layer.m_layerName.Upper() ); |
|||
twriter.WriteEquationLine( "OLD_NAME", wxEmptyString ); |
|||
twriter.write_line_enum( "POLARITY", layer.m_polarity ); |
|||
|
|||
if( layer.m_diType.has_value() ) |
|||
{ |
|||
twriter.write_line_enum( "DIELECTRIC_TYPE", layer.m_diType.value() ); |
|||
} |
|||
|
|||
twriter.WriteEquationLine( "DIELECTRIC_NAME", wxEmptyString ); |
|||
twriter.WriteEquationLine( "CU_TOP", wxEmptyString ); |
|||
twriter.WriteEquationLine( "CU_BOTTOM", wxEmptyString ); |
|||
twriter.WriteEquationLine( "REF", wxEmptyString ); |
|||
|
|||
if( layer.m_span.has_value() ) |
|||
{ |
|||
twriter.WriteEquationLine( "START_NAME", layer.m_span->first.Upper() ); |
|||
twriter.WriteEquationLine( "END_NAME", layer.m_span->second.Upper() ); |
|||
} |
|||
else |
|||
{ |
|||
twriter.WriteEquationLine( "START_NAME", wxEmptyString ); |
|||
twriter.WriteEquationLine( "END_NAME", wxEmptyString ); |
|||
} |
|||
twriter.WriteEquationLine( "COLOR", wxEmptyString ); |
|||
} |
|||
} |
|||
|
|||
|
|||
ODB_LAYER_ENTITY::ODB_LAYER_ENTITY( BOARD* aBoard, PCB_IO_ODBPP* aPlugin, |
|||
std::map<int, std::vector<BOARD_ITEM*>>& aMap, |
|||
const PCB_LAYER_ID& aLayerID, const wxString& aLayerName ) : |
|||
ODB_ENTITY_BASE( aBoard, aPlugin ), m_layerItems( aMap ), m_layerID( aLayerID ), |
|||
m_matrixLayerName( aLayerName ) |
|||
{ |
|||
m_featuresMgr = std::make_unique<FEATURES_MANAGER>( aBoard, aPlugin, aLayerName ); |
|||
} |
|||
|
|||
|
|||
void ODB_LAYER_ENTITY::InitEntityData() |
|||
{ |
|||
if( m_matrixLayerName.Contains( "drill" ) ) |
|||
{ |
|||
InitDrillData(); |
|||
InitFeatureData(); |
|||
return; |
|||
} |
|||
|
|||
if( m_layerID != PCB_LAYER_ID::UNDEFINED_LAYER ) |
|||
{ |
|||
InitFeatureData(); |
|||
} |
|||
} |
|||
|
|||
void ODB_LAYER_ENTITY::InitFeatureData() |
|||
{ |
|||
if( m_layerItems.empty() ) |
|||
return; |
|||
|
|||
const NETINFO_LIST& nets = m_board->GetNetInfo(); |
|||
|
|||
for( const NETINFO_ITEM* net : nets ) |
|||
{ |
|||
std::vector<BOARD_ITEM*>& vec = m_layerItems[net->GetNetCode()]; |
|||
|
|||
std::stable_sort( vec.begin(), vec.end(), |
|||
[]( BOARD_ITEM* a, BOARD_ITEM* b ) |
|||
{ |
|||
if( a->GetParentFootprint() == b->GetParentFootprint() ) |
|||
return a->Type() < b->Type(); |
|||
|
|||
return a->GetParentFootprint() < b->GetParentFootprint(); |
|||
} ); |
|||
|
|||
if( vec.empty() ) |
|||
continue; |
|||
|
|||
m_featuresMgr->InitFeatureList( m_layerID, vec ); |
|||
} |
|||
} |
|||
|
|||
|
|||
ODB_COMPONENT& ODB_LAYER_ENTITY::InitComponentData( const FOOTPRINT* aFp, |
|||
const EDA_DATA::PACKAGE& aPkg ) |
|||
{ |
|||
if( m_matrixLayerName == "COMP_+_BOT" ) |
|||
{ |
|||
if( !m_compBot.has_value() ) |
|||
{ |
|||
m_compBot.emplace(); |
|||
} |
|||
return m_compBot.value().AddComponent( aFp, aPkg ); |
|||
} |
|||
else |
|||
{ |
|||
if( !m_compTop.has_value() ) |
|||
{ |
|||
m_compTop.emplace(); |
|||
} |
|||
|
|||
return m_compTop.value().AddComponent( aFp, aPkg ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_LAYER_ENTITY::InitDrillData() |
|||
{ |
|||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& drill_layers = |
|||
m_plugin->GetDrillLayerItemsMap(); |
|||
|
|||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes = |
|||
m_plugin->GetSlotHolesMap(); |
|||
|
|||
if( !m_layerItems.empty() ) |
|||
{ |
|||
m_layerItems.clear(); |
|||
} |
|||
|
|||
m_tools.emplace( PCB_IO_ODBPP::m_unitsStr ); |
|||
|
|||
bool is_npth_layer = false; |
|||
wxString plated_name = "plated"; |
|||
|
|||
if( m_matrixLayerName.Contains( "non-plated" ) ) |
|||
{ |
|||
is_npth_layer = true; |
|||
plated_name = "non-plated"; |
|||
} |
|||
|
|||
|
|||
for( const auto& [layer_pair, vec] : slot_holes ) |
|||
{ |
|||
wxString dLayerName = wxString::Format( "drill_%s_%s-%s", plated_name, |
|||
m_board->GetLayerName( layer_pair.first ), |
|||
m_board->GetLayerName( layer_pair.second ) ); |
|||
|
|||
if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName ) |
|||
{ |
|||
for( BOARD_ITEM* item : vec ) |
|||
{ |
|||
if( item->Type() == PCB_PAD_T ) |
|||
{ |
|||
PAD* pad = static_cast<PAD*>( item ); |
|||
|
|||
if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH ) |
|||
|| ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) ) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
m_tools.value().AddDrillTools( |
|||
pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NON_PLATED", |
|||
ODB::SymDouble2String( |
|||
std::min( pad->GetDrillSizeX(), pad->GetDrillSizeY() ) ) ); |
|||
|
|||
// for drill features
|
|||
m_layerItems[pad->GetNetCode()].push_back( item ); |
|||
} |
|||
} |
|||
|
|||
break; |
|||
} |
|||
} |
|||
|
|||
for( const auto& [layer_pair, vec] : drill_layers ) |
|||
{ |
|||
wxString dLayerName = wxString::Format( "drill_%s_%s-%s", plated_name, |
|||
m_board->GetLayerName( layer_pair.first ), |
|||
m_board->GetLayerName( layer_pair.second ) ); |
|||
|
|||
if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName ) |
|||
{ |
|||
for( BOARD_ITEM* item : vec ) |
|||
{ |
|||
if( item->Type() == PCB_VIA_T && !is_npth_layer ) |
|||
{ |
|||
PCB_VIA* via = static_cast<PCB_VIA*>( item ); |
|||
|
|||
m_tools.value().AddDrillTools( "VIA", |
|||
ODB::SymDouble2String( via->GetDrillValue() ) ); |
|||
|
|||
// for drill features
|
|||
m_layerItems[via->GetNetCode()].push_back( item ); |
|||
} |
|||
else if( item->Type() == PCB_PAD_T ) |
|||
{ |
|||
PAD* pad = static_cast<PAD*>( item ); |
|||
|
|||
if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH ) |
|||
|| ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) ) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
m_tools.value().AddDrillTools( |
|||
pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NON_PLATED", |
|||
ODB::SymDouble2String( pad->GetDrillSizeX() ) ); |
|||
|
|||
// for drill features
|
|||
m_layerItems[pad->GetNetCode()].push_back( item ); |
|||
} |
|||
} |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::InitEntityData() |
|||
{ |
|||
MakeLayerEntity(); |
|||
|
|||
InitEdaData(); |
|||
|
|||
// Init Layer Entity Data
|
|||
for( const auto& [layerName, layer_entity_ptr] : m_layerEntityMap ) |
|||
{ |
|||
layer_entity_ptr->InitEntityData(); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_LAYER_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
GenAttrList( writer ); |
|||
|
|||
GenFeatures( writer ); |
|||
|
|||
if( m_compTop.has_value() || m_compBot.has_value() ) |
|||
{ |
|||
GenComponents( writer ); |
|||
} |
|||
|
|||
if( m_tools.has_value() ) |
|||
{ |
|||
GenTools( writer ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_LAYER_ENTITY::GenComponents( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "components" ); |
|||
|
|||
if( m_compTop.has_value() ) |
|||
{ |
|||
m_compTop->Write( fileproxy.GetStream() ); |
|||
} |
|||
else if( m_compBot.has_value() ) |
|||
{ |
|||
m_compBot->Write( fileproxy.GetStream() ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_LAYER_ENTITY::GenFeatures( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "features" ); |
|||
|
|||
m_featuresMgr->GenerateFeatureFile( fileproxy.GetStream() ); |
|||
} |
|||
|
|||
|
|||
void ODB_LAYER_ENTITY::GenAttrList( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "attrlist" ); |
|||
} |
|||
|
|||
|
|||
void ODB_LAYER_ENTITY::GenTools( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "tools" ); |
|||
|
|||
m_tools.value().GenerateFile( fileproxy.GetStream() ); |
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::InitEdaData() |
|||
{ |
|||
//InitPackage
|
|||
for( const FOOTPRINT* fp : m_board->Footprints() ) |
|||
{ |
|||
m_edaData.AddPackage( fp ); |
|||
} |
|||
|
|||
// for NET
|
|||
const NETINFO_LIST& nets = m_board->GetNetInfo(); |
|||
|
|||
for( const NETINFO_ITEM* net : nets ) |
|||
{ |
|||
m_edaData.AddNET( net ); |
|||
} |
|||
|
|||
// for CMP
|
|||
size_t j = 0; |
|||
|
|||
for( const FOOTPRINT* fp : m_board->Footprints() ) |
|||
{ |
|||
wxString compName = ODB::GenLegalEntityName( "COMP_+_TOP" ); |
|||
if( fp->IsFlipped() ) |
|||
compName = ODB::GenLegalEntityName( "COMP_+_BOT" ); |
|||
|
|||
auto iter = m_layerEntityMap.find( compName ); |
|||
|
|||
if( iter == m_layerEntityMap.end() ) |
|||
{ |
|||
wxLogError( _( "Failed to add component data" ) ); |
|||
return; |
|||
} |
|||
|
|||
// ODBPP only need unique PACKAGE in PKG record in eda/data file.
|
|||
// the PKG index can repeat to be ref in CMP record in component file.
|
|||
std::shared_ptr<FOOTPRINT> fp_pkg = m_edaData.GetEdaFootprints().at( j ); |
|||
++j; |
|||
|
|||
const EDA_DATA::PACKAGE& eda_pkg = |
|||
m_edaData.GetPackage( hash_fp_item( fp_pkg.get(), HASH_POS | REL_COORD ) ); |
|||
|
|||
ODB_COMPONENT& comp = iter->second->InitComponentData( fp, eda_pkg ); |
|||
|
|||
for( int i = 0; i < fp->Pads().size(); ++i ) |
|||
{ |
|||
PAD* pad = fp->Pads()[i]; |
|||
auto& eda_net = m_edaData.GetNet( pad->GetNetCode() ); |
|||
|
|||
auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_TOEPRINT>( |
|||
&m_edaData, |
|||
fp->IsFlipped() ? EDA_DATA::SUB_NET_TOEPRINT::SIDE::BOTTOM |
|||
: EDA_DATA::SUB_NET_TOEPRINT::SIDE::TOP, |
|||
comp.m_index, comp.m_toeprints.size() ); |
|||
|
|||
m_plugin->GetPadSubnetMap().emplace( pad, &subnet ); |
|||
|
|||
const std::shared_ptr<EDA_DATA::PIN> pin = eda_pkg.GetEdaPkgPin( i ); |
|||
const EDA_DATA::PIN& pin_ref = *pin; |
|||
auto& toep = comp.m_toeprints.emplace_back( pin_ref ); |
|||
|
|||
toep.m_net_num = eda_net.m_index; |
|||
toep.m_subnet_num = subnet.m_index; |
|||
|
|||
toep.m_center = ODB::AddXY( pad->GetPosition() ); |
|||
|
|||
toep.m_rot = ODB::Double2String( |
|||
( ANGLE_360 - pad->GetOrientation() ).Normalize().AsDegrees() ); |
|||
|
|||
if( pad->IsFlipped() ) |
|||
toep.m_mirror = wxT( "M" ); |
|||
else |
|||
toep.m_mirror = wxT( "N" ); |
|||
} |
|||
} |
|||
|
|||
for( PCB_TRACK* track : m_board->Tracks() ) |
|||
{ |
|||
auto& eda_net = m_edaData.GetNet( track->GetNetCode() ); |
|||
EDA_DATA::SUB_NET* subnet = nullptr; |
|||
|
|||
if( track->Type() == PCB_VIA_T ) |
|||
subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_VIA>( &m_edaData ) ); |
|||
else |
|||
subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_TRACE>( &m_edaData ) ); |
|||
|
|||
m_plugin->GetViaTraceSubnetMap().emplace( track, subnet ); |
|||
} |
|||
|
|||
for( ZONE* zone : m_board->Zones() ) |
|||
{ |
|||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() ) |
|||
{ |
|||
auto& eda_net = m_edaData.GetNet( zone->GetNetCode() ); |
|||
auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_PLANE>( |
|||
&m_edaData, EDA_DATA::SUB_NET_PLANE::FILL_TYPE::SOLID, |
|||
EDA_DATA::SUB_NET_PLANE::CUTOUT_TYPE::EXACT, 0 ); |
|||
m_plugin->GetPlaneSubnetMap().emplace( std::piecewise_construct, |
|||
std::forward_as_tuple( layer, zone ), |
|||
std::forward_as_tuple( &subnet ) ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
wxString step_root = writer.GetCurrentPath(); |
|||
|
|||
writer.CreateEntityDirectory( step_root, "layers" ); |
|||
GenerateLayerFiles( writer ); |
|||
|
|||
writer.CreateEntityDirectory( step_root, "eda" ); |
|||
GenerateEdaFiles( writer ); |
|||
|
|||
writer.CreateEntityDirectory( step_root, "netlists/cadnet" ); |
|||
GenerateNetlistsFiles( writer ); |
|||
|
|||
writer.SetCurrentPath( step_root ); |
|||
GenerateProfileFile( writer ); |
|||
|
|||
GenerateStepHeaderFile( writer ); |
|||
|
|||
//TODO: system attributes
|
|||
// GenerateAttrListFile( writer );
|
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::GenerateProfileFile( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "profile" ); |
|||
|
|||
m_profile = std::make_unique<FEATURES_MANAGER>( m_board, m_plugin, wxEmptyString ); |
|||
|
|||
SHAPE_POLY_SET board_outline; |
|||
|
|||
if( !m_board->GetBoardPolygonOutlines( board_outline ) ) |
|||
{ |
|||
wxLogError( "Failed to get board outline" ); |
|||
} |
|||
|
|||
if( !m_profile->AddContour( board_outline, 0 ) ) |
|||
{ |
|||
wxLogError( "Failed to add polygon to profile" ); |
|||
} |
|||
|
|||
m_profile->GenerateProfileFeatures( fileproxy.GetStream() ); |
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::GenerateStepHeaderFile( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "stephdr" ); |
|||
|
|||
m_stephdr = { |
|||
{ ODB_UNITS, PCB_IO_ODBPP::m_unitsStr }, |
|||
{ "X_DATUM", "0" }, |
|||
{ "Y_DATUM", "0" }, |
|||
{ "X_ORIGIN", "0" }, |
|||
{ "Y_ORIGIN", "0" }, |
|||
{ "TOP_ACTIVE", "0" }, |
|||
{ "BOTTOM_ACTIVE", "0" }, |
|||
{ "RIGHT_ACTIVE", "0" }, |
|||
{ "LEFT_ACTIVE", "0" }, |
|||
{ "AFFECTING_BOM", "" }, |
|||
{ "AFFECTING_BOM_CHANGED", "0" }, |
|||
}; |
|||
|
|||
ODB_TEXT_WRITER twriter( fileproxy.GetStream() ); |
|||
|
|||
for( const auto& [key, value] : m_stephdr ) |
|||
{ |
|||
twriter.WriteEquationLine( key, value ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::GenerateLayerFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
wxString layers_root = writer.GetCurrentPath(); |
|||
|
|||
for( auto& [layerName, layerEntity] : m_layerEntityMap ) |
|||
{ |
|||
writer.CreateEntityDirectory( layers_root, layerName ); |
|||
|
|||
layerEntity->GenerateFiles( writer ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::GenerateEdaFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "data" ); |
|||
|
|||
m_edaData.Write( fileproxy.GetStream() ); |
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::GenerateNetlistsFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "netlist" ); |
|||
|
|||
m_netlist.Write( fileproxy.GetStream() ); |
|||
} |
|||
|
|||
|
|||
bool ODB_STEP_ENTITY::CreateDirectiryTree( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
try |
|||
{ |
|||
writer.CreateEntityDirectory( writer.GetRootPath(), "steps" ); |
|||
writer.CreateEntityDirectory( writer.GetCurrentPath(), GetEntityName() ); |
|||
return true; |
|||
} |
|||
catch( const std::exception& e ) |
|||
{ |
|||
std::cerr << e.what() << std::endl; |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_STEP_ENTITY::MakeLayerEntity() |
|||
{ |
|||
LSEQ layers = m_board->GetEnabledLayers().Seq(); |
|||
const NETINFO_LIST& nets = m_board->GetNetInfo(); |
|||
|
|||
// To avoid the overhead of repeatedly cycling through the layers and nets,
|
|||
// we pre-sort the board items into a map of layer -> net -> items
|
|||
std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>>& elements = |
|||
m_plugin->GetLayerElementsMap(); |
|||
|
|||
std::for_each( m_board->Tracks().begin(), m_board->Tracks().end(), |
|||
[&layers, &elements]( PCB_TRACK* aTrack ) |
|||
{ |
|||
if( aTrack->Type() == PCB_VIA_T ) |
|||
{ |
|||
PCB_VIA* via = static_cast<PCB_VIA*>( aTrack ); |
|||
|
|||
for( PCB_LAYER_ID layer : layers ) |
|||
{ |
|||
if( via->FlashLayer( layer ) ) |
|||
elements[layer][via->GetNetCode()].push_back( via ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack ); |
|||
} |
|||
} ); |
|||
|
|||
std::for_each( m_board->Zones().begin(), m_board->Zones().end(), |
|||
[&elements]( ZONE* zone ) |
|||
{ |
|||
LSEQ zone_layers = zone->GetLayerSet().Seq(); |
|||
|
|||
for( PCB_LAYER_ID layer : zone_layers ) |
|||
{ |
|||
elements[layer][zone->GetNetCode()].push_back( zone ); |
|||
} |
|||
} ); |
|||
|
|||
for( BOARD_ITEM* item : m_board->Drawings() ) |
|||
{ |
|||
if( BOARD_CONNECTED_ITEM* conn_it = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) ) |
|||
elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it ); |
|||
else |
|||
elements[item->GetLayer()][0].push_back( item ); |
|||
} |
|||
|
|||
for( FOOTPRINT* fp : m_board->Footprints() ) |
|||
{ |
|||
for( PCB_FIELD* field : fp->GetFields() ) |
|||
elements[field->GetLayer()][0].push_back( field ); |
|||
|
|||
for( BOARD_ITEM* item : fp->GraphicalItems() ) |
|||
elements[item->GetLayer()][0].push_back( item ); |
|||
|
|||
for( PAD* pad : fp->Pads() ) |
|||
{ |
|||
LSEQ pad_layers = pad->GetLayerSet().Seq(); |
|||
VECTOR2I margin; |
|||
|
|||
for( PCB_LAYER_ID layer : pad_layers ) |
|||
{ |
|||
bool onCopperLayer = ( LSET::AllCuMask() & LSET( { layer } ) ).any(); |
|||
bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & LSET( { layer } ) ).any(); |
|||
bool onSolderPasteLayer = |
|||
( LSET( { F_Paste, B_Paste } ) & LSET( { layer } ) ).any(); |
|||
|
|||
if( onSolderMaskLayer ) |
|||
margin.x = margin.y = pad->GetSolderMaskExpansion(); |
|||
|
|||
if( onSolderPasteLayer ) |
|||
margin = pad->GetSolderPasteMargin(); |
|||
|
|||
VECTOR2I padPlotsSize = pad->GetSize() + margin * 2; |
|||
|
|||
if( onCopperLayer && !pad->IsOnCopperLayer() ) |
|||
continue; |
|||
|
|||
if( onCopperLayer && !pad->FlashLayer( layer ) ) |
|||
continue; |
|||
|
|||
if( pad->GetShape() != PAD_SHAPE::CUSTOM |
|||
&& ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) ) |
|||
continue; |
|||
|
|||
elements[layer][pad->GetNetCode()].push_back( pad ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
for( const auto& [layerID, layerName] : m_plugin->GetLayerNameList() ) |
|||
{ |
|||
std::shared_ptr<ODB_LAYER_ENTITY> layer_entity_ptr = std::make_shared<ODB_LAYER_ENTITY>( |
|||
m_board, m_plugin, elements[layerID], layerID, layerName ); |
|||
|
|||
m_layerEntityMap.emplace( layerName, layer_entity_ptr ); |
|||
} |
|||
} |
@ -0,0 +1,273 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
#ifndef _ODB_ENTITY_H_ |
|||
#define _ODB_ENTITY_H_ |
|||
|
|||
|
|||
#include <optional> |
|||
#include <vector> |
|||
#include <map> |
|||
#include <wx/string.h> |
|||
#include <iostream> |
|||
#include <functional> |
|||
#include "odb_feature.h" |
|||
#include "odb_eda_data.h" |
|||
#include "odb_netlist.h" |
|||
#include "odb_component.h" |
|||
|
|||
|
|||
class BOARD; |
|||
class ODB_TREE_WRITER; |
|||
class BOARD_ITEM; |
|||
class PCB_IO_ODBPP; |
|||
|
|||
class ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_ENTITY_BASE( BOARD* aBoard, PCB_IO_ODBPP* aPlugin ) : m_board( aBoard ), m_plugin( aPlugin ) |
|||
{ |
|||
} |
|||
|
|||
ODB_ENTITY_BASE() : m_board( nullptr ), m_plugin( nullptr ) {} |
|||
|
|||
virtual ~ODB_ENTITY_BASE() = default; |
|||
virtual void GenerateFiles( ODB_TREE_WRITER& writer ) {} |
|||
virtual bool CreateDirectiryTree( ODB_TREE_WRITER& writer ); |
|||
virtual std::string GetEntityName() = 0; |
|||
virtual void InitEntityData() {} |
|||
|
|||
|
|||
protected: |
|||
BOARD* m_board; |
|||
std::vector<std::string> m_fileName; |
|||
PCB_IO_ODBPP* m_plugin; |
|||
}; |
|||
|
|||
enum class ODB_SUBTYPE; |
|||
enum class ODB_POLARITY; |
|||
enum class ODB_CONTEXT; |
|||
enum class ODB_TYPE; |
|||
|
|||
class ODB_MATRIX_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_MATRIX_ENTITY( BOARD* aBoard, PCB_IO_ODBPP* aPlugin ) : ODB_ENTITY_BASE( aBoard, aPlugin ) |
|||
{ |
|||
} |
|||
|
|||
virtual ~ODB_MATRIX_ENTITY() = default; |
|||
|
|||
inline virtual std::string GetEntityName() { return "matrix"; } |
|||
|
|||
struct MATRIX_LAYER |
|||
{ |
|||
std::optional<std::pair<wxString, wxString>> m_span; // !< start, end |
|||
std::optional<ODB_SUBTYPE> m_addType; |
|||
std::optional<ODB_DIELECTRIC_TYPE> m_diType; |
|||
|
|||
uint32_t m_rowNumber; |
|||
wxString m_layerName; |
|||
ODB_CONTEXT m_context; |
|||
ODB_TYPE m_type; |
|||
ODB_POLARITY m_polarity = ODB_POLARITY::POSITIVE; |
|||
|
|||
MATRIX_LAYER( uint32_t aRow, const wxString& aLayerName ) : |
|||
m_rowNumber( aRow ), m_layerName( ODB::GenLegalEntityName( aLayerName ) ) |
|||
{ |
|||
} |
|||
}; |
|||
|
|||
virtual void GenerateFiles( ODB_TREE_WRITER& writer ); |
|||
virtual void InitEntityData(); |
|||
void InitMatrixLayerData(); |
|||
|
|||
void AddStep( const wxString& aStepName ); |
|||
void AddMatrixLayerField( MATRIX_LAYER& aMLayer, PCB_LAYER_ID aLayer ); |
|||
void AddDrillMatrixLayer(); |
|||
void AddCOMPMatrixLayer(); |
|||
|
|||
private: |
|||
std::map<wxString, unsigned int> m_matrixSteps; |
|||
std::vector<MATRIX_LAYER> m_matrixLayers; |
|||
unsigned int m_row = 1; |
|||
unsigned int m_col = 1; |
|||
bool m_hasBotComp = false; |
|||
}; |
|||
|
|||
class ODB_MISC_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_MISC_ENTITY(); |
|||
virtual ~ODB_MISC_ENTITY() = default; |
|||
inline virtual std::string GetEntityName() { return "misc"; } |
|||
|
|||
//TODO |
|||
// bool AddAttrList(); |
|||
// bool AddSysAttrFiles(); |
|||
virtual void GenerateFiles( ODB_TREE_WRITER& writer ); |
|||
|
|||
private: |
|||
std::map<wxString, wxString> m_info; |
|||
// ODB_ATTRLIST m_attrlist; |
|||
}; |
|||
|
|||
class FEATURES_MANAGER; |
|||
class ODB_LAYER_ENTITY; |
|||
class ODB_STEP_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_STEP_ENTITY( BOARD* aBoard, PCB_IO_ODBPP* aPlugin ) : |
|||
ODB_ENTITY_BASE( aBoard, aPlugin ), m_profile( nullptr ), m_netlist( aBoard ) |
|||
{ |
|||
} |
|||
|
|||
virtual ~ODB_STEP_ENTITY() = default; |
|||
|
|||
inline virtual std::string GetEntityName() { return "pcb"; } |
|||
|
|||
void InitEdaData(); |
|||
void InitPackage(); |
|||
void InitNetListData(); |
|||
void MakeLayerEntity(); |
|||
bool AddNetList(); |
|||
bool AddProfile(); |
|||
bool AddStepHeader(); |
|||
|
|||
virtual bool CreateDirectiryTree( ODB_TREE_WRITER& writer ); |
|||
|
|||
virtual void InitEntityData(); |
|||
void GenerateLayerFiles( ODB_TREE_WRITER& writer ); |
|||
void GenerateEdaFiles( ODB_TREE_WRITER& writer ); |
|||
void GenerateNetlistsFiles( ODB_TREE_WRITER& writer ); |
|||
void GenerateProfileFile( ODB_TREE_WRITER& writer ); |
|||
void GenerateStepHeaderFile( ODB_TREE_WRITER& writer ); |
|||
|
|||
virtual void GenerateFiles( ODB_TREE_WRITER& writer ); |
|||
|
|||
private: |
|||
// ODB_ATTRLIST m_attrList; |
|||
std::map<wxString, std::shared_ptr<ODB_LAYER_ENTITY>> m_layerEntityMap; |
|||
std::unique_ptr<FEATURES_MANAGER> m_profile; |
|||
|
|||
EDA_DATA m_edaData; |
|||
std::unordered_map<wxString, wxString> m_stephdr; |
|||
ODB_NET_LIST m_netlist; |
|||
}; |
|||
|
|||
|
|||
class ODB_LAYER_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_LAYER_ENTITY( BOARD* aBoard, PCB_IO_ODBPP* aPlugin, |
|||
std::map<int, std::vector<BOARD_ITEM*>>& aMap, const PCB_LAYER_ID& aLayerID, |
|||
const wxString& aLayerName ); |
|||
|
|||
virtual ~ODB_LAYER_ENTITY() = default; |
|||
|
|||
inline virtual std::string GetEntityName() { return "layers"; } |
|||
virtual void InitEntityData(); |
|||
void InitFeatureData(); |
|||
ODB_COMPONENT& InitComponentData( const FOOTPRINT* aFp, const EDA_DATA::PACKAGE& aPkg ); |
|||
void InitDrillData(); |
|||
|
|||
void AddLayerFeatures(); |
|||
|
|||
|
|||
void GenAttrList( ODB_TREE_WRITER& writer ); |
|||
void GenComponents( ODB_TREE_WRITER& writer ); |
|||
void GenTools( ODB_TREE_WRITER& writer ); |
|||
|
|||
void GenFeatures( ODB_TREE_WRITER& writer ); |
|||
|
|||
virtual void GenerateFiles( ODB_TREE_WRITER& writer ); |
|||
|
|||
private: |
|||
std::map<int, std::vector<BOARD_ITEM*>> m_layerItems; |
|||
PCB_LAYER_ID m_layerID; |
|||
wxString m_matrixLayerName; |
|||
// ODB_ATTRLIST m_attrList; |
|||
std::optional<ODB_DRILL_TOOLS> m_tools; |
|||
std::optional<COMPONENTS_MANAGER> m_compTop; |
|||
std::optional<COMPONENTS_MANAGER> m_compBot; |
|||
std::unique_ptr<FEATURES_MANAGER> m_featuresMgr; |
|||
}; |
|||
|
|||
class ODB_SYMBOLS_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_SYMBOLS_ENTITY() = default; |
|||
|
|||
virtual ~ODB_SYMBOLS_ENTITY() = default; |
|||
|
|||
inline virtual std::string GetEntityName() { return "symbols"; } |
|||
|
|||
//TODO |
|||
// virtual void GenerateFiles( ODB_TREE_WRITER& writer ); |
|||
}; |
|||
|
|||
class ODB_FONTS_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_FONTS_ENTITY() = default; |
|||
virtual ~ODB_FONTS_ENTITY() = default; |
|||
|
|||
inline virtual std::string GetEntityName() { return "fonts"; } |
|||
|
|||
virtual void GenerateFiles( ODB_TREE_WRITER& writer ); |
|||
}; |
|||
|
|||
class ODB_WHEELS_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_WHEELS_ENTITY() = default; |
|||
virtual ~ODB_WHEELS_ENTITY() = default; |
|||
|
|||
inline virtual std::string GetEntityName() { return "wheels"; } |
|||
|
|||
// TODO |
|||
// virtual void GenerateFiles( ODB_TREE_WRITER& writer ); |
|||
}; |
|||
|
|||
class ODB_INPUT_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_INPUT_ENTITY() = default; |
|||
virtual ~ODB_INPUT_ENTITY() = default; |
|||
|
|||
inline virtual std::string GetEntityName() { return "input"; } |
|||
|
|||
// TODO |
|||
// virtual void GenerateFiles( ODB_TREE_WRITER &writer ); |
|||
}; |
|||
|
|||
class ODB_USER_ENTITY : public ODB_ENTITY_BASE |
|||
{ |
|||
public: |
|||
ODB_USER_ENTITY() = default; |
|||
virtual ~ODB_USER_ENTITY() = default; |
|||
|
|||
inline virtual std::string GetEntityName() { return "user"; } |
|||
|
|||
// TODO |
|||
// virtual void GenerateFiles( ODB_TREE_WRITER &writer ); |
|||
}; |
|||
|
|||
#endif // _ODB_ENTITY_H_ |
1002
pcbnew/pcb_io/odbpp/odb_feature.cpp
File diff suppressed because it is too large
View File
@ -0,0 +1,349 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
|
|||
#ifndef _ODB_FEATURE_H_ |
|||
#define _ODB_FEATURE_H_ |
|||
|
|||
#include "odb_attribute.h" |
|||
#include "pad.h" |
|||
#include "convert_basic_shapes_to_polygon.h" |
|||
#include "footprint.h" |
|||
#include <list> |
|||
#include "math/vector2d.h" |
|||
#include "odb_defines.h" |
|||
|
|||
|
|||
enum class ODB_DIRECTION |
|||
{ |
|||
CW, |
|||
CCW |
|||
}; |
|||
|
|||
|
|||
class ODB_LINE; |
|||
class ODB_ARC; |
|||
class ODB_PAD; |
|||
class ODB_SURFACE; |
|||
class ODB_FEATURE; |
|||
class PCB_IO_ODBPP; |
|||
class PCB_VIA; |
|||
|
|||
class FEATURES_MANAGER : public ATTR_MANAGER |
|||
{ |
|||
public: |
|||
FEATURES_MANAGER( BOARD* aBoard, PCB_IO_ODBPP* aPlugin, const wxString& aLayerName ) : |
|||
m_board( aBoard ), m_plugin( aPlugin ), m_layerName( aLayerName ) |
|||
{ |
|||
} |
|||
|
|||
virtual ~FEATURES_MANAGER() { m_featuresList.clear(); } |
|||
|
|||
void InitFeatureList( PCB_LAYER_ID aLayer, std::vector<BOARD_ITEM*>& aItems ); |
|||
|
|||
void AddFeatureLine( const VECTOR2I& aStart, const VECTOR2I& aEnd, uint64_t aWidth ); |
|||
|
|||
void AddFeatureArc( const VECTOR2I& aStart, const VECTOR2I& aEnd, const VECTOR2I& aCenter, |
|||
uint64_t aWidth, ODB_DIRECTION aDirection ); |
|||
|
|||
void AddPadCircle( const VECTOR2I& aCenter, uint64_t aDiameter, const EDA_ANGLE& aAngle, |
|||
bool aMirror, double aResize = 1.0 ); |
|||
|
|||
void AddPadShape( const PAD& aPad, PCB_LAYER_ID aLayer ); |
|||
|
|||
void AddFeatureSurface( const SHAPE_POLY_SET::POLYGON& aPolygon, |
|||
FILL_T aFillType = FILL_T::FILLED_SHAPE ); |
|||
|
|||
void AddShape( const PCB_SHAPE& aShape, PCB_LAYER_ID aLayer = UNDEFINED_LAYER ); |
|||
|
|||
void AddVia( const PCB_VIA* aVia, PCB_LAYER_ID aLayer ); |
|||
|
|||
void AddViaDrillHole( const PCB_VIA* aVia, PCB_LAYER_ID aLayer ); |
|||
|
|||
bool AddContour( const SHAPE_POLY_SET& aPolySet, int aOutline = 0, |
|||
FILL_T aFillType = FILL_T::FILLED_SHAPE ); |
|||
|
|||
bool AddPolygon( const SHAPE_POLY_SET::POLYGON& aPolygon, FILL_T aFillType, int aWidth, |
|||
LINE_STYLE aDashType ); |
|||
|
|||
bool AddPolygonCutouts( const SHAPE_POLY_SET::POLYGON& aPolygon ); |
|||
|
|||
void GenerateFeatureFile( std::ostream& ost ) const; |
|||
|
|||
void GenerateProfileFeatures( std::ostream& ost ) const; |
|||
|
|||
private: |
|||
inline uint32_t AddCircleSymbol( const wxString& aDiameter ) |
|||
{ |
|||
return GetSymbolIndex( m_circleSymMap, "r" + aDiameter ); |
|||
} |
|||
|
|||
uint32_t AddRoundDonutSymbol( const wxString& aOuterDim, const wxString& aInnerDim ) |
|||
{ |
|||
wxString sym = "donut_r" + aOuterDim + ODB_DIM_X + aInnerDim; |
|||
return GetSymbolIndex( m_roundDonutSymMap, sym ); |
|||
} |
|||
|
|||
uint32_t AddRectSymbol( const wxString& aWidth, const wxString& aHeight ) |
|||
{ |
|||
wxString sym = "rect" + aWidth + ODB_DIM_X + aHeight; |
|||
return GetSymbolIndex( m_rectSymMap, sym ); |
|||
} |
|||
|
|||
uint32_t AddOvalSymbol( const wxString& aWidth, const wxString& aHeight ) |
|||
{ |
|||
wxString sym = "oval" + aWidth + ODB_DIM_X + aHeight; |
|||
return GetSymbolIndex( m_ovalSymMap, sym ); |
|||
} |
|||
|
|||
uint32_t AddRoundRectSymbol( const wxString& aWidth, const wxString& aHeight, |
|||
const wxString& aRadius ) |
|||
{ |
|||
wxString sym = "rect" + aWidth + ODB_DIM_X + aHeight + ODB_DIM_X + ODB_DIM_R + aRadius; |
|||
return GetSymbolIndex( m_roundRectSymMap, sym ); |
|||
} |
|||
|
|||
uint32_t AddRoundRectDonutSymbol( const wxString& aOuterWidth, const wxString& aOuterHeight, |
|||
const wxString& aLineWidth, const wxString& aRadius ) |
|||
{ |
|||
wxString sym = "donut_rc" + aOuterWidth + ODB_DIM_X + aOuterHeight + ODB_DIM_X + aLineWidth |
|||
+ ODB_DIM_X + ODB_DIM_R + aRadius; |
|||
return GetSymbolIndex( m_roundRectDonutSymMap, sym ); |
|||
} |
|||
|
|||
uint32_t AddChamferRectSymbol( const wxString& aWidth, const wxString& aHeight, |
|||
const wxString& aRadius, int aPositions ) |
|||
{ |
|||
wxString sym = "rect" + aWidth + ODB_DIM_X + aHeight + ODB_DIM_X + ODB_DIM_C + aRadius; |
|||
|
|||
if( aPositions != RECT_CHAMFER_ALL ) |
|||
{ |
|||
sym += ODB_DIM_X; |
|||
if( aPositions & RECT_CHAMFER_TOP_RIGHT ) |
|||
sym += "1"; |
|||
if( aPositions & RECT_CHAMFER_TOP_LEFT ) |
|||
sym += "2"; |
|||
if( aPositions & RECT_CHAMFER_BOTTOM_LEFT ) |
|||
sym += "3"; |
|||
if( aPositions & RECT_CHAMFER_BOTTOM_RIGHT ) |
|||
sym += "4"; |
|||
} |
|||
|
|||
return GetSymbolIndex( m_chamRectSymMap, sym ); |
|||
} |
|||
|
|||
|
|||
uint32_t GetSymbolIndex( std::map<wxString, uint32_t>& aSymMap, const wxString& aKey ) |
|||
{ |
|||
if( aSymMap.count( aKey ) ) |
|||
{ |
|||
return aSymMap.at( aKey ); |
|||
} |
|||
else |
|||
{ |
|||
uint32_t index = m_symIndex; |
|||
m_symIndex++; |
|||
aSymMap.emplace( aKey, index ); |
|||
m_allSymMap.emplace( index, aKey ); |
|||
return index; |
|||
} |
|||
} |
|||
|
|||
std::map<wxString, uint32_t> m_circleSymMap; // diameter -> symbol index |
|||
std::map<wxString, uint32_t> m_roundDonutSymMap; |
|||
std::map<wxString, uint32_t> m_padSymMap; // name -> symbol index |
|||
std::map<wxString, uint32_t> m_rectSymMap; // w,h -> symbol index |
|||
std::map<wxString, uint32_t> m_ovalSymMap; // w,h -> symbol index |
|||
std::map<wxString, uint32_t> m_roundRectSymMap; |
|||
std::map<wxString, uint32_t> m_roundRectDonutSymMap; |
|||
std::map<wxString, uint32_t> m_chamRectSymMap; |
|||
|
|||
std::map<uint32_t, wxString> m_allSymMap; |
|||
|
|||
template <typename T, typename... Args> |
|||
void AddFeature( Args&&... args ) |
|||
{ |
|||
auto feature = std::make_unique<T>( m_featuresList.size(), std::forward<Args>( args )... ); |
|||
|
|||
m_featuresList.emplace_back( std::move( feature ) ); |
|||
} |
|||
|
|||
inline PCB_IO_ODBPP* GetODBPlugin() { return m_plugin; } |
|||
|
|||
BOARD* m_board; |
|||
PCB_IO_ODBPP* m_plugin; |
|||
wxString m_layerName; |
|||
uint32_t m_symIndex = 0; |
|||
|
|||
std::list<std::unique_ptr<ODB_FEATURE>> m_featuresList; |
|||
std::map<BOARD_ITEM*, std::vector<uint32_t>> m_featureIDMap; |
|||
}; |
|||
|
|||
|
|||
class ODB_FEATURE : public ATTR_RECORD_WRITER |
|||
{ |
|||
public: |
|||
// template <typename T> using check_type = attribute::is_feature<T>; |
|||
ODB_FEATURE( uint32_t aIndex ) : m_index( aIndex ) {} |
|||
virtual void WriteFeatures( std::ostream& ost ); |
|||
|
|||
virtual ~ODB_FEATURE() = default; |
|||
|
|||
protected: |
|||
enum class FEATURE_TYPE |
|||
{ |
|||
LINE, |
|||
ARC, |
|||
PAD, |
|||
SURFACE |
|||
}; |
|||
|
|||
virtual FEATURE_TYPE GetFeatureType() = 0; |
|||
|
|||
virtual void WriteRecordContent( std::ostream& ost ) = 0; |
|||
|
|||
const uint32_t m_index; |
|||
}; |
|||
|
|||
class ODB_LINE : public ODB_FEATURE |
|||
{ |
|||
public: |
|||
ODB_LINE( uint32_t aIndex, const std::pair<wxString, wxString>& aStart, |
|||
const std::pair<wxString, wxString>& aEnd, uint32_t aSym ) : |
|||
ODB_FEATURE( aIndex ), m_start( aStart ), m_end( aEnd ), m_symIndex( aSym ) |
|||
{ |
|||
} |
|||
|
|||
inline virtual FEATURE_TYPE GetFeatureType() override { return FEATURE_TYPE::LINE; } |
|||
|
|||
protected: |
|||
virtual void WriteRecordContent( std::ostream& ost ) override; |
|||
|
|||
private: |
|||
std::pair<wxString, wxString> m_start; |
|||
std::pair<wxString, wxString> m_end; |
|||
uint32_t m_symIndex; |
|||
}; |
|||
|
|||
|
|||
class ODB_ARC : public ODB_FEATURE |
|||
{ |
|||
public: |
|||
inline virtual FEATURE_TYPE GetFeatureType() override { return FEATURE_TYPE::ARC; } |
|||
|
|||
|
|||
ODB_ARC( uint32_t aIndex, const std::pair<wxString, wxString>& aStart, |
|||
const std::pair<wxString, wxString>& aEnd, |
|||
const std::pair<wxString, wxString>& aCenter, uint32_t aSym, |
|||
ODB_DIRECTION aDirection ) : |
|||
ODB_FEATURE( aIndex ), m_start( aStart ), m_end( aEnd ), m_center( aCenter ), |
|||
m_symIndex( aSym ), m_direction( aDirection ) |
|||
{ |
|||
} |
|||
|
|||
protected: |
|||
virtual void WriteRecordContent( std::ostream& ost ) override; |
|||
|
|||
private: |
|||
std::pair<wxString, wxString> m_start; |
|||
std::pair<wxString, wxString> m_end; |
|||
std::pair<wxString, wxString> m_center; |
|||
uint32_t m_symIndex; |
|||
ODB_DIRECTION m_direction; |
|||
}; |
|||
|
|||
class ODB_PAD : public ODB_FEATURE |
|||
{ |
|||
public: |
|||
ODB_PAD( uint32_t aIndex, const std::pair<wxString, wxString>& aCenter, uint32_t aSym, |
|||
EDA_ANGLE aAngle = ANGLE_0, bool aMirror = false, double aResize = 1.0 ) : |
|||
ODB_FEATURE( aIndex ), m_center( aCenter ), m_symIndex( aSym ), m_angle( aAngle ), |
|||
m_mirror( aMirror ), m_resize( aResize ) |
|||
{ |
|||
} |
|||
|
|||
inline virtual FEATURE_TYPE GetFeatureType() override { return FEATURE_TYPE::PAD; } |
|||
|
|||
protected: |
|||
virtual void WriteRecordContent( std::ostream& ost ) override; |
|||
|
|||
private: |
|||
std::pair<wxString, wxString> m_center; |
|||
uint32_t m_symIndex; |
|||
EDA_ANGLE m_angle; |
|||
bool m_mirror; |
|||
double m_resize; |
|||
}; |
|||
|
|||
class ODB_SURFACE_DATA; |
|||
class ODB_SURFACE : public ODB_FEATURE |
|||
{ |
|||
public: |
|||
ODB_SURFACE( uint32_t aIndex, const SHAPE_POLY_SET::POLYGON& aPolygon, |
|||
FILL_T aFillType = FILL_T::FILLED_SHAPE ); |
|||
|
|||
virtual ~ODB_SURFACE() = default; |
|||
|
|||
inline virtual FEATURE_TYPE GetFeatureType() override { return FEATURE_TYPE::SURFACE; } |
|||
|
|||
std::unique_ptr<ODB_SURFACE_DATA> m_surfaces; |
|||
|
|||
protected: |
|||
virtual void WriteRecordContent( std::ostream& ost ) override; |
|||
}; |
|||
|
|||
|
|||
class ODB_SURFACE_DATA |
|||
{ |
|||
public: |
|||
ODB_SURFACE_DATA( const SHAPE_POLY_SET::POLYGON& aPolygon ); |
|||
|
|||
struct SURFACE_LINE |
|||
{ |
|||
enum class LINE_TYPE |
|||
{ |
|||
SEGMENT, |
|||
ARC |
|||
}; |
|||
SURFACE_LINE() = default; |
|||
|
|||
SURFACE_LINE( const VECTOR2I& aEnd ) : m_end( aEnd ) {} |
|||
|
|||
SURFACE_LINE( const VECTOR2I& aEnd, const VECTOR2I& aCenter, ODB_DIRECTION aDirection ) : |
|||
m_end( aEnd ), m_type( LINE_TYPE::ARC ), m_center( aCenter ), |
|||
m_direction( aDirection ) |
|||
{ |
|||
} |
|||
|
|||
VECTOR2I m_end; |
|||
LINE_TYPE m_type = LINE_TYPE::SEGMENT; |
|||
|
|||
VECTOR2I m_center; |
|||
ODB_DIRECTION m_direction; |
|||
}; |
|||
|
|||
void AddPolygonHoles( const SHAPE_POLY_SET::POLYGON& aPolygon ); |
|||
void WriteData( std::ostream& ost ) const; |
|||
|
|||
std::vector<std::vector<SURFACE_LINE>> m_polygons; |
|||
}; |
|||
|
|||
|
|||
#endif // _ODB_FEATURE_H_ |
@ -0,0 +1,671 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <string.h>
|
|||
#include "odb_entity.h"
|
|||
|
|||
const std::string odb_fonts1 = R"( |
|||
XSIZE 0.302000 |
|||
YSIZE 0.302000 |
|||
OFFSET 0.000000 |
|||
CHAR ! |
|||
LINE 0.000000 0.000000 0.000000 0.200000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.000000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR " |
|||
LINE -0.050000 0.100000 -0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.050000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR # |
|||
LINE -0.050000 -0.100000 -0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.050000 0.200000 P R 0.012000 |
|||
LINE -0.100000 0.000000 0.100000 0.000000 P R 0.012000 |
|||
LINE -0.100000 0.100000 0.100000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR $ |
|||
LINE 0.000000 -0.100000 0.000000 0.200000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 0.050000 -0.050000 P R 0.012000 |
|||
LINE 0.050000 -0.050000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 -0.050000 0.050000 P R 0.012000 |
|||
LINE -0.050000 0.050000 -0.100000 0.100000 P R 0.012000 |
|||
LINE -0.100000 0.100000 -0.050000 0.150000 P R 0.012000 |
|||
LINE -0.050000 0.150000 0.100000 0.150000 P R 0.012000 |
|||
ECHAR |
|||
CHAR % |
|||
LINE -0.100000 -0.100000 0.100000 0.200000 P R 0.012000 |
|||
LINE -0.075000 0.175000 -0.075000 0.175000 P R 0.012000 |
|||
LINE 0.075000 -0.075000 0.075000 -0.075000 P R 0.012000 |
|||
ECHAR |
|||
CHAR & |
|||
LINE 0.100000 -0.100000 -0.100000 0.100000 P R 0.012000 |
|||
LINE -0.100000 0.100000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.000000 0.150000 P R 0.012000 |
|||
LINE 0.000000 0.150000 0.000000 0.100000 P R 0.012000 |
|||
LINE 0.000000 0.100000 -0.100000 0.000000 P R 0.012000 |
|||
LINE -0.100000 0.000000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.100000 0.000000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ' |
|||
LINE 0.000000 0.050000 0.050000 0.150000 P R 0.012000 |
|||
LINE 0.025000 0.175000 0.025000 0.175000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ( |
|||
LINE 0.050000 -0.100000 -0.050000 0.000000 P R 0.012000 |
|||
LINE -0.050000 0.000000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 0.050000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ) |
|||
LINE -0.050000 -0.100000 0.050000 0.000000 P R 0.012000 |
|||
LINE 0.050000 0.000000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 -0.050000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR * |
|||
LINE -0.100000 -0.050000 0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.000000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR + |
|||
LINE -0.100000 0.050000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.000000 -0.050000 0.000000 0.150000 P R 0.012000 |
|||
ECHAR |
|||
CHAR , |
|||
LINE 0.000000 -0.100000 0.050000 0.000000 P R 0.012000 |
|||
LINE 0.025000 0.025000 0.025000 0.025000 P R 0.012000 |
|||
ECHAR |
|||
CHAR - |
|||
LINE -0.100000 0.050000 0.100000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR . |
|||
LINE 0.025000 -0.075000 0.025000 -0.075000 P R 0.012000 |
|||
ECHAR |
|||
CHAR / |
|||
LINE -0.100000 -0.050000 0.100000 0.150000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 0 |
|||
LINE -0.100000 -0.050000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 0.100000 0.150000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 1 |
|||
LINE -0.050000 0.150000 0.000000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.200000 0.000000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 2 |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 0.100000 P R 0.012000 |
|||
LINE 0.100000 0.100000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 0.000000 0.050000 P R 0.012000 |
|||
LINE 0.000000 0.050000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 3 |
|||
LINE -0.100000 0.200000 0.100000 0.200000 P R 0.012000 |
|||
LINE 0.100000 0.200000 0.100000 0.100000 P R 0.012000 |
|||
LINE 0.100000 0.100000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 0.000000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 4 |
|||
LINE 0.050000 -0.100000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 -0.100000 0.000000 P R 0.012000 |
|||
LINE -0.100000 0.000000 0.100000 0.000000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 5 |
|||
LINE 0.100000 0.200000 -0.100000 0.200000 P R 0.012000 |
|||
LINE -0.100000 0.200000 -0.100000 0.100000 P R 0.012000 |
|||
LINE -0.100000 0.100000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 6 |
|||
LINE 0.100000 0.200000 0.000000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.200000 -0.100000 0.100000 P R 0.012000 |
|||
LINE -0.100000 0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 -0.100000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 7 |
|||
LINE -0.100000 0.200000 0.100000 0.200000 P R 0.012000 |
|||
LINE 0.100000 0.200000 -0.050000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 8 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.050000 0.050000 0.050000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.100000 0.100000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 0.100000 P R 0.012000 |
|||
LINE -0.100000 0.000000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE -0.050000 0.200000 -0.100000 0.150000 P R 0.012000 |
|||
LINE 0.050000 0.050000 0.100000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.050000 -0.100000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.050000 0.100000 0.000000 P R 0.012000 |
|||
LINE -0.050000 0.050000 -0.100000 0.000000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR 9 |
|||
LINE -0.100000 -0.100000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.100000 0.100000 P R 0.012000 |
|||
LINE -0.100000 0.100000 -0.050000 0.050000 P R 0.012000 |
|||
LINE -0.050000 0.050000 0.100000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR : |
|||
LINE 0.000000 0.012000 0.000000 0.012000 P R 0.012000 |
|||
LINE 0.000000 -0.025000 0.000000 -0.025000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ; |
|||
LINE 0.000000 0.025000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 0.025000 0.000000 0.025000 P R 0.012000 |
|||
LINE 0.000000 0.175000 0.000000 0.175000 P R 0.012000 |
|||
ECHAR |
|||
CHAR < |
|||
LINE 0.100000 0.200000 -0.050000 0.050000 P R 0.012000 |
|||
LINE -0.050000 0.050000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR = |
|||
LINE -0.100000 0.100000 0.100000 0.100000 P R 0.012000 |
|||
LINE -0.100000 0.000000 0.100000 0.000000 P R 0.012000 |
|||
ECHAR |
|||
CHAR > |
|||
LINE -0.100000 0.200000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 -0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ? |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.000000 0.050000 P R 0.012000 |
|||
LINE 0.000000 0.050000 0.000000 0.000000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.000000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR @ |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.000000 0.000000 P R 0.012000 |
|||
LINE 0.000000 0.000000 0.000000 0.100000 P R 0.012000 |
|||
LINE 0.000000 0.100000 0.100000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR A |
|||
LINE -0.100000 -0.100000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 0.050000 0.100000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR B |
|||
LINE -0.100000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 0.100000 P R 0.012000 |
|||
LINE 0.100000 0.100000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.050000 0.050000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR C |
|||
LINE 0.100000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
ECHAR |
|||
CHAR D |
|||
LINE -0.100000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.050000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR E |
|||
LINE -0.100000 0.200000 0.100000 0.200000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 0.050000 0.050000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR F |
|||
LINE -0.100000 0.200000 0.100000 0.200000 P R 0.012000 |
|||
LINE -0.100000 0.050000 0.050000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR G |
|||
LINE -0.050000 0.200000 0.100000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 -0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.050000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR H |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 0.200000 0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 0.050000 0.100000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR I |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 0.200000 0.000000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR J |
|||
LINE 0.100000 0.200000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR K |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 0.200000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR L |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR M |
|||
LINE -0.100000 -0.100000 -0.100000 0.200000 P R 0.012000 |
|||
LINE -0.100000 0.200000 0.000000 0.050000 P R 0.012000 |
|||
LINE 0.000000 0.050000 0.100000 0.200000 P R 0.012000 |
|||
LINE 0.100000 0.200000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR N |
|||
LINE -0.100000 -0.100000 -0.100000 0.200000 P R 0.012000 |
|||
LINE -0.100000 0.200000 0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 -0.100000 0.100000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR O |
|||
LINE -0.100000 -0.050000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR P |
|||
LINE -0.100000 -0.100000 -0.100000 0.200000 P R 0.012000 |
|||
LINE -0.100000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 0.100000 P R 0.012000 |
|||
LINE 0.100000 0.100000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 -0.100000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR Q |
|||
LINE -0.100000 -0.050000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.000000 0.000000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR R |
|||
LINE -0.100000 -0.100000 -0.100000 0.200000 P R 0.012000 |
|||
LINE -0.100000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE 0.100000 0.150000 0.100000 0.100000 P R 0.012000 |
|||
LINE 0.100000 0.100000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.050000 0.050000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR S |
|||
LINE -0.100000 -0.050000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.050000 0.050000 P R 0.012000 |
|||
LINE 0.050000 0.050000 -0.050000 0.050000 P R 0.012000 |
|||
LINE -0.050000 0.050000 -0.100000 0.100000 P R 0.012000 |
|||
LINE -0.100000 0.100000 -0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
ECHAR |
|||
CHAR T |
|||
LINE -0.100000 0.200000 0.100000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.200000 0.000000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR U |
|||
LINE -0.100000 0.200000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.100000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR V |
|||
LINE -0.100000 0.200000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.100000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR W |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.000000 0.050000 P R 0.012000 |
|||
LINE 0.000000 0.050000 0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 -0.100000 0.100000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR X |
|||
LINE -0.100000 0.200000 0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.100000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR Y |
|||
LINE -0.100000 0.200000 0.000000 0.050000 P R 0.012000 |
|||
LINE 0.000000 0.050000 0.100000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.050000 0.000000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR Z |
|||
LINE -0.100000 0.200000 0.100000 0.200000 P R 0.012000 |
|||
LINE 0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR [ |
|||
LINE 0.050000 0.200000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
ECHAR)"; |
|||
|
|||
const std::string odb_fonts2 = R"( |
|||
CHAR \ |
|||
LINE -0.100000 0.200000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ] |
|||
LINE -0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ^ |
|||
LINE -0.100000 0.100000 0.000000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.200000 0.100000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR _ |
|||
LINE -0.100000 -0.100000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ` |
|||
LINE -0.050000 0.200000 0.000000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR a |
|||
LINE -0.050000 0.100000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.050000 0.000000 P R 0.012000 |
|||
LINE -0.050000 0.000000 0.100000 0.000000 P R 0.012000 |
|||
ECHAR |
|||
CHAR b |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.000000 0.100000 P R 0.012000 |
|||
LINE 0.000000 0.100000 -0.100000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR c |
|||
LINE 0.100000 0.100000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR d |
|||
LINE 0.100000 0.200000 0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 0.000000 0.100000 P R 0.012000 |
|||
LINE 0.000000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR e |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.050000 0.000000 P R 0.012000 |
|||
LINE 0.050000 0.000000 -0.100000 0.000000 P R 0.012000 |
|||
ECHAR |
|||
CHAR f |
|||
LINE -0.050000 -0.100000 -0.050000 0.150000 P R 0.012000 |
|||
LINE -0.050000 0.150000 0.000000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.100000 0.150000 P R 0.012000 |
|||
LINE -0.100000 0.050000 0.000000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR g |
|||
LINE -0.050000 -0.150000 0.050000 -0.150000 P R 0.012000 |
|||
LINE 0.050000 -0.150000 0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 -0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.100000 0.000000 P R 0.012000 |
|||
LINE -0.100000 0.000000 -0.050000 -0.050000 P R 0.012000 |
|||
LINE -0.050000 -0.050000 0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR h |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 0.050000 0.000000 0.100000 P R 0.012000 |
|||
LINE 0.000000 0.100000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR i |
|||
LINE 0.000000 0.100000 0.000000 -0.050000 P R 0.012000 |
|||
LINE 0.000000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 0.200000 0.000000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR j |
|||
LINE 0.050000 0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.000000 -0.150000 P R 0.012000 |
|||
LINE 0.000000 -0.150000 -0.050000 -0.150000 P R 0.012000 |
|||
LINE -0.050000 -0.150000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 0.200000 0.050000 0.200000 P R 0.012000 |
|||
ECHAR |
|||
CHAR k |
|||
LINE -0.100000 0.200000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 0.000000 0.000000 0.000000 P R 0.012000 |
|||
LINE 0.000000 0.000000 0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 0.000000 0.050000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR l |
|||
LINE -0.050000 0.200000 0.000000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.200000 0.000000 -0.050000 P R 0.012000 |
|||
LINE 0.000000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR m |
|||
LINE -0.100000 -0.100000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 0.000000 0.050000 P R 0.012000 |
|||
LINE 0.000000 0.050000 0.000000 0.000000 P R 0.012000 |
|||
LINE 0.000000 0.050000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR n |
|||
LINE -0.100000 0.100000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 0.000000 0.000000 0.100000 P R 0.012000 |
|||
LINE 0.000000 0.100000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR o |
|||
LINE -0.100000 -0.050000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR p |
|||
LINE -0.100000 -0.150000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 0.000000 0.050000 -0.050000 P R 0.012000 |
|||
LINE 0.050000 -0.050000 -0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR q |
|||
LINE 0.100000 -0.150000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.100000 0.000000 P R 0.012000 |
|||
LINE -0.100000 0.000000 -0.050000 -0.050000 P R 0.012000 |
|||
LINE -0.050000 -0.050000 0.100000 -0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR r |
|||
LINE -0.100000 0.100000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 0.000000 0.000000 0.100000 P R 0.012000 |
|||
LINE 0.000000 0.100000 0.050000 0.050000 P R 0.012000 |
|||
ECHAR |
|||
CHAR s |
|||
LINE -0.100000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 -0.050000 0.050000 0.000000 P R 0.012000 |
|||
LINE 0.050000 0.000000 -0.050000 0.000000 P R 0.012000 |
|||
LINE -0.050000 0.000000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 0.100000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR t |
|||
LINE -0.050000 0.200000 -0.050000 -0.050000 P R 0.012000 |
|||
LINE -0.050000 -0.050000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 0.100000 0.050000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR u |
|||
LINE -0.100000 0.100000 -0.100000 -0.050000 P R 0.012000 |
|||
LINE -0.100000 -0.050000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.100000 0.000000 P R 0.012000 |
|||
LINE 0.100000 -0.100000 0.100000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR v |
|||
LINE -0.100000 0.100000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.100000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR w |
|||
LINE -0.100000 0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
LINE -0.050000 -0.100000 0.000000 0.000000 P R 0.012000 |
|||
LINE 0.000000 0.000000 0.050000 -0.100000 P R 0.012000 |
|||
LINE 0.050000 -0.100000 0.100000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR x |
|||
LINE -0.100000 0.100000 0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.100000 0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR y |
|||
LINE -0.100000 0.100000 -0.100000 0.000000 P R 0.012000 |
|||
LINE -0.100000 0.000000 -0.050000 -0.050000 P R 0.012000 |
|||
LINE -0.050000 -0.050000 0.100000 -0.050000 P R 0.012000 |
|||
LINE 0.100000 0.100000 0.100000 -0.100000 P R 0.012000 |
|||
LINE 0.100000 -0.100000 0.050000 -0.150000 P R 0.012000 |
|||
LINE 0.050000 -0.150000 -0.050000 -0.150000 P R 0.012000 |
|||
ECHAR |
|||
CHAR z |
|||
LINE -0.100000 0.100000 0.100000 0.100000 P R 0.012000 |
|||
LINE 0.100000 0.100000 -0.100000 -0.100000 P R 0.012000 |
|||
LINE -0.100000 -0.100000 0.100000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR { |
|||
LINE 0.050000 0.200000 0.000000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.200000 -0.050000 0.150000 P R 0.012000 |
|||
LINE -0.050000 0.150000 -0.050000 0.100000 P R 0.012000 |
|||
LINE -0.050000 0.100000 -0.100000 0.050000 P R 0.012000 |
|||
LINE -0.100000 0.050000 -0.050000 0.000000 P R 0.012000 |
|||
LINE -0.050000 0.000000 -0.050000 -0.050000 P R 0.012000 |
|||
LINE -0.050000 -0.050000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 0.050000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR | |
|||
LINE 0.000000 0.200000 0.000000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR } |
|||
LINE -0.050000 0.200000 0.000000 0.200000 P R 0.012000 |
|||
LINE 0.000000 0.200000 0.050000 0.150000 P R 0.012000 |
|||
LINE 0.050000 0.150000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.050000 P R 0.012000 |
|||
LINE 0.100000 0.050000 0.050000 0.000000 P R 0.012000 |
|||
LINE 0.050000 0.000000 0.050000 -0.050000 P R 0.012000 |
|||
LINE 0.050000 -0.050000 0.000000 -0.100000 P R 0.012000 |
|||
LINE 0.000000 -0.100000 -0.050000 -0.100000 P R 0.012000 |
|||
ECHAR |
|||
CHAR ~ |
|||
LINE -0.100000 0.150000 -0.050000 0.200000 P R 0.012000 |
|||
LINE -0.050000 0.200000 0.050000 0.100000 P R 0.012000 |
|||
LINE 0.050000 0.100000 0.100000 0.150000 P R 0.012000 |
|||
ECHAR)"; |
|||
|
|||
// just implementation here
|
|||
void ODB_FONTS_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
auto fileproxy = writer.CreateFileProxy( "standard" ); |
|||
|
|||
fileproxy.GetStream() << odb_fonts1 << odb_fonts2 << std::endl; |
|||
} |
@ -0,0 +1,285 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
|
|||
#include <confirm.h>
|
|||
#include <gestfich.h>
|
|||
#include <kiface_base.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <trigo.h>
|
|||
#include <build_version.h>
|
|||
#include <macros.h>
|
|||
#include <wildcards_and_files_ext.h>
|
|||
#include <locale_io.h>
|
|||
#include <board.h>
|
|||
#include <board_design_settings.h>
|
|||
#include <footprint.h>
|
|||
#include <pad.h>
|
|||
#include <pcb_track.h>
|
|||
#include <vector>
|
|||
#include <cctype>
|
|||
#include <odb_netlist.h>
|
|||
#include <wx/filedlg.h>
|
|||
#include <wx/log.h>
|
|||
#include "odb_util.h"
|
|||
|
|||
|
|||
// Compute the side code for a pad. Returns "" if there is no copper
|
|||
std::string ODB_NET_LIST::ComputePadAccessSide( BOARD* aBoard, LSET aLayerMask ) |
|||
{ |
|||
// Non-copper is not interesting here
|
|||
aLayerMask &= LSET::AllCuMask(); |
|||
if( !aLayerMask.any() ) |
|||
return ""; |
|||
|
|||
// Traditional TH pad
|
|||
if( aLayerMask[F_Cu] && aLayerMask[B_Cu] ) |
|||
return "B"; |
|||
|
|||
// Front SMD pad
|
|||
if( aLayerMask[F_Cu] ) |
|||
return "T"; |
|||
|
|||
// Back SMD pad
|
|||
if( aLayerMask[B_Cu] ) |
|||
return "D"; |
|||
|
|||
// Inner
|
|||
for( int layer = In1_Cu; layer < B_Cu; ++layer ) |
|||
{ |
|||
if( aLayerMask[layer] ) |
|||
return "I"; |
|||
} |
|||
|
|||
// This shouldn't happen
|
|||
wxLogDebug( "Unhandled layer mask input when compute pad access side of ODB++ netlist file." ); |
|||
return ""; |
|||
} |
|||
|
|||
|
|||
void ODB_NET_LIST::InitPadNetPoints( BOARD* aBoard, |
|||
std::map<size_t, std::vector<ODB_NET_RECORD>>& aRecords ) |
|||
{ |
|||
VECTOR2I origin = aBoard->GetDesignSettings().GetAuxOrigin(); |
|||
|
|||
for( FOOTPRINT* footprint : aBoard->Footprints() ) |
|||
{ |
|||
for( PAD* pad : footprint->Pads() ) |
|||
{ |
|||
ODB_NET_RECORD net_point; |
|||
net_point.side = ComputePadAccessSide( aBoard, pad->GetLayerSet() ); |
|||
|
|||
// It could be a mask only pad, we only handle pads with copper here
|
|||
if( !net_point.side.empty() && net_point.side != "I" ) |
|||
{ |
|||
if( pad->GetNetCode() == 0 ) |
|||
net_point.netname = "$NONE$"; |
|||
else |
|||
net_point.netname = pad->GetNetname(); |
|||
// net_point.pin = pad->GetNumber();
|
|||
net_point.refdes = footprint->GetReference(); |
|||
const VECTOR2I& drill = pad->GetDrillSize(); |
|||
net_point.hole = pad->HasHole(); |
|||
|
|||
if( !net_point.hole ) |
|||
net_point.drill_radius = 0; |
|||
else |
|||
net_point.drill_radius = std::min( drill.x, drill.y ); |
|||
|
|||
net_point.smd = pad->GetAttribute() == PAD_ATTRIB::SMD |
|||
|| pad->GetAttribute() == PAD_ATTRIB::CONN; |
|||
net_point.is_via = false; |
|||
net_point.mechanical = ( pad->GetAttribute() == PAD_ATTRIB::NPTH ); |
|||
net_point.x_location = pad->GetPosition().x - origin.x; |
|||
net_point.y_location = origin.y - pad->GetPosition().y; |
|||
net_point.x_size = pad->GetSize().x; |
|||
|
|||
// Rule: round pads have y = 0
|
|||
if( pad->GetShape() == PAD_SHAPE::CIRCLE ) |
|||
net_point.y_size = net_point.x_size; |
|||
else |
|||
net_point.y_size = pad->GetSize().y; |
|||
|
|||
// net_point.rotation = ( ANGLE_360 - pad->GetOrientation() ).Normalize().AsDegrees();
|
|||
|
|||
// if( net_point.rotation < 0 )
|
|||
// net_point.rotation += 360;
|
|||
|
|||
// always output NET end point as net test point
|
|||
net_point.epoint = "e"; |
|||
|
|||
// the value indicates which sides are *not* accessible
|
|||
net_point.soldermask = 3; |
|||
|
|||
if( pad->GetLayerSet()[F_Mask] ) |
|||
net_point.soldermask &= ~1; |
|||
|
|||
if( pad->GetLayerSet()[B_Mask] ) |
|||
net_point.soldermask &= ~2; |
|||
|
|||
aRecords[pad->GetNetCode()].push_back( net_point ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Compute the side code for a via.
|
|||
std::string ODB_NET_LIST::ComputeViaAccessSide( BOARD* aBoard, int top_layer, int bottom_layer ) |
|||
{ |
|||
// Easy case for through vias: top_layer is component, bottom_layer is
|
|||
// solder, side code is Both
|
|||
if( ( top_layer == F_Cu ) && ( bottom_layer == B_Cu ) ) |
|||
return "B"; |
|||
|
|||
// Blind via, reachable from front, Top
|
|||
if( top_layer == F_Cu ) |
|||
return "T"; |
|||
|
|||
// Blind via, reachable from bottom, Down
|
|||
if( bottom_layer == B_Cu ) |
|||
return "D"; |
|||
|
|||
// It's a buried via, accessible from some inner layer, Inner
|
|||
return "I"; |
|||
} |
|||
|
|||
|
|||
void ODB_NET_LIST::InitViaNetPoints( BOARD* aBoard, |
|||
std::map<size_t, std::vector<ODB_NET_RECORD>>& aRecords ) |
|||
{ |
|||
VECTOR2I origin = aBoard->GetDesignSettings().GetAuxOrigin(); |
|||
|
|||
// Enumerate all the track segments and keep the vias
|
|||
for( auto track : aBoard->Tracks() ) |
|||
{ |
|||
if( track->Type() == PCB_VIA_T ) |
|||
{ |
|||
PCB_VIA* via = static_cast<PCB_VIA*>( track ); |
|||
PCB_LAYER_ID top_layer, bottom_layer; |
|||
|
|||
via->LayerPair( &top_layer, &bottom_layer ); |
|||
|
|||
ODB_NET_RECORD net_point; |
|||
net_point.side = ComputeViaAccessSide( aBoard, top_layer, bottom_layer ); |
|||
|
|||
if( net_point.side != "I" ) |
|||
{ |
|||
NETINFO_ITEM* net = track->GetNet(); |
|||
net_point.smd = false; |
|||
net_point.hole = true; |
|||
|
|||
if( net->GetNetCode() == 0 ) |
|||
net_point.netname = "$NONE$"; |
|||
else |
|||
net_point.netname = net->GetNetname(); |
|||
|
|||
net_point.refdes = "VIA"; |
|||
net_point.is_via = true; |
|||
net_point.drill_radius = via->GetDrillValue(); |
|||
net_point.mechanical = false; |
|||
net_point.x_location = via->GetPosition().x - origin.x; |
|||
net_point.y_location = origin.y - via->GetPosition().y; |
|||
|
|||
// via always has drill radius, Width and Height are 0
|
|||
net_point.x_size = 0; |
|||
net_point.y_size = 0; // Round so height = 0
|
|||
net_point.epoint = "e"; // only buried via is "m" net mid point
|
|||
|
|||
// the value indicates which sides are *not* accessible
|
|||
net_point.soldermask = 3; |
|||
|
|||
if( via->GetLayerSet()[F_Mask] ) |
|||
net_point.soldermask &= ~1; |
|||
|
|||
if( via->GetLayerSet()[B_Mask] ) |
|||
net_point.soldermask &= ~2; |
|||
|
|||
aRecords[net->GetNetCode()].push_back( net_point ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_NET_LIST::WriteNetPointRecords( std::map<size_t, std::vector<ODB_NET_RECORD>>& aRecords, |
|||
std::ostream& aStream ) |
|||
{ |
|||
aStream << "H optimize n staggered n" << std::endl; |
|||
|
|||
for( const auto& [key, vec] : aRecords ) |
|||
{ |
|||
aStream << "$" << key << " " << ODB::GenLegalNetName( vec.front().netname ) << std::endl; |
|||
} |
|||
|
|||
aStream << "#" << std::endl << "#Netlist points" << std::endl << "#" << std::endl; |
|||
|
|||
for( const auto& [key, vec] : aRecords ) |
|||
{ |
|||
for( const auto& net_point : vec ) |
|||
{ |
|||
aStream << key << " "; |
|||
|
|||
if( net_point.hole ) |
|||
aStream << ODB::Data2String( net_point.drill_radius ); |
|||
else |
|||
aStream << 0; |
|||
|
|||
aStream << " " << ODB::Data2String( net_point.x_location ) << " " |
|||
<< ODB::Data2String( net_point.y_location ) << " " << net_point.side << " "; |
|||
|
|||
if( !net_point.hole ) |
|||
aStream << ODB::Data2String( net_point.x_size ) << " " |
|||
<< ODB::Data2String( net_point.y_size ) << " "; |
|||
|
|||
std::string exp; |
|||
|
|||
if( net_point.soldermask == 3 ) |
|||
exp = "c"; |
|||
else if( net_point.soldermask == 2 ) |
|||
exp = "s"; |
|||
else if( net_point.soldermask == 1 ) |
|||
exp = "p"; |
|||
else if( net_point.soldermask == 0 ) |
|||
exp = "e"; |
|||
|
|||
aStream << net_point.epoint << " " << exp; |
|||
|
|||
if( net_point.hole ) |
|||
aStream << " staggered 0 0 0"; |
|||
|
|||
if( net_point.is_via ) |
|||
aStream << " v"; |
|||
|
|||
aStream << std::endl; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void ODB_NET_LIST::Write( std::ostream& aStream ) |
|||
{ |
|||
std::map<size_t, std::vector<ODB_NET_RECORD>> net_point_records; |
|||
|
|||
InitViaNetPoints( m_board, net_point_records ); |
|||
|
|||
InitPadNetPoints( m_board, net_point_records ); |
|||
|
|||
WriteNetPointRecords( net_point_records, aStream ); |
|||
} |
@ -0,0 +1,77 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
#ifndef _ODB_NETLIST_H_ |
|||
#define _ODB_NETLIST_H_ |
|||
|
|||
#include <wx/string.h> |
|||
|
|||
// Structure for holding the ODB net point record. |
|||
struct ODB_NET_RECORD |
|||
{ |
|||
bool smd; |
|||
bool hole; |
|||
bool is_via; |
|||
wxString netname; |
|||
std::string refdes; |
|||
int drill_radius; |
|||
bool mechanical; |
|||
std::string side; // B: Both, T: Top, D: Down |
|||
|
|||
// All these in PCB units, will be output in decimils |
|||
int x_location; |
|||
int y_location; |
|||
// Width and height of non-drilled pads (only when radius = 0). |
|||
int x_size; // Width |
|||
int y_size; // Height |
|||
// int rotation; |
|||
|
|||
std::string epoint; // e: net end point, m: net mid point |
|||
|
|||
int soldermask; // !< e — Solder mask exposed point. soldermask = 0 |
|||
// !< c — Solder mask covered point. = 3 |
|||
// !< p — Solder mask covered point on top side of product model. = 1 |
|||
// !< s — Solder mask covered point on bottom side of product model. = 2 |
|||
}; |
|||
|
|||
|
|||
class BOARD; |
|||
class ODB_NET_LIST |
|||
{ |
|||
public: |
|||
ODB_NET_LIST( BOARD* aBoard ) : m_board( aBoard ) {} |
|||
|
|||
virtual ~ODB_NET_LIST() {} |
|||
|
|||
void Write( std::ostream& aStream ); |
|||
|
|||
private: |
|||
BOARD* m_board; |
|||
std::string ComputePadAccessSide( BOARD* aBoard, LSET aLayerMask ); |
|||
std::string ComputeViaAccessSide( BOARD* aBoard, int top_layer, int bottom_layer ); |
|||
|
|||
void InitPadNetPoints( BOARD* aBoard, std::map<size_t, std::vector<ODB_NET_RECORD>>& aRecords ); |
|||
void InitViaNetPoints( BOARD* aBoard, std::map<size_t, std::vector<ODB_NET_RECORD>>& aRecords ); |
|||
/// Writes a list of records to the given output stream |
|||
void WriteNetPointRecords( std::map<size_t, std::vector<ODB_NET_RECORD>>& aRecords, |
|||
std::ostream& aStream ); |
|||
}; |
|||
|
|||
#endif // _ODB_NETLIST_H_ |
@ -0,0 +1,352 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <string>
|
|||
#include <algorithm>
|
|||
#include <locale>
|
|||
#include "odb_util.h"
|
|||
#include <wx/chartype.h>
|
|||
#include <wx/dir.h>
|
|||
#include "idf_helpers.h"
|
|||
#include "odb_defines.h"
|
|||
#include "pcb_io_odbpp.h"
|
|||
|
|||
namespace ODB |
|||
{ |
|||
|
|||
wxString GenODBString( const wxString& aStr ) |
|||
{ |
|||
wxString str; |
|||
|
|||
for( size_t ii = 0; ii < aStr.Len(); ++ii ) |
|||
{ |
|||
// Rule: we can only use the standard ASCII, control excluded
|
|||
wxUniChar ch = aStr[ii]; |
|||
|
|||
if( ch > 126 || !std::isgraph( static_cast<unsigned char>( ch ) ) ) |
|||
ch = '?'; |
|||
|
|||
str += ch; |
|||
} |
|||
|
|||
// Rule: only uppercase
|
|||
str.MakeUpper(); |
|||
|
|||
return str; |
|||
} |
|||
|
|||
|
|||
wxString GenLegalNetName( const wxString& aStr ) |
|||
{ |
|||
std::string str = aStr.ToStdString(); |
|||
wxString out; |
|||
out.reserve( str.size() ); |
|||
|
|||
for( auto c : str ) |
|||
{ |
|||
if( ( c >= 33 && c <= 126 ) && c != ';' ) |
|||
{ |
|||
out.append( 1, c ); |
|||
} |
|||
else |
|||
{ |
|||
out.append( 1, '_' ); // Replace invalid characters with underscore
|
|||
} |
|||
} |
|||
|
|||
return out; |
|||
} |
|||
|
|||
|
|||
// The names of these ODB++ entities must comply with
|
|||
// the rules for legal entity names:
|
|||
// product, model, step, layer, symbol, and attribute.
|
|||
wxString GenLegalEntityName( const wxString& aStr ) |
|||
{ |
|||
std::string str = aStr.ToStdString(); |
|||
wxString out; |
|||
out.reserve( str.size() ); |
|||
|
|||
for( auto c : str ) |
|||
{ |
|||
if( isalpha( c ) ) |
|||
c = tolower( c ); |
|||
else if( isdigit( c ) || c == '-' || c == '_' || c == '+' || c == '.' ) |
|||
; |
|||
else |
|||
c = '_'; |
|||
|
|||
out.append( 1, c ); |
|||
} |
|||
|
|||
if( out.length() > 64 ) |
|||
{ |
|||
out.Truncate( 64 ); |
|||
} |
|||
|
|||
while( !out.IsEmpty() && ( out[0] == '.' || out[0] == '-' || out[0] == '+' ) ) |
|||
{ |
|||
out.erase( 0, 1 ); |
|||
} |
|||
|
|||
while( !out.IsEmpty() && out.Last() == '.' ) |
|||
{ |
|||
out.RemoveLast(); |
|||
} |
|||
|
|||
return out; |
|||
} |
|||
|
|||
|
|||
wxString Double2String( double aVal ) |
|||
{ |
|||
// We don't want to output -0.0 as this value is just 0 for fabs
|
|||
if( aVal == -0.0 ) |
|||
aVal = 0.0; |
|||
|
|||
wxString str = wxString::FromCDouble( aVal, PCB_IO_ODBPP::m_sigfig ); |
|||
|
|||
// Remove all but the last trailing zeros from str
|
|||
while( str.EndsWith( wxT( "00" ) ) ) |
|||
str.RemoveLast(); |
|||
|
|||
return str; |
|||
} |
|||
|
|||
|
|||
std::string Double2String( double aVal, int32_t aDigits ) |
|||
{ |
|||
// We don't want to output -0.0 as this value is just 0 for fabs
|
|||
if( aVal == -0.0 ) |
|||
aVal = 0.0; |
|||
|
|||
wxString str = wxString::FromCDouble( aVal, aDigits ); |
|||
|
|||
return str.ToStdString(); |
|||
} |
|||
|
|||
|
|||
wxString SymDouble2String( double aVal ) |
|||
{ |
|||
return Double2String( PCB_IO_ODBPP::m_symbolScale * aVal ); |
|||
} |
|||
|
|||
|
|||
wxString Data2String( double aVal ) |
|||
{ |
|||
return Double2String( PCB_IO_ODBPP::m_scale * aVal ); |
|||
} |
|||
|
|||
|
|||
std::pair<wxString, wxString> AddXY( const VECTOR2I& aVec ) |
|||
{ |
|||
// TODO: to deal with user preference x y increment setting
|
|||
std::pair<wxString, wxString> xy = |
|||
std::pair<wxString, wxString>( Double2String( PCB_IO_ODBPP::m_scale * aVec.x ), |
|||
Double2String( -PCB_IO_ODBPP::m_scale * aVec.y ) ); |
|||
|
|||
return xy; |
|||
} |
|||
|
|||
|
|||
VECTOR2I GetShapePosition( const PCB_SHAPE& aShape ) |
|||
{ |
|||
VECTOR2D pos{}; |
|||
|
|||
switch( aShape.GetShape() ) |
|||
{ |
|||
// Rectangles in KiCad are mapped by their corner while ODBPP uses the center
|
|||
case SHAPE_T::RECTANGLE: |
|||
pos = aShape.GetPosition() |
|||
+ VECTOR2I( aShape.GetRectangleWidth() / 2.0, aShape.GetRectangleHeight() / 2.0 ); |
|||
break; |
|||
// Both KiCad and ODBPP use the center of the circle
|
|||
case SHAPE_T::CIRCLE: |
|||
// KiCad uses the exact points on the board
|
|||
case SHAPE_T::POLY: |
|||
case SHAPE_T::BEZIER: |
|||
case SHAPE_T::SEGMENT: |
|||
case SHAPE_T::ARC: pos = aShape.GetPosition(); break; |
|||
} |
|||
|
|||
return pos; |
|||
} |
|||
} // namespace ODB
|
|||
|
|||
|
|||
void ODB_TREE_WRITER::CreateEntityDirectory( const wxString& aPareDir, |
|||
const wxString& aSubDir /*= wxEmptyString*/ ) |
|||
{ |
|||
wxFileName path = wxFileName::DirName( aPareDir ); |
|||
|
|||
wxArrayString subDirs = wxFileName::DirName( aSubDir.Lower() ).GetDirs(); |
|||
|
|||
for( size_t i = 0; i < subDirs.GetCount(); i++ ) |
|||
path.AppendDir( subDirs[i] ); |
|||
|
|||
if( !path.DirExists() ) |
|||
{ |
|||
if( !path.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) ) |
|||
{ |
|||
throw( std::runtime_error( "Could not create directory" + path.GetPath() ) ); |
|||
} |
|||
} |
|||
|
|||
m_currentPath = path.GetPath(); |
|||
} |
|||
|
|||
|
|||
ODB_FILE_WRITER::ODB_FILE_WRITER( ODB_TREE_WRITER& aTreeWriter, const wxString& aFileName ) : |
|||
m_treeWriter( aTreeWriter ) |
|||
{ |
|||
CreateFile( aFileName ); |
|||
} |
|||
|
|||
|
|||
void ODB_FILE_WRITER::CreateFile( const wxString& aFileName ) |
|||
{ |
|||
if( aFileName.IsEmpty() || m_treeWriter.GetCurrentPath().IsEmpty() ) |
|||
return; |
|||
|
|||
wxFileName fn; |
|||
fn.SetPath( m_treeWriter.GetCurrentPath() ); |
|||
fn.SetFullName( aFileName ); |
|||
|
|||
wxString dirPath = fn.GetPath(); |
|||
|
|||
if( !wxDir::Exists( dirPath ) ) |
|||
{ |
|||
if( !wxDir::Make( dirPath ) ) |
|||
throw( std::runtime_error( "Could not create directory" + dirPath ) ); |
|||
} |
|||
|
|||
if( !fn.IsDirWritable() || ( fn.Exists() && !fn.IsFileWritable() ) ) |
|||
return; |
|||
|
|||
if( m_ostream.is_open() ) |
|||
m_ostream.close(); |
|||
|
|||
m_ostream.open( TO_UTF8( fn.GetFullPath() ), |
|||
std::ios_base::out | std::ios_base::trunc | std::ios_base::binary ); |
|||
|
|||
m_ostream.imbue( std::locale::classic() ); |
|||
|
|||
if( !m_ostream.is_open() || !m_ostream.good() ) |
|||
throw std::runtime_error( "Failed to open file: " + fn.GetFullPath() ); |
|||
} |
|||
|
|||
|
|||
bool ODB_FILE_WRITER::CloseFile() |
|||
{ |
|||
if( m_ostream.is_open() ) |
|||
{ |
|||
m_ostream.close(); |
|||
|
|||
if( !m_ostream.good() ) |
|||
{ |
|||
throw std::runtime_error( "close file failed" ); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
void ODB_TEXT_WRITER::WriteEquationLine( const std::string& var, int value ) |
|||
{ |
|||
WriteIndent(); |
|||
m_ostream << var << "=" << value << std::endl; |
|||
} |
|||
|
|||
|
|||
void ODB_TEXT_WRITER::WriteEquationLine( const wxString& var, const wxString& value ) |
|||
{ |
|||
WriteIndent(); |
|||
m_ostream << var << "=" << value << std::endl; |
|||
} |
|||
|
|||
|
|||
void ODB_TEXT_WRITER::WriteIndent() |
|||
{ |
|||
if( in_array ) |
|||
m_ostream << " "; |
|||
} |
|||
|
|||
|
|||
void ODB_TEXT_WRITER::BeginArray( const std::string& a ) |
|||
{ |
|||
if( in_array ) |
|||
throw std::runtime_error( "already in array" ); |
|||
in_array = true; |
|||
m_ostream << a << " {" << std::endl; |
|||
} |
|||
|
|||
|
|||
void ODB_TEXT_WRITER::EndArray() |
|||
{ |
|||
if( !in_array ) |
|||
throw std::runtime_error( "not in array" ); |
|||
in_array = false; |
|||
m_ostream << "}" << std::endl << std::endl; |
|||
} |
|||
|
|||
|
|||
ODB_TEXT_WRITER::ARRAY_PROXY::ARRAY_PROXY( ODB_TEXT_WRITER& aWriter, const std::string& aStr ) : |
|||
m_writer( aWriter ) |
|||
{ |
|||
m_writer.BeginArray( aStr ); |
|||
} |
|||
|
|||
|
|||
ODB_TEXT_WRITER::ARRAY_PROXY::~ARRAY_PROXY() |
|||
{ |
|||
m_writer.EndArray(); |
|||
} |
|||
|
|||
|
|||
ODB_DRILL_TOOLS::ODB_DRILL_TOOLS( const wxString& aUnits, const wxString& aThickness, |
|||
const wxString& aUserParams ) : |
|||
m_units( aUnits ), m_thickness( aThickness ), m_userParams( aUserParams ) |
|||
{ |
|||
} |
|||
|
|||
|
|||
void ODB_DRILL_TOOLS::GenerateFile( std::ostream& aStream ) |
|||
{ |
|||
ODB_TEXT_WRITER twriter( aStream ); |
|||
|
|||
twriter.WriteEquationLine( "UNITS", m_units ); |
|||
twriter.WriteEquationLine( "THICKNESS", m_thickness ); |
|||
twriter.WriteEquationLine( "USER_PARAMS", m_userParams ); |
|||
|
|||
for( const auto& tool : m_tools ) |
|||
{ |
|||
const auto array_proxy = twriter.MakeArrayProxy( "TOOLS" ); |
|||
twriter.WriteEquationLine( "NUM", tool.m_num ); |
|||
twriter.WriteEquationLine( "TYPE", tool.m_type ); |
|||
twriter.WriteEquationLine( "TYPE2", tool.m_type2 ); |
|||
twriter.WriteEquationLine( "MIN_TOL", tool.m_minTol ); |
|||
twriter.WriteEquationLine( "MAX_TOL", tool.m_maxTol ); |
|||
twriter.WriteEquationLine( "BIT", tool.m_bit ); |
|||
twriter.WriteEquationLine( "FINISH_SIZE", tool.m_finishSize ); |
|||
twriter.WriteEquationLine( "DRILL_SIZE", tool.m_drillSize ); |
|||
} |
|||
} |
@ -0,0 +1,355 @@ |
|||
#ifndef _ODB_UTIL_H_ |
|||
#define _ODB_UTIL_H_ |
|||
|
|||
#include <map> |
|||
#include <iostream> |
|||
#include <fstream> |
|||
#include <vector> |
|||
#include <string> |
|||
#include <wx/string.h> |
|||
#include "pcb_shape.h" |
|||
#include <wx/filename.h> |
|||
|
|||
|
|||
enum class ODB_POLARITY |
|||
{ |
|||
POSITIVE, |
|||
NEGATIVE |
|||
}; |
|||
|
|||
enum class ODB_CONTEXT |
|||
{ |
|||
BOARD, |
|||
MISC |
|||
}; |
|||
|
|||
enum class ODB_DIELECTRIC_TYPE |
|||
{ |
|||
NONE, |
|||
PREPREG, |
|||
CORE |
|||
}; |
|||
|
|||
enum class ODB_TYPE |
|||
{ |
|||
UNDEFINED, |
|||
|
|||
SIGNAL, |
|||
POWER_GROUND, |
|||
DIELECTRIC, |
|||
MIXED, |
|||
SOLDER_MASK, |
|||
SOLDER_PASTE, |
|||
SILK_SCREEN, |
|||
DRILL, |
|||
ROUT, |
|||
DOCUMENT, |
|||
COMPONENT, |
|||
MASK, |
|||
CONDUCTIVE_PASTE, |
|||
}; |
|||
|
|||
enum class ODB_SUBTYPE |
|||
{ |
|||
COVERLAY, |
|||
COVERCOAT, |
|||
STIFFENER, |
|||
BEND_AREA, |
|||
FLEX_AREA, |
|||
RIGID_AREA, |
|||
PSA, |
|||
SILVER_MASK, |
|||
CARBON_MASK, |
|||
}; |
|||
|
|||
enum class ODB_FID_TYPE |
|||
{ |
|||
COPPER, |
|||
LAMINATE, |
|||
HOLE |
|||
}; |
|||
|
|||
|
|||
namespace ODB |
|||
{ |
|||
wxString GenODBString( const wxString& aStr ); |
|||
|
|||
wxString GenLegalNetName( const wxString& aStr ); |
|||
|
|||
wxString GenLegalEntityName( const wxString& aStr ); |
|||
|
|||
wxString Double2String( double aVal ); |
|||
|
|||
std::string Double2String( double aVal, int32_t aDigits ); |
|||
|
|||
wxString Data2String( double aVal ); |
|||
|
|||
wxString SymDouble2String( double aVal ); |
|||
|
|||
std::pair<wxString, wxString> AddXY( const VECTOR2I& aVec ); |
|||
|
|||
VECTOR2I GetShapePosition( const PCB_SHAPE& aShape ); |
|||
|
|||
template <typename T> |
|||
class EnumStringMap |
|||
{ |
|||
public: |
|||
static std::map<T, std::string>& GetMap() |
|||
{ |
|||
static_assert( std::is_enum_v<T>, "Template parameter T must be an enum type" ); |
|||
|
|||
static std::map<T, std::string> map = []() |
|||
{ |
|||
std::map<T, std::string> result; |
|||
|
|||
if constexpr( std::is_same_v<T, ODB_POLARITY> ) |
|||
{ |
|||
result[ODB_POLARITY::POSITIVE] = "POSITIVE"; |
|||
result[ODB_POLARITY::NEGATIVE] = "NEGATIVE"; |
|||
} |
|||
|
|||
if constexpr( std::is_same_v<T, ODB_CONTEXT> ) |
|||
{ |
|||
result[ODB_CONTEXT::BOARD] = "BOARD"; |
|||
result[ODB_CONTEXT::MISC] = "MISC"; |
|||
} |
|||
|
|||
if constexpr( std::is_same_v<T, ODB_TYPE> ) |
|||
{ |
|||
//just for logical reasons.TYPE field must be defined. |
|||
result[ODB_TYPE::UNDEFINED] = ""; |
|||
|
|||
result[ODB_TYPE::SIGNAL] = "SIGNAL"; |
|||
result[ODB_TYPE::POWER_GROUND] = "POWER_GROUND"; |
|||
result[ODB_TYPE::DIELECTRIC] = "DIELECTRIC"; |
|||
result[ODB_TYPE::MIXED] = "MIXED"; |
|||
result[ODB_TYPE::SOLDER_MASK] = "SOLDER_MASK"; |
|||
result[ODB_TYPE::SOLDER_PASTE] = "SOLDER_PASTE"; |
|||
result[ODB_TYPE::SILK_SCREEN] = "SILK_SCREEN"; |
|||
result[ODB_TYPE::DRILL] = "DRILL"; |
|||
result[ODB_TYPE::ROUT] = "ROUT"; |
|||
result[ODB_TYPE::DOCUMENT] = "DOCUMENT"; |
|||
result[ODB_TYPE::COMPONENT] = "COMPONENT"; |
|||
result[ODB_TYPE::MASK] = "MASK"; |
|||
result[ODB_TYPE::CONDUCTIVE_PASTE] = "CONDUCTIVE_PASTE"; |
|||
} |
|||
|
|||
if constexpr( std::is_same_v<T, ODB_SUBTYPE> ) |
|||
{ |
|||
result[ODB_SUBTYPE::COVERLAY] = "COVERLAY"; |
|||
result[ODB_SUBTYPE::COVERCOAT] = "COVERCOAT"; |
|||
result[ODB_SUBTYPE::STIFFENER] = "STIFFENER"; |
|||
result[ODB_SUBTYPE::BEND_AREA] = "BEND_AREA"; |
|||
result[ODB_SUBTYPE::FLEX_AREA] = "FLEX_AREA"; |
|||
result[ODB_SUBTYPE::RIGID_AREA] = "RIGID_AREA"; |
|||
result[ODB_SUBTYPE::PSA] = "PSA"; |
|||
result[ODB_SUBTYPE::SILVER_MASK] = "SILVER_MASK"; |
|||
result[ODB_SUBTYPE::CARBON_MASK] = "CARBON_MASK"; |
|||
} |
|||
|
|||
if constexpr( std::is_same_v<T, ODB_DIELECTRIC_TYPE> ) |
|||
{ |
|||
result[ODB_DIELECTRIC_TYPE::NONE] = "NONE"; |
|||
result[ODB_DIELECTRIC_TYPE::PREPREG] = "PREPREG"; |
|||
result[ODB_DIELECTRIC_TYPE::CORE] = "CORE"; |
|||
} |
|||
|
|||
if constexpr( std::is_same_v<T, ODB_FID_TYPE> ) |
|||
{ |
|||
result[ODB_FID_TYPE::COPPER] = "C"; |
|||
result[ODB_FID_TYPE::LAMINATE] = "L"; |
|||
result[ODB_FID_TYPE::HOLE] = "H"; |
|||
} |
|||
|
|||
return result; |
|||
}(); |
|||
|
|||
return map; |
|||
} |
|||
}; |
|||
|
|||
template <typename T> |
|||
std::string Enum2String( T value ) |
|||
{ |
|||
const auto& map = EnumStringMap<T>::GetMap(); |
|||
auto it = map.find( value ); |
|||
if( it != map.end() ) |
|||
{ |
|||
return it->second; |
|||
} |
|||
else |
|||
{ |
|||
throw std::out_of_range( "Enum value not found in map" ); |
|||
} |
|||
} |
|||
|
|||
class CHECK_ONCE |
|||
{ |
|||
public: |
|||
bool operator()() |
|||
{ |
|||
if( first ) |
|||
{ |
|||
first = false; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private: |
|||
bool first = true; |
|||
}; |
|||
|
|||
} // namespace ODB |
|||
|
|||
class ODB_TREE_WRITER; |
|||
class ODB_FILE_WRITER |
|||
{ |
|||
public: |
|||
ODB_FILE_WRITER( ODB_TREE_WRITER& aTreeWriter, const wxString& aFileName ); |
|||
|
|||
virtual ~ODB_FILE_WRITER() { CloseFile(); } |
|||
|
|||
ODB_FILE_WRITER( ODB_FILE_WRITER&& ) = delete; |
|||
ODB_FILE_WRITER& operator=( ODB_FILE_WRITER&& ) = delete; |
|||
|
|||
ODB_FILE_WRITER( ODB_FILE_WRITER const& ) = delete; |
|||
ODB_FILE_WRITER& operator=( ODB_FILE_WRITER const& ) = delete; |
|||
|
|||
void CreateFile( const wxString& aFileName ); |
|||
bool CloseFile(); |
|||
inline std::ostream& GetStream() { return m_ostream; } |
|||
|
|||
private: |
|||
ODB_TREE_WRITER& m_treeWriter; |
|||
std::ofstream m_ostream; |
|||
}; |
|||
|
|||
|
|||
class ODB_TREE_WRITER |
|||
{ |
|||
public: |
|||
ODB_TREE_WRITER( const wxString& aDir ) : m_currentPath( aDir ) {} |
|||
|
|||
ODB_TREE_WRITER( const wxString& aPareDir, const wxString& aSubDir ) |
|||
{ |
|||
CreateEntityDirectory( aPareDir, aSubDir ); |
|||
} |
|||
|
|||
virtual ~ODB_TREE_WRITER() {} |
|||
|
|||
[[nodiscard]] ODB_FILE_WRITER CreateFileProxy( const wxString& aFileName ) |
|||
{ |
|||
return ODB_FILE_WRITER( *this, aFileName ); |
|||
} |
|||
|
|||
void CreateEntityDirectory( const wxString& aPareDir, const wxString& aSubDir = wxEmptyString ); |
|||
|
|||
inline const wxString GetCurrentPath() const { return m_currentPath; } |
|||
|
|||
inline void SetCurrentPath( const wxString& aDir ) { m_currentPath = aDir; } |
|||
|
|||
inline void SetRootPath( const wxString& aDir ) { m_rootPath = aDir; } |
|||
|
|||
inline const wxString GetRootPath() const { return m_rootPath; } |
|||
|
|||
|
|||
private: |
|||
wxString m_currentPath; |
|||
wxString m_rootPath; |
|||
}; |
|||
|
|||
|
|||
class ODB_TEXT_WRITER |
|||
{ |
|||
public: |
|||
ODB_TEXT_WRITER( std::ostream& aStream ) : m_ostream( aStream ) {} |
|||
virtual ~ODB_TEXT_WRITER() {} |
|||
|
|||
// void WriteEquationLine( const std::string &var, const std::string &value ); |
|||
void WriteEquationLine( const std::string& var, int value ); |
|||
void WriteEquationLine( const wxString& var, const wxString& value ); |
|||
template <typename T> |
|||
void write_line_enum( const std::string& var, const T& value ) |
|||
{ |
|||
WriteEquationLine( var, ODB::Enum2String( value ) ); |
|||
} |
|||
|
|||
class ARRAY_PROXY |
|||
{ |
|||
friend ODB_TEXT_WRITER; |
|||
|
|||
public: |
|||
~ARRAY_PROXY(); |
|||
|
|||
private: |
|||
ARRAY_PROXY( ODB_TEXT_WRITER& aWriter, const std::string& aStr ); |
|||
|
|||
ODB_TEXT_WRITER& m_writer; |
|||
|
|||
ARRAY_PROXY( ARRAY_PROXY&& ) = delete; |
|||
|
|||
ARRAY_PROXY& operator=( ARRAY_PROXY&& ) = delete; |
|||
|
|||
ARRAY_PROXY( ARRAY_PROXY const& ) = delete; |
|||
|
|||
ARRAY_PROXY& operator=( ARRAY_PROXY const& ) = delete; |
|||
}; |
|||
|
|||
[[nodiscard]] ARRAY_PROXY MakeArrayProxy( const std::string& aStr ) |
|||
{ |
|||
return ARRAY_PROXY( *this, aStr ); |
|||
} |
|||
|
|||
private: |
|||
void WriteIndent(); |
|||
|
|||
void BeginArray( const std::string& a ); |
|||
|
|||
void EndArray(); |
|||
|
|||
std::ostream& m_ostream; |
|||
bool in_array = false; |
|||
}; |
|||
|
|||
|
|||
class ODB_DRILL_TOOLS |
|||
{ |
|||
public: |
|||
struct TOOLS |
|||
{ |
|||
uint32_t m_num; |
|||
wxString m_type; |
|||
wxString m_type2 = wxT( "STANDARD" ); |
|||
uint32_t m_minTol; |
|||
uint32_t m_maxTol; |
|||
wxString m_bit = wxEmptyString; |
|||
wxString m_finishSize; |
|||
wxString m_drillSize; |
|||
|
|||
TOOLS() : m_num( 0 ), m_minTol( 0 ), m_maxTol( 0 ) {} |
|||
}; |
|||
|
|||
ODB_DRILL_TOOLS( const wxString& aUnits, const wxString& aThickness = "0", |
|||
const wxString& aUserParams = wxEmptyString ); |
|||
|
|||
void AddDrillTools( const wxString& aType, const wxString& aFinishSize ) |
|||
{ |
|||
TOOLS tool; |
|||
tool.m_num = m_tools.size() + 1; |
|||
tool.m_type = aType; |
|||
tool.m_finishSize = aFinishSize; |
|||
tool.m_drillSize = aFinishSize; |
|||
|
|||
m_tools.push_back( tool ); |
|||
} |
|||
|
|||
void GenerateFile( std::ostream& aStream ); |
|||
|
|||
wxString m_units; |
|||
wxString m_thickness; |
|||
wxString m_userParams; |
|||
std::vector<ODB_DRILL_TOOLS::TOOLS> m_tools; |
|||
}; |
|||
|
|||
#endif // _ODB_UTIL_H_ |
@ -0,0 +1,170 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include "pcb_io_odbpp.h"
|
|||
#include "progress_reporter.h"
|
|||
#include "odb_util.h"
|
|||
#include "odb_attribute.h"
|
|||
|
|||
#include "odb_defines.h"
|
|||
#include "odb_feature.h"
|
|||
#include "odb_entity.h"
|
|||
#include "wx/log.h"
|
|||
|
|||
|
|||
double PCB_IO_ODBPP::m_scale = 1.0 / PCB_IU_PER_MM; |
|||
double PCB_IO_ODBPP::m_symbolScale = 1.0 / PL_IU_PER_MM; |
|||
int PCB_IO_ODBPP::m_sigfig = 4; |
|||
std::string PCB_IO_ODBPP::m_unitsStr = "MM"; |
|||
|
|||
PCB_IO_ODBPP::~PCB_IO_ODBPP() |
|||
{ |
|||
ClearLoadedFootprints(); |
|||
} |
|||
|
|||
|
|||
void PCB_IO_ODBPP::ClearLoadedFootprints() |
|||
{ |
|||
m_loaded_footprints.clear(); |
|||
} |
|||
|
|||
|
|||
void PCB_IO_ODBPP::CreateEntity() |
|||
{ |
|||
Make<ODB_FONTS_ENTITY>(); |
|||
Make<ODB_INPUT_ENTITY>(); |
|||
Make<ODB_MATRIX_ENTITY>( m_board, this ); |
|||
Make<ODB_STEP_ENTITY>( m_board, this ); |
|||
Make<ODB_MISC_ENTITY>(); |
|||
Make<ODB_SYMBOLS_ENTITY>(); |
|||
Make<ODB_USER_ENTITY>(); |
|||
Make<ODB_WHEELS_ENTITY>(); |
|||
} |
|||
|
|||
|
|||
bool PCB_IO_ODBPP::GenerateFiles( ODB_TREE_WRITER& writer ) |
|||
{ |
|||
for( const auto entity : m_entities ) |
|||
{ |
|||
if( !entity->CreateDirectiryTree( writer ) ) |
|||
{ |
|||
throw std::runtime_error( "Failed in create directiry tree process" ); |
|||
return false; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
entity->GenerateFiles( writer ); |
|||
} |
|||
catch( const std::exception& e ) |
|||
{ |
|||
throw std::runtime_error( "Failed in generate files process.\n" |
|||
+ std::string( e.what() ) ); |
|||
return false; |
|||
} |
|||
|
|||
} |
|||
return true; |
|||
} |
|||
|
|||
|
|||
bool PCB_IO_ODBPP::ExportODB( const wxString& aFileName ) |
|||
{ |
|||
try |
|||
{ |
|||
std::shared_ptr<ODB_TREE_WRITER> writer = |
|||
std::make_shared<ODB_TREE_WRITER>( aFileName, "odb" ); |
|||
writer->SetRootPath( writer->GetCurrentPath() ); |
|||
|
|||
if( m_progressReporter ) |
|||
{ |
|||
m_progressReporter->SetNumPhases( 3 ); |
|||
m_progressReporter->BeginPhase( 0 ); |
|||
m_progressReporter->Report( _( "Creating Entities" ) ); |
|||
} |
|||
|
|||
CreateEntity(); |
|||
|
|||
if( m_progressReporter ) |
|||
{ |
|||
m_progressReporter->SetCurrentProgress( 1.0 ); |
|||
m_progressReporter->AdvancePhase( _( "Init Entity Data" ) ); |
|||
} |
|||
|
|||
for( auto const& entity : m_entities ) |
|||
{ |
|||
entity->InitEntityData(); |
|||
} |
|||
|
|||
if( m_progressReporter ) |
|||
{ |
|||
m_progressReporter->SetCurrentProgress( 1.0 ); |
|||
m_progressReporter->AdvancePhase( _( "Generating Entities Files" ) ); |
|||
} |
|||
|
|||
if( !GenerateFiles( *writer ) ) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
catch( const std::exception& e ) |
|||
{ |
|||
wxLogError( "Exception in ODB++ ExportODB process: %s", e.what() ); |
|||
std::cerr << e.what() << std::endl; |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
|
|||
std::vector<FOOTPRINT*> PCB_IO_ODBPP::GetImportedCachedLibraryFootprints() |
|||
{ |
|||
std::vector<FOOTPRINT*> retval; |
|||
retval.reserve( m_loaded_footprints.size() ); |
|||
|
|||
for( const auto& fp : m_loaded_footprints ) |
|||
{ |
|||
retval.push_back( static_cast<FOOTPRINT*>( fp->Clone() ) ); |
|||
} |
|||
|
|||
return retval; |
|||
} |
|||
|
|||
|
|||
void PCB_IO_ODBPP::SaveBoard( const wxString& aFileName, BOARD* aBoard, |
|||
const std::map<std::string, UTF8>* aProperties ) |
|||
{ |
|||
m_board = aBoard; |
|||
|
|||
if( auto it = aProperties->find( "units" ); it != aProperties->end() ) |
|||
{ |
|||
if( it->second == "inch" ) |
|||
{ |
|||
m_unitsStr = "INCH"; |
|||
m_scale = 25.4 / PCB_IU_PER_MM; |
|||
m_symbolScale = 25.4 / PL_IU_PER_MM; |
|||
} |
|||
} |
|||
|
|||
if( auto it = aProperties->find( "sigfig" ); it != aProperties->end() ) |
|||
m_sigfig = std::stoi( it->second ); |
|||
|
|||
ExportODB( aFileName ); |
|||
|
|||
} |
@ -0,0 +1,182 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* Author: SYSUEric <jzzhuang666@gmail.com>. |
|||
* |
|||
* 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 3 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, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
|
|||
#ifndef _PCB_IO_ODBPP_H_ |
|||
#define _PCB_IO_ODBPP_H_ |
|||
|
|||
#include <pcb_io/pcb_io.h> |
|||
#include <pcb_io/pcb_io_mgr.h> |
|||
#include <pcb_io/common/plugin_common_layer_mapping.h> |
|||
|
|||
#include <eda_shape.h> |
|||
#include <layer_ids.h> // PCB_LAYER_ID |
|||
#include <font/font.h> |
|||
#include <geometry/shape_segment.h> |
|||
#include <stroke_params.h> |
|||
#include <memory> |
|||
#include "odb_entity.h" |
|||
|
|||
class BOARD; |
|||
class BOARD_ITEM; |
|||
class EDA_TEXT; |
|||
class FOOTPRINT; |
|||
class PROGRESS_REPORTER; |
|||
class NETINFO_ITEM; |
|||
class PAD; |
|||
class PCB_SHAPE; |
|||
class PCB_VIA; |
|||
class PROGRESS_REPORTER; |
|||
class SHAPE_POLY_SET; |
|||
class SHAPE_SEGMENT; |
|||
class EDA_DATA::SUB_NET; |
|||
|
|||
|
|||
class PCB_IO_ODBPP : public PCB_IO |
|||
{ |
|||
public: |
|||
PCB_IO_ODBPP() : PCB_IO( wxS( "ODBPlusPlus" ) ) { m_board = nullptr; } |
|||
|
|||
~PCB_IO_ODBPP() override; |
|||
|
|||
void SaveBoard( const wxString& aFileName, BOARD* aBoard, |
|||
const std::map<std::string, UTF8>* aProperties = nullptr ) override; |
|||
const IO_BASE::IO_FILE_DESC GetBoardFileDesc() const override |
|||
{ |
|||
return IO_BASE::IO_FILE_DESC( _HKI( "ODB++ Production File" ), { "ZIP" } ); |
|||
} |
|||
|
|||
const IO_BASE::IO_FILE_DESC GetLibraryDesc() const override |
|||
{ |
|||
// No library description for this plugin |
|||
return IO_BASE::IO_FILE_DESC( wxEmptyString, {} ); |
|||
} |
|||
|
|||
|
|||
std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints() override; |
|||
|
|||
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override { return 0; } |
|||
|
|||
// Reading currently disabled |
|||
bool CanReadBoard( const wxString& aFileName ) const override { return false; } |
|||
|
|||
// Reading currently disabled |
|||
bool CanReadFootprint( const wxString& aFileName ) const override { return false; } |
|||
|
|||
// Reading currently disabled |
|||
bool CanReadLibrary( const wxString& aFileName ) const override { return false; } |
|||
|
|||
public: |
|||
inline std::vector<std::pair<PCB_LAYER_ID, wxString>>& GetLayerNameList() |
|||
{ |
|||
return m_layer_name_list; |
|||
} |
|||
|
|||
inline std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>>& GetLayerElementsMap() |
|||
{ |
|||
return m_layer_elements; |
|||
} |
|||
|
|||
inline std::vector<std::shared_ptr<FOOTPRINT>>& GetLoadedFootprintList() |
|||
{ |
|||
return m_loaded_footprints; |
|||
} |
|||
|
|||
inline std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& |
|||
GetDrillLayerItemsMap() |
|||
{ |
|||
return m_drill_layers; |
|||
} |
|||
|
|||
inline std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& |
|||
GetSlotHolesMap() |
|||
{ |
|||
return m_slot_holes; |
|||
} |
|||
|
|||
inline std::map<const PAD*, EDA_DATA::SUB_NET_TOEPRINT*>& GetPadSubnetMap() |
|||
{ |
|||
return m_topeprint_subnets; |
|||
} |
|||
|
|||
inline std::map<std::pair<PCB_LAYER_ID, ZONE*>, EDA_DATA::SUB_NET_PLANE*>& GetPlaneSubnetMap() |
|||
{ |
|||
return m_plane_subnets; |
|||
} |
|||
|
|||
inline std::map<PCB_TRACK*, EDA_DATA::SUB_NET*>& GetViaTraceSubnetMap() |
|||
{ |
|||
return m_via_trace_subnets; |
|||
} |
|||
|
|||
|
|||
std::shared_ptr<ODB_TREE_WRITER> m_writer; |
|||
|
|||
bool GenerateFiles( ODB_TREE_WRITER& writer ); |
|||
bool ExportODB( const wxString& aFileName ); |
|||
void CreateEntity(); |
|||
|
|||
bool CreateDirectories( ODB_TREE_WRITER& writer ); |
|||
|
|||
// Frees the memory allocated for the loaded footprints in #m_loaded_footprints. |
|||
void ClearLoadedFootprints(); |
|||
|
|||
static double m_scale; |
|||
static double m_symbolScale; |
|||
static int m_sigfig; |
|||
static std::string m_unitsStr; |
|||
|
|||
private: |
|||
template <typename T, typename... Args> |
|||
void Make( Args&&... args ) |
|||
{ |
|||
std::shared_ptr<ODB_ENTITY_BASE> entity = |
|||
std::make_shared<T>( std::forward<Args>( args )... ); |
|||
|
|||
if( entity ) |
|||
m_entities.push_back( entity ); |
|||
} |
|||
|
|||
BOARD* m_board; |
|||
|
|||
std::vector<std::shared_ptr<FOOTPRINT>> m_loaded_footprints; |
|||
|
|||
std::vector<std::pair<PCB_LAYER_ID, wxString>> |
|||
m_layer_name_list; //<! layer name in matrix entity to the internal layer id |
|||
|
|||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>> |
|||
m_drill_layers; //<! Drill sets are output as layers (to/from pairs) |
|||
|
|||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>> |
|||
m_slot_holes; //<! Storage vector of slotted holes that need to be output as cutouts |
|||
|
|||
std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> |
|||
m_layer_elements; //<! Storage map of layer to element list |
|||
|
|||
std::map<const PAD*, EDA_DATA::SUB_NET_TOEPRINT*> m_topeprint_subnets; |
|||
|
|||
std::map<std::pair<PCB_LAYER_ID, ZONE*>, EDA_DATA::SUB_NET_PLANE*> m_plane_subnets; |
|||
|
|||
std::map<PCB_TRACK*, EDA_DATA::SUB_NET*> m_via_trace_subnets; |
|||
|
|||
std::vector<std::shared_ptr<ODB_ENTITY_BASE>> m_entities; |
|||
}; |
|||
|
|||
#endif // _PCB_IO_ODBPP_H_ |
After Width: 16 | Height: 16 | Size: 592 B |
After Width: 24 | Height: 24 | Size: 781 B |
After Width: 32 | Height: 32 | Size: 1.0 KiB |
After Width: 48 | Height: 48 | Size: 1.5 KiB |
After Width: 64 | Height: 64 | Size: 2.0 KiB |
After Width: 16 | Height: 16 | Size: 557 B |
After Width: 24 | Height: 24 | Size: 760 B |
After Width: 32 | Height: 32 | Size: 1009 B |
After Width: 48 | Height: 48 | Size: 1.5 KiB |
After Width: 64 | Height: 64 | Size: 1.9 KiB |
@ -0,0 +1,147 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<svg |
|||
id="Слой_1" |
|||
data-name="Слой 1" |
|||
viewBox="0 0 24 24" |
|||
version="1.1" |
|||
sodipodi:docname="post_odb.svg" |
|||
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/"> |
|||
<sodipodi:namedview |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1" |
|||
objecttolerance="10" |
|||
gridtolerance="10" |
|||
guidetolerance="10" |
|||
inkscape:pageopacity="0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:window-width="1920" |
|||
inkscape:window-height="1017" |
|||
id="namedview159354" |
|||
showgrid="true" |
|||
inkscape:zoom="30.291667" |
|||
inkscape:cx="13.171939" |
|||
inkscape:cy="13.980743" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:current-layer="text5854" |
|||
inkscape:showpageshadow="2" |
|||
inkscape:pagecheckerboard="0" |
|||
inkscape:deskcolor="#d1d1d1"> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid6877" |
|||
empspacing="2" |
|||
spacingx="0.5" |
|||
spacingy="0.5" |
|||
originx="0" |
|||
originy="0" |
|||
units="px" |
|||
visible="true" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata43"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title>post_odb</dc:title> |
|||
<cc:license |
|||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /> |
|||
</cc:Work> |
|||
<cc:License |
|||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> |
|||
<cc:permits |
|||
rdf:resource="http://creativecommons.org/ns#Reproduction" /> |
|||
<cc:permits |
|||
rdf:resource="http://creativecommons.org/ns#Distribution" /> |
|||
<cc:requires |
|||
rdf:resource="http://creativecommons.org/ns#Notice" /> |
|||
<cc:requires |
|||
rdf:resource="http://creativecommons.org/ns#Attribution" /> |
|||
<cc:permits |
|||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> |
|||
<cc:requires |
|||
rdf:resource="http://creativecommons.org/ns#ShareAlike" /> |
|||
</cc:License> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<defs |
|||
id="defs159331"> |
|||
<style |
|||
id="style159329">.cls-1{fill:#b9b9b9;}.cls-2{fill:#1a81c4;}.cls-3{fill:#fff;}.cls-4{fill:#bf2641;}.cls-5{fill:none;stroke:#f5f5f5;stroke-linecap:round;stroke-linejoin:round;stroke-width:2px;}</style> |
|||
</defs> |
|||
<title |
|||
id="title159333">post_odb</title> |
|||
<rect |
|||
class="cls-1" |
|||
x="3.0489998" |
|||
y="0" |
|||
width="17.937201" |
|||
height="17.983299" |
|||
rx="2.9934001" |
|||
id="rect159335" |
|||
style="fill:#8f8f8f;fill-opacity:1" /> |
|||
<rect |
|||
class="cls-2" |
|||
x="0.00010001659" |
|||
y="2.9995" |
|||
width="18.7099" |
|||
height="9.2299004" |
|||
id="rect159337" |
|||
style="fill:#42b8eb;fill-opacity:1" /> |
|||
<g |
|||
aria-label="xml" |
|||
id="text5854" |
|||
style="font-size:8.52777px;line-height:1.25;font-family:'Tiresias LPfont';-inkscape-font-specification:'Tiresias LPfont';stroke-width:0.700254"> |
|||
<path |
|||
class="cls-3" |
|||
d="M 2.4739587,7.5242975 A 2.4445396,2.4329348 0 0 1 3.0182779,5.8948399 1.8741713,1.8652742 0 0 1 4.515156,5.2568698 1.8667734,1.8579115 0 0 1 6.0200571,5.8948399 2.4198452,2.4083576 0 0 1 6.5685442,7.5242975 v 0.086072 A 2.4325571,2.4210092 0 0 1 6.0200571,9.2479159 1.8705245,1.8616447 0 0 1 4.5232833,9.8768639 1.8812567,1.8723259 0 0 1 3.0182779,9.2442863 2.4406843,2.4290979 0 0 1 2.4739587,7.6103695 Z m 1.0022601,0.084102 a 2.003791,1.9942786 0 0 0 0.2553842,1.0602415 0.9640203,0.95944389 0 0 0 1.5751291,0 1.948463,1.9392132 0 0 0 0.2636156,-1.0602415 V 7.5223272 A 1.9218931,1.9127694 0 0 0 5.3067321,6.474115 a 0.95193358,0.94741455 0 0 0 -1.5751291,0 1.98837,1.9789308 0 0 0 -0.2556967,1.0482122 z" |
|||
id="path26539" |
|||
style="fill:#ffffff;stroke-width:0.727902" /> |
|||
<path |
|||
class="cls-3" |
|||
d="M 7.5318324,7.805352 A 3.2017341,2.8187362 0 0 1 8.0279112,6.1589374 1.6036387,1.4118082 0 0 1 9.4226163,5.5333798 1.5206901,1.3387821 0 0 1 10.126319,5.6737531 1.5772322,1.3885606 0 0 1 10.664728,6.0740213 v -2.347749 h 1.085588 V 9.880695 H 10.83899 L 10.731651,9.3518548 A 1.6005143,1.4090576 0 0 1 10.173588,9.8075802 1.5695724,1.381817 0 0 1 9.413747,9.9635702 1.6418374,1.4454375 0 0 1 8.0279112,9.3908079 2.7377059,2.410216 0 0 1 7.5318324,7.888316 Z m 1.0856889,0.08323 a 1.9575056,1.7233448 0 0 0 0.256808,0.9427733 0.90044047,0.79272798 0 0 0 0.8163832,0.3509334 1.0920386,0.96140672 0 0 0 0.5836635,-0.1299918 1.1243915,0.98988956 0 0 0 0.390755,-0.370898 V 6.8192779 A 1.1368892,1.0008923 0 0 0 10.271453,6.4509531 1.0569643,0.93052813 0 0 0 9.6995819,6.3183881 0.87685606,0.77196479 0 0 0 8.8816868,6.7309012 2.4783782,2.1819097 0 0 0 8.6179245,7.805352 Z" |
|||
id="path26593" |
|||
style="fill:#ffffff;stroke-width:0.662215" /> |
|||
<path |
|||
class="cls-3" |
|||
d="m 16.749071,7.8650048 a 2.4272,2.4272 0 0 1 -0.4373,1.5137 1.4574,1.4574 0 0 1 -1.2324,0.5733 1.414,1.414 0 0 1 -0.6943,-0.1621 1.3569,1.3569 0 0 1 -0.4922,-0.4766 l -0.0957,0.5557 h -0.8068 v -6.1895 h 0.9614 v 2.3848 a 1.3812,1.3812 0 0 1 0.4756,-0.4209 1.3576,1.3576 0 0 1 0.6444,-0.1465 1.4227,1.4227 0 0 1 1.24,0.6269 2.84,2.84 0 0 1 0.4375,1.6582 z m -0.9609,-0.083 a 2.2162,2.2162 0 0 0 -0.2305,-1.0825 0.7714,0.7714 0 0 0 -0.7275,-0.4121 0.9453,0.9453 0 0 0 -0.5361,0.1421 1.0023,1.0023 0 0 0 -0.3428,0.3965 v 1.8008 a 0.9408,0.9408 0 0 0 0.3408,0.3994 0.9862,0.9862 0 0 0 0.5459,0.1406 0.7975,0.7975 0 0 0 0.7246,-0.3516 1.74,1.74 0 0 0 0.2256,-0.95 z" |
|||
id="path26537" |
|||
style="fill:#ffffff" /> |
|||
</g> |
|||
<path |
|||
class="cls-3" |
|||
d="M 2.07,9.9365 H 0.9965 V 8.9 H 2.07 Z" |
|||
id="path159339" /> |
|||
<ellipse |
|||
class="cls-4" |
|||
cx="17.0075" |
|||
cy="16.996099" |
|||
rx="6.9924002" |
|||
ry="7.0039001" |
|||
id="ellipse159347" |
|||
style="fill:#f2647e;fill-opacity:1" /> |
|||
<line |
|||
class="cls-5" |
|||
x1="17.1112" |
|||
y1="13.6254" |
|||
x2="17.1112" |
|||
y2="20.629299" |
|||
id="line159349" /> |
|||
<polyline |
|||
class="cls-5" |
|||
points="15.362 17.16 18.111 14.406 20.861 17.16" |
|||
id="polyline159351" |
|||
transform="translate(-1,-1)" /> |
|||
</svg> |
@ -0,0 +1,145 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<svg |
|||
id="Слой_1" |
|||
data-name="Слой 1" |
|||
viewBox="0 0 24 24" |
|||
version="1.1" |
|||
sodipodi:docname="post_odb.svg" |
|||
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/"> |
|||
<sodipodi:namedview |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1" |
|||
objecttolerance="10" |
|||
gridtolerance="10" |
|||
guidetolerance="10" |
|||
inkscape:pageopacity="0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:window-width="1920" |
|||
inkscape:window-height="1017" |
|||
id="namedview159354" |
|||
showgrid="true" |
|||
inkscape:zoom="15.145834" |
|||
inkscape:cx="1.8817056" |
|||
inkscape:cy="13.832187" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:current-layer="Слой_1" |
|||
inkscape:showpageshadow="2" |
|||
inkscape:pagecheckerboard="0" |
|||
inkscape:deskcolor="#d1d1d1"> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid6877" |
|||
empspacing="2" |
|||
spacingx="0.5" |
|||
spacingy="0.5" |
|||
originx="0" |
|||
originy="0" |
|||
units="px" |
|||
visible="true" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata43"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title>post_odb</dc:title> |
|||
<cc:license |
|||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /> |
|||
</cc:Work> |
|||
<cc:License |
|||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> |
|||
<cc:permits |
|||
rdf:resource="http://creativecommons.org/ns#Reproduction" /> |
|||
<cc:permits |
|||
rdf:resource="http://creativecommons.org/ns#Distribution" /> |
|||
<cc:requires |
|||
rdf:resource="http://creativecommons.org/ns#Notice" /> |
|||
<cc:requires |
|||
rdf:resource="http://creativecommons.org/ns#Attribution" /> |
|||
<cc:permits |
|||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> |
|||
<cc:requires |
|||
rdf:resource="http://creativecommons.org/ns#ShareAlike" /> |
|||
</cc:License> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<defs |
|||
id="defs159331"> |
|||
<style |
|||
id="style159329">.cls-1{fill:#b9b9b9;}.cls-2{fill:#1a81c4;}.cls-3{fill:#fff;}.cls-4{fill:#bf2641;}.cls-5{fill:none;stroke:#f5f5f5;stroke-linecap:round;stroke-linejoin:round;stroke-width:2px;}</style> |
|||
</defs> |
|||
<title |
|||
id="title159333">post_odb</title> |
|||
<rect |
|||
class="cls-1" |
|||
x="3.0489998" |
|||
y="0" |
|||
width="17.937201" |
|||
height="17.983299" |
|||
rx="2.9934001" |
|||
id="rect159335" /> |
|||
<rect |
|||
class="cls-2" |
|||
x="0.00010001659" |
|||
y="2.9995" |
|||
width="18.7099" |
|||
height="9.2299004" |
|||
id="rect159337" /> |
|||
<g |
|||
aria-label="xml" |
|||
id="text5854" |
|||
style="font-size:8.52777px;line-height:1.25;font-family:'Tiresias LPfont';-inkscape-font-specification:'Tiresias LPfont';stroke-width:0.700254" |
|||
transform="translate(0.42916093,0.03301238)"> |
|||
<path |
|||
class="cls-3" |
|||
d="M 16.537701,8.0612976 A 2.5309534,2.2753582 0 0 1 16.082227,9.4788421 1.5215652,1.3679058 0 0 1 14.798716,10.015759 1.4774119,1.3282115 0 0 1 14.075163,9.8631659 1.4072317,1.2651185 0 0 1 13.562334,9.4175876 l -0.099,0.5198696 H 12.621732 V 4.1416781 h 1.002138 v 2.2327391 a 1.4352108,1.2902721 0 0 1 0.494702,-0.3933493 1.4036065,1.2618594 0 0 1 0.671779,-0.1378853 1.4828963,1.3331419 0 0 1 1.292061,0.5867229 2.9601223,2.6611864 0 0 1 0.455476,1.5530064 z M 15.536493,7.9829119 A 2.3043315,2.0716222 0 0 0 15.296858,6.9693296 0.80470339,0.72343822 0 0 0 14.538911,6.5825821 0.99507336,0.89458313 0 0 0 13.979699,6.7162892 1.038204,0.93335811 0 0 0 13.62387,7.0875766 v 1.6869641 a 0.98531315,0.88580861 0 0 0 0.353969,0.3737945 1.0355083,0.9309347 0 0 0 0.569158,0.1313671 0.8301728,0.74633554 0 0 0 0.754416,-0.3289192 1.8179028,1.6343169 0 0 0 0.23508,-0.8894855 z" |
|||
id="path26651" |
|||
style="fill:#ffffff;stroke-width:0.617173" /> |
|||
<path |
|||
class="cls-3" |
|||
d="m 2.7200892,7.7128856 a 2.3461,2.3461 0 0 1 0.5224,-1.5713002 1.7987,1.7987 0 0 1 1.4366,-0.6152 1.7916,1.7916 0 0 1 1.4443001,0.6152 2.3224,2.3224 0 0 1 0.5264,1.5713002 v 0.083 a 2.3346,2.3346 0 0 1 -0.5264,1.5791 1.7952,1.7952 0 0 1 -1.4365001,0.6065 1.8055,1.8055 0 0 1 -1.4444,-0.61 2.3424,2.3424 0 0 1 -0.5224,-1.5756 z m 0.9619,0.0811 a 1.9231,1.9231 0 0 0 0.2451,1.0224 0.9252,0.9252 0 0 0 1.5117001,0 1.87,1.87 0 0 0 0.253,-1.0224 v -0.083 a 1.8445,1.8445 0 0 0 -0.253,-1.0108002 0.9136,0.9136 0 0 0 -1.5117001,0 1.9083,1.9083 0 0 0 -0.2454,1.0108002 z" |
|||
id="path26539" |
|||
style="fill:#ffffff" /> |
|||
<path |
|||
class="cls-3" |
|||
d="M 7.3845385,7.952119 A 3.1015978,2.6397544 0 0 1 7.8651021,6.4102472 1.5534838,1.3221623 0 0 1 9.2161869,5.8244106 1.4731296,1.2537732 0 0 1 9.8978802,5.9558707 1.5279033,1.3003909 0 0 1 10.419451,6.330723 V 4.1320494 h 1.051637 v 5.763634 H 10.588265 L 10.484283,9.4004232 A 1.5504571,1.3195864 0 0 1 9.9436722,9.8272112 1.520483,1.2940754 0 0 1 9.2075949,9.9732972 1.5904879,1.3536564 0 0 1 7.8651021,9.436903 2.6520823,2.257174 0 0 1 7.3845385,8.029815 Z M 8.4362717,8.030065 A 1.8962832,1.6139172 0 0 0 8.6850479,8.9129741 0.87227859,0.74239198 0 0 0 9.4758982,9.2416242 1.0578843,0.90036008 0 0 0 10.041308,9.1198866 1.0892255,0.92703434 0 0 0 10.419842,8.7725396 V 7.0286579 A 1.1013322,0.93733841 0 0 0 10.038476,6.6837205 1.0239071,0.87144221 0 0 0 9.4844901,6.5595731 0.84943181,0.72294718 0 0 0 8.6921753,6.9458929 2.4008653,2.0433644 0 0 0 8.4366623,7.952119 Z" |
|||
id="path26593" |
|||
style="fill:#ffffff;stroke-width:0.630744" /> |
|||
</g> |
|||
<path |
|||
class="cls-3" |
|||
d="M 2.07,9.9365 H 0.9965 V 8.9 H 2.07 Z" |
|||
id="path159339" /> |
|||
<ellipse |
|||
class="cls-4" |
|||
cx="17.0075" |
|||
cy="16.996099" |
|||
rx="6.9924002" |
|||
ry="7.0039001" |
|||
id="ellipse159347" /> |
|||
<line |
|||
class="cls-5" |
|||
x1="17.1112" |
|||
y1="13.6254" |
|||
x2="17.1112" |
|||
y2="20.629299" |
|||
id="line159349" /> |
|||
<polyline |
|||
class="cls-5" |
|||
points="15.362 17.16 18.111 14.406 20.861 17.16" |
|||
id="polyline159351" |
|||
transform="translate(-1,-1)" /> |
|||
</svg> |