vrml exporter: more cleaning code and enhancements. Dialog exporter: Add option to use board center as coord origin.

This commit is contained in:
jean-pierre charras 2021-03-17 14:26:26 +01:00
parent b050823c98
commit 074f0432f0
9 changed files with 850 additions and 782 deletions

View File

@ -1,7 +1,3 @@
/**
* @file dialog_export_vrml.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
@ -26,6 +22,10 @@
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file dialog_export_vrml.cpp
*/
#include <wx/dir.h>
#include <board.h>
@ -53,6 +53,8 @@ private:
int m_RefUnits; // Remember last units for Reference Point
double m_XRef; // Remember last X Reference Point
double m_YRef; // Remember last Y Reference Point
int m_originMode; // Origin selection option
// (0 = user, 1 = board center)
public:
DIALOG_EXPORT_3DFILE( PCB_EDIT_FRAME* parent ) :
@ -60,7 +62,7 @@ public:
{
m_filePicker->SetFocus();
auto cfg = m_parent->GetPcbNewSettings();
PCBNEW_SETTINGS* cfg = m_parent->GetPcbNewSettings();
m_unitsOpt = cfg->m_ExportVrml.units;
m_copy3DFilesOpt = cfg->m_ExportVrml.copy_3d_models;
@ -69,7 +71,10 @@ public:
m_RefUnits = cfg->m_ExportVrml.ref_units;
m_XRef = cfg->m_ExportVrml.ref_x;
m_YRef = cfg->m_ExportVrml.ref_y;
m_originMode = cfg->m_ExportVrml.origin_mode;
m_rbCoordOrigin->SetSelection( m_originMode );
m_rbSelectUnits->SetSelection( m_unitsOpt );
m_cbCopyFiles->SetValue( m_copy3DFilesOpt );
m_cbUseRelativePaths->SetValue( m_useRelativePathsOpt );
@ -81,13 +86,10 @@ public:
tmpStr = wxT( "" );
tmpStr << m_YRef;
m_VRML_Yref->SetValue( tmpStr );
m_sdbSizer1OK->SetDefault();
m_sdbSizerOK->SetDefault();
// Now all widgets have the size fixed, call FinishDialogSettings
finishDialogSettings();
Connect( ID_USE_ABS_PATH, wxEVT_UPDATE_UI,
wxUpdateUIEventHandler( DIALOG_EXPORT_3DFILE::OnUpdateUseRelativePath ) );
}
~DIALOG_EXPORT_3DFILE()
@ -95,13 +97,14 @@ public:
m_unitsOpt = GetUnits();
m_copy3DFilesOpt = GetCopyFilesOption();
auto cfg = m_parent->GetPcbNewSettings();
PCBNEW_SETTINGS* cfg = m_parent->GetPcbNewSettings();
cfg->m_ExportVrml.units = m_unitsOpt;
cfg->m_ExportVrml.copy_3d_models = m_copy3DFilesOpt;
cfg->m_ExportVrml.use_relative_paths = m_useRelativePathsOpt;
cfg->m_ExportVrml.use_plain_pcb = m_usePlainPCBOpt;
cfg->m_ExportVrml.ref_units = m_VRML_RefUnitChoice->GetSelection();
cfg->m_ExportVrml.origin_mode = m_rbCoordOrigin->GetSelection();
double val = 0.0;
m_VRML_Xref->GetValue().ToDouble( &val );
@ -131,6 +134,11 @@ public:
return m_VRML_RefUnitChoice->GetSelection();
}
int GetOriginChoice()
{
return m_rbCoordOrigin->GetSelection();
}
double GetXRef()
{
return DoubleValueFromString( EDA_UNITS::UNSCALED, m_VRML_Xref->GetValue() );
@ -161,7 +169,7 @@ public:
return m_usePlainPCBOpt = m_cbPlainPCB->GetValue();
}
void OnUpdateUseRelativePath( wxUpdateUIEvent& event )
void OnUpdateUseRelativePath( wxUpdateUIEvent& event ) override
{
// Making path relative or absolute has no meaning when VRML files are not copied.
event.Enable( m_cbCopyFiles->GetValue() );
@ -226,6 +234,15 @@ void PCB_EDIT_FRAME::OnExportVRML( wxCommandEvent& event )
aYRef *= 25.4;
}
if( dlg.GetOriginChoice() == 1 )
{
// Origin = board center:
BOARD* pcb = GetBoard();
wxPoint center = pcb->GetBoundingBox().GetCenter();
aXRef = Iu2Millimeter( center.x );
aYRef = Iu2Millimeter( center.y );
}
double scale = scaleList[dlg.GetUnits()]; // final scale export
bool export3DFiles = dlg.GetCopyFilesOption();
bool useRelativePaths = dlg.GetUseRelativePathsOption();

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.9.0 Nov 1 2020)
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -38,19 +38,21 @@ DIALOG_EXPORT_3DFILE_BASE::DIALOG_EXPORT_3DFILE_BASE( wxWindow* parent, wxWindow
bSizer1->Add( bUpperSizer, 0, wxALL|wxEXPAND, 5 );
wxBoxSizer* bSizer12;
bSizer12 = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* bSizerOptions;
bSizerOptions = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* bSizer5;
bSizer5 = new wxBoxSizer( wxVERTICAL );
wxString m_rbCoordOriginChoices[] = { _("User defined origin"), _("Board center origin") };
int m_rbCoordOriginNChoices = sizeof( m_rbCoordOriginChoices ) / sizeof( wxString );
m_rbCoordOrigin = new wxRadioBox( this, wxID_ANY, _("Coordinate origin options:"), wxDefaultPosition, wxDefaultSize, m_rbCoordOriginNChoices, m_rbCoordOriginChoices, 1, wxRA_SPECIFY_COLS );
m_rbCoordOrigin->SetSelection( 0 );
bSizerOptions->Add( m_rbCoordOrigin, 1, wxALL|wxEXPAND, 5 );
m_panel1 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer9;
bSizer9 = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bSizerVrmlUnits;
bSizerVrmlUnits = new wxBoxSizer( wxVERTICAL );
m_staticText6 = new wxStaticText( m_panel1, wxID_ANY, _("Grid reference point:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText6 = new wxStaticText( this, wxID_ANY, _("User defined origin:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText6->Wrap( -1 );
bSizer9->Add( m_staticText6, 0, wxALL, 5 );
bSizerVrmlUnits->Add( m_staticText6, 0, wxALL, 5 );
wxFlexGridSizer* fgSizerOptions;
fgSizerOptions = new wxFlexGridSizer( 0, 2, 0, 0 );
@ -58,21 +60,21 @@ DIALOG_EXPORT_3DFILE_BASE::DIALOG_EXPORT_3DFILE_BASE( wxWindow* parent, wxWindow
fgSizerOptions->SetFlexibleDirection( wxBOTH );
fgSizerOptions->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_staticText61 = new wxStaticText( m_panel1, wxID_ANY, _("Units:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText61 = new wxStaticText( this, wxID_ANY, _("Units:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText61->Wrap( -1 );
fgSizerOptions->Add( m_staticText61, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
wxString m_VRML_RefUnitChoiceChoices[] = { _("mm"), _("inch") };
int m_VRML_RefUnitChoiceNChoices = sizeof( m_VRML_RefUnitChoiceChoices ) / sizeof( wxString );
m_VRML_RefUnitChoice = new wxChoice( m_panel1, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_VRML_RefUnitChoiceNChoices, m_VRML_RefUnitChoiceChoices, 0 );
m_VRML_RefUnitChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_VRML_RefUnitChoiceNChoices, m_VRML_RefUnitChoiceChoices, 0 );
m_VRML_RefUnitChoice->SetSelection( 0 );
fgSizerOptions->Add( m_VRML_RefUnitChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
m_staticText4 = new wxStaticText( m_panel1, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText4 = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText4->Wrap( -1 );
fgSizerOptions->Add( m_staticText4, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
m_VRML_Xref = new wxTextCtrl( m_panel1, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
m_VRML_Xref = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
#ifdef __WXGTK__
if ( !m_VRML_Xref->HasFlag( wxTE_MULTILINE ) )
{
@ -83,11 +85,11 @@ DIALOG_EXPORT_3DFILE_BASE::DIALOG_EXPORT_3DFILE_BASE( wxWindow* parent, wxWindow
#endif
fgSizerOptions->Add( m_VRML_Xref, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
m_staticText5 = new wxStaticText( m_panel1, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText5 = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText5->Wrap( -1 );
fgSizerOptions->Add( m_staticText5, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
m_VRML_Yref = new wxTextCtrl( m_panel1, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
m_VRML_Yref = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
#ifdef __WXGTK__
if ( !m_VRML_Yref->HasFlag( wxTE_MULTILINE ) )
{
@ -99,25 +101,19 @@ DIALOG_EXPORT_3DFILE_BASE::DIALOG_EXPORT_3DFILE_BASE( wxWindow* parent, wxWindow
fgSizerOptions->Add( m_VRML_Yref, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
bSizer9->Add( fgSizerOptions, 1, wxEXPAND, 5 );
bSizerVrmlUnits->Add( fgSizerOptions, 1, wxEXPAND, 5 );
m_panel1->SetSizer( bSizer9 );
m_panel1->Layout();
bSizer9->Fit( m_panel1 );
bSizer5->Add( m_panel1, 1, wxEXPAND | wxALL, 5 );
bSizer12->Add( bSizer5, 1, wxEXPAND, 5 );
bSizerOptions->Add( bSizerVrmlUnits, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
wxString m_rbSelectUnitsChoices[] = { _("mm"), _("meter"), _("0.1 Inch"), _("Inch") };
int m_rbSelectUnitsNChoices = sizeof( m_rbSelectUnitsChoices ) / sizeof( wxString );
m_rbSelectUnits = new wxRadioBox( this, wxID_ANY, _("Output Units"), wxDefaultPosition, wxDefaultSize, m_rbSelectUnitsNChoices, m_rbSelectUnitsChoices, 1, wxRA_SPECIFY_COLS );
m_rbSelectUnits = new wxRadioBox( this, wxID_ANY, _("Vrml Units for Output Files"), wxDefaultPosition, wxDefaultSize, m_rbSelectUnitsNChoices, m_rbSelectUnitsChoices, 1, wxRA_SPECIFY_COLS );
m_rbSelectUnits->SetSelection( 0 );
bSizer12->Add( m_rbSelectUnits, 1, wxALL|wxEXPAND, 5 );
bSizerOptions->Add( m_rbSelectUnits, 1, wxALL|wxEXPAND, 5 );
bSizer1->Add( bSizer12, 0, wxEXPAND, 5 );
bSizer1->Add( bSizerOptions, 0, wxEXPAND, 5 );
wxBoxSizer* bLowerSizer;
bLowerSizer = new wxBoxSizer( wxHORIZONTAL );
@ -126,10 +122,11 @@ DIALOG_EXPORT_3DFILE_BASE::DIALOG_EXPORT_3DFILE_BASE( wxWindow* parent, wxWindow
bSizer4 = new wxBoxSizer( wxVERTICAL );
m_cbCopyFiles = new wxCheckBox( this, wxID_ANY, _("Copy 3D model files to 3D model path"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbCopyFiles->SetValue(true);
m_cbCopyFiles->SetToolTip( _("If checked: copy footprints 3D models in a folder\nIf not checked: merge footprints 3D models in the vrml board file\n") );
bSizer4->Add( m_cbCopyFiles, 0, wxALL, 5 );
m_cbUseRelativePaths = new wxCheckBox( this, ID_USE_ABS_PATH, _("Use relative paths to model files in board VRML file"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbUseRelativePaths = new wxCheckBox( this, wxID_ANY, _("Use relative paths to model files in board VRML file"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbUseRelativePaths->SetToolTip( _("Use paths for model files in board VRML file relative to the vrml file") );
bSizer4->Add( m_cbUseRelativePaths, 0, wxALL, 5 );
@ -149,21 +146,27 @@ DIALOG_EXPORT_3DFILE_BASE::DIALOG_EXPORT_3DFILE_BASE( wxWindow* parent, wxWindow
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();
m_sdbSizer = new wxStdDialogButtonSizer();
m_sdbSizerOK = new wxButton( this, wxID_OK );
m_sdbSizer->AddButton( m_sdbSizerOK );
m_sdbSizerCancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer->AddButton( m_sdbSizerCancel );
m_sdbSizer->Realize();
bSizer1->Add( m_sdbSizer1, 0, wxEXPAND|wxALL, 5 );
bSizer1->Add( m_sdbSizer, 0, wxEXPAND|wxALL, 5 );
this->SetSizer( bSizer1 );
this->Layout();
bSizer1->Fit( this );
// Connect Events
m_cbUseRelativePaths->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_EXPORT_3DFILE_BASE::OnUpdateUseRelativePath ), NULL, this );
}
DIALOG_EXPORT_3DFILE_BASE::~DIALOG_EXPORT_3DFILE_BASE()
{
// Disconnect Events
m_cbUseRelativePaths->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_EXPORT_3DFILE_BASE::OnUpdateUseRelativePath ), NULL, this );
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.9.0 Nov 1 2020)
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -20,9 +20,8 @@
#include <wx/filepicker.h>
#include <wx/textctrl.h>
#include <wx/sizer.h>
#include <wx/choice.h>
#include <wx/panel.h>
#include <wx/radiobox.h>
#include <wx/choice.h>
#include <wx/checkbox.h>
#include <wx/statline.h>
#include <wx/button.h>
@ -30,6 +29,7 @@
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_EXPORT_3DFILE_BASE
///////////////////////////////////////////////////////////////////////////////
@ -38,16 +38,11 @@ class DIALOG_EXPORT_3DFILE_BASE : public DIALOG_SHIM
private:
protected:
enum
{
ID_USE_ABS_PATH = 1000
};
wxStaticText* m_staticText1;
wxFilePickerCtrl* m_filePicker;
wxStaticText* m_staticText3;
wxTextCtrl* m_SubdirNameCtrl;
wxPanel* m_panel1;
wxRadioBox* m_rbCoordOrigin;
wxStaticText* m_staticText6;
wxStaticText* m_staticText61;
wxChoice* m_VRML_RefUnitChoice;
@ -60,9 +55,13 @@ class DIALOG_EXPORT_3DFILE_BASE : public DIALOG_SHIM
wxCheckBox* m_cbUseRelativePaths;
wxCheckBox* m_cbPlainPCB;
wxStaticLine* m_staticline1;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Cancel;
wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK;
wxButton* m_sdbSizerCancel;
// Virtual event handlers, overide them in your derived class
virtual void OnUpdateUseRelativePath( wxUpdateUIEvent& event ) { event.Skip(); }
public:

View File

@ -54,25 +54,21 @@
#include <exporter_vrml.h>
static bool USE_INLINES; // true to use legacy inline{} behavior
static bool USE_DEFS; // true to reuse component definitions
static bool USE_RELPATH; // true to use relative paths in VRML inline{}
static double WORLD_SCALE = 1.0; // scaling from 0.1 in to desired VRML unit
static double BOARD_SCALE; // scaling from mm to desired VRML world scale
static const int PRECISION = 6; // legacy precision factor (now set to 6)
static wxString SUBDIR_3D; // legacy 3D subdirectory
static wxString PROJ_DIR; // project directory
static S3D_CACHE* cache;
VRML_COLOR colors[VRML_COLOR_LAST];
VRML_COLOR vrml_colors_list[VRML_COLOR_LAST];
static SGNODE* sgmaterial[VRML_COLOR_LAST] = { NULL };
MODEL_VRML::MODEL_VRML() :
m_OutputPCB( (SGNODE*) NULL )
{
m_ReuseDef = true;
m_precision = 6;
m_WorldScale = 1.0;
for( unsigned i = 0; i < arrayDim( m_layer_z ); ++i )
m_layer_z[i] = 0;
@ -82,16 +78,16 @@ MODEL_VRML::MODEL_VRML() :
m_brd_thickness = 1.6;
// pcb green
colors[VRML_COLOR_PCB] = VRML_COLOR(
vrml_colors_list[VRML_COLOR_PCB] = VRML_COLOR(
0.07f, 0.3f, 0.12f, 0.01f, 0.03f, 0.01f, 0.0f, 0.0f, 0.0f, 0.8f, 0.0f, 0.02f );
// copper color
colors[VRML_COLOR_COPPER] = VRML_COLOR(
vrml_colors_list[VRML_COLOR_COPPER] = VRML_COLOR(
0.72f, 0.45f, 0.2f, 0.01f, 0.05f, 0.01f, 0.0f, 0.0f, 0.0f, 0.8f, 0.0f, 0.02f );
// silkscreen white
colors[VRML_COLOR_SILK] = VRML_COLOR(
vrml_colors_list[VRML_COLOR_SILK] = VRML_COLOR(
0.9f, 0.9f, 0.9f, 0.1f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f, 0.9f, 0.0f, 0.02f );
// solder paste silver
colors[VRML_COLOR_TIN] = VRML_COLOR( 0.749f, 0.756f, 0.761f, 0.749f, 0.756f, 0.761f, 0.0f,
vrml_colors_list[VRML_COLOR_TIN] = VRML_COLOR( 0.749f, 0.756f, 0.761f, 0.749f, 0.756f, 0.761f, 0.0f,
0.0f, 0.0f, 0.8f, 0.0f, 0.8f );
m_plainPCB = false;
@ -136,7 +132,7 @@ bool MODEL_VRML::SetScale( double aWorldScale )
throw( std::runtime_error( "WorldScale out of range (valid range is 0.001 to 10.0)" ) );
m_OutputPCB.SetScale( aWorldScale * 2.54 );
WORLD_SCALE = aWorldScale * 2.54;
m_WorldScale = aWorldScale * 2.54;
return true;
}
@ -175,6 +171,7 @@ bool MODEL_VRML::GetLayer3D( LAYER_NUM layer, VRML_LAYER** vlayer )
void MODEL_VRML::ExportVrmlSolderMask( BOARD* aPcb )
{
//TODO
}
@ -182,13 +179,7 @@ void MODEL_VRML::ExportVrmlSolderMask( BOARD* aPcb )
static MODEL_VRML* model_vrml;
static void create_vrml_shell( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX colorID,
VRML_LAYER* layer, double top_z, double bottom_z );
static void create_vrml_plane( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX colorID,
VRML_LAYER* layer, double aHeight, bool aTopPlane );
static void write_triangle_bag( std::ostream& aOut_file, const VRML_COLOR& aColor,
void MODEL_VRML::write_triangle_bag( std::ostream& aOut_file, const VRML_COLOR& aColor,
VRML_LAYER* aLayer, bool aPlane, bool aTop,
double aTop_z, double aBottom_z )
{
@ -265,9 +256,9 @@ static void write_triangle_bag( std::ostream& aOut_file, const VRML_COLOR& aColo
case 2:
if( aPlane )
aLayer->WriteVertices( aTop_z, aOut_file, PRECISION );
aLayer->WriteVertices( aTop_z, aOut_file, m_precision );
else
aLayer->Write3DVertices( aTop_z, aBottom_z, aOut_file, PRECISION );
aLayer->Write3DVertices( aTop_z, aBottom_z, aOut_file, m_precision );
aOut_file << "\n";
break;
@ -292,144 +283,142 @@ static void write_triangle_bag( std::ostream& aOut_file, const VRML_COLOR& aColo
}
static void write_layers( MODEL_VRML& aModel, BOARD* aPcb, const char* aFileName,
OSTREAM* aOutputFile )
void MODEL_VRML::writeLayers( BOARD* aPcb, const char* aFileName,
OSTREAM* aOutputFile )
{
// VRML_LAYER board;
aModel.m_board.Tesselate( &aModel.m_holes );
double brdz = aModel.m_brd_thickness / 2.0
- ( Millimeter2iu( ART_OFFSET / 2.0 ) ) * BOARD_SCALE;
m_board.Tesselate( &m_holes );
double brdz = m_brd_thickness / 2.0
- ( Millimeter2iu( ART_OFFSET / 2.0 ) ) * m_BoardToVrmlScale;
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
write_triangle_bag( *aOutputFile, aModel.GetColor( VRML_COLOR_PCB ),
&aModel.m_board, false, false, brdz, -brdz );
write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_PCB ),
&m_board, false, false, brdz, -brdz );
}
else
{
create_vrml_shell( aModel.m_OutputPCB, VRML_COLOR_PCB, &aModel.m_board, brdz, -brdz );
create_vrml_shell( m_OutputPCB, VRML_COLOR_PCB, &m_board, brdz, -brdz );
}
if( aModel.m_plainPCB )
if( m_plainPCB )
{
if( !USE_INLINES )
S3D::WriteVRML( aFileName, true, aModel.m_OutputPCB.GetRawPtr(), USE_DEFS, true );
if( !m_UseInlineModelsInBrdfile )
S3D::WriteVRML( aFileName, true, m_OutputPCB.GetRawPtr(), m_ReuseDef, true );
return;
}
// VRML_LAYER m_top_copper;
aModel.m_top_copper.Tesselate( &aModel.m_holes );
m_top_copper.Tesselate( &m_holes );
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
write_triangle_bag( *aOutputFile, aModel.GetColor( VRML_COLOR_COPPER ),
&aModel.m_top_copper, true, true,
aModel.GetLayerZ( F_Cu ), 0 );
write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_COPPER ),
&m_top_copper, true, true, GetLayerZ( F_Cu ), 0 );
}
else
{
create_vrml_plane( aModel.m_OutputPCB, VRML_COLOR_COPPER, &aModel.m_top_copper,
aModel.GetLayerZ( F_Cu ), true );
create_vrml_plane( m_OutputPCB, VRML_COLOR_COPPER, &m_top_copper,
GetLayerZ( F_Cu ), true );
}
// VRML_LAYER m_top_tin;
aModel.m_top_tin.Tesselate( &aModel.m_holes );
m_top_tin.Tesselate( &m_holes );
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
write_triangle_bag( *aOutputFile, aModel.GetColor( VRML_COLOR_TIN ),
&aModel.m_top_tin, true, true,
aModel.GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) * BOARD_SCALE,
write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_TIN ),
&m_top_tin, true, true,
GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale,
0 );
}
else
{
create_vrml_plane( aModel.m_OutputPCB, VRML_COLOR_TIN, &aModel.m_top_tin,
aModel.GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) * BOARD_SCALE,
create_vrml_plane( m_OutputPCB, VRML_COLOR_TIN, &m_top_tin,
GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale,
true );
}
// VRML_LAYER m_bot_copper;
aModel.m_bot_copper.Tesselate( &aModel.m_holes );
m_bot_copper.Tesselate( &m_holes );
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
write_triangle_bag( *aOutputFile, aModel.GetColor( VRML_COLOR_COPPER ),
&aModel.m_bot_copper, true, false,
aModel.GetLayerZ( B_Cu ), 0 );
write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_COPPER ),
&m_bot_copper, true, false, GetLayerZ( B_Cu ), 0 );
}
else
{
create_vrml_plane( aModel.m_OutputPCB, VRML_COLOR_COPPER, &aModel.m_bot_copper,
aModel.GetLayerZ( B_Cu ), false );
create_vrml_plane( m_OutputPCB, VRML_COLOR_COPPER, &m_bot_copper,
GetLayerZ( B_Cu ), false );
}
// VRML_LAYER m_bot_tin;
aModel.m_bot_tin.Tesselate( &aModel.m_holes );
m_bot_tin.Tesselate( &m_holes );
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
write_triangle_bag( *aOutputFile, aModel.GetColor( VRML_COLOR_TIN ),
&aModel.m_bot_tin, true, false,
aModel.GetLayerZ( B_Cu )
- Millimeter2iu( ART_OFFSET / 2.0 ) * BOARD_SCALE,
write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_TIN ),
&m_bot_tin, true, false,
GetLayerZ( B_Cu )
- Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale,
0 );
}
else
{
create_vrml_plane( aModel.m_OutputPCB, VRML_COLOR_TIN, &aModel.m_bot_tin,
aModel.GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) * BOARD_SCALE,
create_vrml_plane( m_OutputPCB, VRML_COLOR_TIN, &m_bot_tin,
GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale,
false );
}
// VRML_LAYER PTH;
aModel.m_plated_holes.Tesselate( NULL, true );
m_plated_holes.Tesselate( NULL, true );
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
write_triangle_bag( *aOutputFile, aModel.GetColor( VRML_COLOR_TIN ),
&aModel.m_plated_holes, false, false,
aModel.GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) * BOARD_SCALE,
aModel.GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) * BOARD_SCALE );
write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_TIN ),
&m_plated_holes, false, false,
GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale,
GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale );
}
else
{
create_vrml_shell( aModel.m_OutputPCB, VRML_COLOR_TIN, &aModel.m_plated_holes,
aModel.GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) * BOARD_SCALE,
aModel.GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) * BOARD_SCALE );
create_vrml_shell( m_OutputPCB, VRML_COLOR_TIN, &m_plated_holes,
GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale,
GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale );
}
// VRML_LAYER m_top_silk;
aModel.m_top_silk.Tesselate( &aModel.m_holes );
m_top_silk.Tesselate( &m_holes );
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
write_triangle_bag( *aOutputFile, aModel.GetColor( VRML_COLOR_SILK ), &aModel.m_top_silk,
true, true, aModel.GetLayerZ( F_SilkS ), 0 );
write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_SILK ), &m_top_silk,
true, true, GetLayerZ( F_SilkS ), 0 );
}
else
{
create_vrml_plane( aModel.m_OutputPCB, VRML_COLOR_SILK, &aModel.m_top_silk,
aModel.GetLayerZ( F_SilkS ), true );
create_vrml_plane( m_OutputPCB, VRML_COLOR_SILK, &m_top_silk,
GetLayerZ( F_SilkS ), true );
}
// VRML_LAYER m_bot_silk;
aModel.m_bot_silk.Tesselate( &aModel.m_holes );
m_bot_silk.Tesselate( &m_holes );
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
write_triangle_bag( *aOutputFile, aModel.GetColor( VRML_COLOR_SILK ), &aModel.m_bot_silk,
true, false, aModel.GetLayerZ( B_SilkS ), 0 );
write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_SILK ), &m_bot_silk,
true, false, GetLayerZ( B_SilkS ), 0 );
}
else
{
create_vrml_plane( aModel.m_OutputPCB, VRML_COLOR_SILK, &aModel.m_bot_silk,
aModel.GetLayerZ( B_SilkS ), false );
create_vrml_plane( m_OutputPCB, VRML_COLOR_SILK, &m_bot_silk,
GetLayerZ( B_SilkS ), false );
}
if( !USE_INLINES )
S3D::WriteVRML( aFileName, true, aModel.m_OutputPCB.GetRawPtr(), true, true );
if( !m_UseInlineModelsInBrdfile )
S3D::WriteVRML( aFileName, true, m_OutputPCB.GetRawPtr(), true, true );
}
@ -438,7 +427,7 @@ void MODEL_VRML::ComputeLayer3D_Zpos( BOARD* pcb )
int copper_layers = pcb->GetCopperLayerCount();
// We call it 'layer' thickness, but it's the whole board thickness!
m_brd_thickness = pcb->GetDesignSettings().GetBoardThickness() * BOARD_SCALE;
m_brd_thickness = pcb->GetDesignSettings().GetBoardThickness() * m_BoardToVrmlScale;
double half_thickness = m_brd_thickness / 2;
// Compute each layer's Z value, more or less like the 3d view
@ -453,7 +442,7 @@ void MODEL_VRML::ComputeLayer3D_Zpos( BOARD* pcb )
}
// To avoid rounding interference, we apply an epsilon to each successive layer
double epsilon_z = Millimeter2iu( ART_OFFSET ) * BOARD_SCALE;
double epsilon_z = Millimeter2iu( ART_OFFSET ) * m_BoardToVrmlScale;
SetLayerZ( B_Paste, -half_thickness - epsilon_z * 4 );
SetLayerZ( B_Adhes, -half_thickness - epsilon_z * 3 );
SetLayerZ( B_SilkS, -half_thickness - epsilon_z * 2 );
@ -574,8 +563,8 @@ void MODEL_VRML::ExportVrmlPolygon( LAYER_NUM layer, PCB_SHAPE *aOutline,
for( int j = 0; j < outline.PointCount(); j++ )
{
if( !vlayer->AddVertex( seg, outline.CPoint( j ).x * BOARD_SCALE,
-outline.CPoint( j ).y * BOARD_SCALE ) )
if( !vlayer->AddVertex( seg, outline.CPoint( j ).x * m_BoardToVrmlScale,
-outline.CPoint( j ).y * m_BoardToVrmlScale ) )
throw( std::runtime_error( vlayer->GetError() ) );
}
@ -587,11 +576,11 @@ void MODEL_VRML::ExportVrmlPolygon( LAYER_NUM layer, PCB_SHAPE *aOutline,
void MODEL_VRML::ExportVrmlDrawsegment( PCB_SHAPE* drawseg )
{
LAYER_NUM layer = drawseg->GetLayer();
double w = drawseg->GetWidth() * BOARD_SCALE;
double x = drawseg->GetStart().x * BOARD_SCALE;
double y = drawseg->GetStart().y * BOARD_SCALE;
double xf = drawseg->GetEnd().x * BOARD_SCALE;
double yf = drawseg->GetEnd().y * BOARD_SCALE;
double w = drawseg->GetWidth() * m_BoardToVrmlScale;
double x = drawseg->GetStart().x * m_BoardToVrmlScale;
double y = drawseg->GetStart().y * m_BoardToVrmlScale;
double xf = drawseg->GetEnd().x * m_BoardToVrmlScale;
double yf = drawseg->GetEnd().y * m_BoardToVrmlScale;
double r = sqrt( pow( x - xf, 2 ) + pow( y - yf, 2 ) );
// Items on the edge layer are handled elsewhere; just return
@ -602,10 +591,10 @@ void MODEL_VRML::ExportVrmlDrawsegment( PCB_SHAPE* drawseg )
{
case S_ARC:
ExportVrmlArc( layer,
(double) drawseg->GetCenter().x * BOARD_SCALE,
(double) drawseg->GetCenter().y * BOARD_SCALE,
(double) drawseg->GetArcStart().x * BOARD_SCALE,
(double) drawseg->GetArcStart().y * BOARD_SCALE,
(double) drawseg->GetCenter().x * m_BoardToVrmlScale,
(double) drawseg->GetCenter().y * m_BoardToVrmlScale,
(double) drawseg->GetArcStart().x * m_BoardToVrmlScale,
(double) drawseg->GetArcStart().y * m_BoardToVrmlScale,
w, drawseg->GetAngle() / 10 );
break;
@ -630,10 +619,10 @@ void MODEL_VRML::ExportVrmlDrawsegment( PCB_SHAPE* drawseg )
std::vector<VECTOR2D> pointCtrl;
pointCtrl.emplace_back( x, y );
pointCtrl.emplace_back( drawseg->GetBezControl1().x * BOARD_SCALE,
drawseg->GetBezControl1().y * BOARD_SCALE );
pointCtrl.emplace_back( drawseg->GetBezControl2().x * BOARD_SCALE,
drawseg->GetBezControl2().y * BOARD_SCALE );
pointCtrl.emplace_back( drawseg->GetBezControl1().x * m_BoardToVrmlScale,
drawseg->GetBezControl1().y * m_BoardToVrmlScale );
pointCtrl.emplace_back( drawseg->GetBezControl2().x * m_BoardToVrmlScale,
drawseg->GetBezControl2().y * m_BoardToVrmlScale );
pointCtrl.emplace_back( xf, yf );
BEZIER_POLY converter( pointCtrl );
@ -661,17 +650,20 @@ void MODEL_VRML::ExportVrmlDrawsegment( PCB_SHAPE* drawseg )
}
/* C++ doesn't have closures and neither continuation forms... this is
* for coupling the vrml_text_callback with the common parameters */
/* GRText needs a callback function to return the shape of the text to plot...
* this is for coupling the vrml_text_callback with the vrml exporter parameters
*/
static void vrml_text_callback( int x0, int y0, int xf, int yf, void* aData )
{
LAYER_NUM m_text_layer = model_vrml->m_text_layer;
int m_text_width = model_vrml->m_text_width;
model_vrml->ExportVrmlLine( m_text_layer,
x0 * BOARD_SCALE, y0 * BOARD_SCALE,
xf * BOARD_SCALE, yf * BOARD_SCALE,
m_text_width * BOARD_SCALE );
x0 * model_vrml->m_BoardToVrmlScale,
y0 * model_vrml->m_BoardToVrmlScale,
xf * model_vrml->m_BoardToVrmlScale,
yf * model_vrml->m_BoardToVrmlScale,
m_text_width * model_vrml->m_BoardToVrmlScale );
}
@ -758,8 +750,8 @@ void MODEL_VRML::ExportVrmlBoard( BOARD* aPcb )
for( int j = 0; j < outline.PointCount(); j++ )
{
m_board.AddVertex( seg, (double)outline.CPoint(j).x * BOARD_SCALE,
-((double)outline.CPoint(j).y * BOARD_SCALE ) );
m_board.AddVertex( seg, (double)outline.CPoint(j).x * m_BoardToVrmlScale,
-((double)outline.CPoint(j).y * m_BoardToVrmlScale ) );
}
@ -780,8 +772,8 @@ void MODEL_VRML::ExportVrmlBoard( BOARD* aPcb )
for( int j = 0; j < hole.PointCount(); j++ )
{
m_holes.AddVertex( seg, (double) hole.CPoint(j).x * BOARD_SCALE,
-( (double) hole.CPoint(j).y * BOARD_SCALE ) );
m_holes.AddVertex( seg, (double) hole.CPoint(j).x * m_BoardToVrmlScale,
-( (double) hole.CPoint(j).y * m_BoardToVrmlScale ) );
}
m_holes.EnsureWinding( seg, true );
@ -840,10 +832,10 @@ void MODEL_VRML::ExportVrmlVia( BOARD* aPcb, const VIA* aVia )
double x, y, r, hole;
PCB_LAYER_ID top_layer, bottom_layer;
hole = aVia->GetDrillValue() * BOARD_SCALE / 2.0;
r = aVia->GetWidth() * BOARD_SCALE / 2.0;
x = aVia->GetStart().x * BOARD_SCALE;
y = aVia->GetStart().y * BOARD_SCALE;
hole = aVia->GetDrillValue() * m_BoardToVrmlScale / 2.0;
r = aVia->GetWidth() * m_BoardToVrmlScale / 2.0;
x = aVia->GetStart().x * m_BoardToVrmlScale;
y = aVia->GetStart().y * m_BoardToVrmlScale;
aVia->LayerPair( &top_layer, &bottom_layer );
// do not render a buried via
@ -877,36 +869,36 @@ void MODEL_VRML::ExportVrmlTracks( BOARD* pcb )
if( arc_angle_degree < -1.0 || arc_angle_degree > 1.0 )
{
ExportVrmlArc( track->GetLayer(),
center.x * BOARD_SCALE, center.y * BOARD_SCALE,
arc->GetStart().x * BOARD_SCALE,
arc->GetStart().y * BOARD_SCALE,
arc->GetWidth() * BOARD_SCALE, arc_angle_degree );
center.x * m_BoardToVrmlScale, center.y * m_BoardToVrmlScale,
arc->GetStart().x * m_BoardToVrmlScale,
arc->GetStart().y * m_BoardToVrmlScale,
arc->GetWidth() * m_BoardToVrmlScale, arc_angle_degree );
}
else
{
ExportVrmlLine( arc->GetLayer(),
arc->GetStart().x * BOARD_SCALE,
arc->GetStart().y * BOARD_SCALE,
arc->GetEnd().x * BOARD_SCALE,
arc->GetEnd().y * BOARD_SCALE,
arc->GetWidth() * BOARD_SCALE );
arc->GetStart().x * m_BoardToVrmlScale,
arc->GetStart().y * m_BoardToVrmlScale,
arc->GetEnd().x * m_BoardToVrmlScale,
arc->GetEnd().y * m_BoardToVrmlScale,
arc->GetWidth() * m_BoardToVrmlScale );
}
}
else
{
ExportVrmlLine( track->GetLayer(),
track->GetStart().x * BOARD_SCALE,
track->GetStart().y * BOARD_SCALE,
track->GetEnd().x * BOARD_SCALE,
track->GetEnd().y * BOARD_SCALE,
track->GetWidth() * BOARD_SCALE );
track->GetStart().x * m_BoardToVrmlScale,
track->GetStart().y * m_BoardToVrmlScale,
track->GetEnd().x * m_BoardToVrmlScale,
track->GetEnd().y * m_BoardToVrmlScale,
track->GetWidth() * m_BoardToVrmlScale );
}
}
}
}
void MODEL_VRML::ExportVrmlZones( BOARD* aPcb, COMMIT* aCommit )
void MODEL_VRML::ExportVrmlZones( BOARD* aPcb )
{
for( ZONE* zone : aPcb->Zones() )
{
@ -918,16 +910,7 @@ void MODEL_VRML::ExportVrmlZones( BOARD* aPcb, COMMIT* aCommit )
continue;
if( !zone->IsFilled() )
{
ZONE_FILLER filler( aPcb, aCommit );
zone->SetFillMode( ZONE_FILL_MODE::POLYGONS ); // use filled polygons
// If the zone fill failed, don't try adding it to the export
std::vector<ZONE*> toFill = { zone };
if( !filler.Fill( toFill ) )
continue;
}
continue;
const SHAPE_POLY_SET& poly = zone->GetFilledPolysList( layer );
@ -939,8 +922,8 @@ void MODEL_VRML::ExportVrmlZones( BOARD* aPcb, COMMIT* aCommit )
for( int j = 0; j < outline.PointCount(); j++ )
{
if( !vl->AddVertex( seg, (double) outline.CPoint( j ).x * BOARD_SCALE,
-( (double) outline.CPoint( j ).y * BOARD_SCALE ) ) )
if( !vl->AddVertex( seg, (double) outline.CPoint( j ).x * m_BoardToVrmlScale,
-( (double) outline.CPoint( j ).y * m_BoardToVrmlScale ) ) )
{
throw( std::runtime_error( vl->GetError() ) );
}
@ -953,7 +936,7 @@ void MODEL_VRML::ExportVrmlZones( BOARD* aPcb, COMMIT* aCommit )
}
static void export_vrml_fp_text( FP_TEXT* item )
void MODEL_VRML::ExportVrmlFpText( FP_TEXT* item )
{
if( item->IsVisible() )
{
@ -978,11 +961,11 @@ static void export_vrml_fp_text( FP_TEXT* item )
void MODEL_VRML::ExportVrmlFpShape( FP_SHAPE* aOutline, FOOTPRINT* aFootprint )
{
LAYER_NUM layer = aOutline->GetLayer();
double x = aOutline->GetStart().x * BOARD_SCALE;
double y = aOutline->GetStart().y * BOARD_SCALE;
double xf = aOutline->GetEnd().x * BOARD_SCALE;
double yf = aOutline->GetEnd().y * BOARD_SCALE;
double w = aOutline->GetWidth() * BOARD_SCALE;
double x = aOutline->GetStart().x * m_BoardToVrmlScale;
double y = aOutline->GetStart().y * m_BoardToVrmlScale;
double xf = aOutline->GetEnd().x * m_BoardToVrmlScale;
double yf = aOutline->GetEnd().y * m_BoardToVrmlScale;
double w = aOutline->GetWidth() * m_BoardToVrmlScale;
switch( aOutline->GetShape() )
{
@ -1009,10 +992,10 @@ void MODEL_VRML::ExportVrmlFpShape( FP_SHAPE* aOutline, FOOTPRINT* aFootprint )
std::vector<VECTOR2D> pointCtrl;
pointCtrl.emplace_back( x, y );
pointCtrl.emplace_back( aOutline->GetBezControl1().x * BOARD_SCALE,
aOutline->GetBezControl1().y * BOARD_SCALE );
pointCtrl.emplace_back( aOutline->GetBezControl2().x * BOARD_SCALE,
aOutline->GetBezControl2().y * BOARD_SCALE );
pointCtrl.emplace_back( aOutline->GetBezControl1().x * m_BoardToVrmlScale,
aOutline->GetBezControl1().y * m_BoardToVrmlScale );
pointCtrl.emplace_back( aOutline->GetBezControl2().x * m_BoardToVrmlScale,
aOutline->GetBezControl2().y * m_BoardToVrmlScale );
pointCtrl.emplace_back( xf, yf );
BEZIER_POLY converter( pointCtrl );
@ -1044,15 +1027,15 @@ void MODEL_VRML::ExportVrmlPadshape( VRML_LAYER* aTinLayer, PAD* aPad )
{
// The (maybe offset) pad position
wxPoint pad_pos = aPad->ShapePos();
double pad_x = pad_pos.x * BOARD_SCALE;
double pad_y = pad_pos.y * BOARD_SCALE;
double pad_x = pad_pos.x * m_BoardToVrmlScale;
double pad_y = pad_pos.y * m_BoardToVrmlScale;
wxSize pad_delta = aPad->GetDelta();
double pad_dx = pad_delta.x * BOARD_SCALE / 2.0;
double pad_dy = pad_delta.y * BOARD_SCALE / 2.0;
double pad_dx = pad_delta.x * m_BoardToVrmlScale / 2.0;
double pad_dy = pad_delta.y * m_BoardToVrmlScale / 2.0;
double pad_w = aPad->GetSize().x * BOARD_SCALE / 2.0;
double pad_h = aPad->GetSize().y * BOARD_SCALE / 2.0;
double pad_w = aPad->GetSize().x * m_BoardToVrmlScale / 2.0;
double pad_h = aPad->GetSize().y * m_BoardToVrmlScale / 2.0;
switch( aPad->GetShape() )
{
@ -1085,7 +1068,7 @@ void MODEL_VRML::ExportVrmlPadshape( VRML_LAYER* aTinLayer, PAD* aPad )
cornerList.reserve( poly.PointCount() );
for( int ii = 0; ii < poly.PointCount(); ++ii )
cornerList.emplace_back(
poly.CPoint( ii ).x * BOARD_SCALE, -poly.CPoint( ii ).y * BOARD_SCALE );
poly.CPoint( ii ).x * m_BoardToVrmlScale, -poly.CPoint( ii ).y * m_BoardToVrmlScale );
// Close polygon
cornerList.push_back( cornerList[0] );
@ -1108,7 +1091,7 @@ void MODEL_VRML::ExportVrmlPadshape( VRML_LAYER* aTinLayer, PAD* aPad )
for( int ii = 0; ii < poly.PointCount(); ++ii )
cornerList.emplace_back(
poly.CPoint( ii ).x * BOARD_SCALE, -poly.CPoint( ii ).y * BOARD_SCALE );
poly.CPoint( ii ).x * m_BoardToVrmlScale, -poly.CPoint( ii ).y * m_BoardToVrmlScale );
// Close polygon
cornerList.push_back( cornerList[0] );
@ -1175,11 +1158,11 @@ void MODEL_VRML::ExportVrmlPadshape( VRML_LAYER* aTinLayer, PAD* aPad )
void MODEL_VRML::ExportVrmlPad( BOARD* aPcb, PAD* aPad )
{
double hole_drill_w = (double) aPad->GetDrillSize().x * BOARD_SCALE / 2.0;
double hole_drill_h = (double) aPad->GetDrillSize().y * BOARD_SCALE / 2.0;
double hole_drill_w = (double) aPad->GetDrillSize().x * m_BoardToVrmlScale / 2.0;
double hole_drill_h = (double) aPad->GetDrillSize().y * m_BoardToVrmlScale / 2.0;
double hole_drill = std::min( hole_drill_w, hole_drill_h );
double hole_x = aPad->GetPosition().x * BOARD_SCALE;
double hole_y = aPad->GetPosition().y * BOARD_SCALE;
double hole_x = aPad->GetPosition().x * m_BoardToVrmlScale;
double hole_y = aPad->GetPosition().y * m_BoardToVrmlScale;
// Export the hole on the edge layer
if( hole_drill > 0 )
@ -1297,10 +1280,10 @@ void MODEL_VRML::ExportVrmlFootprint( BOARD* aPcb, FOOTPRINT* aFootprint,
{
// Reference and value
if( aFootprint->Reference().IsVisible() )
export_vrml_fp_text( &aFootprint->Reference() );
ExportVrmlFpText( &aFootprint->Reference() );
if( aFootprint->Value().IsVisible() )
export_vrml_fp_text( &aFootprint->Value() );
ExportVrmlFpText( &aFootprint->Value() );
// Export footprint graphics
@ -1309,7 +1292,7 @@ void MODEL_VRML::ExportVrmlFootprint( BOARD* aPcb, FOOTPRINT* aFootprint,
switch( item->Type() )
{
case PCB_FP_TEXT_T:
export_vrml_fp_text( static_cast<FP_TEXT*>( item ) );
ExportVrmlFpText( static_cast<FP_TEXT*>( item ) );
break;
case PCB_FP_SHAPE_T:
@ -1332,7 +1315,7 @@ void MODEL_VRML::ExportVrmlFootprint( BOARD* aPcb, FOOTPRINT* aFootprint,
auto sM = aFootprint->Models().begin();
auto eM = aFootprint->Models().end();
wxFileName subdir( SUBDIR_3D, "" );
wxFileName subdir( m_Subdir3DFpModels, "" );
while( sM != eM )
{
@ -1390,15 +1373,15 @@ void MODEL_VRML::ExportVrmlFootprint( BOARD* aPcb, FOOTPRINT* aFootprint,
RotatePoint( &offsetx, &offsety, aFootprint->GetOrientation() );
SGPOINT trans;
trans.x = ( offsetx + aFootprint->GetPosition().x ) * BOARD_SCALE + m_tx;
trans.y = -( offsety + aFootprint->GetPosition().y) * BOARD_SCALE - m_ty;
trans.z = (offsetz * BOARD_SCALE ) + GetLayerZ( aFootprint->GetLayer() );
trans.x = ( offsetx + aFootprint->GetPosition().x ) * m_BoardToVrmlScale + m_tx;
trans.y = -( offsety + aFootprint->GetPosition().y) * m_BoardToVrmlScale - m_ty;
trans.z = (offsetz * m_BoardToVrmlScale ) + GetLayerZ( aFootprint->GetLayer() );
if( USE_INLINES )
if( m_UseInlineModelsInBrdfile )
{
wxFileName srcFile = cache->GetResolver()->ResolvePath( sM->m_Filename );
wxFileName dstFile;
dstFile.SetPath( SUBDIR_3D );
dstFile.SetPath( m_Subdir3DFpModels );
dstFile.SetName( srcFile.GetName() );
dstFile.SetExt( "wrl" );
@ -1425,7 +1408,7 @@ void MODEL_VRML::ExportVrmlFootprint( BOARD* aPcb, FOOTPRINT* aFootprint,
}
else
{
if( !S3D::WriteVRML( dstFile.GetFullPath().ToUTF8(), true, mod3d, USE_DEFS, true ) )
if( !S3D::WriteVRML( dstFile.GetFullPath().ToUTF8(), true, mod3d, m_ReuseDef, true ) )
continue;
}
}
@ -1439,7 +1422,7 @@ void MODEL_VRML::ExportVrmlFootprint( BOARD* aPcb, FOOTPRINT* aFootprint,
(*aOutputFile) << rot[0] << " " << rot[1] << " " << rot[2] << " " << rot[3] << "\n";
}
(*aOutputFile) << " translation " << std::setprecision( PRECISION );
(*aOutputFile) << " translation " << std::setprecision( m_precision );
(*aOutputFile) << trans.x << " ";
(*aOutputFile) << trans.y << " ";
(*aOutputFile) << trans.z << "\n";
@ -1451,7 +1434,7 @@ void MODEL_VRML::ExportVrmlFootprint( BOARD* aPcb, FOOTPRINT* aFootprint,
(*aOutputFile) << " children [\n Inline {\n url \"";
if( USE_RELPATH )
if( m_UseRelPathIn3DModelFilename )
{
wxFileName tmp = dstFile;
tmp.SetExt( "" );
@ -1500,28 +1483,25 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName, double aMMt
{
BOARD* pcb = GetBoard();
bool ok = true;
BOARD_COMMIT commit( this ); // We may need to modify the board (for instance to
// fill zones), so make sure we can revert.
USE_INLINES = aExport3DFiles;
USE_DEFS = true;
USE_RELPATH = aUseRelativePaths;
cache = Prj().Get3DCacheManager();
PROJ_DIR = Prj().GetProjectPath();
SUBDIR_3D = a3D_Subdir;
MODEL_VRML model3d;
model_vrml = &model3d;
model3d.SetScale( aMMtoWRMLunit );
model3d.m_UseInlineModelsInBrdfile = aExport3DFiles;
model3d.m_Subdir3DFpModels = a3D_Subdir;
model3d.m_UseRelPathIn3DModelFilename = aUseRelativePaths;
if( USE_INLINES )
if( model3d.m_UseInlineModelsInBrdfile )
{
BOARD_SCALE = MM_PER_IU / 2.54;
model3d.m_BoardToVrmlScale = MM_PER_IU / 2.54;
model3d.SetOffset( -aXRef / 2.54, aYRef / 2.54 );
}
else
{
BOARD_SCALE = MM_PER_IU;
model3d.m_BoardToVrmlScale = MM_PER_IU;
model3d.SetOffset( -aXRef, aYRef );
}
@ -1549,64 +1529,22 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName, double aMMt
// Export zone fills
if( !aUsePlainPCB )
model3d.ExportVrmlZones( pcb, &commit );
model3d.ExportVrmlZones( pcb );
if( USE_INLINES )
if( model3d.m_UseInlineModelsInBrdfile )
{
// check if the 3D Subdir exists - create if not
wxFileName subdir( SUBDIR_3D, "" );
if( ! subdir.DirExists() )
{
if( !wxDir::Make( subdir.GetFullPath() ) )
throw( std::runtime_error( "Could not create 3D model subdirectory" ) );
}
OPEN_OSTREAM( output_file, TO_UTF8( aFullFileName ) );
if( output_file.fail() )
{
std::ostringstream ostr;
ostr << "Could not open file '" << TO_UTF8( aFullFileName ) << "'";
throw( std::runtime_error( ostr.str().c_str() ) );
}
output_file.imbue( std::locale::classic() );
// Begin with the usual VRML boilerplate
wxString fn = aFullFileName;
fn.Replace( "\\" , "/" );
output_file << "#VRML V2.0 utf8\n";
output_file << "WorldInfo {\n";
output_file << " title \"" << TO_UTF8( fn ) << " - Generated by Pcbnew\"\n";
output_file << "}\n";
output_file << "Transform {\n";
output_file << " scale " << std::setprecision( PRECISION );
output_file << WORLD_SCALE << " ";
output_file << WORLD_SCALE << " ";
output_file << WORLD_SCALE << "\n";
output_file << " children [\n";
// Export footprints
for( FOOTPRINT* footprint : pcb->Footprints() )
model3d.ExportVrmlFootprint( pcb, footprint, &output_file );
// write out the board and all layers
write_layers( model3d, pcb, TO_UTF8( aFullFileName ), &output_file );
// Close the outer 'transform' node
output_file << "]\n}\n";
CLOSE_STREAM( output_file );
// Copy fp 3D models in a folder, and link these files in
// the board .vrml file
model3d.ExportFp3DModelsAsLinkedFile( pcb, aFullFileName );
}
else
{
// Export footprints
// merge footprints in the .vrml board file
for( FOOTPRINT* footprint : pcb->Footprints() )
model3d.ExportVrmlFootprint( pcb, footprint, NULL );
// write out the board and all layers
write_layers( model3d, pcb, TO_UTF8( aFullFileName ), NULL );
model3d.writeLayers( pcb, TO_UTF8( aFullFileName ), NULL );
}
}
catch( const std::exception& e )
@ -1618,10 +1556,57 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName, double aMMt
ok = false;
}
commit.Revert();
return ok;
}
void MODEL_VRML::ExportFp3DModelsAsLinkedFile( BOARD* aPcb, const wxString& aFullFileName )
{
// check if the 3D Subdir exists - create if not
wxFileName subdir( m_Subdir3DFpModels, "" );
if( ! subdir.DirExists() )
{
if( !wxDir::Make( subdir.GetFullPath() ) )
throw( std::runtime_error( "Could not create 3D model subdirectory" ) );
}
OPEN_OSTREAM( output_file, TO_UTF8( aFullFileName ) );
if( output_file.fail() )
{
std::ostringstream ostr;
ostr << "Could not open file '" << TO_UTF8( aFullFileName ) << "'";
throw( std::runtime_error( ostr.str().c_str() ) );
}
output_file.imbue( std::locale::classic() );
// Begin with the usual VRML boilerplate
wxString fn = aFullFileName;
fn.Replace( "\\" , "/" );
output_file << "#VRML V2.0 utf8\n";
output_file << "WorldInfo {\n";
output_file << " title \"" << TO_UTF8( fn ) << " - Generated by Pcbnew\"\n";
output_file << "}\n";
output_file << "Transform {\n";
output_file << " scale " << std::setprecision( m_precision );
output_file << m_WorldScale << " ";
output_file << m_WorldScale << " ";
output_file << m_WorldScale << "\n";
output_file << " children [\n";
// Export footprints
for( FOOTPRINT* footprint : aPcb->Footprints() )
ExportVrmlFootprint( aPcb, footprint, &output_file );
// write out the board and all layers
writeLayers( aPcb, TO_UTF8( aFullFileName ), &output_file );
// Close the outer 'transform' node
output_file << "]\n}\n";
CLOSE_STREAM( output_file );
}
static SGNODE* getSGColor( VRML_COLOR_INDEX colorIdx )
{
@ -1634,7 +1619,7 @@ static SGNODE* getSGColor( VRML_COLOR_INDEX colorIdx )
return sgmaterial[colorIdx];
IFSG_APPEARANCE vcolor( (SGNODE*) NULL );
VRML_COLOR* cp = &colors[colorIdx];
VRML_COLOR* cp = &vrml_colors_list[colorIdx];
vcolor.SetSpecular( cp->spec_red, cp->spec_grn, cp->spec_blu );
vcolor.SetDiffuse( cp->diffuse_red, cp->diffuse_grn, cp->diffuse_blu );
@ -1650,8 +1635,8 @@ static SGNODE* getSGColor( VRML_COLOR_INDEX colorIdx )
}
static void create_vrml_plane( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX colorID,
VRML_LAYER* layer, double top_z, bool aTopPlane )
void MODEL_VRML::create_vrml_plane( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX colorID,
VRML_LAYER* layer, double top_z, bool aTopPlane )
{
std::vector< double > vertices;
std::vector< int > idxPlane;
@ -1708,8 +1693,8 @@ static void create_vrml_plane( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX color
}
static void create_vrml_shell( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX colorID,
VRML_LAYER* layer, double top_z, double bottom_z )
void MODEL_VRML::create_vrml_shell( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX colorID,
VRML_LAYER* layer, double top_z, double bottom_z )
{
std::vector< double > vertices;
std::vector< int > idxPlane;

View File

@ -34,13 +34,29 @@ class VRML_WRITER
{
public:
/**
* Exports the board and its footprint shapes 3D (vrml files only) as a
* vrml file
* @param aFullFileName is the full filename of the board vrml file to create
* @param aMMtoWRMLunit is the convert factor from mm to the desired vrml file
* @param aExport3DFiles = true to copy 3D fp vrml models to a folder,
* and use " { inline fp_3d_model_filename }" keyword in vrml board file
* false to include them in the vrml board file
* @param aUseRelativePaths = true to use fp 3D relative paths,
* false to use absolute paths
* @param aUsePlainPCB = true to create a body board shape only,
* false to create a full board shape with tracks, vias ...
* @param a3D_Subdir is the folder to copy 3D fp models
* @param aXRef = X position of board (in mm)
* @param aYRef = Y position of board (in mm)
*/
bool ExportVRML_File( const wxString& aFullFileName, double aMMtoWRMLunit,
bool aExport3DFiles, bool aUseRelativePaths,
bool aUsePlainPCB, const wxString& a3D_Subdir,
double aXRef, double aYRef )
{
return ExportVRML(aFullFileName, aMMtoWRMLunit,
aExport3DFiles, aUseRelativePaths,
aUsePlainPCB, a3D_Subdir, aXRef, aYRef);
return ExportVRML( aFullFileName, aMMtoWRMLunit,
aExport3DFiles, aUseRelativePaths,
aUsePlainPCB, a3D_Subdir, aXRef, aYRef);
}
};

View File

@ -101,7 +101,7 @@ struct VRML_COLOR
};
extern VRML_COLOR colors[VRML_COLOR_LAST];
extern VRML_COLOR vrml_colors_list[VRML_COLOR_LAST];
// Handle the board ans its board items to convert them to a VRML representation:
@ -113,6 +113,8 @@ private:
int m_iMaxSeg; // max. sides to a small circle
double m_arcMinLen, m_arcMaxLen; // min and max lengths of an arc chord
int m_precision; // precision factor when exportin fp shapes
// to separate files
public:
IFSG_TRANSFORM m_OutputPCB;
@ -130,6 +132,28 @@ public:
bool m_plainPCB;
/* true to use VRML inline{} syntax for footprint 3D models, like:
* Inline { url "F:/tmp/pic_programmer/shapes3D/DIP-18_W7.62mm_Socket.wrl" }
* false to merge VRML 3D modeles in the .wrl board file
*/
bool m_UseInlineModelsInBrdfile;
// 3D subdirectory to copy footprint vrml 3D models when not merged in board file
wxString m_Subdir3DFpModels;
// true to use relative paths in VRML inline{} for footprint 3D models
// used only if m_UseInlineModelsInBrdfile = true
bool m_UseRelPathIn3DModelFilename;
// true to reuse component definitions
bool m_ReuseDef;
// scaling from 0.1 inch to desired VRML unit
double m_WorldScale = 1.0;
// scaling from mm to desired VRML world scale
double m_BoardToVrmlScale;
double m_minLineWidth; // minimum width of a VRML line segment
double m_tx; // global translation along X
@ -145,7 +169,7 @@ public:
VRML_COLOR& GetColor( VRML_COLOR_INDEX aIndex )
{
return colors[aIndex];
return vrml_colors_list[aIndex];
}
void SetOffset( double aXoff, double aYoff );
@ -172,7 +196,7 @@ public:
// Build and exports the board outlines (board body)
void ExportVrmlBoard( BOARD* aPcb );
void ExportVrmlZones( BOARD* aPcb, COMMIT* aCommit );
void ExportVrmlZones( BOARD* aPcb );
void ExportVrmlTracks( BOARD* pcb );
@ -182,6 +206,10 @@ public:
void ExportVrmlPcbtext( PCB_TEXT* text );
void ExportVrmlFpText( FP_TEXT* item );
void ExportFp3DModelsAsLinkedFile( BOARD* aPcb, const wxString& aFullFileName );
void ExportRoundPadstack( BOARD* pcb,
double x, double y, double r,
LAYER_NUM bottom_layer, LAYER_NUM top_layer,
@ -215,6 +243,8 @@ public:
void ExportVrmlPolygon( LAYER_NUM layer, PCB_SHAPE *aOutline,
double aOrientation, wxPoint aPos );
void writeLayers( BOARD* aPcb, const char* aFileName, OSTREAM* aOutputFile );
// select the VRML layer object to draw on
// return true if a layer has been selected.
bool GetLayer3D( LAYER_NUM layer, VRML_LAYER** vlayer );
@ -222,4 +252,15 @@ public:
// Build the Z position of 3D layers
void ComputeLayer3D_Zpos(BOARD* pcb );
private:
void write_triangle_bag( std::ostream& aOut_file, const VRML_COLOR& aColor,
VRML_LAYER* aLayer, bool aPlane, bool aTop,
double aTop_z, double aBottom_z );
void create_vrml_shell( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX colorID,
VRML_LAYER* layer, double top_z, double bottom_z );
void create_vrml_plane( IFSG_TRANSFORM& PcbOutput, VRML_COLOR_INDEX colorID,
VRML_LAYER* layer, double aHeight, bool aTopPlane );
};

View File

@ -312,6 +312,9 @@ PCBNEW_SETTINGS::PCBNEW_SETTINGS()
m_params.emplace_back( new PARAM<double>( "export_vrml.ref_y",
&m_ExportVrml.ref_y, 0 ) );
m_params.emplace_back( new PARAM<int>( "export_vrml.origin_mode",
&m_ExportVrml.origin_mode, 0 ) );
m_params.emplace_back( new PARAM<int>( "zones.hatching_style",
&m_Zones.hatching_style, 0 ) );
@ -647,6 +650,7 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
ret &= fromLegacy<int>( aCfg, "VrmlRefUnits", "export_vrml.ref_units" );
ret &= fromLegacy<double>( aCfg, "VrmlRefX", "export_vrml.ref_x" );
ret &= fromLegacy<double>( aCfg, "VrmlRefY", "export_vrml.ref_y" );
ret &= fromLegacy<int> ( aCfg, "VrmlOriginMode", "export_vrml.origin_mode" );
ret &= fromLegacy<int>( aCfg, "Zone_Ouline_Hatch_Opt", "zones.hatching_style" );
ret &= fromLegacyString( aCfg, "Zone_Filter_Opt", "zones.net_filter" );

View File

@ -128,6 +128,7 @@ public:
int ref_units;
double ref_x;
double ref_y;
int origin_mode;
};
struct DIALOG_FOOTPRINT_WIZARD_LIST