Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
0b853c5a
Commit
0b853c5a
authored
Jan 02, 2014
by
Cirilo Bernardo
Committed by
jean-pierre charras
Jan 02, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds basic IDF3 export (board and cutouts / holes only)
parent
c2648237
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
2401 additions
and
0 deletions
+2401
-0
wxPcbStruct.h
include/wxPcbStruct.h
+6
-0
CMakeLists.txt
pcbnew/CMakeLists.txt
+4
-0
dialog_export_idf.cpp
pcbnew/dialogs/dialog_export_idf.cpp
+121
-0
dialog_export_idf_base.cpp
pcbnew/dialogs/dialog_export_idf_base.cpp
+49
-0
dialog_export_idf_base.fbp
pcbnew/dialogs/dialog_export_idf_base.fbp
+383
-0
dialog_export_idf_base.h
pcbnew/dialogs/dialog_export_idf_base.h
+52
-0
export_idf.cpp
pcbnew/export_idf.cpp
+357
-0
idf.cpp
pcbnew/idf.cpp
+968
-0
idf.h
pcbnew/idf.h
+454
-0
menubar_pcbframe.cpp
pcbnew/menubar_pcbframe.cpp
+5
-0
pcbframe.cpp
pcbnew/pcbframe.cpp
+1
-0
pcbnew_id.h
pcbnew/pcbnew_id.h
+1
-0
No files found.
include/wxPcbStruct.h
View file @
0b853c5a
...
@@ -977,6 +977,12 @@ public:
...
@@ -977,6 +977,12 @@ public:
bool
ExportVRML_File
(
const
wxString
&
aFullFileName
,
double
aMMtoWRMLunit
,
bool
ExportVRML_File
(
const
wxString
&
aFullFileName
,
double
aMMtoWRMLunit
,
bool
aExport3DFiles
,
const
wxString
&
a3D_Subdir
);
bool
aExport3DFiles
,
const
wxString
&
a3D_Subdir
);
/**
* Function ExportToIDF3
* will export the current BOARD to a IDFv3 board and lib files.
*/
void
ExportToIDF3
(
wxCommandEvent
&
event
);
/**
/**
* Function ExporttoSPECCTRA
* Function ExporttoSPECCTRA
* will export the current BOARD to a specctra dsn file. See
* will export the current BOARD to a specctra dsn file. See
...
...
pcbnew/CMakeLists.txt
View file @
0b853c5a
...
@@ -55,6 +55,8 @@ set( PCBNEW_DIALOGS
...
@@ -55,6 +55,8 @@ set( PCBNEW_DIALOGS
dialogs/dialog_edit_module_text.cpp
dialogs/dialog_edit_module_text.cpp
dialogs/dialog_edit_module_text_base.cpp
dialogs/dialog_edit_module_text_base.cpp
dialogs/dialog_exchange_modules_base.cpp
dialogs/dialog_exchange_modules_base.cpp
dialogs/dialog_export_idf.cpp
dialogs/dialog_export_idf_base.cpp
dialogs/dialog_export_vrml_base.cpp
dialogs/dialog_export_vrml_base.cpp
dialogs/dialog_export_vrml.cpp
dialogs/dialog_export_vrml.cpp
dialogs/dialog_find_base.cpp
dialogs/dialog_find_base.cpp
...
@@ -173,6 +175,7 @@ set( PCBNEW_CLASS_SRCS
...
@@ -173,6 +175,7 @@ set( PCBNEW_CLASS_SRCS
event_handlers_tracks_vias_sizes.cpp
event_handlers_tracks_vias_sizes.cpp
export_d356.cpp
export_d356.cpp
export_gencad.cpp
export_gencad.cpp
export_idf.cpp
export_vrml.cpp
export_vrml.cpp
files.cpp
files.cpp
gen_drill_report_files.cpp
gen_drill_report_files.cpp
...
@@ -183,6 +186,7 @@ set( PCBNEW_CLASS_SRCS
...
@@ -183,6 +186,7 @@ set( PCBNEW_CLASS_SRCS
hotkeys.cpp
hotkeys.cpp
hotkeys_board_editor.cpp
hotkeys_board_editor.cpp
hotkeys_module_editor.cpp
hotkeys_module_editor.cpp
idf.cpp
initpcb.cpp
initpcb.cpp
layer_widget.cpp
layer_widget.cpp
librairi.cpp
librairi.cpp
...
...
pcbnew/dialogs/dialog_export_idf.cpp
0 → 100644
View file @
0b853c5a
/**
* @file dialog_export_idf.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Cirilo Bernardo
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wxPcbStruct.h>
#include <appl_wxstruct.h>
#include <pcbnew.h>
#include <class_board.h>
// IDF export header generated by wxFormBuilder
#include <dialog_export_idf_base.h>
#define OPTKEY_IDF_THOU wxT( "IDFExportThou" )
bool
Export_IDF3
(
BOARD
*
aPcb
,
const
wxString
&
aFullFileName
,
double
aUseThou
);
class
DIALOG_EXPORT_IDF3
:
public
DIALOG_EXPORT_IDF3_BASE
{
private
:
PCB_EDIT_FRAME
*
m_parent
;
wxConfig
*
m_config
;
bool
m_idfThouOpt
;
// remember last preference for units in THOU
void
OnCancelClick
(
wxCommandEvent
&
event
)
{
EndModal
(
wxID_CANCEL
);
}
void
OnOkClick
(
wxCommandEvent
&
event
)
{
EndModal
(
wxID_OK
);
}
public
:
DIALOG_EXPORT_IDF3
(
PCB_EDIT_FRAME
*
parent
)
:
DIALOG_EXPORT_IDF3_BASE
(
parent
)
{
m_parent
=
parent
;
m_config
=
wxGetApp
().
GetSettings
();
SetFocus
();
m_idfThouOpt
=
false
;
m_config
->
Read
(
OPTKEY_IDF_THOU
,
&
m_idfThouOpt
);
m_chkThou
->
SetValue
(
m_idfThouOpt
);
GetSizer
()
->
SetSizeHints
(
this
);
Centre
();
}
~
DIALOG_EXPORT_IDF3
()
{
m_idfThouOpt
=
m_chkThou
->
GetValue
();
m_config
->
Write
(
OPTKEY_IDF_THOU
,
m_idfThouOpt
);
}
bool
GetThouOption
()
{
return
m_chkThou
->
GetValue
();
}
wxFilePickerCtrl
*
FilePicker
()
{
return
m_filePickerIDF
;
}
};
/**
* Function OnExportIDF3
* will export the current BOARD to IDF board and lib files.
*/
void
PCB_EDIT_FRAME
::
ExportToIDF3
(
wxCommandEvent
&
event
)
{
wxFileName
fn
;
// Build default file name
fn
=
GetBoard
()
->
GetFileName
();
fn
.
SetExt
(
wxT
(
"emn"
)
);
DIALOG_EXPORT_IDF3
dlg
(
this
);
dlg
.
FilePicker
()
->
SetPath
(
fn
.
GetFullPath
()
);
if
(
dlg
.
ShowModal
()
!=
wxID_OK
)
return
;
bool
thou
=
dlg
.
GetThouOption
();
wxBusyCursor
dummy
;
wxString
fullFilename
=
dlg
.
FilePicker
()
->
GetPath
();
if
(
!
Export_IDF3
(
GetBoard
(),
fullFilename
,
thou
)
)
{
wxString
msg
=
_
(
"Unable to create "
)
+
fullFilename
;
wxMessageBox
(
msg
);
return
;
}
}
pcbnew/dialogs/dialog_export_idf_base.cpp
0 → 100644
View file @
0b853c5a
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 8 2012)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_export_idf_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_EXPORT_IDF3_BASE
::
DIALOG_EXPORT_IDF3_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
*
bSizerIDFFile
;
bSizerIDFFile
=
new
wxBoxSizer
(
wxVERTICAL
);
m_txtBrdFile
=
new
wxStaticText
(
this
,
wxID_ANY
,
wxT
(
"IDF Board file"
),
wxDefaultPosition
,
wxDefaultSize
,
0
);
m_txtBrdFile
->
Wrap
(
-
1
);
bSizerIDFFile
->
Add
(
m_txtBrdFile
,
0
,
wxALL
,
5
);
m_filePickerIDF
=
new
wxFilePickerCtrl
(
this
,
wxID_ANY
,
wxEmptyString
,
wxT
(
"Select a board file"
),
wxT
(
"*.emn"
),
wxDefaultPosition
,
wxDefaultSize
,
wxFLP_OVERWRITE_PROMPT
|
wxFLP_SAVE
|
wxFLP_USE_TEXTCTRL
);
m_filePickerIDF
->
SetMinSize
(
wxSize
(
420
,
30
)
);
bSizerIDFFile
->
Add
(
m_filePickerIDF
,
0
,
wxALL
,
5
);
m_chkThou
=
new
wxCheckBox
(
this
,
wxID_ANY
,
wxT
(
"unit: THOU"
),
wxDefaultPosition
,
wxDefaultSize
,
0
);
bSizerIDFFile
->
Add
(
m_chkThou
,
0
,
wxALL
,
5
);
m_sdbSizer1
=
new
wxStdDialogButtonSizer
();
m_sdbSizer1OK
=
new
wxButton
(
this
,
wxID_OK
);
m_sdbSizer1
->
AddButton
(
m_sdbSizer1OK
);
m_sdbSizer1Cancel
=
new
wxButton
(
this
,
wxID_CANCEL
);
m_sdbSizer1
->
AddButton
(
m_sdbSizer1Cancel
);
m_sdbSizer1
->
Realize
();
bSizerIDFFile
->
Add
(
m_sdbSizer1
,
1
,
wxEXPAND
,
5
);
this
->
SetSizer
(
bSizerIDFFile
);
this
->
Layout
();
this
->
Centre
(
wxBOTH
);
}
DIALOG_EXPORT_IDF3_BASE
::~
DIALOG_EXPORT_IDF3_BASE
()
{
}
pcbnew/dialogs/dialog_export_idf_base.fbp
0 → 100644
View file @
0b853c5a
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion
major=
"1"
minor=
"11"
/>
<object
class=
"Project"
expanded=
"1"
>
<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_idf_base
</property>
<property
name=
"first_id"
>
1000
</property>
<property
name=
"help_provider"
>
none
</property>
<property
name=
"internationalize"
>
0
</property>
<property
name=
"name"
>
dialog_export_idf3_base
</property>
<property
name=
"namespace"
></property>
<property
name=
"path"
>
.
</property>
<property
name=
"precompiled_header"
></property>
<property
name=
"relative_path"
>
1
</property>
<property
name=
"skip_php_events"
>
1
</property>
<property
name=
"skip_python_events"
>
1
</property>
<property
name=
"use_enum"
>
1
</property>
<property
name=
"use_microsoft_bom"
>
0
</property>
<object
class=
"Dialog"
expanded=
"1"
>
<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=
"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_IDF3_BASE
</property>
<property
name=
"pos"
></property>
<property
name=
"size"
>
458,177
</property>
<property
name=
"style"
>
wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER
</property>
<property
name=
"subclass"
>
DIALOG_SHIM; dialog_shim.h
</property>
<property
name=
"title"
>
Export IDFv3
</property>
<property
name=
"tooltip"
></property>
<property
name=
"window_extra_style"
></property>
<property
name=
"window_name"
></property>
<property
name=
"window_style"
></property>
<event
name=
"OnActivate"
></event>
<event
name=
"OnActivateApp"
></event>
<event
name=
"OnAuiFindManager"
></event>
<event
name=
"OnAuiPaneButton"
></event>
<event
name=
"OnAuiPaneClose"
></event>
<event
name=
"OnAuiPaneMaximize"
></event>
<event
name=
"OnAuiPaneRestore"
></event>
<event
name=
"OnAuiRender"
></event>
<event
name=
"OnChar"
></event>
<event
name=
"OnClose"
></event>
<event
name=
"OnEnterWindow"
></event>
<event
name=
"OnEraseBackground"
></event>
<event
name=
"OnHibernate"
></event>
<event
name=
"OnIconize"
></event>
<event
name=
"OnIdle"
></event>
<event
name=
"OnInitDialog"
></event>
<event
name=
"OnKeyDown"
></event>
<event
name=
"OnKeyUp"
></event>
<event
name=
"OnKillFocus"
></event>
<event
name=
"OnLeaveWindow"
></event>
<event
name=
"OnLeftDClick"
></event>
<event
name=
"OnLeftDown"
></event>
<event
name=
"OnLeftUp"
></event>
<event
name=
"OnMiddleDClick"
></event>
<event
name=
"OnMiddleDown"
></event>
<event
name=
"OnMiddleUp"
></event>
<event
name=
"OnMotion"
></event>
<event
name=
"OnMouseEvents"
></event>
<event
name=
"OnMouseWheel"
></event>
<event
name=
"OnPaint"
></event>
<event
name=
"OnRightDClick"
></event>
<event
name=
"OnRightDown"
></event>
<event
name=
"OnRightUp"
></event>
<event
name=
"OnSetFocus"
></event>
<event
name=
"OnSize"
></event>
<event
name=
"OnUpdateUI"
></event>
<object
class=
"wxBoxSizer"
expanded=
"1"
>
<property
name=
"minimum_size"
></property>
<property
name=
"name"
>
bSizerIDFFile
</property>
<property
name=
"orient"
>
wxVERTICAL
</property>
<property
name=
"permission"
>
none
</property>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxALL
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxStaticText"
expanded=
"1"
>
<property
name=
"BottomDockable"
>
1
</property>
<property
name=
"LeftDockable"
>
1
</property>
<property
name=
"RightDockable"
>
1
</property>
<property
name=
"TopDockable"
>
1
</property>
<property
name=
"aui_layer"
></property>
<property
name=
"aui_name"
></property>
<property
name=
"aui_position"
></property>
<property
name=
"aui_row"
></property>
<property
name=
"best_size"
></property>
<property
name=
"bg"
></property>
<property
name=
"caption"
></property>
<property
name=
"caption_visible"
>
1
</property>
<property
name=
"center_pane"
>
0
</property>
<property
name=
"close_button"
>
1
</property>
<property
name=
"context_help"
></property>
<property
name=
"context_menu"
>
1
</property>
<property
name=
"default_pane"
>
0
</property>
<property
name=
"dock"
>
Dock
</property>
<property
name=
"dock_fixed"
>
0
</property>
<property
name=
"docking"
>
Left
</property>
<property
name=
"enabled"
>
1
</property>
<property
name=
"fg"
></property>
<property
name=
"floatable"
>
1
</property>
<property
name=
"font"
></property>
<property
name=
"gripper"
>
0
</property>
<property
name=
"hidden"
>
0
</property>
<property
name=
"id"
>
wxID_ANY
</property>
<property
name=
"label"
>
IDF Board file
</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_txtBrdFile
</property>
<property
name=
"pane_border"
>
1
</property>
<property
name=
"pane_position"
></property>
<property
name=
"pane_size"
></property>
<property
name=
"permission"
>
protected
</property>
<property
name=
"pin_button"
>
1
</property>
<property
name=
"pos"
></property>
<property
name=
"resize"
>
Resizable
</property>
<property
name=
"show"
>
1
</property>
<property
name=
"size"
></property>
<property
name=
"style"
></property>
<property
name=
"subclass"
></property>
<property
name=
"toolbar_pane"
>
0
</property>
<property
name=
"tooltip"
></property>
<property
name=
"window_extra_style"
></property>
<property
name=
"window_name"
></property>
<property
name=
"window_style"
></property>
<property
name=
"wrap"
>
-1
</property>
<event
name=
"OnChar"
></event>
<event
name=
"OnEnterWindow"
></event>
<event
name=
"OnEraseBackground"
></event>
<event
name=
"OnKeyDown"
></event>
<event
name=
"OnKeyUp"
></event>
<event
name=
"OnKillFocus"
></event>
<event
name=
"OnLeaveWindow"
></event>
<event
name=
"OnLeftDClick"
></event>
<event
name=
"OnLeftDown"
></event>
<event
name=
"OnLeftUp"
></event>
<event
name=
"OnMiddleDClick"
></event>
<event
name=
"OnMiddleDown"
></event>
<event
name=
"OnMiddleUp"
></event>
<event
name=
"OnMotion"
></event>
<event
name=
"OnMouseEvents"
></event>
<event
name=
"OnMouseWheel"
></event>
<event
name=
"OnPaint"
></event>
<event
name=
"OnRightDClick"
></event>
<event
name=
"OnRightDown"
></event>
<event
name=
"OnRightUp"
></event>
<event
name=
"OnSetFocus"
></event>
<event
name=
"OnSize"
></event>
<event
name=
"OnUpdateUI"
></event>
</object>
</object>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxALL
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxFilePickerCtrl"
expanded=
"1"
>
<property
name=
"BottomDockable"
>
1
</property>
<property
name=
"LeftDockable"
>
1
</property>
<property
name=
"RightDockable"
>
1
</property>
<property
name=
"TopDockable"
>
1
</property>
<property
name=
"aui_layer"
></property>
<property
name=
"aui_name"
></property>
<property
name=
"aui_position"
></property>
<property
name=
"aui_row"
></property>
<property
name=
"best_size"
></property>
<property
name=
"bg"
></property>
<property
name=
"caption"
></property>
<property
name=
"caption_visible"
>
1
</property>
<property
name=
"center_pane"
>
0
</property>
<property
name=
"close_button"
>
1
</property>
<property
name=
"context_help"
></property>
<property
name=
"context_menu"
>
1
</property>
<property
name=
"default_pane"
>
0
</property>
<property
name=
"dock"
>
Dock
</property>
<property
name=
"dock_fixed"
>
0
</property>
<property
name=
"docking"
>
Left
</property>
<property
name=
"enabled"
>
1
</property>
<property
name=
"fg"
></property>
<property
name=
"floatable"
>
1
</property>
<property
name=
"font"
></property>
<property
name=
"gripper"
>
0
</property>
<property
name=
"hidden"
>
0
</property>
<property
name=
"id"
>
wxID_ANY
</property>
<property
name=
"max_size"
></property>
<property
name=
"maximize_button"
>
0
</property>
<property
name=
"maximum_size"
></property>
<property
name=
"message"
>
Select a board file
</property>
<property
name=
"min_size"
></property>
<property
name=
"minimize_button"
>
0
</property>
<property
name=
"minimum_size"
>
420,30
</property>
<property
name=
"moveable"
>
1
</property>
<property
name=
"name"
>
m_filePickerIDF
</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"
>
wxFLP_OVERWRITE_PROMPT|wxFLP_SAVE|wxFLP_USE_TEXTCTRL
</property>
<property
name=
"subclass"
></property>
<property
name=
"toolbar_pane"
>
0
</property>
<property
name=
"tooltip"
></property>
<property
name=
"validator_data_type"
></property>
<property
name=
"validator_style"
>
wxFILTER_NONE
</property>
<property
name=
"validator_type"
>
wxDefaultValidator
</property>
<property
name=
"validator_variable"
></property>
<property
name=
"value"
></property>
<property
name=
"wildcard"
>
*.emn
</property>
<property
name=
"window_extra_style"
></property>
<property
name=
"window_name"
></property>
<property
name=
"window_style"
></property>
<event
name=
"OnChar"
></event>
<event
name=
"OnEnterWindow"
></event>
<event
name=
"OnEraseBackground"
></event>
<event
name=
"OnFileChanged"
></event>
<event
name=
"OnKeyDown"
></event>
<event
name=
"OnKeyUp"
></event>
<event
name=
"OnKillFocus"
></event>
<event
name=
"OnLeaveWindow"
></event>
<event
name=
"OnLeftDClick"
></event>
<event
name=
"OnLeftDown"
></event>
<event
name=
"OnLeftUp"
></event>
<event
name=
"OnMiddleDClick"
></event>
<event
name=
"OnMiddleDown"
></event>
<event
name=
"OnMiddleUp"
></event>
<event
name=
"OnMotion"
></event>
<event
name=
"OnMouseEvents"
></event>
<event
name=
"OnMouseWheel"
></event>
<event
name=
"OnPaint"
></event>
<event
name=
"OnRightDClick"
></event>
<event
name=
"OnRightDown"
></event>
<event
name=
"OnRightUp"
></event>
<event
name=
"OnSetFocus"
></event>
<event
name=
"OnSize"
></event>
<event
name=
"OnUpdateUI"
></event>
</object>
</object>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxALL
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxCheckBox"
expanded=
"1"
>
<property
name=
"BottomDockable"
>
1
</property>
<property
name=
"LeftDockable"
>
1
</property>
<property
name=
"RightDockable"
>
1
</property>
<property
name=
"TopDockable"
>
1
</property>
<property
name=
"aui_layer"
></property>
<property
name=
"aui_name"
></property>
<property
name=
"aui_position"
></property>
<property
name=
"aui_row"
></property>
<property
name=
"best_size"
></property>
<property
name=
"bg"
></property>
<property
name=
"caption"
></property>
<property
name=
"caption_visible"
>
1
</property>
<property
name=
"center_pane"
>
0
</property>
<property
name=
"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=
"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"
>
unit: THOU
</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_chkThou
</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=
"validator_data_type"
></property>
<property
name=
"validator_style"
>
wxFILTER_NONE
</property>
<property
name=
"validator_type"
>
wxDefaultValidator
</property>
<property
name=
"validator_variable"
></property>
<property
name=
"window_extra_style"
></property>
<property
name=
"window_name"
></property>
<property
name=
"window_style"
></property>
<event
name=
"OnChar"
></event>
<event
name=
"OnCheckBox"
></event>
<event
name=
"OnEnterWindow"
></event>
<event
name=
"OnEraseBackground"
></event>
<event
name=
"OnKeyDown"
></event>
<event
name=
"OnKeyUp"
></event>
<event
name=
"OnKillFocus"
></event>
<event
name=
"OnLeaveWindow"
></event>
<event
name=
"OnLeftDClick"
></event>
<event
name=
"OnLeftDown"
></event>
<event
name=
"OnLeftUp"
></event>
<event
name=
"OnMiddleDClick"
></event>
<event
name=
"OnMiddleDown"
></event>
<event
name=
"OnMiddleUp"
></event>
<event
name=
"OnMotion"
></event>
<event
name=
"OnMouseEvents"
></event>
<event
name=
"OnMouseWheel"
></event>
<event
name=
"OnPaint"
></event>
<event
name=
"OnRightDClick"
></event>
<event
name=
"OnRightDown"
></event>
<event
name=
"OnRightUp"
></event>
<event
name=
"OnSetFocus"
></event>
<event
name=
"OnSize"
></event>
<event
name=
"OnUpdateUI"
></event>
</object>
</object>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxEXPAND
</property>
<property
name=
"proportion"
>
1
</property>
<object
class=
"wxStdDialogButtonSizer"
expanded=
"1"
>
<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_sdbSizer1
</property>
<property
name=
"permission"
>
protected
</property>
<event
name=
"OnApplyButtonClick"
></event>
<event
name=
"OnCancelButtonClick"
></event>
<event
name=
"OnContextHelpButtonClick"
></event>
<event
name=
"OnHelpButtonClick"
></event>
<event
name=
"OnNoButtonClick"
></event>
<event
name=
"OnOKButtonClick"
></event>
<event
name=
"OnSaveButtonClick"
></event>
<event
name=
"OnYesButtonClick"
></event>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>
pcbnew/dialogs/dialog_export_idf_base.h
0 → 100644
View file @
0b853c5a
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 8 2012)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __DIALOG_EXPORT_IDF_BASE_H__
#define __DIALOG_EXPORT_IDF_BASE_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
class
DIALOG_SHIM
;
#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/filepicker.h>
#include <wx/checkbox.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_EXPORT_IDF3_BASE
///////////////////////////////////////////////////////////////////////////////
class
DIALOG_EXPORT_IDF3_BASE
:
public
DIALOG_SHIM
{
private
:
protected
:
wxStaticText
*
m_txtBrdFile
;
wxFilePickerCtrl
*
m_filePickerIDF
;
wxCheckBox
*
m_chkThou
;
wxStdDialogButtonSizer
*
m_sdbSizer1
;
wxButton
*
m_sdbSizer1OK
;
wxButton
*
m_sdbSizer1Cancel
;
public
:
DIALOG_EXPORT_IDF3_BASE
(
wxWindow
*
parent
,
wxWindowID
id
=
wxID_ANY
,
const
wxString
&
title
=
wxT
(
"Export IDFv3"
),
const
wxPoint
&
pos
=
wxDefaultPosition
,
const
wxSize
&
size
=
wxSize
(
458
,
177
),
long
style
=
wxDEFAULT_DIALOG_STYLE
|
wxRESIZE_BORDER
);
~
DIALOG_EXPORT_IDF3_BASE
();
};
#endif //__DIALOG_EXPORT_IDF_BASE_H__
pcbnew/export_idf.cpp
0 → 100644
View file @
0b853c5a
/**
* @file export_idf.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Cirilo Bernardo
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <list>
#include <wxPcbStruct.h>
#include <macros.h>
#include <pcbnew.h>
#include <class_board.h>
#include <class_module.h>
#include <class_edge_mod.h>
#include <idf.h>
// assumed default graphical line thickness: 10000 IU == 0.1mm
#define LINE_WIDTH (100000)
/**
* Function idf_export_outline
* retrieves line segment information from the edge layer and compiles
* the data into a form which can be output as an IDFv3 compliant
* BOARD_OUTLINE section.
*/
static
void
idf_export_outline
(
BOARD
*
aPcb
,
IDF_BOARD
&
aIDFBoard
)
{
double
scale
=
aIDFBoard
.
GetScale
();
DRAWSEGMENT
*
graphic
;
// KiCad graphical item
IDF_POINT
sp
,
ep
;
// start and end points from KiCad item
std
::
list
<
IDF_SEGMENT
*
>
lines
;
// IDF intermediate form of KiCad graphical item
IDF_OUTLINE
outline
;
// graphical items forming an outline or cutout
// NOTE: IMPLEMENTATION
// If/when component cutouts are allowed, we must implement them separately. Cutouts
// must be added to the board outline section and not to the Other Outline section.
// The module cutouts should be handled via the idf_export_module() routine.
double
offX
,
offY
;
aIDFBoard
.
GetOffset
(
offX
,
offY
);
// Retrieve segments and arcs from the board
for
(
BOARD_ITEM
*
item
=
aPcb
->
m_Drawings
;
item
;
item
=
item
->
Next
()
)
{
if
(
item
->
Type
()
!=
PCB_LINE_T
||
item
->
GetLayer
()
!=
EDGE_N
)
continue
;
graphic
=
(
DRAWSEGMENT
*
)
item
;
switch
(
graphic
->
GetShape
()
)
{
case
S_SEGMENT
:
{
sp
.
x
=
graphic
->
GetStart
().
x
*
scale
+
offX
;
sp
.
y
=
-
graphic
->
GetStart
().
y
*
scale
+
offY
;
ep
.
x
=
graphic
->
GetEnd
().
x
*
scale
+
offX
;
ep
.
y
=
-
graphic
->
GetEnd
().
y
*
scale
+
offY
;
IDF_SEGMENT
*
seg
=
new
IDF_SEGMENT
(
sp
,
ep
);
if
(
seg
)
lines
.
push_back
(
seg
);
}
break
;
case
S_ARC
:
{
sp
.
x
=
graphic
->
GetCenter
().
x
*
scale
+
offX
;
sp
.
y
=
-
graphic
->
GetCenter
().
y
*
scale
+
offY
;
ep
.
x
=
graphic
->
GetArcStart
().
x
*
scale
+
offX
;
ep
.
y
=
-
graphic
->
GetArcStart
().
y
*
scale
+
offY
;
IDF_SEGMENT
*
seg
=
new
IDF_SEGMENT
(
sp
,
ep
,
-
graphic
->
GetAngle
()
/
10.0
,
true
);
if
(
seg
)
lines
.
push_back
(
seg
);
}
break
;
case
S_CIRCLE
:
{
sp
.
x
=
graphic
->
GetCenter
().
x
*
scale
+
offX
;
sp
.
y
=
-
graphic
->
GetCenter
().
y
*
scale
+
offY
;
ep
.
x
=
sp
.
x
-
graphic
->
GetRadius
()
*
scale
;
ep
.
y
=
sp
.
y
;
// Circles must always have an angle of +360 deg. to appease
// quirky MCAD implementations of IDF.
IDF_SEGMENT
*
seg
=
new
IDF_SEGMENT
(
sp
,
ep
,
360.0
,
true
);
if
(
seg
)
lines
.
push_back
(
seg
);
}
break
;
default:
break
;
}
}
// if there is no outline then use the bounding box
if
(
lines
.
empty
()
)
{
goto
UseBoundingBox
;
}
// get the board outline and write it out
// note: we do not use a try/catch block here since we intend
// to simply ignore unclosed loops and continue processing
// until we're out of segments to process
IDF3
::
GetOutline
(
lines
,
outline
);
if
(
outline
.
empty
()
)
goto
UseBoundingBox
;
aIDFBoard
.
AddOutline
(
outline
);
// get all cutouts and write them out
while
(
!
lines
.
empty
()
)
{
IDF3
::
GetOutline
(
lines
,
outline
);
if
(
outline
.
empty
()
)
continue
;
aIDFBoard
.
AddOutline
(
outline
);
}
return
;
UseBoundingBox:
// clean up if necessary
while
(
!
lines
.
empty
()
)
{
delete
lines
.
front
();
lines
.
pop_front
();
}
outline
.
Clear
();
// fetch a rectangular bounding box for the board;
// there is always some uncertainty in the board dimensions
// computed via ComputeBoundingBox() since this depends on the
// individual module entities.
EDA_RECT
bbbox
=
aPcb
->
ComputeBoundingBox
(
true
);
// convert to mm and compensate for an assumed LINE_WIDTH line thickness
double
x
=
(
bbbox
.
GetOrigin
().
x
+
LINE_WIDTH
/
2
)
*
scale
+
offX
;
double
y
=
(
bbbox
.
GetOrigin
().
y
+
LINE_WIDTH
/
2
)
*
scale
+
offY
;
double
dx
=
(
bbbox
.
GetSize
().
x
-
LINE_WIDTH
)
*
scale
;
double
dy
=
(
bbbox
.
GetSize
().
y
-
LINE_WIDTH
)
*
scale
;
double
px
[
4
],
py
[
4
];
px
[
0
]
=
x
;
py
[
0
]
=
y
;
px
[
1
]
=
x
;
py
[
1
]
=
y
+
dy
;
px
[
2
]
=
x
+
dx
;
py
[
2
]
=
y
+
dy
;
px
[
3
]
=
x
+
dx
;
py
[
3
]
=
y
;
IDF_POINT
p1
,
p2
;
p1
.
x
=
px
[
3
];
p1
.
y
=
py
[
3
];
p2
.
x
=
px
[
0
];
p2
.
y
=
py
[
0
];
outline
.
push
(
new
IDF_SEGMENT
(
p1
,
p2
)
);
for
(
int
i
=
1
;
i
<
4
;
++
i
)
{
p1
.
x
=
px
[
i
-
1
];
p1
.
y
=
py
[
i
-
1
];
p2
.
x
=
px
[
i
];
p2
.
y
=
py
[
i
];
outline
.
push
(
new
IDF_SEGMENT
(
p1
,
p2
)
);
}
aIDFBoard
.
AddOutline
(
outline
);
}
/**
* Function idf_export_module
* retrieves information from all board modules, adds drill holes to
* the DRILLED_HOLES or BOARD_OUTLINE section as appropriate,
* compiles data for the PLACEMENT section and compiles data for
* the library ELECTRICAL section.
*/
static
void
idf_export_module
(
BOARD
*
aPcb
,
MODULE
*
aModule
,
IDF_BOARD
&
aIDFBoard
)
{
// Reference Designator
std
::
string
crefdes
=
TO_UTF8
(
aModule
->
GetReference
()
);
if
(
crefdes
.
empty
()
||
!
crefdes
.
compare
(
"~"
)
)
{
std
::
string
cvalue
=
TO_UTF8
(
aModule
->
GetValue
()
);
// if both the RefDes and Value are empty or set to '~' the board owns the part,
// otherwise associated parts of the module must be marked NOREFDES.
if
(
cvalue
.
empty
()
||
!
cvalue
.
compare
(
"~"
)
)
crefdes
=
"BOARD"
;
else
crefdes
=
"NOREFDES"
;
}
// TODO: If module cutouts are supported we must add code here
// for( EDA_ITEM* item = aModule->GraphicalItems(); item != NULL; item = item->Next() )
// {
// if( ( item->Type() != PCB_MODULE_EDGE_T )
// || (item->GetLayer() != EDGE_N ) ) continue;
// code to export cutouts
// }
// Export pads
double
drill
,
x
,
y
;
double
scale
=
aIDFBoard
.
GetScale
();
IDF3
::
KEY_PLATING
kplate
;
std
::
string
pintype
;
std
::
string
tstr
;
double
dx
,
dy
;
aIDFBoard
.
GetOffset
(
dx
,
dy
);
for
(
D_PAD
*
pad
=
aModule
->
Pads
();
pad
;
pad
=
pad
->
Next
()
)
{
drill
=
(
double
)
pad
->
GetDrillSize
().
x
*
scale
;
x
=
pad
->
GetPosition
().
x
*
scale
+
dx
;
y
=
-
pad
->
GetPosition
().
y
*
scale
+
dy
;
// Export the hole on the edge layer
if
(
drill
>
0.0
)
{
// plating
if
(
pad
->
GetAttribute
()
==
PAD_HOLE_NOT_PLATED
)
kplate
=
IDF3
::
NPTH
;
else
kplate
=
IDF3
::
PTH
;
// hole type
tstr
=
TO_UTF8
(
pad
->
GetPadName
()
);
if
(
tstr
.
empty
()
||
!
tstr
.
compare
(
"0"
)
||
!
tstr
.
compare
(
"~"
)
||
(
kplate
==
IDF3
::
NPTH
)
||
(
pad
->
GetDrillShape
()
==
PAD_OVAL
)
)
pintype
=
"MTG"
;
else
pintype
=
"PIN"
;
// fields:
// 1. hole dia. : float
// 2. X coord : float
// 3. Y coord : float
// 4. plating : PTH | NPTH
// 5. Assoc. part : BOARD | NOREFDES | PANEL | {"refdes"}
// 6. type : PIN | VIA | MTG | TOOL | { "other" }
// 7. owner : MCAD | ECAD | UNOWNED
if
(
(
pad
->
GetDrillShape
()
==
PAD_OVAL
)
&&
(
pad
->
GetDrillSize
().
x
!=
pad
->
GetDrillSize
().
y
)
)
{
// NOTE: IDF does not have direct support for slots;
// slots are implemented as a board cutout and we
// cannot represent plating or reference designators
double
dlength
=
pad
->
GetDrillSize
().
y
*
scale
;
// NOTE: The orientation of modules and pads have
// the opposite sense due to KiCad drawing on a
// screen with a LH coordinate system
double
angle
=
pad
->
GetOrientation
()
/
10.0
;
if
(
dlength
<
drill
)
{
std
::
swap
(
drill
,
dlength
);
angle
+=
M_PI2
;
}
// NOTE: KiCad measures a slot's length from end to end
// rather than between the centers of the arcs
dlength
-=
drill
;
aIDFBoard
.
AddSlot
(
drill
,
dlength
,
angle
,
x
,
y
);
}
else
{
aIDFBoard
.
AddDrill
(
drill
,
x
,
y
,
kplate
,
crefdes
,
pintype
,
IDF3
::
ECAD
);
}
}
}
// TODO
// add to the library item list
}
/**
* Function Export_IDF3
* generates IDFv3 compliant board (*.emn) and library (*.emp)
* files representing the user's PCB design.
*/
bool
Export_IDF3
(
BOARD
*
aPcb
,
const
wxString
&
aFullFileName
,
double
aUseThou
)
{
IDF_BOARD
idfBoard
;
SetLocaleTo_C_standard
();
// NOTE:
// XXX We may enclose all this in a TRY .. CATCH block
idfBoard
.
Setup
(
aPcb
->
GetFileName
(),
aFullFileName
,
aUseThou
,
aPcb
->
GetDesignSettings
().
GetBoardThickness
()
);
// set up the global offsets
EDA_RECT
bbox
=
aPcb
->
ComputeBoundingBox
(
true
);
idfBoard
.
SetOffset
(
bbox
.
Centre
().
x
*
idfBoard
.
GetScale
(),
bbox
.
Centre
().
y
*
idfBoard
.
GetScale
()
);
// Export the board outline
idf_export_outline
(
aPcb
,
idfBoard
);
// Output the drill holes and module (library) data.
for
(
MODULE
*
module
=
aPcb
->
m_Modules
;
module
!=
0
;
module
=
module
->
Next
()
)
idf_export_module
(
aPcb
,
module
,
idfBoard
);
idfBoard
.
Finish
();
SetLocaleTo_Default
();
return
true
;
}
pcbnew/idf.cpp
0 → 100644
View file @
0b853c5a
/**
* file: idf.cpp
*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Cirilo Bernardo
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
// TODO: Consider using different precision formats for THOU vs MM output
// Keep in mind that THOU cannot represent MM very well although MM can
// represent 1 THOU with 4 decimal places. For modern manufacturing we
// are interested in a resolution of about 0.1 THOU.
#include <list>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <wx/filename.h>
#include <macros.h>
#include <idf.h>
#include <build_version.h>
// differences in angle smaller than MIN_ANG are considered equal
#define MIN_ANG (0.01)
// minimum drill diameter (nanometers) - 10000 is a 0.01mm drill
#define IDF_MIN_DIA ( 10000.0 )
// minimum board thickness; this is about 0.012mm (0.5 mils)
// which is about the thickness of a single kapton layer typically
// used in a flexible design.
#define IDF_MIN_BRD_THICKNESS (12000)
bool
IDF_POINT
::
Matches
(
const
IDF_POINT
&
aPoint
,
double
aRadius
)
{
double
dx
=
x
-
aPoint
.
x
;
double
dy
=
y
-
aPoint
.
y
;
double
d2
=
dx
*
dx
+
dy
*
dy
;
if
(
d2
<=
aRadius
*
aRadius
)
return
true
;
return
false
;
}
double
IDF_POINT
::
CalcDistance
(
const
IDF_POINT
&
aPoint
)
const
{
double
dx
=
aPoint
.
x
-
x
;
double
dy
=
aPoint
.
y
-
y
;
double
dist
=
sqrt
(
dx
*
dx
+
dy
*
dy
);
return
dist
;
}
double
IDF3
::
CalcAngleRad
(
const
IDF_POINT
&
aStartPoint
,
const
IDF_POINT
&
aEndPoint
)
{
return
atan2
(
aEndPoint
.
y
-
aStartPoint
.
y
,
aEndPoint
.
x
-
aStartPoint
.
x
);
}
double
IDF3
::
CalcAngleDeg
(
const
IDF_POINT
&
aStartPoint
,
const
IDF_POINT
&
aEndPoint
)
{
double
ang
=
CalcAngleRad
(
aStartPoint
,
aEndPoint
);
// round to thousandths of a degree
int
iang
=
int
(
ang
/
M_PI
*
1800000.0
);
ang
=
iang
/
10000.0
;
return
ang
;
}
IDF_SEGMENT
::
IDF_SEGMENT
()
{
angle
=
0.0
;
offsetAngle
=
0.0
;
radius
=
0.0
;
}
IDF_SEGMENT
::
IDF_SEGMENT
(
const
IDF_POINT
&
aStartPoint
,
const
IDF_POINT
&
aEndPoint
)
{
angle
=
0.0
;
offsetAngle
=
0.0
;
radius
=
0.0
;
startPoint
=
aStartPoint
;
endPoint
=
aEndPoint
;
}
IDF_SEGMENT
::
IDF_SEGMENT
(
const
IDF_POINT
&
aStartPoint
,
const
IDF_POINT
&
aEndPoint
,
double
aAngle
,
bool
aFromKicad
)
{
double
diff
=
abs
(
aAngle
)
-
360.0
;
if
(
(
diff
<
MIN_ANG
&&
diff
>
-
MIN_ANG
)
||
(
aAngle
<
MIN_ANG
&&
aAngle
>
-
MIN_ANG
)
||
(
!
aFromKicad
)
)
{
angle
=
0.0
;
startPoint
=
aStartPoint
;
endPoint
=
aEndPoint
;
if
(
diff
<
MIN_ANG
&&
diff
>
-
MIN_ANG
)
{
angle
=
360.0
;
center
=
aStartPoint
;
offsetAngle
=
0.0
;
radius
=
aStartPoint
.
CalcDistance
(
aEndPoint
);
}
else
if
(
aAngle
<
MIN_ANG
&&
aAngle
>
-
MIN_ANG
)
{
CalcCenterAndRadius
();
}
return
;
}
// we need to convert from the KiCad arc convention
angle
=
aAngle
;
center
=
aStartPoint
;
offsetAngle
=
IDF3
::
CalcAngleDeg
(
aStartPoint
,
aEndPoint
);
radius
=
aStartPoint
.
CalcDistance
(
aEndPoint
);
startPoint
=
aEndPoint
;
double
ang
=
offsetAngle
+
aAngle
;
ang
=
(
ang
/
180.0
)
*
M_PI
;
endPoint
.
x
=
(
radius
*
cos
(
ang
)
)
+
center
.
x
;
endPoint
.
y
=
(
radius
*
sin
(
ang
)
)
+
center
.
y
;
}
bool
IDF_SEGMENT
::
MatchesStart
(
const
IDF_POINT
&
aPoint
,
double
aRadius
)
{
return
startPoint
.
Matches
(
aPoint
,
aRadius
);
}
bool
IDF_SEGMENT
::
MatchesEnd
(
const
IDF_POINT
&
aPoint
,
double
aRadius
)
{
return
endPoint
.
Matches
(
aPoint
,
aRadius
);
}
void
IDF_SEGMENT
::
CalcCenterAndRadius
(
void
)
{
// NOTE: this routine does not check if the points are the same
// or too close to be sensible in a production setting.
double
offAng
=
IDF3
::
CalcAngleRad
(
startPoint
,
endPoint
);
double
d
=
startPoint
.
CalcDistance
(
endPoint
)
/
2.0
;
double
xm
=
(
startPoint
.
x
+
endPoint
.
x
)
*
0.5
;
double
ym
=
(
startPoint
.
y
+
endPoint
.
y
)
*
0.5
;
radius
=
d
/
sin
(
angle
*
M_PI
/
180.0
);
if
(
radius
<
0.0
)
{
radius
=
-
radius
;
}
// calculate the height of the triangle with base d and hypotenuse r
double
dh2
=
radius
*
radius
-
d
*
d
;
if
(
dh2
<
0
)
{
// this should only ever happen due to rounding errors when r == d
dh2
=
0
;
}
double
h
=
sqrt
(
dh2
);
if
(
angle
>
0.0
)
offAng
+=
M_PI2
;
else
offAng
-=
M_PI2
;
if
(
(
angle
>
M_PI
)
||
(
angle
<
-
M_PI
)
)
offAng
+=
M_PI
;
center
.
x
=
h
*
cos
(
offAng
)
+
xm
;
center
.
y
=
h
*
sin
(
offAng
)
+
ym
;
offsetAngle
=
IDF3
::
CalcAngleDeg
(
center
,
startPoint
);
}
bool
IDF_SEGMENT
::
IsCircle
(
void
)
{
double
diff
=
abs
(
angle
)
-
360.0
;
if
(
(
diff
<
MIN_ANG
)
&&
(
diff
>
-
MIN_ANG
)
)
return
true
;
return
false
;
}
double
IDF_SEGMENT
::
GetMinX
(
void
)
{
if
(
angle
==
0.0
)
return
std
::
min
(
startPoint
.
x
,
endPoint
.
x
);
// Calculate the leftmost point of the circle or arc
if
(
IsCircle
()
)
{
// if only everything were this easy
return
center
.
x
-
radius
;
}
// cases:
// 1. CCW arc: if offset + included angle >= 180 deg then
// MinX = center.x - radius, otherwise MinX is the
// same as for the case of a line.
// 2. CW arc: if offset + included angle <= -180 deg then
// MinX = center.x - radius, otherwise MinX is the
// same as for the case of a line.
if
(
angle
>
0
)
{
// CCW case
if
(
(
offsetAngle
+
angle
)
>=
180.0
)
{
return
center
.
x
-
radius
;
}
else
{
return
std
::
min
(
startPoint
.
x
,
endPoint
.
x
);
}
}
// CW case
if
(
(
offsetAngle
+
angle
)
<=
-
180.0
)
{
return
center
.
x
-
radius
;
}
return
std
::
min
(
startPoint
.
x
,
endPoint
.
x
);
}
void
IDF_SEGMENT
::
SwapEnds
(
void
)
{
if
(
IsCircle
()
)
{
// reverse the direction
angle
=
-
angle
;
return
;
}
IDF_POINT
tmp
=
startPoint
;
startPoint
=
endPoint
;
endPoint
=
tmp
;
if
(
(
angle
<
MIN_ANG
)
&&
(
angle
>
-
MIN_ANG
)
)
return
;
// nothing more to do
// change the direction of the arc
angle
=
-
angle
;
// calculate the new offset angle
offsetAngle
=
IDF3
::
CalcAngleDeg
(
center
,
startPoint
);
}
IDF_DRILL_DATA
::
IDF_DRILL_DATA
(
double
aDrillDia
,
double
aPosX
,
double
aPosY
,
IDF3
::
KEY_PLATING
aPlating
,
const
std
::
string
aRefDes
,
const
std
::
string
aHoleType
,
IDF3
::
KEY_OWNER
aOwner
)
{
if
(
aDrillDia
<
0.3
)
dia
=
0.3
;
else
dia
=
aDrillDia
;
x
=
aPosX
;
y
=
aPosY
;
plating
=
aPlating
;
if
(
!
aRefDes
.
compare
(
"BOARD"
)
)
{
kref
=
IDF3
::
BOARD
;
}
else
if
(
aRefDes
.
empty
()
||
!
aRefDes
.
compare
(
"NOREFDES"
)
)
{
kref
=
IDF3
::
NOREFDES
;
}
else
if
(
!
aRefDes
.
compare
(
"PANEL"
)
)
{
kref
=
IDF3
::
PANEL
;
}
else
{
kref
=
IDF3
::
REFDES
;
refdes
=
aRefDes
;
}
if
(
!
aHoleType
.
compare
(
"PIN"
)
)
{
khole
=
IDF3
::
PIN
;
}
else
if
(
!
aHoleType
.
compare
(
"VIA"
)
)
{
khole
=
IDF3
::
VIA
;
}
else
if
(
aHoleType
.
empty
()
||
!
aHoleType
.
compare
(
"MTG"
)
)
{
khole
=
IDF3
::
MTG
;
}
else
if
(
!
aHoleType
.
compare
(
"TOOL"
)
)
{
khole
=
IDF3
::
TOOL
;
}
else
{
khole
=
IDF3
::
OTHER
;
holetype
=
aHoleType
;
}
owner
=
aOwner
;
}
// IDF_DRILL_DATA::IDF_DRILL_DATA( ... )
bool
IDF_DRILL_DATA
::
Write
(
FILE
*
aLayoutFile
)
{
// TODO: check stream integrity and return 'false' as appropriate
if
(
!
aLayoutFile
)
return
false
;
std
::
string
holestr
;
std
::
string
refstr
;
std
::
string
ownstr
;
std
::
string
pltstr
;
switch
(
khole
)
{
case
IDF3
:
:
PIN
:
holestr
=
"PIN"
;
break
;
case
IDF3
:
:
VIA
:
holestr
=
"VIA"
;
break
;
case
IDF3
:
:
TOOL
:
holestr
=
"TOOL"
;
break
;
case
IDF3
:
:
OTHER
:
holestr
=
"
\"
"
+
holetype
+
"
\"
"
;
break
;
default
:
holestr
=
"MTG"
;
break
;
}
switch
(
kref
)
{
case
IDF3
:
:
BOARD
:
refstr
=
"BOARD"
;
break
;
case
IDF3
:
:
PANEL
:
refstr
=
"PANEL"
;
break
;
case
IDF3
:
:
REFDES
:
refstr
=
"
\"
"
+
refdes
+
"
\"
"
;
break
;
default
:
refstr
=
"NOREFDES"
;
break
;
}
if
(
plating
==
IDF3
::
PTH
)
pltstr
=
"PTH"
;
else
pltstr
=
"NPTH"
;
switch
(
owner
)
{
case
IDF3
:
:
MCAD
:
ownstr
=
"MCAD"
;
break
;
case
IDF3
:
:
ECAD
:
ownstr
=
"ECAD"
;
break
;
default
:
ownstr
=
"UNOWNED"
;
}
fprintf
(
aLayoutFile
,
"%.3f %.5f %.5f %s %s %s %s
\n
"
,
dia
,
x
,
y
,
pltstr
.
c_str
(),
refstr
.
c_str
(),
holestr
.
c_str
(),
ownstr
.
c_str
()
);
return
true
;
}
// IDF_DRILL_DATA::Write( aLayoutFile )
IDF_BOARD
::
IDF_BOARD
()
{
outlineIndex
=
0
;
scale
=
1e-6
;
boardThickness
=
1.6
;
// default to 1.6mm thick boards
useThou
=
false
;
// by default we want mm output
hasBrdOutlineHdr
=
false
;
layoutFile
=
NULL
;
libFile
=
NULL
;
}
IDF_BOARD
::~
IDF_BOARD
()
{
Finish
();
}
bool
IDF_BOARD
::
Setup
(
wxString
aBoardName
,
wxString
aFullFileName
,
bool
aUseThou
,
int
aBoardThickness
)
{
if
(
aBoardThickness
<
IDF_MIN_BRD_THICKNESS
)
return
false
;
if
(
aUseThou
)
{
useThou
=
true
;
scale
=
1e-3
/
25.4
;
}
else
{
useThou
=
false
;
scale
=
1e-6
;
}
boardThickness
=
aBoardThickness
*
scale
;
wxFileName
brdname
(
aBoardName
);
wxFileName
idfname
(
aFullFileName
);
// open the layout file
idfname
.
SetExt
(
wxT
(
"emn"
)
);
layoutFile
=
wxFopen
(
aFullFileName
,
wxT
(
"wt"
)
);
if
(
layoutFile
==
NULL
)
return
false
;
// open the library file
idfname
.
SetExt
(
wxT
(
"emp"
)
);
libFile
=
wxFopen
(
idfname
.
GetFullPath
(),
wxT
(
"wt"
)
);
if
(
libFile
==
NULL
)
{
fclose
(
layoutFile
);
layoutFile
=
NULL
;
return
false
;
}
time_t
date
;
time
(
&
date
);
struct
tm
tdate
;
time
(
&
date
);
localtime_r
(
&
date
,
&
tdate
);
fprintf
(
layoutFile
,
".HEADER
\n
"
"BOARD_FILE 3.0
\"
Created by KiCad %s
\"
"
" %.4d/%.2d/%.2d.%.2d:%.2d:%.2d 1
\n
"
"
\"
%s
\"
%s
\n
"
".END_HEADER
\n\n
"
,
TO_UTF8
(
GetBuildVersion
()
),
tdate
.
tm_year
+
1900
,
tdate
.
tm_mon
+
1
,
tdate
.
tm_mday
,
tdate
.
tm_hour
,
tdate
.
tm_min
,
tdate
.
tm_sec
,
TO_UTF8
(
brdname
.
GetFullName
()
),
useThou
?
"THOU"
:
"MM"
);
fprintf
(
libFile
,
".HEADER
\n
"
"BOARD_FILE 3.0
\"
Created by KiCad %s
\"
%.4d/%.2d/%.2d.%.2d:%.2d:%.2d 1
\n
"
".END_HEADER
\n\n
"
,
TO_UTF8
(
GetBuildVersion
()
),
tdate
.
tm_year
+
1900
,
tdate
.
tm_mon
+
1
,
tdate
.
tm_mday
,
tdate
.
tm_hour
,
tdate
.
tm_min
,
tdate
.
tm_sec
);
return
true
;
}
bool
IDF_BOARD
::
Finish
(
void
)
{
// Steps to finalize the board and library files:
// 1. (emp) finalize the library file
// 2. (emn) close the BOARD_OUTLINE section
// 3. (emn) write out the DRILLED_HOLES section
// 4. (emn) write out the COMPONENT_PLACEMENT section
// TODO:
// idfLib.Finish();
if
(
libFile
!=
NULL
)
{
fclose
(
libFile
);
libFile
=
NULL
;
}
if
(
layoutFile
==
NULL
)
return
false
;
// Finalize the board outline section
fprintf
(
layoutFile
,
".END_BOARD_OUTLINE
\n\n
"
);
// Write out the drill section
if
(
WriteDrills
()
)
{
fclose
(
layoutFile
);
layoutFile
=
NULL
;
return
false
;
}
// TODO: Write out the component placement section
// IDF3::export_placement();
fclose
(
layoutFile
);
layoutFile
=
NULL
;
return
true
;
}
bool
IDF_BOARD
::
AddOutline
(
IDF_OUTLINE
&
aOutline
)
{
if
(
!
layoutFile
)
return
false
;
// TODO: check the stream integrity
std
::
list
<
IDF_SEGMENT
*>::
iterator
bo
;
std
::
list
<
IDF_SEGMENT
*>::
iterator
eo
;
if
(
!
hasBrdOutlineHdr
)
{
fprintf
(
layoutFile
,
".BOARD_OUTLINE ECAD
\n
%.5f
\n
"
,
boardThickness
);
hasBrdOutlineHdr
=
true
;
}
if
(
aOutline
.
size
()
==
1
)
{
if
(
!
aOutline
.
front
()
->
IsCircle
()
)
return
false
;
// this is a bad outline
// NOTE: a circle always has an angle of 360, never -360,
// otherwise SolidWorks chokes on the file.
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
aOutline
.
front
()
->
startPoint
.
x
,
aOutline
.
front
()
->
startPoint
.
y
);
fprintf
(
layoutFile
,
"%d %.5f %.5f 360
\n
"
,
outlineIndex
,
aOutline
.
front
()
->
endPoint
.
x
,
aOutline
.
front
()
->
endPoint
.
y
);
++
outlineIndex
;
return
true
;
}
// ensure that the very last point is the same as the very first point
aOutline
.
back
()
->
endPoint
=
aOutline
.
front
()
->
startPoint
;
// check if we must reverse things
if
(
(
aOutline
.
IsCCW
()
&&
(
outlineIndex
>
0
)
)
||
(
(
!
aOutline
.
IsCCW
()
)
&&
(
outlineIndex
==
0
)
)
)
{
eo
=
aOutline
.
begin
();
bo
=
aOutline
.
end
();
--
bo
;
// for the first item we write out both points
if
(
aOutline
.
front
()
->
angle
<
MIN_ANG
&&
aOutline
.
front
()
->
angle
>
-
MIN_ANG
)
{
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
aOutline
.
front
()
->
endPoint
.
x
,
aOutline
.
front
()
->
endPoint
.
y
);
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
aOutline
.
front
()
->
startPoint
.
x
,
aOutline
.
front
()
->
startPoint
.
y
);
}
else
{
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
aOutline
.
front
()
->
endPoint
.
x
,
aOutline
.
front
()
->
endPoint
.
y
);
fprintf
(
layoutFile
,
"%d %.5f %.5f %.5f
\n
"
,
outlineIndex
,
aOutline
.
front
()
->
startPoint
.
x
,
aOutline
.
front
()
->
startPoint
.
y
,
-
aOutline
.
front
()
->
angle
);
}
// for all other segments we only write out the start point
while
(
bo
!=
eo
)
{
if
(
(
*
bo
)
->
angle
<
MIN_ANG
&&
(
*
bo
)
->
angle
>
-
MIN_ANG
)
{
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
(
*
bo
)
->
startPoint
.
x
,
(
*
bo
)
->
startPoint
.
y
);
}
else
{
fprintf
(
layoutFile
,
"%d %.5f %.5f %.5f
\n
"
,
outlineIndex
,
(
*
bo
)
->
startPoint
.
x
,
(
*
bo
)
->
startPoint
.
y
,
-
(
*
bo
)
->
angle
);
}
--
bo
;
}
}
else
{
bo
=
aOutline
.
begin
();
eo
=
aOutline
.
end
();
// for the first item we write out both points
if
(
(
*
bo
)
->
angle
<
MIN_ANG
&&
(
*
bo
)
->
angle
>
-
MIN_ANG
)
{
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
(
*
bo
)
->
startPoint
.
x
,
(
*
bo
)
->
startPoint
.
y
);
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
(
*
bo
)
->
endPoint
.
x
,
(
*
bo
)
->
endPoint
.
y
);
}
else
{
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
(
*
bo
)
->
startPoint
.
x
,
(
*
bo
)
->
startPoint
.
y
);
fprintf
(
layoutFile
,
"%d %.5f %.5f %.5f
\n
"
,
outlineIndex
,
(
*
bo
)
->
endPoint
.
x
,
(
*
bo
)
->
endPoint
.
y
,
(
*
bo
)
->
angle
);
}
++
bo
;
// for all other segments we only write out the last point
while
(
bo
!=
eo
)
{
if
(
(
*
bo
)
->
angle
<
MIN_ANG
&&
(
*
bo
)
->
angle
>
-
MIN_ANG
)
{
fprintf
(
layoutFile
,
"%d %.5f %.5f 0
\n
"
,
outlineIndex
,
(
*
bo
)
->
endPoint
.
x
,
(
*
bo
)
->
endPoint
.
y
);
}
else
{
fprintf
(
layoutFile
,
"%d %.5f %.5f %.5f
\n
"
,
outlineIndex
,
(
*
bo
)
->
endPoint
.
x
,
(
*
bo
)
->
endPoint
.
y
,
(
*
bo
)
->
angle
);
}
++
bo
;
}
}
++
outlineIndex
;
return
true
;
}
bool
IDF_BOARD
::
AddDrill
(
double
dia
,
double
x
,
double
y
,
IDF3
::
KEY_PLATING
plating
,
const
std
::
string
refdes
,
const
std
::
string
holeType
,
IDF3
::
KEY_OWNER
owner
)
{
if
(
dia
<
IDF_MIN_DIA
*
scale
)
return
false
;
IDF_DRILL_DATA
*
dp
=
new
IDF_DRILL_DATA
(
dia
,
x
,
y
,
plating
,
refdes
,
holeType
,
owner
);
drills
.
push_back
(
dp
);
return
true
;
}
bool
IDF_BOARD
::
AddSlot
(
double
aWidth
,
double
aLength
,
double
aOrientation
,
double
aX
,
double
aY
)
{
if
(
aWidth
<
IDF_MIN_DIA
*
scale
)
return
false
;
if
(
aLength
<
IDF_MIN_DIA
*
scale
)
return
false
;
IDF_POINT
c
[
2
];
// centers
IDF_POINT
pt
[
4
];
double
a1
=
aOrientation
/
180.0
*
M_PI
;
double
a2
=
a1
+
M_PI2
;
double
d1
=
aLength
/
2.0
;
double
d2
=
aWidth
/
2.0
;
double
sa1
=
sin
(
a1
);
double
ca1
=
cos
(
a1
);
double
dsa2
=
d2
*
sin
(
a2
);
double
dca2
=
d2
*
cos
(
a2
);
c
[
0
].
x
=
aX
+
d1
*
ca1
;
c
[
0
].
y
=
aY
+
d1
*
sa1
;
c
[
1
].
x
=
aX
-
d1
*
ca1
;
c
[
1
].
y
=
aY
-
d1
*
sa1
;
pt
[
0
].
x
=
c
[
0
].
x
-
dca2
;
pt
[
0
].
y
=
c
[
0
].
y
-
dsa2
;
pt
[
1
].
x
=
c
[
1
].
x
-
dca2
;
pt
[
1
].
y
=
c
[
1
].
y
-
dsa2
;
pt
[
2
].
x
=
c
[
1
].
x
+
dca2
;
pt
[
2
].
y
=
c
[
1
].
y
+
dsa2
;
pt
[
3
].
x
=
c
[
0
].
x
+
dca2
;
pt
[
3
].
y
=
c
[
0
].
y
+
dsa2
;
IDF_OUTLINE
outline
;
// first straight run
IDF_SEGMENT
*
seg
=
new
IDF_SEGMENT
(
pt
[
0
],
pt
[
1
]
);
outline
.
push
(
seg
);
// first 180 degree cap
seg
=
new
IDF_SEGMENT
(
c
[
1
],
pt
[
1
],
-
180.0
,
true
);
outline
.
push
(
seg
);
// final straight run
seg
=
new
IDF_SEGMENT
(
pt
[
2
],
pt
[
3
]
);
outline
.
push
(
seg
);
// final 180 degree cap
seg
=
new
IDF_SEGMENT
(
c
[
0
],
pt
[
3
],
-
180.0
,
true
);
outline
.
push
(
seg
);
return
AddOutline
(
outline
);
}
bool
IDF_BOARD
::
WriteDrills
(
void
)
{
if
(
!
layoutFile
)
return
false
;
// TODO: check the stream integrity and return false as appropriate
if
(
drills
.
empty
()
)
return
true
;
fprintf
(
layoutFile
,
".DRILLED_HOLES
\n
"
);
std
::
list
<
struct
IDF_DRILL_DATA
*>::
iterator
ds
=
drills
.
begin
();
std
::
list
<
struct
IDF_DRILL_DATA
*>::
iterator
de
=
drills
.
end
();
while
(
ds
!=
de
)
{
if
(
!
(
*
ds
)
->
Write
(
layoutFile
)
)
return
false
;
++
ds
;
}
fprintf
(
layoutFile
,
".END_DRILLED_HOLES
\n
"
);
return
true
;
}
double
IDF_BOARD
::
GetScale
(
void
)
{
return
scale
;
}
void
IDF_BOARD
::
SetOffset
(
double
x
,
double
y
)
{
offsetX
=
x
;
offsetY
=
y
;
}
void
IDF_BOARD
::
GetOffset
(
double
&
x
,
double
&
y
)
{
x
=
offsetX
;
y
=
offsetY
;
}
void
IDF3
::
GetOutline
(
std
::
list
<
IDF_SEGMENT
*>&
aLines
,
IDF_OUTLINE
&
aOutline
)
{
aOutline
.
Clear
();
// NOTE: To tell if the point order is CCW or CW,
// sum all: (endPoint.X[n] - startPoint.X[n])*(endPoint[n] + startPoint.Y[n])
// If the result is >0, the direction is CW, otherwise
// it is CCW. Note that the result cannot be 0 unless
// we have a bounded area of 0.
// First we find the segment with the leftmost point
std
::
list
<
IDF_SEGMENT
*>::
iterator
bl
=
aLines
.
begin
();
std
::
list
<
IDF_SEGMENT
*>::
iterator
el
=
aLines
.
end
();
std
::
list
<
IDF_SEGMENT
*>::
iterator
idx
=
bl
++
;
// iterator for the object with minX
double
minx
=
(
*
idx
)
->
GetMinX
();
double
curx
;
while
(
bl
!=
el
)
{
curx
=
(
*
bl
)
->
GetMinX
();
if
(
curx
<
minx
)
{
minx
=
curx
;
idx
=
bl
;
}
++
bl
;
}
aOutline
.
push
(
*
idx
);
aLines
.
erase
(
idx
);
// If the item is a circle then we're done
if
(
aOutline
.
front
()
->
IsCircle
()
)
return
;
// Assemble the loop
bool
complete
=
false
;
// set if loop is complete
bool
matched
;
// set if a segment's end point was matched
while
(
!
complete
)
{
matched
=
false
;
bl
=
aLines
.
begin
();
el
=
aLines
.
end
();
while
(
bl
!=
el
&&
!
matched
)
{
if
(
(
*
bl
)
->
MatchesStart
(
aOutline
.
back
()
->
endPoint
)
)
{
if
(
(
*
bl
)
->
IsCircle
()
)
{
// a circle on the perimeter is pathological but we just ignore it
++
bl
;
}
else
{
matched
=
true
;
aOutline
.
push
(
*
bl
);
aLines
.
erase
(
bl
);
}
continue
;
}
++
bl
;
}
if
(
!
matched
)
{
// attempt to match the end points
bl
=
aLines
.
begin
();
el
=
aLines
.
end
();
while
(
bl
!=
el
&&
!
matched
)
{
if
(
(
*
bl
)
->
MatchesEnd
(
aOutline
.
back
()
->
endPoint
)
)
{
if
(
(
*
bl
)
->
IsCircle
()
)
{
// a circle on the perimeter is pathological but we just ignore it
++
bl
;
}
else
{
matched
=
true
;
(
*
bl
)
->
SwapEnds
();
aOutline
.
push
(
*
bl
);
aLines
.
erase
(
bl
);
}
continue
;
}
++
bl
;
}
}
if
(
!
matched
)
{
// still no match - attempt to close the loop
if
(
(
aOutline
.
size
()
>
1
)
||
(
aOutline
.
front
()
->
angle
<
-
MIN_ANG
)
||
(
aOutline
.
front
()
->
angle
>
MIN_ANG
)
)
{
// close the loop
IDF_SEGMENT
*
seg
=
new
IDF_SEGMENT
(
aOutline
.
back
()
->
endPoint
,
aOutline
.
front
()
->
startPoint
);
if
(
seg
)
{
complete
=
true
;
aOutline
.
push
(
seg
);
break
;
}
}
// the outline is bad; drop the segments
aOutline
.
Clear
();
return
;
}
// check if the loop is complete
if
(
aOutline
.
front
()
->
MatchesStart
(
aOutline
.
back
()
->
endPoint
)
)
{
complete
=
true
;
break
;
}
}
}
bool
IDF_LIB
::
WriteLib
(
FILE
*
aLibFile
)
{
if
(
!
aLibFile
)
return
false
;
// TODO: check stream integrity and return false as appropriate
// TODO: export models
return
true
;
}
bool
IDF_LIB
::
WriteBrd
(
FILE
*
aLayoutFile
)
{
if
(
!
aLayoutFile
)
return
false
;
// TODO: check stream integrity and return false as appropriate
// TODO: write out the board placement information
return
true
;
}
pcbnew/idf.h
0 → 100644
View file @
0b853c5a
/**
* @file idf.h
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Cirilo Bernardo
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef IDF_H
#define IDF_H
#include <wx/string.h>
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841
#endif
#ifndef M_PI2
#define M_PI2 ( M_PI / 2.0 )
#endif
#ifndef M_PI4
#define M_PI4 ( M_PI / 4.0 )
#endif
class
IDF_POINT
;
class
IDF_SEGMENT
;
class
IDF_DRILL_DATA
;
class
IDF_OUTLINE
;
namespace
IDF3
{
enum
KEY_OWNER
{
UNOWNED
=
0
,
// < either MCAD or ECAD may modify a feature
MCAD
,
// < only MCAD may modify a feature
ECAD
// < only ECAD may modify a feature
};
enum
KEY_HOLETYPE
{
PIN
=
0
,
// < drill hole is for a pin
VIA
,
// < drill hole is for a via
MTG
,
// < drill hole is for mounting
TOOL
,
// < drill hole is for tooling
OTHER
// < user has specified a custom type
};
enum
KEY_PLATING
{
PTH
=
0
,
// < Plate-Through Hole
NPTH
// < Non-Plate-Through Hole
};
enum
KEY_REFDES
{
BOARD
=
0
,
// < feature is associated with the board
NOREFDES
,
// < feature is associated with a component with no RefDes
PANEL
,
// < feature is associated with an IDF panel
REFDES
// < reference designator as assigned by the CAD software
};
// calculate the angle between the horizon and the segment aStartPoint to aEndPoint
double
CalcAngleRad
(
const
IDF_POINT
&
aStartPoint
,
const
IDF_POINT
&
aEndPoint
);
double
CalcAngleDeg
(
const
IDF_POINT
&
aStartPoint
,
const
IDF_POINT
&
aEndPoint
);
// take contiguous elements from 'lines' and stuff them into 'outline'
void
GetOutline
(
std
::
list
<
IDF_SEGMENT
*>&
aLines
,
IDF_OUTLINE
&
aOutline
);
}
/**
* @Class IDF_POINT
* represents a point
*/
class
IDF_POINT
{
public
:
double
x
;
// < X coordinate
double
y
;
// < Y coordinate
IDF_POINT
()
{
x
=
0
.
0
;
y
=
0
.
0
;
}
/**
* Function Matches()
* returns true if the given coordinate point is within the given radius
* of the point.
* @param aPoint : coordinates of the point being compared
* @param aRadius : radius within which the points are considered the same
*/
bool
Matches
(
const
IDF_POINT
&
aPoint
,
double
aRadius
=
1e-5
);
double
CalcDistance
(
const
IDF_POINT
&
aPoint
)
const
;
};
/**
* @Class IDF_SEGMENT
* represents a geometry segment as used in IDFv3 outlines
*/
class
IDF_SEGMENT
{
private
:
/**
* Function CalcCenterAndRadius()
* Calculates the center, radius, and angle between center and start point given the
* IDF compliant points and included angle.
* @var startPoint, @var endPoint, and @var angle must be set prior as per IDFv3
*/
void
CalcCenterAndRadius
(
void
);
public
:
IDF_POINT
startPoint
;
// starting point in IDF coordinates
IDF_POINT
endPoint
;
// end point in IDF coordinates
IDF_POINT
center
;
// center of an arc or circle; used primarily for calculating min X
double
angle
;
// included angle (degrees) according to IDFv3 specification
double
offsetAngle
;
// angle between center and start of arc; used to speed up some calcs.
double
radius
;
// radius of the arc or circle; used to speed up some calcs.
/**
* Function IDF_SEGMENT()
* initializes the internal variables
*/
IDF_SEGMENT
();
/**
* Function IDF_SEGMENT( start, end )
* creates a straight segment
*/
IDF_SEGMENT
(
const
IDF_POINT
&
aStartPoint
,
const
IDF_POINT
&
aEndPoint
);
/**
* Function IDF_SEGMENT( start, end )
* creates a straight segment, arc, or circle depending on the angle
* @param aStartPoint : start point (center if using KiCad convention, otherwise IDF convention)
* @param aEndPoint : end point (start of arc if using KiCad convention, otherwise IDF convention)
* @param aAngle : included angle; the KiCad convention is equivalent to the IDF convention
* @param fromKicad : set true if we need to convert from KiCad to IDF convention
*/
IDF_SEGMENT
(
const
IDF_POINT
&
aStartPoint
,
const
IDF_POINT
&
aEndPoint
,
double
aAngle
,
bool
aFromKicad
);
/**
* Function MatchesStart()
* returns true if the given coordinate is within a radius 'rad'
* of the start point.
* @param aPoint : coordinates of the point being compared
* @param aRadius : radius within which the points are considered the same
*/
bool
MatchesStart
(
const
IDF_POINT
&
aPoint
,
double
aRadius
=
1e-3
);
/**
* Function MatchesEnd()
* returns true if the given coordinate is within a radius 'rad'
* of the end point.
* @param aPoint : coordinates of the point being compared
* @param aRadius : radius within which the points are considered the same
*/
bool
MatchesEnd
(
const
IDF_POINT
&
aPoint
,
double
aRadius
=
1e-3
);
/**
* Function IsCircle()
* returns true if this segment is a circle
*/
bool
IsCircle
(
void
);
/**
* Function GetMinX()
* returns the minimum X coordinate of this segment
*/
double
GetMinX
(
void
);
/**
* Function SwapEnds()
* Swaps the start and end points and alters internal
* variables as necessary for arcs
*/
void
SwapEnds
(
void
);
};
/**
* @Class IDF_OUTLINE
* contains segment and winding information for an IDF outline
*/
class
IDF_OUTLINE
{
private
:
double
dir
;
std
::
list
<
IDF_SEGMENT
*>
outline
;
public
:
IDF_OUTLINE
()
{
dir
=
0
.
0
;
}
~
IDF_OUTLINE
()
{
Clear
();
}
// returns true if the current list of points represents a counterclockwise winding
bool
IsCCW
(
void
)
{
if
(
dir
>
0
.
0
)
return
false
;
return
true
;
}
// clears the internal list of outline segments
void
Clear
(
void
)
{
dir
=
0
.
0
;
while
(
!
outline
.
empty
()
)
{
delete
outline
.
front
();
outline
.
pop_front
();
}
}
// returns the size of the internal segment list
size_t
size
(
void
)
{
return
outline
.
size
();
}
// returns true if the internal segment list is empty
bool
empty
(
void
)
{
return
outline
.
empty
();
}
// return the front() of the internal segment list
IDF_SEGMENT
*&
front
(
void
)
{
return
outline
.
front
();
}
// return the back() of the internal segment list
IDF_SEGMENT
*&
back
(
void
)
{
return
outline
.
back
();
}
// return the begin() iterator of the internal segment list
std
::
list
<
IDF_SEGMENT
*>::
iterator
begin
(
void
)
{
return
outline
.
begin
();
}
// return the end() iterator of the internal segment list
std
::
list
<
IDF_SEGMENT
*>::
iterator
end
(
void
)
{
return
outline
.
end
();
}
// push a segment onto the internal list
void
push
(
IDF_SEGMENT
*
item
)
{
// XXX - check that startPoint[N] == endPoint[N -1], otherwise THROW
// XXX - a Circle must stand alone; if we add to a circle or add a
// circle to an existing list, we should throw an exception.
outline
.
push_back
(
item
);
dir
+=
(
outline
.
back
()
->
endPoint
.
x
-
outline
.
back
()
->
startPoint
.
x
)
*
(
outline
.
back
()
->
endPoint
.
y
+
outline
.
back
()
->
startPoint
.
y
);
}
};
/**
* @Class IDF_BOARD
* contains objects necessary for the maintenance of the IDF board and library files.
*/
class
IDF_BOARD
{
private
:
std
::
list
<
IDF_DRILL_DATA
*>
drills
;
///< IDF drill data
int
outlineIndex
;
///< next outline index to use
bool
useThou
;
///< true if output is THOU
double
scale
;
///< scale from KiCad IU to IDF output units
double
boardThickness
;
///< total thickness of the PCB
bool
hasBrdOutlineHdr
;
///< true when a board outline header has been written
double
offsetX
;
///< offset to roughly center the board on the world origin
double
offsetY
;
FILE
*
layoutFile
;
///< IDF board file (*.emn)
FILE
*
libFile
;
///< IDF library file (*.emp)
/**
* Function Write
* outputs a .DRILLED_HOLES section compliant with the
* IDFv3 specification.
* @param aLayoutFile : open file (*.emn) for output
*/
bool
WriteDrills
(
void
);
public
:
IDF_BOARD
();
~
IDF_BOARD
();
// Set up the output files and scale factor;
// return TRUE if everything is OK
bool
Setup
(
wxString
aBoardName
,
wxString
aFullFileName
,
bool
aUseThou
,
int
aBoardThickness
);
// Finish a board
// Write out all current data and close files.
// Return true for success
bool
Finish
(
void
);
/**
* Function GetScale
* returns the output scaling factor
*/
double
GetScale
(
void
);
/**
* Function SetOffset
* sets the global coordinate offsets
*/
void
SetOffset
(
double
x
,
double
y
);
/**
* Function GetOffset
* returns the global coordinate offsets
*/
void
GetOffset
(
double
&
x
,
double
&
y
);
// Add an outline; the very first outline is the board perimeter;
// all additional outlines are cutouts.
bool
AddOutline
(
IDF_OUTLINE
&
aOutline
);
/**
* Function AddDrill
* creates a drill entry and adds it to the list of PCB holes
* @param dia : drill diameter
* @param x : X coordinate of the drill center
* @param y : Y coordinate of the drill center
* @param plating : flag, PTH or NPTH
* @param refdes : component Reference Designator
* @param holetype : purpose of hole
* @param owner : one of MCAD, ECAD, UNOWNED
*/
bool
AddDrill
(
double
dia
,
double
x
,
double
y
,
IDF3
::
KEY_PLATING
plating
,
const
std
::
string
refdes
,
const
std
::
string
holeType
,
IDF3
::
KEY_OWNER
owner
);
/**
* Function AddSlot
* creates a slot cutout within the IDF BOARD section; this is a deficient representation
* of a KiCad 'oval' drill; IDF is unable to represent a plated slot and unable to
* represent the Reference Designator association with a slot.
*/
bool
AddSlot
(
double
aWidth
,
double
aLength
,
double
aOrientation
,
double
aX
,
double
aY
);
};
/**
* @Class IDF_DRILL_DATA
* contains information describing a drilled hole and is responsible for
* writing this information to a file in compliance with the IDFv3 specification.
*/
class
IDF_DRILL_DATA
{
private
:
double
dia
;
double
x
;
double
y
;
IDF3
::
KEY_PLATING
plating
;
IDF3
::
KEY_REFDES
kref
;
IDF3
::
KEY_HOLETYPE
khole
;
std
::
string
refdes
;
std
::
string
holetype
;
IDF3
::
KEY_OWNER
owner
;
public
:
/**
* Constructor IDF_DRILL_DATA
* creates a drill entry with information compliant with the
* IDFv3 specifications.
* @param aDrillDia : drill diameter
* @param aPosX : X coordinate of the drill center
* @param aPosY : Y coordinate of the drill center
* @param aPlating : flag, PTH or NPTH
* @param aRefDes : component Reference Designator
* @param aHoleType : purpose of hole
* @param aOwner : one of MCAD, ECAD, UNOWNED
*/
IDF_DRILL_DATA
(
double
aDrillDia
,
double
aPosX
,
double
aPosY
,
IDF3
::
KEY_PLATING
aPlating
,
const
std
::
string
aRefDes
,
const
std
::
string
aHoleType
,
IDF3
::
KEY_OWNER
aOwner
);
/**
* Function Write
* writes a single line representing the hole within a .DRILLED_HOLES section
*/
bool
Write
(
FILE
*
aLayoutFile
);
};
/**
* @Class IDF_LIB
* stores information on IDF models ( also has an inbuilt NOMODEL model )
* and is responsible for writing the ELECTRICAL sections of the library file
* (*.emp) and the PLACEMENT section of the board file.
*/
class
IDF_LIB
{
// TODO: IMPLEMENT
public
:
/**
* Function WriteLib
* writes all current library information to the output file
*/
bool
WriteLib
(
FILE
*
aLibFile
);
// write placement information to the board file
bool
WriteBrd
(
FILE
*
aLayoutFile
);
// bool Finish( void )
// {
// TODO: Write out the library (*.emp) file
// idf_lib.Write( lib_file );
// TODO: fclose( lib_file );
// }
};
#endif // IDF_H
pcbnew/menubar_pcbframe.cpp
View file @
0b853c5a
...
@@ -204,6 +204,11 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
...
@@ -204,6 +204,11 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
_
(
"Export a VRML board representation"
),
_
(
"Export a VRML board representation"
),
KiBitmap
(
three_d_xpm
)
);
KiBitmap
(
three_d_xpm
)
);
// IDF3
AddMenuItem
(
submenuexport
,
ID_GEN_EXPORT_FILE_IDF3
,
_
(
"I&DFv3 Board Shape Export"
),
_
(
"Basci export of board shape only IDFv3 format"
),
KiBitmap
(
export_xpm
)
);
AddMenuItem
(
filesMenu
,
submenuexport
,
AddMenuItem
(
filesMenu
,
submenuexport
,
ID_GEN_EXPORT_FILE
,
_
(
"E&xport"
),
ID_GEN_EXPORT_FILE
,
_
(
"E&xport"
),
_
(
"Export board"
),
KiBitmap
(
export_xpm
)
);
_
(
"Export board"
),
KiBitmap
(
export_xpm
)
);
...
...
pcbnew/pcbframe.cpp
View file @
0b853c5a
...
@@ -115,6 +115,7 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
...
@@ -115,6 +115,7 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
EVT_MENU
(
ID_GEN_EXPORT_FILE_GENCADFORMAT
,
PCB_EDIT_FRAME
::
ExportToGenCAD
)
EVT_MENU
(
ID_GEN_EXPORT_FILE_GENCADFORMAT
,
PCB_EDIT_FRAME
::
ExportToGenCAD
)
EVT_MENU
(
ID_GEN_EXPORT_FILE_MODULE_REPORT
,
PCB_EDIT_FRAME
::
GenFootprintsReport
)
EVT_MENU
(
ID_GEN_EXPORT_FILE_MODULE_REPORT
,
PCB_EDIT_FRAME
::
GenFootprintsReport
)
EVT_MENU
(
ID_GEN_EXPORT_FILE_VRML
,
PCB_EDIT_FRAME
::
OnExportVRML
)
EVT_MENU
(
ID_GEN_EXPORT_FILE_VRML
,
PCB_EDIT_FRAME
::
OnExportVRML
)
EVT_MENU
(
ID_GEN_EXPORT_FILE_IDF3
,
PCB_EDIT_FRAME
::
ExportToIDF3
)
EVT_MENU
(
ID_GEN_IMPORT_SPECCTRA_SESSION
,
PCB_EDIT_FRAME
::
ImportSpecctraSession
)
EVT_MENU
(
ID_GEN_IMPORT_SPECCTRA_SESSION
,
PCB_EDIT_FRAME
::
ImportSpecctraSession
)
EVT_MENU
(
ID_GEN_IMPORT_SPECCTRA_DESIGN
,
PCB_EDIT_FRAME
::
ImportSpecctraDesign
)
EVT_MENU
(
ID_GEN_IMPORT_SPECCTRA_DESIGN
,
PCB_EDIT_FRAME
::
ImportSpecctraDesign
)
...
...
pcbnew/pcbnew_id.h
View file @
0b853c5a
...
@@ -246,6 +246,7 @@ enum pcbnew_ids
...
@@ -246,6 +246,7 @@ enum pcbnew_ids
ID_MENU_PCB_SWAP_LAYERS
,
ID_MENU_PCB_SWAP_LAYERS
,
ID_MENU_PCB_RESET_TEXTMODULE_FIELDS_SIZES
,
ID_MENU_PCB_RESET_TEXTMODULE_FIELDS_SIZES
,
ID_GEN_EXPORT_FILE_IDF3
,
ID_GEN_EXPORT_FILE_VRML
,
ID_GEN_EXPORT_FILE_VRML
,
ID_GEN_EXPORT_SPECCTRA
,
ID_GEN_EXPORT_SPECCTRA
,
ID_GEN_EXPORT_FILE_GENCADFORMAT
,
ID_GEN_EXPORT_FILE_GENCADFORMAT
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment