← Back to team overview

kicad-developers team mailing list archive

PATCH: add option to VRML Export for Plain PCB

 

The attached patch addresses wishlist item #1393941 which is to add an
option
to export VRML models with no silkscreen or copper in the model in order to
produce a model which is easily converted to STEP format for use with MCADs.
This is useful for users who currently use VRML to obtain a mechanical model
to work with.

The diff is against rev. 5328. The patch has been checked on the
pic_programmer
and video demo projects by exporting a plain VRML board and exporting an
IDF board.
The IDF output was converted into a VRML model with the idf2vrml utility
and compared
with the output of the VRML exporter to verify that all holes (PTH, NPTH,
via) are
rendered by the VRML exporter.

- Cirilo
=== modified file 'include/wxPcbStruct.h'
--- include/wxPcbStruct.h	2014-11-15 13:43:23 +0000
+++ include/wxPcbStruct.h	2014-12-20 00:26:11 +0000
@@ -938,7 +938,7 @@
      * @todo Use mm inside the file.  A general scale transform is applied to the whole
      *       file (1.0 to have the actual WRML unit im mm, 0.001 to have the actual WRML
      *       unit in meters.
-     * @note For 3D models built by a 3D modeler, the unit is 0,1 inches.  A specfic scale
+     * @note For 3D models built by a 3D modeler, the unit is 0,1 inches.  A specific scale
      *       is applied to 3D models to convert them to internal units.
      *
      * @param aFullFileName = the full filename of the file to create
@@ -947,13 +947,16 @@
      * @param aExport3DFiles = true to copy 3D shapes in the subir a3D_Subdir
      * @param aUseRelativePaths set to true to use relative paths instead of absolute paths
      *                          in the board VRML file URLs.
+     * @param aUsePlainPCB set to true to export a board with no copper or silkskreen;
+     *                          this is useful for generating a VRML file which can be
+     *                          converted to a STEP model.
      * @param a3D_Subdir = sub directory where 3D shapes files are copied.  This is only used
      *                     when aExport3DFiles == true
      * @return true if Ok.
      */
     bool ExportVRML_File( const wxString & aFullFileName, double aMMtoWRMLunit,
                           bool aExport3DFiles, bool aUseRelativePaths,
-                          const wxString & a3D_Subdir );
+                          bool aUsePlainPCB, const wxString & a3D_Subdir );
 
     /**
      * Function ExportToIDF3

=== modified file 'pcbnew/dialogs/dialog_export_vrml.cpp'
--- pcbnew/dialogs/dialog_export_vrml.cpp	2014-11-17 13:55:26 +0000
+++ pcbnew/dialogs/dialog_export_vrml.cpp	2014-12-20 00:19:38 +0000
@@ -41,6 +41,7 @@
 #define OPTKEY_OUTPUT_UNIT wxT( "VrmlExportUnit" )
 #define OPTKEY_3DFILES_OPT wxT( "VrmlExportCopyFiles" )
 #define OPTKEY_USE_RELATIVE_PATHS wxT( "VrmlUseRelativePaths" )
+#define OPTKEY_USE_PLAIN_PCB wxT( "VrmlUsePlainPCB" )
 
 
 class DIALOG_EXPORT_3DFILE : public DIALOG_EXPORT_3DFILE_BASE
@@ -51,6 +52,7 @@
     int             m_unitsOpt;          // Remember last units option
     bool            m_copy3DFilesOpt;    // Remember last copy model files option
     bool            m_useRelativePathsOpt;    // Remember last use absolut paths option
+    bool            m_usePlainPCBOpt;  // Remember last Plain Board option
 
 public:
     DIALOG_EXPORT_3DFILE( PCB_EDIT_FRAME* parent ) :
@@ -62,9 +64,11 @@
         m_config->Read( OPTKEY_OUTPUT_UNIT, &m_unitsOpt );
         m_config->Read( OPTKEY_3DFILES_OPT, &m_copy3DFilesOpt );
         m_config->Read( OPTKEY_USE_RELATIVE_PATHS, &m_useRelativePathsOpt );
+        m_config->Read( OPTKEY_USE_PLAIN_PCB, &m_usePlainPCBOpt );
         m_rbSelectUnits->SetSelection( m_unitsOpt );
         m_cbCopyFiles->SetValue( m_copy3DFilesOpt );
         m_cbUseRelativePaths->SetValue( m_useRelativePathsOpt );
+        m_cbPlainPCB->SetValue( m_usePlainPCBOpt );
         wxButton* okButton = (wxButton*) FindWindowByLabel( wxT( "OK" ) );
 
         if( okButton )
@@ -84,6 +88,7 @@
         m_config->Write( OPTKEY_OUTPUT_UNIT, m_unitsOpt );
         m_config->Write( OPTKEY_3DFILES_OPT, m_copy3DFilesOpt );
         m_config->Write( OPTKEY_USE_RELATIVE_PATHS, m_useRelativePathsOpt );
+        m_config->Write( OPTKEY_USE_PLAIN_PCB, m_usePlainPCBOpt );
     };
 
     void SetSubdir( const wxString & aDir )
@@ -116,6 +121,11 @@
         return m_useRelativePathsOpt = m_cbUseRelativePaths->GetValue();
     }
 
+    bool GetUsePlainPCBOption()
+    {
+        return m_usePlainPCBOpt = m_cbPlainPCB->GetValue();
+    }
+
     void OnUpdateUseRelativePath( wxUpdateUIEvent& event )
     {
         // Making path relative or absolute has no meaning when VRML files are not copied.
@@ -158,6 +168,7 @@
     double scale = scaleList[dlg.GetUnits()];     // final scale export
     bool export3DFiles = dlg.GetCopyFilesOption();
     bool useRelativePaths = dlg.GetUseRelativePathsOption();
+    bool usePlainPCB = dlg.GetUsePlainPCBOption();
     wxString fullFilename = dlg.FilePicker()->GetPath();
     wxFileName modelPath = fullFilename;
     wxBusyCursor dummy;
@@ -174,7 +185,7 @@
     }
 
     if( !ExportVRML_File( fullFilename, scale, export3DFiles, useRelativePaths,
-                          modelPath.GetPath() ) )
+                          usePlainPCB, modelPath.GetPath() ) )
     {
         wxString msg = _( "Unable to create " ) + fullFilename;
         wxMessageBox( msg );

=== modified file 'pcbnew/dialogs/dialog_export_vrml_base.cpp'
--- pcbnew/dialogs/dialog_export_vrml_base.cpp	2014-11-17 13:55:26 +0000
+++ pcbnew/dialogs/dialog_export_vrml_base.cpp	2014-12-19 23:18:33 +0000
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Nov  6 2013)
+// C++ code generated with wxFormBuilder (version Aug 17 2014)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
@@ -52,6 +52,9 @@
 	
 	bSizer4->Add( m_cbUseRelativePaths, 0, wxALL, 5 );
 	
+	m_cbPlainPCB = new wxCheckBox( this, wxID_ANY, _("Plain PCB (no copper or silk)"), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizer4->Add( m_cbPlainPCB, 0, wxALL, 5 );
+	
 	
 	bLowerSizer->Add( bSizer4, 3, wxEXPAND, 5 );
 	

=== modified file 'pcbnew/dialogs/dialog_export_vrml_base.fbp'
--- pcbnew/dialogs/dialog_export_vrml_base.fbp	2014-11-17 13:55:26 +0000
+++ pcbnew/dialogs/dialog_export_vrml_base.fbp	2014-12-19 23:14:35 +0000
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
 <wxFormBuilder_Project>
-    <FileVersion major="1" minor="11" />
+    <FileVersion major="1" minor="13" />
     <object class="Project" expanded="1">
         <property name="class_decoration"></property>
         <property name="code_generation">C++</property>
@@ -644,6 +644,94 @@
                                         <event name="OnUpdateUI"></event>
                                     </object>
                                 </object>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxALL</property>
+                                    <property name="proportion">0</property>
+                                    <object class="wxCheckBox" expanded="1">
+                                        <property name="BottomDockable">1</property>
+                                        <property name="LeftDockable">1</property>
+                                        <property name="RightDockable">1</property>
+                                        <property name="TopDockable">1</property>
+                                        <property name="aui_layer"></property>
+                                        <property name="aui_name"></property>
+                                        <property name="aui_position"></property>
+                                        <property name="aui_row"></property>
+                                        <property name="best_size"></property>
+                                        <property name="bg"></property>
+                                        <property name="caption"></property>
+                                        <property name="caption_visible">1</property>
+                                        <property name="center_pane">0</property>
+                                        <property name="checked">0</property>
+                                        <property name="close_button">1</property>
+                                        <property name="context_help"></property>
+                                        <property name="context_menu">1</property>
+                                        <property name="default_pane">0</property>
+                                        <property name="dock">Dock</property>
+                                        <property name="dock_fixed">0</property>
+                                        <property name="docking">Left</property>
+                                        <property name="enabled">1</property>
+                                        <property name="fg"></property>
+                                        <property name="floatable">1</property>
+                                        <property name="font"></property>
+                                        <property name="gripper">0</property>
+                                        <property name="hidden">0</property>
+                                        <property name="id">wxID_ANY</property>
+                                        <property name="label">Plain PCB (no copper or silk)</property>
+                                        <property name="max_size"></property>
+                                        <property name="maximize_button">0</property>
+                                        <property name="maximum_size"></property>
+                                        <property name="min_size"></property>
+                                        <property name="minimize_button">0</property>
+                                        <property name="minimum_size"></property>
+                                        <property name="moveable">1</property>
+                                        <property name="name">m_cbPlainPCB</property>
+                                        <property name="pane_border">1</property>
+                                        <property name="pane_position"></property>
+                                        <property name="pane_size"></property>
+                                        <property name="permission">protected</property>
+                                        <property name="pin_button">1</property>
+                                        <property name="pos"></property>
+                                        <property name="resize">Resizable</property>
+                                        <property name="show">1</property>
+                                        <property name="size"></property>
+                                        <property name="style"></property>
+                                        <property name="subclass"></property>
+                                        <property name="toolbar_pane">0</property>
+                                        <property name="tooltip"></property>
+                                        <property name="validator_data_type"></property>
+                                        <property name="validator_style">wxFILTER_NONE</property>
+                                        <property name="validator_type">wxDefaultValidator</property>
+                                        <property name="validator_variable"></property>
+                                        <property name="window_extra_style"></property>
+                                        <property name="window_name"></property>
+                                        <property name="window_style"></property>
+                                        <event name="OnChar"></event>
+                                        <event name="OnCheckBox"></event>
+                                        <event name="OnEnterWindow"></event>
+                                        <event name="OnEraseBackground"></event>
+                                        <event name="OnKeyDown"></event>
+                                        <event name="OnKeyUp"></event>
+                                        <event name="OnKillFocus"></event>
+                                        <event name="OnLeaveWindow"></event>
+                                        <event name="OnLeftDClick"></event>
+                                        <event name="OnLeftDown"></event>
+                                        <event name="OnLeftUp"></event>
+                                        <event name="OnMiddleDClick"></event>
+                                        <event name="OnMiddleDown"></event>
+                                        <event name="OnMiddleUp"></event>
+                                        <event name="OnMotion"></event>
+                                        <event name="OnMouseEvents"></event>
+                                        <event name="OnMouseWheel"></event>
+                                        <event name="OnPaint"></event>
+                                        <event name="OnRightDClick"></event>
+                                        <event name="OnRightDown"></event>
+                                        <event name="OnRightUp"></event>
+                                        <event name="OnSetFocus"></event>
+                                        <event name="OnSize"></event>
+                                        <event name="OnUpdateUI"></event>
+                                    </object>
+                                </object>
                             </object>
                         </object>
                         <object class="sizeritem" expanded="1">

=== modified file 'pcbnew/dialogs/dialog_export_vrml_base.h'
--- pcbnew/dialogs/dialog_export_vrml_base.h	2014-11-17 13:55:26 +0000
+++ pcbnew/dialogs/dialog_export_vrml_base.h	2014-12-19 23:18:33 +0000
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Nov  6 2013)
+// C++ code generated with wxFormBuilder (version Aug 17 2014)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
@@ -50,6 +50,7 @@
 		wxTextCtrl* m_SubdirNameCtrl;
 		wxCheckBox* m_cbCopyFiles;
 		wxCheckBox* m_cbUseRelativePaths;
+		wxCheckBox* m_cbPlainPCB;
 		wxRadioBox* m_rbSelectUnits;
 		wxStaticLine* m_staticline1;
 		wxStdDialogButtonSizer* m_sdbSizer1;

=== modified file 'pcbnew/exporters/export_vrml.cpp'
--- pcbnew/exporters/export_vrml.cpp	2014-10-17 23:28:12 +0000
+++ pcbnew/exporters/export_vrml.cpp	2014-12-20 01:18:15 +0000
@@ -148,6 +148,8 @@
     VRML_LAYER  bot_tin;
     VRML_LAYER  plated_holes;
 
+    bool plainPCB;
+
     double scale;           // board internal units to output scaling
     double minLineWidth;    // minimum width of a VRML line segment
     int    precision;       // precision of output units
@@ -403,6 +405,9 @@
     write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_PCB ),
                         &aModel.board, false, false, brdz, -brdz, aModel.precision );
 
+    if( aModel.plainPCB )
+        return;
+
     // VRML_LAYER top_copper;
     aModel.top_copper.Tesselate( &aModel.holes );
     write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_TRACK ),
@@ -791,6 +796,9 @@
     if( thru && hole > 0 )
         aModel.holes.AddCircle( x, -y, hole, true );
 
+    if( aModel.plainPCB )
+        return;
+
     while( 1 )
     {
         if( layer == B_Cu )
@@ -846,7 +854,8 @@
         {
             export_vrml_via( aModel, pcb, (const VIA*) track );
         }
-        else if( track->GetLayer() == B_Cu || track->GetLayer() == F_Cu )
+        else if( ( track->GetLayer() == B_Cu || track->GetLayer() == F_Cu )
+            && !aModel.plainPCB )
             export_vrml_line( aModel, track->GetLayer(),
                               track->GetStart().x * aModel.scale,
                               track->GetStart().y * aModel.scale,
@@ -1102,7 +1111,8 @@
     {
         bool pth = false;
 
-        if( aPad->GetAttribute() != PAD_HOLE_NOT_PLATED )
+        if( ( aPad->GetAttribute() != PAD_HOLE_NOT_PLATED )
+            && !aModel.plainPCB )
             pth = true;
 
         if( aPad->GetDrillShape() == PAD_DRILL_OBLONG )
@@ -1127,6 +1137,9 @@
         }
     }
 
+    if( aModel.plainPCB )
+        return;
+
     // The pad proper, on the selected layers
     LSET layer_mask = aPad->GetLayerSet();
 
@@ -1188,29 +1201,32 @@
                                 bool aExport3DFiles, bool aUseRelativePaths,
                                 const wxString& a3D_Subdir )
 {
-    // Reference and value
-    if( aModule->Reference().IsVisible() )
-        export_vrml_text_module( &aModule->Reference() );
-
-    if( aModule->Value().IsVisible() )
-        export_vrml_text_module( &aModule->Value() );
-
-    // Export module edges
-    for( EDA_ITEM* item = aModule->GraphicalItems(); item; item = item->Next() )
+    if( !aModel.plainPCB )
     {
-        switch( item->Type() )
+        // Reference and value
+        if( aModule->Reference().IsVisible() )
+            export_vrml_text_module( &aModule->Reference() );
+
+        if( aModule->Value().IsVisible() )
+            export_vrml_text_module( &aModule->Value() );
+
+        // Export module edges
+        for( EDA_ITEM* item = aModule->GraphicalItems(); item; item = item->Next() )
         {
-        case PCB_MODULE_TEXT_T:
-            export_vrml_text_module( static_cast<TEXTE_MODULE*>( item ) );
-            break;
-
-        case PCB_MODULE_EDGE_T:
-            export_vrml_edge_module( aModel, static_cast<EDGE_MODULE*>( item ),
-                                     aModule->GetOrientation() );
-            break;
-
-        default:
-            break;
+            switch( item->Type() )
+            {
+                case PCB_MODULE_TEXT_T:
+                    export_vrml_text_module( static_cast<TEXTE_MODULE*>( item ) );
+                    break;
+
+                case PCB_MODULE_EDGE_T:
+                    export_vrml_edge_module( aModel, static_cast<EDGE_MODULE*>( item ),
+                                             aModule->GetOrientation() );
+                    break;
+
+                default:
+                    break;
+            }
         }
     }
 
@@ -1340,13 +1356,14 @@
 
 bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName, double aMMtoWRMLunit,
                                       bool aExport3DFiles, bool aUseRelativePaths,
-                                      const wxString& a3D_Subdir )
+                                      bool aUsePlainPCB, const wxString& a3D_Subdir )
 {
     wxString        msg;
     BOARD*          pcb = GetBoard();
     bool            ok  = true;
 
     MODEL_VRML model3d;
+    model3d.plainPCB = aUsePlainPCB;
 
     model_vrml = &model3d;
     std::ofstream output_file;
@@ -1387,13 +1404,15 @@
         export_vrml_board( model3d, pcb );
 
         // Drawing and text on the board
-        export_vrml_drawings( model3d, pcb );
+        if( !aUsePlainPCB )
+            export_vrml_drawings( model3d, pcb );
 
         // Export vias and trackage
         export_vrml_tracks( model3d, pcb );
 
         // Export zone fills
-        export_vrml_zones( model3d, pcb);
+        if( !aUsePlainPCB )
+            export_vrml_zones( model3d, pcb);
 
         /* scaling factor to convert 3D models to board units (decimils)
          * Usually we use Wings3D to create thems.


Follow ups