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
8dd76c53
Commit
8dd76c53
authored
Apr 19, 2010
by
jean-pierre charras
Browse files
Options
Browse Files
Download
Plain Diff
Pcbnew: Added VRML export, from the patch sent by Lorenzo Marcantonio ( october 2009, 11)
parents
bffefd7e
6be07af6
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1909 additions
and
0 deletions
+1909
-0
wxPcbStruct.h
include/wxPcbStruct.h
+19
-0
CMakeLists.txt
pcbnew/CMakeLists.txt
+2
-0
dialog_export_3Dfiles_base.cpp
pcbnew/dialog_export_3Dfiles_base.cpp
+80
-0
dialog_export_3Dfiles_base.fbp
pcbnew/dialog_export_3Dfiles_base.fbp
+496
-0
dialog_export_3Dfiles_base.h
pcbnew/dialog_export_3Dfiles_base.h
+59
-0
export_vrml.cpp
pcbnew/export_vrml.cpp
+1244
-0
menubar_pcbframe.cpp
pcbnew/menubar_pcbframe.cpp
+7
-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 @
8dd76c53
...
...
@@ -479,6 +479,25 @@ public:
void
ExportToGenCAD
(
wxCommandEvent
&
event
);
/**
* Function OnExportVRML
* will export the current BOARD to a VRML file.
*/
void
OnExportVRML
(
wxCommandEvent
&
event
);
/**
* Function ExportVRML_File
* Creates the file(s) exporting current BOARD to a VRML file.
* @param aFullFileName = the full filename of the file to create
* @param aScale = the general scaling factor. 1.0 to export in inches
* @param aExport3DFiles = true to copy 3D shapes in the subir a3D_Subdir
* @param a3D_Subdir = sub directory where 3D sahpes files are copied
* used only when aExport3DFiles == true
* @return true if Ok.
*/
bool
ExportVRML_File
(
const
wxString
&
aFullFileName
,
double
aScale
,
bool
aExport3DFiles
,
const
wxString
&
a3D_Subdir
);
/**
* Function ExporttoSPECCTRA
* will export the current BOARD to a specctra dsn file. See
...
...
pcbnew/CMakeLists.txt
View file @
8dd76c53
...
...
@@ -51,6 +51,7 @@ set(PCBNEW_SRCS
dialog_edit_module_text.cpp
dialog_edit_module_text_base.cpp
dialog_exchange_modules_base.cpp
dialog_export_3Dfiles_base.cpp
dialog_freeroute_exchange.cpp
dialog_freeroute_exchange_base.cpp
# dialog_gendrill.cpp
...
...
@@ -99,6 +100,7 @@ set(PCBNEW_SRCS
edtxtmod.cpp
event_handlers_tracks_vias_sizes.cpp
export_gencad.cpp
export_vrml.cpp
files.cpp
find.cpp
gen_drill_report_files.cpp
...
...
pcbnew/dialog_export_3Dfiles_base.cpp
0 → 100644
View file @
8dd76c53
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 16 2008)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_export_3Dfiles_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_EXPORT_3DFILE_BASE
::
DIALOG_EXPORT_3DFILE_BASE
(
wxWindow
*
parent
,
wxWindowID
id
,
const
wxString
&
title
,
const
wxPoint
&
pos
,
const
wxSize
&
size
,
long
style
)
:
wxDialog
(
parent
,
id
,
title
,
pos
,
size
,
style
)
{
this
->
SetSizeHints
(
wxDefaultSize
,
wxDefaultSize
);
wxBoxSizer
*
bSizer1
;
bSizer1
=
new
wxBoxSizer
(
wxVERTICAL
);
wxBoxSizer
*
bUpperSizer
;
bUpperSizer
=
new
wxBoxSizer
(
wxVERTICAL
);
bUpperSizer
->
SetMinSize
(
wxSize
(
450
,
-
1
)
);
m_staticText1
=
new
wxStaticText
(
this
,
wxID_ANY
,
_
(
"Wrml main file filename:"
),
wxDefaultPosition
,
wxDefaultSize
,
0
);
m_staticText1
->
Wrap
(
-
1
);
bUpperSizer
->
Add
(
m_staticText1
,
0
,
wxTOP
|
wxRIGHT
|
wxLEFT
,
5
);
m_filePicker
=
new
wxFilePickerCtrl
(
this
,
wxID_ANY
,
wxEmptyString
,
_
(
"Save VRML Board File"
),
wxT
(
"*.wrl"
),
wxDefaultPosition
,
wxDefaultSize
,
wxFLP_DEFAULT_STYLE
|
wxFLP_SAVE
);
bUpperSizer
->
Add
(
m_filePicker
,
0
,
wxBOTTOM
|
wxRIGHT
|
wxLEFT
|
wxEXPAND
,
5
);
m_staticText3
=
new
wxStaticText
(
this
,
wxID_ANY
,
_
(
"Wrml 3D footprints shapes subdir:"
),
wxDefaultPosition
,
wxDefaultSize
,
0
);
m_staticText3
->
Wrap
(
-
1
);
bUpperSizer
->
Add
(
m_staticText3
,
0
,
wxTOP
|
wxRIGHT
|
wxLEFT
,
5
);
m_SubdirNameCtrl
=
new
wxTextCtrl
(
this
,
wxID_ANY
,
wxEmptyString
,
wxDefaultPosition
,
wxDefaultSize
,
0
);
bUpperSizer
->
Add
(
m_SubdirNameCtrl
,
0
,
wxEXPAND
|
wxBOTTOM
|
wxRIGHT
|
wxLEFT
,
5
);
bSizer1
->
Add
(
bUpperSizer
,
0
,
wxEXPAND
,
5
);
wxBoxSizer
*
bLowerSizer
;
bLowerSizer
=
new
wxBoxSizer
(
wxHORIZONTAL
);
wxString
m_rbSelectUnitsChoices
[]
=
{
_
(
"Inch"
),
_
(
"mm"
),
_
(
"Meter"
)
};
int
m_rbSelectUnitsNChoices
=
sizeof
(
m_rbSelectUnitsChoices
)
/
sizeof
(
wxString
);
m_rbSelectUnits
=
new
wxRadioBox
(
this
,
wxID_ANY
,
_
(
"Units:"
),
wxDefaultPosition
,
wxDefaultSize
,
m_rbSelectUnitsNChoices
,
m_rbSelectUnitsChoices
,
1
,
wxRA_SPECIFY_COLS
);
m_rbSelectUnits
->
SetSelection
(
0
);
bLowerSizer
->
Add
(
m_rbSelectUnits
,
1
,
wxALL
|
wxEXPAND
,
5
);
wxString
m_rb3DFilesOptionChoices
[]
=
{
_
(
"Copy 3D Shapes Files in Subdir"
),
_
(
"Use Absolute Path in Wrml File "
)
};
int
m_rb3DFilesOptionNChoices
=
sizeof
(
m_rb3DFilesOptionChoices
)
/
sizeof
(
wxString
);
m_rb3DFilesOption
=
new
wxRadioBox
(
this
,
wxID_ANY
,
_
(
"3D Shapes Files Option:"
),
wxDefaultPosition
,
wxDefaultSize
,
m_rb3DFilesOptionNChoices
,
m_rb3DFilesOptionChoices
,
1
,
wxRA_SPECIFY_COLS
);
m_rb3DFilesOption
->
SetSelection
(
0
);
bLowerSizer
->
Add
(
m_rb3DFilesOption
,
1
,
wxALL
|
wxEXPAND
,
5
);
bSizer1
->
Add
(
bLowerSizer
,
1
,
wxEXPAND
,
5
);
m_staticline1
=
new
wxStaticLine
(
this
,
wxID_ANY
,
wxDefaultPosition
,
wxDefaultSize
,
wxLI_HORIZONTAL
);
bSizer1
->
Add
(
m_staticline1
,
0
,
wxEXPAND
|
wxRIGHT
|
wxLEFT
,
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
();
bSizer1
->
Add
(
m_sdbSizer1
,
0
,
wxEXPAND
|
wxALL
,
5
);
this
->
SetSizer
(
bSizer1
);
this
->
Layout
();
// Connect Events
m_sdbSizer1Cancel
->
Connect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_EXPORT_3DFILE_BASE
::
OnCancelClick
),
NULL
,
this
);
m_sdbSizer1OK
->
Connect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_EXPORT_3DFILE_BASE
::
OnOkClick
),
NULL
,
this
);
}
DIALOG_EXPORT_3DFILE_BASE
::~
DIALOG_EXPORT_3DFILE_BASE
()
{
// Disconnect Events
m_sdbSizer1Cancel
->
Disconnect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_EXPORT_3DFILE_BASE
::
OnCancelClick
),
NULL
,
this
);
m_sdbSizer1OK
->
Disconnect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_EXPORT_3DFILE_BASE
::
OnOkClick
),
NULL
,
this
);
}
pcbnew/dialog_export_3Dfiles_base.fbp
0 → 100644
View file @
8dd76c53
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion
major=
"1"
minor=
"9"
/>
<object
class=
"Project"
expanded=
"1"
>
<property
name=
"class_decoration"
></property>
<property
name=
"code_generation"
>
C++
</property>
<property
name=
"disconnect_events"
>
1
</property>
<property
name=
"encoding"
>
UTF-8
</property>
<property
name=
"event_generation"
>
connect
</property>
<property
name=
"file"
>
dialog_export_3Dfiles_base
</property>
<property
name=
"first_id"
>
1000
</property>
<property
name=
"help_provider"
>
none
</property>
<property
name=
"internationalize"
>
1
</property>
<property
name=
"name"
>
dialog_export_3Dfiles
</property>
<property
name=
"namespace"
></property>
<property
name=
"path"
>
.
</property>
<property
name=
"precompiled_header"
></property>
<property
name=
"relative_path"
>
1
</property>
<property
name=
"use_enum"
>
1
</property>
<property
name=
"use_microsoft_bom"
>
0
</property>
<object
class=
"Dialog"
expanded=
"1"
>
<property
name=
"bg"
></property>
<property
name=
"center"
></property>
<property
name=
"context_help"
></property>
<property
name=
"enabled"
>
1
</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_3DFILE_BASE
</property>
<property
name=
"pos"
></property>
<property
name=
"size"
>
370,252
</property>
<property
name=
"style"
>
wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER
</property>
<property
name=
"subclass"
></property>
<property
name=
"title"
></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=
"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"
>
-1,-1
</property>
<property
name=
"name"
>
bSizer1
</property>
<property
name=
"orient"
>
wxVERTICAL
</property>
<property
name=
"permission"
>
none
</property>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxEXPAND
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxBoxSizer"
expanded=
"1"
>
<property
name=
"minimum_size"
>
450,-1
</property>
<property
name=
"name"
>
bUpperSizer
</property>
<property
name=
"orient"
>
wxVERTICAL
</property>
<property
name=
"permission"
>
none
</property>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxTOP|wxRIGHT|wxLEFT
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxStaticText"
expanded=
"1"
>
<property
name=
"bg"
></property>
<property
name=
"context_help"
></property>
<property
name=
"enabled"
>
1
</property>
<property
name=
"fg"
></property>
<property
name=
"font"
></property>
<property
name=
"hidden"
>
0
</property>
<property
name=
"id"
>
wxID_ANY
</property>
<property
name=
"label"
>
Wrml main file filename:
</property>
<property
name=
"maximum_size"
></property>
<property
name=
"minimum_size"
></property>
<property
name=
"name"
>
m_staticText1
</property>
<property
name=
"permission"
>
protected
</property>
<property
name=
"pos"
></property>
<property
name=
"size"
></property>
<property
name=
"style"
></property>
<property
name=
"subclass"
></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"
>
wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxFilePickerCtrl"
expanded=
"1"
>
<property
name=
"bg"
></property>
<property
name=
"context_help"
></property>
<property
name=
"enabled"
>
1
</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=
"message"
>
Save VRML Board File
</property>
<property
name=
"minimum_size"
>
-1,-1
</property>
<property
name=
"name"
>
m_filePicker
</property>
<property
name=
"permission"
>
protected
</property>
<property
name=
"pos"
></property>
<property
name=
"size"
></property>
<property
name=
"style"
>
wxFLP_DEFAULT_STYLE|wxFLP_SAVE
</property>
<property
name=
"subclass"
></property>
<property
name=
"tooltip"
></property>
<property
name=
"value"
></property>
<property
name=
"wildcard"
>
*.wrl
</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"
>
wxTOP|wxRIGHT|wxLEFT
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxStaticText"
expanded=
"1"
>
<property
name=
"bg"
></property>
<property
name=
"context_help"
></property>
<property
name=
"enabled"
>
1
</property>
<property
name=
"fg"
></property>
<property
name=
"font"
></property>
<property
name=
"hidden"
>
0
</property>
<property
name=
"id"
>
wxID_ANY
</property>
<property
name=
"label"
>
Wrml 3D footprints shapes subdir:
</property>
<property
name=
"maximum_size"
></property>
<property
name=
"minimum_size"
></property>
<property
name=
"name"
>
m_staticText3
</property>
<property
name=
"permission"
>
protected
</property>
<property
name=
"pos"
></property>
<property
name=
"size"
></property>
<property
name=
"style"
></property>
<property
name=
"subclass"
></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"
>
wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxTextCtrl"
expanded=
"1"
>
<property
name=
"bg"
></property>
<property
name=
"context_help"
></property>
<property
name=
"enabled"
>
1
</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=
"maxlength"
>
0
</property>
<property
name=
"minimum_size"
></property>
<property
name=
"name"
>
m_SubdirNameCtrl
</property>
<property
name=
"permission"
>
protected
</property>
<property
name=
"pos"
></property>
<property
name=
"size"
></property>
<property
name=
"style"
></property>
<property
name=
"subclass"
></property>
<property
name=
"tooltip"
></property>
<property
name=
"value"
></property>
<property
name=
"window_extra_style"
></property>
<property
name=
"window_name"
></property>
<property
name=
"window_style"
></property>
<event
name=
"OnChar"
></event>
<event
name=
"OnEnterWindow"
></event>
<event
name=
"OnEraseBackground"
></event>
<event
name=
"OnKeyDown"
></event>
<event
name=
"OnKeyUp"
></event>
<event
name=
"OnKillFocus"
></event>
<event
name=
"OnLeaveWindow"
></event>
<event
name=
"OnLeftDClick"
></event>
<event
name=
"OnLeftDown"
></event>
<event
name=
"OnLeftUp"
></event>
<event
name=
"OnMiddleDClick"
></event>
<event
name=
"OnMiddleDown"
></event>
<event
name=
"OnMiddleUp"
></event>
<event
name=
"OnMotion"
></event>
<event
name=
"OnMouseEvents"
></event>
<event
name=
"OnMouseWheel"
></event>
<event
name=
"OnPaint"
></event>
<event
name=
"OnRightDClick"
></event>
<event
name=
"OnRightDown"
></event>
<event
name=
"OnRightUp"
></event>
<event
name=
"OnSetFocus"
></event>
<event
name=
"OnSize"
></event>
<event
name=
"OnText"
></event>
<event
name=
"OnTextEnter"
></event>
<event
name=
"OnTextMaxLen"
></event>
<event
name=
"OnTextURL"
></event>
<event
name=
"OnUpdateUI"
></event>
</object>
</object>
</object>
</object>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxEXPAND
</property>
<property
name=
"proportion"
>
1
</property>
<object
class=
"wxBoxSizer"
expanded=
"1"
>
<property
name=
"minimum_size"
></property>
<property
name=
"name"
>
bLowerSizer
</property>
<property
name=
"orient"
>
wxHORIZONTAL
</property>
<property
name=
"permission"
>
none
</property>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxALL|wxEXPAND
</property>
<property
name=
"proportion"
>
1
</property>
<object
class=
"wxRadioBox"
expanded=
"1"
>
<property
name=
"bg"
></property>
<property
name=
"choices"
>
"
Inch
"
"
mm
"
"
Meter
"
</property>
<property
name=
"context_help"
></property>
<property
name=
"enabled"
>
1
</property>
<property
name=
"fg"
></property>
<property
name=
"font"
></property>
<property
name=
"hidden"
>
0
</property>
<property
name=
"id"
>
wxID_ANY
</property>
<property
name=
"label"
>
Units:
</property>
<property
name=
"majorDimension"
>
1
</property>
<property
name=
"maximum_size"
></property>
<property
name=
"minimum_size"
></property>
<property
name=
"name"
>
m_rbSelectUnits
</property>
<property
name=
"permission"
>
protected
</property>
<property
name=
"pos"
></property>
<property
name=
"selection"
>
0
</property>
<property
name=
"size"
></property>
<property
name=
"style"
>
wxRA_SPECIFY_COLS
</property>
<property
name=
"subclass"
></property>
<property
name=
"tooltip"
></property>
<property
name=
"window_extra_style"
></property>
<property
name=
"window_name"
></property>
<property
name=
"window_style"
></property>
<event
name=
"OnChar"
></event>
<event
name=
"OnEnterWindow"
></event>
<event
name=
"OnEraseBackground"
></event>
<event
name=
"OnKeyDown"
></event>
<event
name=
"OnKeyUp"
></event>
<event
name=
"OnKillFocus"
></event>
<event
name=
"OnLeaveWindow"
></event>
<event
name=
"OnLeftDClick"
></event>
<event
name=
"OnLeftDown"
></event>
<event
name=
"OnLeftUp"
></event>
<event
name=
"OnMiddleDClick"
></event>
<event
name=
"OnMiddleDown"
></event>
<event
name=
"OnMiddleUp"
></event>
<event
name=
"OnMotion"
></event>
<event
name=
"OnMouseEvents"
></event>
<event
name=
"OnMouseWheel"
></event>
<event
name=
"OnPaint"
></event>
<event
name=
"OnRadioBox"
></event>
<event
name=
"OnRightDClick"
></event>
<event
name=
"OnRightDown"
></event>
<event
name=
"OnRightUp"
></event>
<event
name=
"OnSetFocus"
></event>
<event
name=
"OnSize"
></event>
<event
name=
"OnUpdateUI"
></event>
</object>
</object>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxALL|wxEXPAND
</property>
<property
name=
"proportion"
>
1
</property>
<object
class=
"wxRadioBox"
expanded=
"1"
>
<property
name=
"bg"
></property>
<property
name=
"choices"
>
"
Copy 3D Shapes Files in Subdir
"
"
Use Absolute Path in Wrml File
"
</property>
<property
name=
"context_help"
></property>
<property
name=
"enabled"
>
1
</property>
<property
name=
"fg"
></property>
<property
name=
"font"
></property>
<property
name=
"hidden"
>
0
</property>
<property
name=
"id"
>
wxID_ANY
</property>
<property
name=
"label"
>
3D Shapes Files Option:
</property>
<property
name=
"majorDimension"
>
1
</property>
<property
name=
"maximum_size"
></property>
<property
name=
"minimum_size"
></property>
<property
name=
"name"
>
m_rb3DFilesOption
</property>
<property
name=
"permission"
>
protected
</property>
<property
name=
"pos"
></property>
<property
name=
"selection"
>
0
</property>
<property
name=
"size"
></property>
<property
name=
"style"
>
wxRA_SPECIFY_COLS
</property>
<property
name=
"subclass"
></property>
<property
name=
"tooltip"
></property>
<property
name=
"window_extra_style"
></property>
<property
name=
"window_name"
></property>
<property
name=
"window_style"
></property>
<event
name=
"OnChar"
></event>
<event
name=
"OnEnterWindow"
></event>
<event
name=
"OnEraseBackground"
></event>
<event
name=
"OnKeyDown"
></event>
<event
name=
"OnKeyUp"
></event>
<event
name=
"OnKillFocus"
></event>
<event
name=
"OnLeaveWindow"
></event>
<event
name=
"OnLeftDClick"
></event>
<event
name=
"OnLeftDown"
></event>
<event
name=
"OnLeftUp"
></event>
<event
name=
"OnMiddleDClick"
></event>
<event
name=
"OnMiddleDown"
></event>
<event
name=
"OnMiddleUp"
></event>
<event
name=
"OnMotion"
></event>
<event
name=
"OnMouseEvents"
></event>
<event
name=
"OnMouseWheel"
></event>
<event
name=
"OnPaint"
></event>
<event
name=
"OnRadioBox"
></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>
</object>
<object
class=
"sizeritem"
expanded=
"1"
>
<property
name=
"border"
>
5
</property>
<property
name=
"flag"
>
wxEXPAND|wxRIGHT|wxLEFT
</property>
<property
name=
"proportion"
>
0
</property>
<object
class=
"wxStaticLine"
expanded=
"1"
>
<property
name=
"bg"
></property>
<property
name=
"context_help"
></property>
<property
name=
"enabled"
>
1
</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"
>
m_staticline1
</property>
<property
name=
"permission"
>
protected
</property>
<property
name=
"pos"
></property>
<property
name=
"size"
></property>
<property
name=
"style"
>
wxLI_HORIZONTAL
</property>
<property
name=
"subclass"
></property>
<property
name=
"tooltip"
></property>
<property
name=
"window_extra_style"
></property>
<property
name=
"window_name"
></property>
<property
name=
"window_style"
></property>
<event
name=
"OnChar"
></event>
<event
name=
"OnEnterWindow"
></event>
<event
name=
"OnEraseBackground"
></event>
<event
name=
"OnKeyDown"
></event>
<event
name=
"OnKeyUp"
></event>
<event
name=
"OnKillFocus"
></event>
<event
name=
"OnLeaveWindow"
></event>
<event
name=
"OnLeftDClick"
></event>
<event
name=
"OnLeftDown"
></event>
<event
name=
"OnLeftUp"
></event>
<event
name=
"OnMiddleDClick"
></event>
<event
name=
"OnMiddleDown"
></event>
<event
name=
"OnMiddleUp"
></event>
<event
name=
"OnMotion"
></event>
<event
name=
"OnMouseEvents"
></event>
<event
name=
"OnMouseWheel"
></event>
<event
name=
"OnPaint"
></event>
<event
name=
"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|wxALL
</property>
<property
name=
"proportion"
>
0
</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"
>
OnCancelClick
</event>
<event
name=
"OnContextHelpButtonClick"
></event>
<event
name=
"OnHelpButtonClick"
></event>
<event
name=
"OnNoButtonClick"
></event>
<event
name=
"OnOKButtonClick"
>
OnOkClick
</event>
<event
name=
"OnSaveButtonClick"
></event>
<event
name=
"OnYesButtonClick"
></event>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>
pcbnew/dialog_export_3Dfiles_base.h
0 → 100644
View file @
8dd76c53
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 16 2008)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __dialog_export_3Dfiles_base__
#define __dialog_export_3Dfiles_base__
#include <wx/intl.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/textctrl.h>
#include <wx/sizer.h>
#include <wx/radiobox.h>
#include <wx/statline.h>
#include <wx/button.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_EXPORT_3DFILE_BASE
///////////////////////////////////////////////////////////////////////////////
class
DIALOG_EXPORT_3DFILE_BASE
:
public
wxDialog
{
private
:
protected
:
wxStaticText
*
m_staticText1
;
wxFilePickerCtrl
*
m_filePicker
;
wxStaticText
*
m_staticText3
;
wxTextCtrl
*
m_SubdirNameCtrl
;
wxRadioBox
*
m_rbSelectUnits
;
wxRadioBox
*
m_rb3DFilesOption
;
wxStaticLine
*
m_staticline1
;
wxStdDialogButtonSizer
*
m_sdbSizer1
;
wxButton
*
m_sdbSizer1OK
;
wxButton
*
m_sdbSizer1Cancel
;
// Virtual event handlers, overide them in your derived class
virtual
void
OnCancelClick
(
wxCommandEvent
&
event
){
event
.
Skip
();
}
virtual
void
OnOkClick
(
wxCommandEvent
&
event
){
event
.
Skip
();
}
public
:
DIALOG_EXPORT_3DFILE_BASE
(
wxWindow
*
parent
,
wxWindowID
id
=
wxID_ANY
,
const
wxString
&
title
=
wxEmptyString
,
const
wxPoint
&
pos
=
wxDefaultPosition
,
const
wxSize
&
size
=
wxSize
(
370
,
252
),
long
style
=
wxDEFAULT_DIALOG_STYLE
|
wxRESIZE_BORDER
);
~
DIALOG_EXPORT_3DFILE_BASE
();
};
#endif //__dialog_export_3Dfiles_base__
pcbnew/export_vrml.cpp
0 → 100644
View file @
8dd76c53
#include "fctsys.h"
#include "common.h"
#include "confirm.h"
#include "kicad_string.h"
#include "gestfich.h"
#include "pcbnew.h"
#include "wxPcbStruct.h"
#include "drawtxt.h"
#include "trigo.h"
#include "appl_wxstruct.h"
#include "3d_struct.h"
#include <vector>
#include <cmath>
/* I use this a lot... */
static
const
double
PI2
=
M_PI
/
2
;
/* Absolutely not optimized triangle bag :D */
struct
VRMLPt
{
double
x
,
y
,
z
;
};
struct
FlatPt
{
FlatPt
(
double
_x
=
0
,
double
_y
=
0
)
:
x
(
_x
),
y
(
_y
)
{
}
double
x
,
y
;
};
struct
Triangle
{
Triangle
(
double
x1
,
double
y1
,
double
z1
,
double
x2
,
double
y2
,
double
z2
,
double
x3
,
double
y3
,
double
z3
)
{
p1
.
x
=
x1
;
p1
.
y
=
y1
;
p1
.
z
=
z1
;
p2
.
x
=
x2
;
p2
.
y
=
y2
;
p2
.
z
=
z2
;
p3
.
x
=
x3
;
p3
.
y
=
y3
;
p3
.
z
=
z3
;
}
Triangle
()
{
}
VRMLPt
p1
,
p2
,
p3
;
};
typedef
std
::
vector
<
Triangle
>
TriangleBag
;
/* A flat triangle fan */
struct
FlatFan
{
FlatPt
c
;
std
::
vector
<
FlatPt
>
pts
;
void
add
(
double
x
,
double
y
)
{
pts
.
push_back
(
FlatPt
(
x
,
y
)
);
}
void
bag
(
int
layer
,
bool
close
=
true
);
};
/* A flat quad ring */
struct
FlatRing
{
std
::
vector
<
FlatPt
>
inner
;
std
::
vector
<
FlatPt
>
outer
;
void
add_inner
(
double
x
,
double
y
)
{
inner
.
push_back
(
FlatPt
(
x
,
y
)
);
}
void
add_outer
(
double
x
,
double
y
)
{
outer
.
push_back
(
FlatPt
(
x
,
y
)
);
}
void
bag
(
int
layer
,
bool
close
=
true
);
};
/* A vertical quad loop */
struct
VLoop
{
std
::
vector
<
FlatPt
>
pts
;
double
z_top
,
z_bottom
;
void
add
(
double
x
,
double
y
)
{
pts
.
push_back
(
FlatPt
(
x
,
y
)
);
}
void
bag
(
TriangleBag
&
triangles
,
bool
close
=
true
);
};
/* The bags for all the layers */
static
TriangleBag
layer_triangles
[
LAYER_COUNT
];
static
TriangleBag
via_triangles
[
4
];
static
double
layer_z
[
LAYER_COUNT
];
static
void
bag_flat_triangle
(
int
layer
,
/*{{{*/
double
x1
,
double
y1
,
double
x2
,
double
y2
,
double
x3
,
double
y3
)
{
double
z
=
layer_z
[
layer
];
layer_triangles
[
layer
].
push_back
(
Triangle
(
x1
,
y1
,
z
,
x2
,
y2
,
z
,
x3
,
y3
,
z
)
);
}
void
FlatFan
::
bag
(
int
layer
,
bool
close
)
/*{{{*/
{
unsigned
i
;
for
(
i
=
0
;
i
<
pts
.
size
()
-
1
;
i
++
)
bag_flat_triangle
(
layer
,
c
.
x
,
c
.
y
,
pts
[
i
].
x
,
pts
[
i
].
y
,
pts
[
i
+
1
].
x
,
pts
[
i
+
1
].
y
);
if
(
close
)
bag_flat_triangle
(
layer
,
c
.
x
,
c
.
y
,
pts
[
i
].
x
,
pts
[
i
].
y
,
pts
[
0
].
x
,
pts
[
0
].
y
);
}
static
void
bag_flat_quad
(
int
layer
,
/*{{{*/
double
x1
,
double
y1
,
double
x2
,
double
y2
,
double
x3
,
double
y3
,
double
x4
,
double
y4
)
{
bag_flat_triangle
(
layer
,
x1
,
y1
,
x3
,
y3
,
x2
,
y2
);
bag_flat_triangle
(
layer
,
x2
,
y2
,
x3
,
y3
,
x4
,
y4
);
}
void
FlatRing
::
bag
(
int
layer
,
bool
close
)
/*{{{*/
{
unsigned
i
;
for
(
i
=
0
;
i
<
inner
.
size
()
-
1
;
i
++
)
bag_flat_quad
(
layer
,
inner
[
i
].
x
,
inner
[
i
].
y
,
outer
[
i
].
x
,
outer
[
i
].
y
,
inner
[
i
+
1
].
x
,
inner
[
i
+
1
].
y
,
outer
[
i
+
1
].
x
,
outer
[
i
+
1
].
y
);
if
(
close
)
bag_flat_quad
(
layer
,
inner
[
i
].
x
,
inner
[
i
].
y
,
outer
[
i
].
x
,
outer
[
i
].
y
,
inner
[
0
].
x
,
inner
[
0
].
y
,
outer
[
0
].
x
,
outer
[
0
].
y
);
}
static
void
bag_vquad
(
TriangleBag
&
triangles
,
/*{{{*/
double
x1
,
double
y1
,
double
x2
,
double
y2
,
double
z1
,
double
z2
)
{
triangles
.
push_back
(
Triangle
(
x1
,
y1
,
z1
,
x2
,
y2
,
z1
,
x2
,
y2
,
z2
)
);
triangles
.
push_back
(
Triangle
(
x1
,
y1
,
z1
,
x2
,
y2
,
z2
,
x1
,
y1
,
z2
)
);
}
void
VLoop
::
bag
(
TriangleBag
&
triangles
,
bool
close
)
/*{{{*/
{
unsigned
i
;
for
(
i
=
0
;
i
<
pts
.
size
()
-
1
;
i
++
)
bag_vquad
(
triangles
,
pts
[
i
].
x
,
pts
[
i
].
y
,
pts
[
i
+
1
].
x
,
pts
[
i
+
1
].
y
,
z_top
,
z_bottom
);
if
(
close
)
bag_vquad
(
triangles
,
pts
[
i
].
x
,
pts
[
i
].
y
,
pts
[
0
].
x
,
pts
[
0
].
y
,
z_top
,
z_bottom
);
}
static
void
write_triangle_bag
(
FILE
*
output_file
,
int
color_index
,
/*{{{*/
const
TriangleBag
&
triangles
)
{
/* A lot of nodes are not required, but blender sometimes chokes
* without them */
static
const
char
*
shape_boiler
[]
=
{
"Transform {
\n
"
,
" translation 0.0 0.0 0.0
\n
"
,
" rotation 1.0 0.0 0.0 0.0
\n
"
,
" scale 1.0 1.0 1.0
\n
"
,
" children [
\n
"
,
" Group {
\n
"
,
" children [
\n
"
,
" Shape {
\n
"
,
" appearance Appearance {
\n
"
,
" material Material {
\n
"
,
0
,
/* Material marker */
" ambientIntensity 0.8
\n
"
,
" transparency 0.2
\n
"
,
" shininess 0.2
\n
"
,
" }
\n
"
,
" }
\n
"
,
" geometry IndexedFaceSet {
\n
"
,
" solid TRUE
\n
"
,
" coord Coordinate {
\n
"
,
" point [
\n
"
,
0
,
/* Coordinates marker */
" ]
\n
"
,
" }
\n
"
,
" coordIndex [
\n
"
,
0
,
/* Index marker */
" ]
\n
"
,
" }
\n
"
,
" }
\n
"
,
" ]
\n
"
,
" }
\n
"
,
" ]
\n
"
,
"}
\n
"
,
0
/* End marker */
};
int
marker_found
=
0
,
lineno
=
0
;
while
(
marker_found
<
4
)
{
if
(
shape_boiler
[
lineno
]
)
fputs
(
shape_boiler
[
lineno
],
output_file
);
else
{
marker_found
++
;
switch
(
marker_found
)
{
case
1
:
/* Material marker */
fprintf
(
output_file
,
" diffuseColor %g %g %g
\n
"
,
(
double
)
ColorRefs
[
color_index
].
m_Red
/
255.0
,
(
double
)
ColorRefs
[
color_index
].
m_Green
/
255.0
,
(
double
)
ColorRefs
[
color_index
].
m_Blue
/
255.0
);
fprintf
(
output_file
,
" specularColor %g %g %g
\n
"
,
(
double
)
ColorRefs
[
color_index
].
m_Red
/
255.0
,
(
double
)
ColorRefs
[
color_index
].
m_Green
/
255.0
,
(
double
)
ColorRefs
[
color_index
].
m_Blue
/
255.0
);
fprintf
(
output_file
,
" emissiveColor %g %g %g
\n
"
,
(
double
)
ColorRefs
[
color_index
].
m_Red
/
255.0
,
(
double
)
ColorRefs
[
color_index
].
m_Green
/
255.0
,
(
double
)
ColorRefs
[
color_index
].
m_Blue
/
255.0
);
break
;
case
2
:
{
/* Coordinates marker */
for
(
TriangleBag
::
const_iterator
i
=
triangles
.
begin
();
i
!=
triangles
.
end
();
i
++
)
{
fprintf
(
output_file
,
"%g %g %g
\n
"
,
i
->
p1
.
x
,
-
i
->
p1
.
y
,
i
->
p1
.
z
);
fprintf
(
output_file
,
"%g %g %g
\n
"
,
i
->
p2
.
x
,
-
i
->
p2
.
y
,
i
->
p2
.
z
);
fprintf
(
output_file
,
"%g %g %g
\n
"
,
i
->
p3
.
x
,
-
i
->
p3
.
y
,
i
->
p3
.
z
);
}
}
break
;
case
3
:
{
/* Index marker */
/* OK, that's sick ... */
int
j
=
0
;
for
(
TriangleBag
::
const_iterator
i
=
triangles
.
begin
();
i
!=
triangles
.
end
();
i
++
)
{
fprintf
(
output_file
,
"%d %d %d -1
\n
"
,
j
,
j
+
1
,
j
+
2
);
j
+=
3
;
}
}
break
;
default
:
break
;
}
}
lineno
++
;
}
}
static
void
compute_layer_Zs
(
BOARD
*
pcb
)
/*{{{*/
{
int
copper_layers
=
pcb
->
GetCopperLayerCount
(
);
// We call it 'layer' thickness, but it's the whole board thickness!
double
board_thickness
=
pcb
->
GetBoardDesignSettings
()
->
m_BoardThickness
;
double
half_thickness
=
board_thickness
/
2
;
/* Compute each layer's Z value, more or less like the 3d view */
for
(
int
i
=
0
;
i
<=
LAYER_N_FRONT
;
i
++
)
{
if
(
i
<
copper_layers
)
layer_z
[
i
]
=
board_thickness
*
i
/
(
copper_layers
-
1
)
-
half_thickness
;
else
layer_z
[
i
]
=
half_thickness
;
/* The component layer... */
}
/* To avoid rounding interference, we apply an epsilon to each
* successive layer */
const
double
epsilon_z
=
10
;
/* That's 1 mils, about 1/50 mm */
layer_z
[
SOLDERPASTE_N_BACK
]
=
-
half_thickness
-
epsilon_z
*
4
;
layer_z
[
ADHESIVE_N_BACK
]
=
-
half_thickness
-
epsilon_z
*
3
;
layer_z
[
SILKSCREEN_N_BACK
]
=
-
half_thickness
-
epsilon_z
*
2
;
layer_z
[
SOLDERMASK_N_BACK
]
=
-
half_thickness
-
epsilon_z
;
layer_z
[
SOLDERMASK_N_FRONT
]
=
half_thickness
+
epsilon_z
;
layer_z
[
SILKSCREEN_N_FRONT
]
=
half_thickness
+
epsilon_z
*
2
;
layer_z
[
ADHESIVE_N_FRONT
]
=
half_thickness
+
epsilon_z
*
3
;
layer_z
[
SOLDERPASTE_N_FRONT
]
=
half_thickness
+
epsilon_z
*
4
;
layer_z
[
DRAW_N
]
=
half_thickness
+
epsilon_z
*
5
;
layer_z
[
COMMENT_N
]
=
half_thickness
+
epsilon_z
*
6
;
layer_z
[
ECO1_N
]
=
half_thickness
+
epsilon_z
*
7
;
layer_z
[
ECO2_N
]
=
half_thickness
+
epsilon_z
*
8
;
layer_z
[
EDGE_N
]
=
0
;
}
static
void
export_vrml_line
(
int
layer
,
double
startx
,
double
starty
,
/*{{{*/
double
endx
,
double
endy
,
double
width
,
int
divisions
)
{
double
r
=
width
/
2
;
double
angle
=
atan2
(
endy
-
starty
,
endx
-
startx
);
double
alpha
;
FlatFan
fan
;
/* Output the 'bone' as a triangle fan, this is the fan centre */
fan
.
c
.
x
=
(
startx
+
endx
)
/
2
;
fan
.
c
.
y
=
(
starty
+
endy
)
/
2
;
/* The 'end' side cap */
for
(
alpha
=
angle
-
PI2
;
alpha
<
angle
+
PI2
;
alpha
+=
PI2
/
divisions
)
fan
.
add
(
endx
+
r
*
cos
(
alpha
),
endy
+
r
*
sin
(
alpha
)
);
alpha
=
angle
+
PI2
;
fan
.
add
(
endx
+
r
*
cos
(
alpha
),
endy
+
r
*
sin
(
alpha
)
);
/* The 'start' side cap */
for
(
alpha
=
angle
+
PI2
;
alpha
<
angle
+
3
*
PI2
;
alpha
+=
PI2
/
divisions
)
fan
.
add
(
startx
+
r
*
cos
(
alpha
),
starty
+
r
*
sin
(
alpha
)
);
alpha
=
angle
+
3
*
PI2
;
fan
.
add
(
startx
+
r
*
cos
(
alpha
),
starty
+
r
*
sin
(
alpha
)
);
/* Export the fan */
fan
.
bag
(
layer
);
}
static
void
export_vrml_circle
(
int
layer
,
double
startx
,
double
starty
,
/*{{{*/
double
endx
,
double
endy
,
double
width
,
int
divisions
)
{
double
hole
,
rayon
;
FlatRing
ring
;
rayon
=
hypot
(
startx
-
endx
,
starty
-
endy
)
+
(
width
/
2
);
hole
=
rayon
-
width
;
for
(
double
alpha
=
0
;
alpha
<
M_PI
*
2
;
alpha
+=
M_PI
*
2
/
divisions
)
{
ring
.
add_inner
(
startx
+
hole
*
cos
(
alpha
),
starty
+
hole
*
sin
(
alpha
)
);
ring
.
add_outer
(
startx
+
rayon
*
cos
(
alpha
),
starty
+
rayon
*
sin
(
alpha
)
);
}
ring
.
bag
(
layer
);
}
static
void
export_vrml_slot
(
TriangleBag
&
triangles
,
/*{{{*/
int
top_layer
,
int
bottom_layer
,
double
xc
,
double
yc
,
double
dx
,
double
dy
,
int
orient
,
int
divisions
)
{
double
capx
,
capy
;
/* Cap center */
VLoop
loop
;
loop
.
z_top
=
layer_z
[
top_layer
];
loop
.
z_bottom
=
layer_z
[
bottom_layer
];
double
angle
=
orient
/
1800.0
*
M_PI
;
if
(
dy
>
dx
)
{
EXCHG
(
dx
,
dy
);
angle
+=
PI2
;
}
/* The exchange above means that cutter radius is alvays dy/2 */
double
r
=
dy
/
2
;
double
alpha
;
/* The first side cap */
capx
=
xc
+
cos
(
angle
)
*
dx
/
2
;
capy
=
yc
+
sin
(
angle
)
*
dx
/
2
;
for
(
alpha
=
angle
-
PI2
;
alpha
<
angle
+
PI2
;
alpha
+=
PI2
/
divisions
)
loop
.
add
(
capx
+
r
*
cos
(
alpha
),
capy
+
r
*
sin
(
alpha
)
);
alpha
=
angle
+
PI2
;
loop
.
add
(
capx
+
r
*
cos
(
alpha
),
capy
+
r
*
sin
(
alpha
)
);
/* The other side cap */
capx
=
xc
-
cos
(
angle
)
*
dx
/
2
;
capy
=
yc
-
sin
(
angle
)
*
dx
/
2
;
for
(
alpha
=
angle
+
PI2
;
alpha
<
angle
+
3
*
PI2
;
alpha
+=
PI2
/
divisions
)
loop
.
add
(
capx
+
r
*
cos
(
alpha
),
capy
+
r
*
sin
(
alpha
)
);
alpha
=
angle
+
3
*
PI2
;
loop
.
add
(
capx
+
r
*
cos
(
alpha
),
capy
+
r
*
sin
(
alpha
)
);
loop
.
bag
(
triangles
);
}
static
void
export_vrml_hole
(
TriangleBag
&
triangles
,
/*{{{*/
int
top_layer
,
int
bottom_layer
,
double
xc
,
double
yc
,
double
hole
,
int
divisions
)
{
VLoop
loop
;
loop
.
z_top
=
layer_z
[
top_layer
];
loop
.
z_bottom
=
layer_z
[
bottom_layer
];
for
(
double
alpha
=
0
;
alpha
<
M_PI
*
2
;
alpha
+=
M_PI
*
2
/
divisions
)
loop
.
add
(
xc
+
cos
(
alpha
)
*
hole
,
yc
+
sin
(
alpha
)
*
hole
);
loop
.
bag
(
triangles
);
}
static
void
export_vrml_varc
(
TriangleBag
&
triangles
,
/*{{{*/
int
top_layer
,
int
bottom_layer
,
double
startx
,
double
starty
,
double
endx
,
double
endy
,
int
divisions
)
{
VLoop
loop
;
loop
.
z_top
=
layer_z
[
top_layer
];
loop
.
z_bottom
=
layer_z
[
bottom_layer
];
double
angle
=
atan2
(
endx
-
startx
,
endy
-
starty
);
double
rayon
=
hypot
(
startx
-
endx
,
starty
-
endy
);
for
(
double
alpha
=
angle
;
alpha
<
angle
+
PI2
;
alpha
+=
PI2
/
divisions
)
{
loop
.
add
(
startx
+
cos
(
alpha
)
*
rayon
,
starty
+
sin
(
alpha
)
*
rayon
);
}
loop
.
bag
(
triangles
);
}
static
void
export_vrml_oval_pad
(
int
layer
,
/*{{{*/
double
xc
,
double
yc
,
double
dx
,
double
dy
,
int
orient
,
int
divisions
)
{
double
capx
,
capy
;
/* Cap center */
FlatFan
fan
;
fan
.
c
.
x
=
xc
;
fan
.
c
.
y
=
yc
;
double
angle
=
orient
/
1800.0
*
M_PI
;
if
(
dy
>
dx
)
{
EXCHG
(
dx
,
dy
);
angle
+=
PI2
;
}
/* The exchange above means that cutter radius is alvays dy/2 */
double
r
=
dy
/
2
;
double
alpha
;
/* The first side cap */
capx
=
xc
+
cos
(
angle
)
*
dx
/
2
;
capy
=
yc
+
sin
(
angle
)
*
dx
/
2
;
for
(
alpha
=
angle
-
PI2
;
alpha
<
angle
+
PI2
;
alpha
+=
PI2
/
divisions
)
fan
.
add
(
capx
+
r
*
cos
(
alpha
),
capy
+
r
*
sin
(
alpha
)
);
alpha
=
angle
+
PI2
;
fan
.
add
(
capx
+
r
*
cos
(
alpha
),
capy
+
r
*
sin
(
alpha
)
);
/* The other side cap */
capx
=
xc
-
cos
(
angle
)
*
dx
/
2
;
capy
=
yc
-
sin
(
angle
)
*
dx
/
2
;
for
(
alpha
=
angle
+
PI2
;
alpha
<
angle
+
3
*
PI2
;
alpha
+=
PI2
/
divisions
)
fan
.
add
(
capx
+
r
*
cos
(
alpha
),
capy
+
r
*
sin
(
alpha
)
);
alpha
=
angle
+
3
*
PI2
;
fan
.
add
(
capx
+
r
*
cos
(
alpha
),
capy
+
r
*
sin
(
alpha
)
);
fan
.
bag
(
layer
);
}
static
void
export_vrml_arc
(
int
layer
,
double
startx
,
double
starty
,
/*{{{*/
double
endx
,
double
endy
,
double
width
,
int
divisions
)
{
FlatRing
ring
;
double
hole
,
rayon
;
double
angle
=
atan2
(
endx
-
startx
,
endy
-
starty
);
rayon
=
hypot
(
startx
-
endx
,
starty
-
endy
)
+
(
width
/
2
);
hole
=
rayon
-
width
;
for
(
double
alpha
=
angle
;
alpha
<
angle
+
PI2
;
alpha
+=
PI2
/
divisions
)
{
ring
.
add_inner
(
startx
+
cos
(
alpha
)
*
hole
,
starty
+
sin
(
alpha
)
*
hole
);
ring
.
add_outer
(
startx
+
cos
(
alpha
)
*
rayon
,
starty
+
sin
(
alpha
)
*
rayon
);
}
ring
.
bag
(
layer
,
false
);
}
static
void
export_vrml_drawsegment
(
DRAWSEGMENT
*
drawseg
)
/*{{{*/
{
int
layer
=
drawseg
->
GetLayer
();
double
w
=
drawseg
->
m_Width
;
double
x
=
drawseg
->
m_Start
.
x
;
double
y
=
drawseg
->
m_Start
.
y
;
double
xf
=
drawseg
->
m_End
.
x
;
double
yf
=
drawseg
->
m_End
.
y
;
/* Items on the edge layer are high, not thick */
if
(
layer
==
EDGE_N
)
{
switch
(
drawseg
->
m_Shape
)
{
/* There is a special 'varc' primitive for this */
case
S_ARC
:
export_vrml_varc
(
layer_triangles
[
layer
],
FIRST_COPPER_LAYER
,
LAST_COPPER_LAYER
,
x
,
y
,
xf
,
yf
,
4
);
break
;
/* Circles on edge are usually important holes */
case
S_CIRCLE
:
export_vrml_hole
(
layer_triangles
[
layer
],
FIRST_COPPER_LAYER
,
LAST_COPPER_LAYER
,
x
,
y
,
hypot
(
xf
-
x
,
yf
-
y
)
/
2
,
12
);
break
;
default
:
{
/* Simply a quad */
double
z_top
=
layer_z
[
FIRST_COPPER_LAYER
];
double
z_bottom
=
layer_z
[
LAST_COPPER_LAYER
];
bag_vquad
(
layer_triangles
[
layer
],
x
,
y
,
xf
,
yf
,
z_top
,
z_bottom
);
break
;
}
}
}
else
{
switch
(
drawseg
->
m_Shape
)
{
case
S_ARC
:
export_vrml_arc
(
layer
,
x
,
y
,
xf
,
yf
,
w
,
3
);
break
;
case
S_CIRCLE
:
export_vrml_circle
(
layer
,
x
,
y
,
xf
,
yf
,
w
,
12
);
break
;
default
:
export_vrml_line
(
layer
,
x
,
y
,
xf
,
yf
,
w
,
1
);
break
;
}
}
}
/* C++ doesn't have closures and neither continuation forms... this is
* for coupling the vrml_text_callback with the common parameters */
static
int
s_text_layer
;
static
int
s_text_width
;
static
void
vrml_text_callback
(
int
x0
,
int
y0
,
int
xf
,
int
yf
)
{
export_vrml_line
(
s_text_layer
,
x0
,
y0
,
xf
,
yf
,
s_text_width
,
1
);
}
static
void
export_vrml_pcbtext
(
TEXTE_PCB
*
text
)
/*{{{*/
/*************************************************************/
{
/* Coupling by globals! Ewwww... */
s_text_layer
=
text
->
GetLayer
();
s_text_width
=
text
->
m_Width
;
wxSize
size
=
text
->
m_Size
;
if
(
text
->
m_Mirror
)
NEGATE
(
size
.
x
);
if
(
text
->
m_MultilineAllowed
)
{
wxPoint
pos
=
text
->
m_Pos
;
wxArrayString
*
list
=
wxStringSplit
(
text
->
m_Text
,
'\n'
);
wxPoint
offset
;
offset
.
y
=
text
->
GetInterline
();
RotatePoint
(
&
offset
,
text
->
m_Orient
);
for
(
unsigned
i
=
0
;
i
<
list
->
Count
();
i
++
)
{
wxString
txt
=
list
->
Item
(
i
);
DrawGraphicText
(
NULL
,
NULL
,
pos
,
(
EDA_Colors
)
0
,
txt
,
text
->
m_Orient
,
size
,
text
->
m_HJustify
,
text
->
m_VJustify
,
text
->
m_Width
,
text
->
m_Italic
,
true
,
vrml_text_callback
);
pos
+=
offset
;
}
delete
(
list
);
}
else
{
DrawGraphicText
(
NULL
,
NULL
,
text
->
m_Pos
,
(
EDA_Colors
)
0
,
text
->
m_Text
,
text
->
m_Orient
,
size
,
text
->
m_HJustify
,
text
->
m_VJustify
,
text
->
m_Width
,
text
->
m_Italic
,
true
,
vrml_text_callback
);
}
}
static
void
export_vrml_drawings
(
BOARD
*
pcb
)
/*{{{*/
{
/* draw graphic items */
for
(
EDA_BaseStruct
*
drawing
=
pcb
->
m_Drawings
;
drawing
!=
0
;
drawing
=
drawing
->
Next
()
)
{
switch
(
drawing
->
Type
()
)
{
case
TYPE_DRAWSEGMENT
:
export_vrml_drawsegment
(
(
DRAWSEGMENT
*
)
drawing
);
break
;
case
TYPE_TEXTE
:
export_vrml_pcbtext
(
(
TEXTE_PCB
*
)
drawing
);
break
;
default:
break
;
}
}
}
static
void
export_round_padstack
(
BOARD
*
pcb
,
double
x
,
double
y
,
double
r
,
/*{{{*/
int
bottom_layer
,
int
top_layer
,
int
divisions
)
{
int
copper_layers
=
pcb
->
GetCopperLayerCount
(
);
for
(
int
layer
=
bottom_layer
;
layer
<
copper_layers
;
layer
++
)
{
/* The last layer is always the component one, unless it's single face */
if
(
(
layer
>
FIRST_COPPER_LAYER
)
&&
(
layer
==
copper_layers
-
1
)
)
layer
=
LAST_COPPER_LAYER
;
if
(
layer
<=
top_layer
)
export_vrml_circle
(
layer
,
x
,
y
,
x
+
r
/
2
,
y
,
r
,
divisions
);
}
}
static
void
export_vrml_via
(
BOARD
*
pcb
,
SEGVIA
*
via
)
/*{{{*/
{
double
x
,
y
,
r
,
hole
;
int
top_layer
,
bottom_layer
;
r
=
via
->
m_Width
/
2
;
hole
=
via
->
GetDrillValue
()
/
2
;
x
=
via
->
m_Start
.
x
;
y
=
via
->
m_Start
.
y
;
via
->
ReturnLayerPair
(
&
top_layer
,
&
bottom_layer
);
/* Export the via padstack */
export_round_padstack
(
pcb
,
x
,
y
,
r
,
bottom_layer
,
top_layer
,
8
);
/* Drill a rough hole */
export_vrml_hole
(
via_triangles
[
via
->
m_Shape
],
top_layer
,
bottom_layer
,
x
,
y
,
hole
,
8
);
}
static
void
export_vrml_tracks
(
BOARD
*
pcb
)
/*{{{*/
{
for
(
TRACK
*
track
=
pcb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
if
(
track
->
Type
()
==
TYPE_VIA
)
export_vrml_via
(
pcb
,
(
SEGVIA
*
)
track
);
else
export_vrml_line
(
track
->
GetLayer
(),
track
->
m_Start
.
x
,
track
->
m_Start
.
y
,
track
->
m_End
.
x
,
track
->
m_End
.
y
,
track
->
m_Width
,
4
);
}
}
static
void
export_vrml_zones
(
BOARD
*
pcb
)
/*{{{*/
{
/* Export fill segments */
for
(
SEGZONE
*
segzone
=
pcb
->
m_Zone
;
segzone
!=
0
;
segzone
=
segzone
->
Next
()
)
{
/* Fill tracks are exported with low subdivisions */
if
(
segzone
->
Type
()
==
TYPE_ZONE
)
export_vrml_line
(
segzone
->
GetLayer
(),
segzone
->
m_Start
.
x
,
segzone
->
m_Start
.
y
,
segzone
->
m_End
.
x
,
segzone
->
m_End
.
y
,
segzone
->
m_Width
,
1
);
}
/* Export zone outlines */
for
(
int
i
=
0
;
i
<
pcb
->
GetAreaCount
();
i
++
)
{
ZONE_CONTAINER
*
zone
=
pcb
->
GetArea
(
i
);
if
(
(
zone
->
m_FilledPolysList
.
size
()
==
0
)
||
(
zone
->
m_ZoneMinThickness
<=
1
)
)
continue
;
int
width
=
zone
->
m_ZoneMinThickness
;
if
(
width
>
0
)
{
int
imax
=
zone
->
m_FilledPolysList
.
size
()
-
1
;
int
layer
=
zone
->
GetLayer
();
CPolyPt
*
firstcorner
=
&
zone
->
m_FilledPolysList
[
0
];
CPolyPt
*
begincorner
=
firstcorner
;
/* I'm not really positive about what he's doing here... */
for
(
int
ic
=
1
;
ic
<=
imax
;
ic
++
)
{
CPolyPt
*
endcorner
=
&
zone
->
m_FilledPolysList
[
ic
];
if
(
begincorner
->
utility
==
0
)
// Draw only basic outlines, not extra segments
export_vrml_line
(
layer
,
begincorner
->
x
,
begincorner
->
y
,
endcorner
->
x
,
endcorner
->
y
,
width
,
1
);
if
(
(
endcorner
->
end_contour
)
||
(
ic
==
imax
)
)
// the last corner of a filled area is found: draw it
{
if
(
endcorner
->
utility
==
0
)
// Draw only basic outlines, not extra segments
export_vrml_line
(
layer
,
endcorner
->
x
,
endcorner
->
y
,
firstcorner
->
x
,
firstcorner
->
y
,
width
,
1
);
ic
++
;
/* A new contour? */
if
(
ic
<
imax
-
1
)
begincorner
=
firstcorner
=
&
zone
->
m_FilledPolysList
[
ic
];
}
else
begincorner
=
endcorner
;
}
}
}
}
static
void
export_vrml_text_module
(
TEXTE_MODULE
*
module
)
/*{{{*/
{
if
(
!
module
->
m_NoShow
)
{
wxSize
size
=
module
->
m_Size
;
if
(
module
->
m_Mirror
)
NEGATE
(
size
.
x
);
// Text is mirrored
s_text_layer
=
module
->
GetLayer
();
s_text_width
=
module
->
m_Width
;
DrawGraphicText
(
NULL
,
NULL
,
module
->
m_Pos
,
(
EDA_Colors
)
0
,
module
->
m_Text
,
module
->
GetDrawRotation
(),
size
,
module
->
m_HJustify
,
module
->
m_VJustify
,
module
->
m_Width
,
module
->
m_Italic
,
true
,
vrml_text_callback
);
}
}
static
void
export_vrml_edge_module
(
EDGE_MODULE
*
module
)
/*{{{*/
{
int
layer
=
module
->
GetLayer
();
double
x
=
module
->
m_Start
.
x
;
double
y
=
module
->
m_Start
.
y
;
double
xf
=
module
->
m_End
.
x
;
double
yf
=
module
->
m_End
.
y
;
double
w
=
module
->
m_Width
;
switch
(
module
->
m_Shape
)
{
case
S_ARC
:
export_vrml_arc
(
layer
,
x
,
y
,
xf
,
yf
,
w
,
3
);
break
;
case
S_CIRCLE
:
export_vrml_circle
(
layer
,
x
,
y
,
xf
,
yf
,
w
,
12
);
break
;
default:
export_vrml_line
(
layer
,
x
,
y
,
xf
,
yf
,
w
,
1
);
break
;
}
}
static
void
export_vrml_pad
(
BOARD
*
pcb
,
D_PAD
*
pad
)
/*{{{*/
{
double
hole_drill_w
=
(
double
)
pad
->
m_Drill
.
x
/
2
;
double
hole_drill_h
=
(
double
)
pad
->
m_Drill
.
y
/
2
;
double
hole_drill
=
MIN
(
hole_drill_w
,
hole_drill_h
);
double
hole_x
=
pad
->
m_Pos
.
x
;
double
hole_y
=
pad
->
m_Pos
.
y
;
/* Export the hole on the edge layer */
if
(
hole_drill
>
0
)
{
if
(
pad
->
m_DrillShape
==
PAD_OVAL
)
{
/* Oblong hole (slot) */
export_vrml_slot
(
layer_triangles
[
EDGE_N
],
FIRST_COPPER_LAYER
,
LAST_COPPER_LAYER
,
hole_x
,
hole_y
,
hole_drill_w
,
hole_drill_h
,
pad
->
m_Orient
,
6
);
}
else
{
// Drill a round hole
export_vrml_hole
(
layer_triangles
[
EDGE_N
],
FIRST_COPPER_LAYER
,
LAST_COPPER_LAYER
,
hole_x
,
hole_y
,
hole_drill
,
12
);
}
}
/* The pad proper, on the selected layers */
unsigned
long
layer_mask
=
pad
->
m_Masque_Layer
;
int
copper_layers
=
pcb
->
GetCopperLayerCount
(
);
/* The (maybe offseted) pad position */
wxPoint
pad_pos
=
pad
->
ReturnShapePos
();
double
pad_x
=
pad_pos
.
x
;
double
pad_y
=
pad_pos
.
y
;
wxSize
pad_delta
=
pad
->
m_DeltaSize
;
double
pad_dx
=
pad_delta
.
x
/
2
;
double
pad_dy
=
pad_delta
.
y
/
2
;
double
pad_w
=
pad
->
m_Size
.
x
/
2
;
double
pad_h
=
pad
->
m_Size
.
y
/
2
;
for
(
int
layer
=
FIRST_COPPER_LAYER
;
layer
<
copper_layers
;
layer
++
)
{
/* The last layer is always the component one, unless it's single face */
if
(
(
layer
>
FIRST_COPPER_LAYER
)
&&
(
layer
==
copper_layers
-
1
)
)
layer
=
LAST_COPPER_LAYER
;
if
(
layer_mask
&
(
1
<<
layer
)
)
{
/* OK, the pad is on this layer, export it */
switch
(
pad
->
m_PadShape
&
0x7F
)
/* What is the masking for? */
{
case
PAD_CIRCLE
:
export_vrml_circle
(
layer
,
pad_x
,
pad_y
,
pad_x
+
pad_w
/
2
,
pad_y
,
pad_w
,
12
);
break
;
case
PAD_OVAL
:
export_vrml_oval_pad
(
layer
,
pad_x
,
pad_y
,
pad_w
*
2
,
pad_h
*
2
,
pad
->
m_Orient
,
4
);
break
;
case
PAD_RECT
:
/* Just to be sure :D */
pad_dx
=
0
;
pad_dy
=
0
;
case
PAD_TRAPEZOID
:
{
int
coord
[
8
]
=
{
-
pad_w
-
pad_dy
,
+
pad_h
+
pad_dx
,
-
pad_w
+
pad_dy
,
-
pad_h
-
pad_dx
,
+
pad_w
-
pad_dy
,
+
pad_h
-
pad_dx
,
+
pad_w
+
pad_dy
,
-
pad_h
+
pad_dx
,
};
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
RotatePoint
(
&
coord
[
i
*
2
],
&
coord
[
i
*
2
+
1
],
pad
->
m_Orient
);
coord
[
i
*
2
]
+=
pad_x
;
coord
[
i
*
2
+
1
]
+=
pad_y
;
}
bag_flat_quad
(
layer
,
coord
[
0
],
coord
[
1
],
coord
[
2
],
coord
[
3
],
coord
[
4
],
coord
[
5
],
coord
[
6
],
coord
[
7
]
);
}
break
;
}
}
}
}
/* From axis/rot to quaternion */
static
void
build_quat
(
double
x
,
double
y
,
double
z
,
double
a
,
double
q
[
4
]
)
{
double
sina
=
sin
(
a
/
2
);
q
[
0
]
=
x
*
sina
;
q
[
1
]
=
y
*
sina
;
q
[
2
]
=
z
*
sina
;
q
[
3
]
=
cos
(
a
/
2
);
}
/* From quaternion to axis/rot */
static
void
from_quat
(
double
q
[
4
],
double
rot
[
4
]
)
{
rot
[
3
]
=
acos
(
q
[
3
]
)
*
2
;
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
rot
[
i
]
=
q
[
i
]
/
sin
(
rot
[
3
]
/
2
);
}
}
/* Quaternion composition */
static
void
compose_quat
(
double
q1
[
4
],
double
q2
[
4
],
double
qr
[
4
]
)
{
double
tmp
[
4
];
tmp
[
0
]
=
q2
[
3
]
*
q1
[
0
]
+
q2
[
0
]
*
q1
[
3
]
+
q2
[
1
]
*
q1
[
2
]
-
q2
[
2
]
*
q1
[
1
];
tmp
[
1
]
=
q2
[
3
]
*
q1
[
1
]
+
q2
[
1
]
*
q1
[
3
]
+
q2
[
2
]
*
q1
[
0
]
-
q2
[
0
]
*
q1
[
2
];
tmp
[
2
]
=
q2
[
3
]
*
q1
[
2
]
+
q2
[
2
]
*
q1
[
3
]
+
q2
[
0
]
*
q1
[
1
]
-
q2
[
1
]
*
q1
[
0
];
tmp
[
3
]
=
q2
[
3
]
*
q1
[
3
]
-
q2
[
0
]
*
q1
[
0
]
-
q2
[
1
]
*
q1
[
1
]
-
q2
[
2
]
*
q1
[
2
];
qr
[
0
]
=
tmp
[
0
];
qr
[
1
]
=
tmp
[
1
];
qr
[
2
]
=
tmp
[
2
];
qr
[
3
]
=
tmp
[
3
];
}
static
void
export_vrml_module
(
BOARD
*
aPcb
,
MODULE
*
aModule
,
FILE
*
aOutputFile
,
double
aScalingFactor
,
bool
aExport3DFiles
,
const
wxString
&
a3D_Subdir
)
{
/* Reference and value */
export_vrml_text_module
(
aModule
->
m_Reference
);
export_vrml_text_module
(
aModule
->
m_Value
);
/* Export module edges */
for
(
EDA_BaseStruct
*
item
=
aModule
->
m_Drawings
;
item
!=
NULL
;
item
=
item
->
Next
()
)
{
switch
(
item
->
Type
()
)
{
case
TYPE_TEXTE_MODULE
:
export_vrml_text_module
(
dynamic_cast
<
TEXTE_MODULE
*>
(
item
)
);
break
;
case
TYPE_EDGE_MODULE
:
export_vrml_edge_module
(
dynamic_cast
<
EDGE_MODULE
*>
(
item
)
);
break
;
default:
break
;
}
}
/* Export pads */
for
(
D_PAD
*
pad
=
aModule
->
m_Pads
;
pad
!=
0
;
pad
=
pad
->
Next
()
)
export_vrml_pad
(
aPcb
,
pad
);
bool
isFlipped
=
aModule
->
GetLayer
()
==
LAYER_N_BACK
;
/* Export the object VRML model(s) */
for
(
S3D_MASTER
*
vrmlm
=
aModule
->
m_3D_Drawings
;
vrmlm
!=
0
;
vrmlm
=
vrmlm
->
Next
()
)
{
wxString
fname
=
vrmlm
->
m_Shape3DName
;
if
(
fname
.
IsEmpty
()
)
continue
;
if
(
!
wxFileName
::
FileExists
(
fname
)
)
{
wxFileName
fn
=
fname
;
fname
=
wxGetApp
().
FindLibraryPath
(
fn
);
if
(
fname
.
IsEmpty
()
)
// keep "short" name if full filemane not found
fname
=
vrmlm
->
m_Shape3DName
;
}
fname
.
Replace
(
wxT
(
"
\\
"
),
wxT
(
"/"
)
);
wxString
source_fname
=
fname
;
if
(
aExport3DFiles
)
{
fname
.
Replace
(
wxT
(
"/"
),
wxT
(
"_"
)
);
fname
.
Replace
(
wxT
(
":_"
),
wxT
(
"_"
)
);
fname
=
a3D_Subdir
+
wxT
(
"/"
)
+
fname
;
if
(
!
wxFileExists
(
fname
)
)
wxCopyFile
(
source_fname
,
fname
);
}
/* Calculate 3D shape rotation:
* this is the rotation parameters, with an additional 180 deg rotation
* for footprints that are flipped
* When flipped, axis rotation is the horizontal axis (X axis)
*/
int
rotx
=
vrmlm
->
m_MatRotation
.
x
;
if
(
isFlipped
)
rotx
+=
1800
;
/* Do some quaternion munching */
double
q1
[
4
],
q2
[
4
],
rot
[
4
];
build_quat
(
1
,
0
,
0
,
rotx
/
1800.0
*
M_PI
,
q1
);
build_quat
(
0
,
1
,
0
,
vrmlm
->
m_MatRotation
.
y
/
1800.0
*
M_PI
,
q2
);
compose_quat
(
q1
,
q2
,
q1
);
build_quat
(
0
,
0
,
1
,
vrmlm
->
m_MatRotation
.
z
/
1800.0
*
M_PI
,
q2
);
compose_quat
(
q1
,
q2
,
q1
);
build_quat
(
0
,
0
,
1
,
aModule
->
m_Orient
/
1800.0
*
M_PI
,
q2
);
compose_quat
(
q1
,
q2
,
q1
);
from_quat
(
q1
,
rot
);
fprintf
(
aOutputFile
,
"Transform {
\n
"
);
/* A null rotation would fail the acos! */
if
(
rot
[
3
]
!=
0.0
)
{
fprintf
(
aOutputFile
,
" rotation %g %g %g %g
\n
"
,
rot
[
0
],
rot
[
1
],
rot
[
2
],
rot
[
3
]
);
}
fprintf
(
aOutputFile
,
" scale %g %g %g
\n
"
,
vrmlm
->
m_MatScale
.
x
*
aScalingFactor
,
vrmlm
->
m_MatScale
.
y
*
aScalingFactor
,
vrmlm
->
m_MatScale
.
z
*
aScalingFactor
);
fprintf
(
aOutputFile
,
" translation %g %g %g
\n
"
,
vrmlm
->
m_MatPosition
.
x
+
aModule
->
m_Pos
.
x
,
-
vrmlm
->
m_MatPosition
.
y
-
aModule
->
m_Pos
.
y
,
vrmlm
->
m_MatPosition
.
z
+
layer_z
[
aModule
->
GetLayer
()]
);
fprintf
(
aOutputFile
,
" children [
\n
Inline {
\n
url [
\"
%s
\"
]
\n
} ]
\n
"
,
CONV_TO_UTF8
(
fname
)
);
fprintf
(
aOutputFile
,
" }
\n
"
);
}
}
static
void
write_and_empty_triangle_bag
(
FILE
*
output_file
,
TriangleBag
&
triangles
,
int
color
)
{
if
(
!
triangles
.
empty
()
)
{
write_triangle_bag
(
output_file
,
color
,
triangles
);
triangles
.
clear
(
);
}
}
/* the dialog to create VRML files, derived from DIALOG_EXPORT_3DFILE_BASE,
* created by wxFormBuilder
*/
#include "dialog_export_3Dfiles_base.h" // the wxFormBuilder header file
class
DIALOG_EXPORT_3DFILE
:
public
DIALOG_EXPORT_3DFILE_BASE
{
private
:
static
int
m_UnitsOpt
;
// to remember last option
static
int
m_3DFilesOpt
;
// to remember last option
virtual
void
OnCancelClick
(
wxCommandEvent
&
event
){
EndModal
(
wxID_CANCEL
);
}
virtual
void
OnOkClick
(
wxCommandEvent
&
event
){
EndModal
(
wxID_OK
);
}
public
:
DIALOG_EXPORT_3DFILE
(
wxWindow
*
parent
)
:
DIALOG_EXPORT_3DFILE_BASE
(
parent
)
{
SetFocus
();
m_rbSelectUnits
->
SetSelection
(
m_UnitsOpt
);
m_rb3DFilesOption
->
SetSelection
(
m_3DFilesOpt
);
GetSizer
()
->
SetSizeHints
(
this
);
Centre
();
}
~
DIALOG_EXPORT_3DFILE
()
{
m_UnitsOpt
=
GetUnits
(
);
m_3DFilesOpt
=
Get3DFilesOption
(
);
};
void
SetSubdir
(
const
wxString
&
aDir
)
{
m_SubdirNameCtrl
->
SetValue
(
aDir
);
}
wxString
GetSubdir
(
)
{
return
m_SubdirNameCtrl
->
GetValue
(
);
}
wxFilePickerCtrl
*
FilePicker
()
{
return
m_filePicker
;
}
int
GetUnits
(
)
{
return
m_UnitsOpt
=
m_rbSelectUnits
->
GetSelection
();
}
int
Get3DFilesOption
(
)
{
return
m_3DFilesOpt
=
m_rb3DFilesOption
->
GetSelection
();
}
};
int
DIALOG_EXPORT_3DFILE
::
m_UnitsOpt
=
0
;
// to remember last option
int
DIALOG_EXPORT_3DFILE
::
m_3DFilesOpt
=
1
;
// to remember last option
/**
* Function OnExportVRML
* will export the current BOARD to a VRML file.
*/
void
WinEDA_PcbFrame
::
OnExportVRML
(
wxCommandEvent
&
event
)
{
wxFileName
fn
;
static
wxString
subDirFor3Dshapes
=
wxT
(
"shapes3D"
);
double
scaleList
[
3
]
=
{
1.0
,
25.4
,
25.4
/
1000
};
// Build default file name
wxString
ext
=
wxT
(
"wrl"
);
fn
=
GetScreen
()
->
m_FileName
;
fn
.
SetExt
(
ext
);
DIALOG_EXPORT_3DFILE
dlg
(
this
);
dlg
.
FilePicker
()
->
SetPath
(
fn
.
GetFullPath
()
);
dlg
.
SetSubdir
(
subDirFor3Dshapes
);
if
(
dlg
.
ShowModal
()
!=
wxID_OK
)
return
;
double
scale
=
scaleList
[
dlg
.
GetUnits
(
)];
// final scale export
bool
export3DFiles
=
dlg
.
Get3DFilesOption
(
)
==
0
;
wxBusyCursor
dummy
;
wxString
fullFilename
=
dlg
.
FilePicker
()
->
GetPath
();
subDirFor3Dshapes
=
dlg
.
GetSubdir
();
if
(
!
wxDirExists
(
subDirFor3Dshapes
)
)
wxMkdir
(
subDirFor3Dshapes
);
if
(
!
ExportVRML_File
(
fullFilename
,
scale
,
export3DFiles
,
subDirFor3Dshapes
)
)
{
wxString
msg
=
_
(
"Unable to create "
)
+
fullFilename
;
DisplayError
(
this
,
msg
);
return
;
}
}
/**
* Function ExportVRML_File
* Creates the file(s) exporting current BOARD to a VRML file.
* @param aFullFileName = the full filename of the file to create
* @param aScale = the general scaling factor. 1.0 to export in inch
* @param aExport3DFiles = true to copy 3D shapes in the subdir a3D_Subdir
* @param a3D_Subdir = sub directory where 3D shapes files are copied
* used only when aExport3DFiles == true
* @return true if Ok.
*/
/* When copying 3D shapes files, the new filename is build from
* the full path name, changing the separators by underscore.
* this is needed because files with the same shortname can exist in different directories
*/
bool
WinEDA_PcbFrame
::
ExportVRML_File
(
const
wxString
&
aFullFileName
,
double
aScale
,
bool
aExport3DFiles
,
const
wxString
&
a3D_Subdir
)
{
wxString
msg
;
FILE
*
output_file
;
BOARD
*
pcb
=
GetBoard
();
output_file
=
wxFopen
(
aFullFileName
,
wxT
(
"wt"
)
);
if
(
output_file
==
NULL
)
return
false
;
// Switch the locale to standard C (needed to print floating point numbers like 1.3)
SetLocaleTo_C_standard
();
/* Begin with the usual VRML boilerplate */
fprintf
(
output_file
,
"#VRML V2.0 utf8
\n
"
"WorldInfo {
\n
"
" title
\"
%s - Generated by PCBNEW
\"\n
"
"}
\n
"
,
CONV_TO_UTF8
(
aFullFileName
)
);
/* The would be in decimils and not in meters, as the standard wants.
* It is trivial to embed everything in a transform node to
* fix it. For example here we build the world in inches...
*/
/* scaling factor to convert internal units (decimils) to inches
*/
double
board_scaling_factor
=
0.0001
;
/* auxiliary scale to export to a different scale.
*/
double
general_scaling_factor
=
board_scaling_factor
*
aScale
;
fprintf
(
output_file
,
"Transform {
\n
"
);
fprintf
(
output_file
,
" scale %g %g %g
\n
"
,
general_scaling_factor
,
general_scaling_factor
,
general_scaling_factor
);
/* Define the translation to have the board centre to the 2D axis origin
* more easy for rotations...
*/
pcb
->
ComputeBoundaryBox
();
double
dx
=
board_scaling_factor
*
pcb
->
m_BoundaryBox
.
Centre
().
x
;
double
dy
=
board_scaling_factor
*
pcb
->
m_BoundaryBox
.
Centre
().
y
;
fprintf
(
output_file
,
" translation %g %g 0.0
\n
"
,
-
dx
,
dy
);
fprintf
(
output_file
,
" children [
\n
"
);
/* scaling factor to convert 3D models to board units (decimils)
* Usually we use Wings3D to create thems.
* One can consider the 3D units is 0.1 inch
* So the scaling factor from 0.1 inch to board units
* is 0.1 / board_scaling_factor
*/
double
wrml_3D_models_scaling_factor
=
0.1
/
board_scaling_factor
;
/* Preliminary computation: the z value for each layer */
compute_layer_Zs
(
pcb
);
/* Drawing and text on the board, and edges which are special */
export_vrml_drawings
(
pcb
);
/* Export vias and trackage */
export_vrml_tracks
(
pcb
);
/* Export zone fills */
/* TODO export_vrml_zones(pcb);
*/
/* Export footprints */
for
(
MODULE
*
module
=
pcb
->
m_Modules
;
module
!=
0
;
module
=
module
->
Next
()
)
export_vrml_module
(
pcb
,
module
,
output_file
,
wrml_3D_models_scaling_factor
,
aExport3DFiles
,
a3D_Subdir
);
/* Output the bagged triangles for each layer
* Each layer will be a separate shape */
for
(
int
layer
=
0
;
layer
<
LAYER_COUNT
;
layer
++
)
write_and_empty_triangle_bag
(
output_file
,
layer_triangles
[
layer
],
pcb
->
GetLayerColor
(
layer
)
);
/* Same thing for the via layers */
for
(
int
i
=
0
;
i
<
4
;
i
++
)
write_and_empty_triangle_bag
(
output_file
,
via_triangles
[
i
],
pcb
->
GetVisibleElementColor
(
VIAS_VISIBLE
+
i
)
);
/* Close the outer 'transform' node */
fputs
(
"]
\n
}
\n
"
,
output_file
);
// End of work
fclose
(
output_file
);
SetLocaleTo_Default
();
// revert to the current locale
return
true
;
}
pcbnew/menubar_pcbframe.cpp
View file @
8dd76c53
...
...
@@ -178,6 +178,13 @@ void WinEDA_PcbFrame::ReCreateMenuBar()
_
(
"Create a report of all modules on the current board"
)
);
item
->
SetBitmap
(
tools_xpm
);
submenuexport
->
Append
(
item
);
item
=
new
wxMenuItem
(
submenuexport
,
ID_GEN_EXPORT_FILE_VRML
,
_
(
"&VRML"
),
_
(
"Export a VRML board representation"
)
);
item
->
SetBitmap
(
show_3d_xpm
);
submenuexport
->
Append
(
item
);
ADD_MENUITEM_WITH_HELP_AND_SUBMENU
(
filesMenu
,
submenuexport
,
ID_GEN_EXPORT_FILE
,
_
(
"&Export"
),
_
(
"Export board"
),
export_xpm
);
...
...
pcbnew/pcbframe.cpp
View file @
8dd76c53
...
...
@@ -94,6 +94,7 @@ BEGIN_EVENT_TABLE( WinEDA_PcbFrame, WinEDA_BasePcbFrame )
EVT_MENU
(
ID_GEN_EXPORT_FILE_GENCADFORMAT
,
WinEDA_PcbFrame
::
ExportToGenCAD
)
EVT_MENU
(
ID_GEN_EXPORT_FILE_MODULE_REPORT
,
WinEDA_PcbFrame
::
GenModuleReport
)
EVT_MENU
(
ID_GEN_EXPORT_FILE_VRML
,
WinEDA_PcbFrame
::
OnExportVRML
)
EVT_MENU
(
ID_GEN_IMPORT_SPECCTRA_SESSION
,
WinEDA_PcbFrame
::
ImportSpecctraSession
)
...
...
pcbnew/pcbnew_id.h
View file @
8dd76c53
...
...
@@ -210,6 +210,7 @@ enum pcbnew_ids
ID_MENU_LIST_NETS
,
ID_MENU_PCB_CLEAN
,
ID_MENU_PCB_SWAP_LAYERS
,
ID_GEN_EXPORT_FILE_VRML
,
ID_TOOLBARH_PCB_AUTOPLACE
,
ID_TOOLBARH_PCB_AUTOROUTE
,
...
...
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