← Back to team overview

kicad-developers team mailing list archive

[PATCH 10/12] Convert idf2vrml to use wxApp etc for option processing

 

From: Cirilo Bernardo <cirilo.bernardo@xxxxxxxxx>

---
 utils/idftools/idf2vrml.cpp | 267 +++++++++++++++++++++-----------------------
 1 file changed, 126 insertions(+), 141 deletions(-)

diff --git a/utils/idftools/idf2vrml.cpp b/utils/idftools/idf2vrml.cpp
index df66e4b..05e375e 100644
--- a/utils/idftools/idf2vrml.cpp
+++ b/utils/idftools/idf2vrml.cpp
@@ -31,6 +31,11 @@
  *  would be more likely if we used a 1:1 scale.
  */
 
+#include <wx/app.h>
+#include <wx/cmdline.h>
+#include <wx/log.h>
+#include <wx/string.h>
+#include <wx/filename.h>
 
 #include <iostream>
 #include <iomanip>
@@ -60,15 +65,97 @@
 #define MIN_ANG 0.01
 #endif
 
-extern char* optarg;
-extern int   optopt;
+class IDF2VRML : public wxAppConsole
+{
+public:
+    virtual bool OnInit();
+    virtual int OnRun();
+    virtual void OnInitCmdLine(wxCmdLineParser& parser);
+    virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
+
+private:
+    double m_ScaleFactor;
+    bool   m_Compact;
+    bool   m_NoOutlineSubs;
+    wxString m_filename;
+};
 
-using namespace std;
-using namespace boost;
+static const wxCmdLineEntryDesc cmdLineDesc[] =
+{
+    { wxCMD_LINE_OPTION, "f", NULL, "input file name",
+        wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
+    { wxCMD_LINE_OPTION, "s", NULL, "scale factor",
+        wxCMD_LINE_VAL_DOUBLE, wxCMD_LINE_PARAM_OPTIONAL },
+    { wxCMD_LINE_SWITCH, "k", NULL, "produce KiCad-friendly VRML output; default is compact VRML",
+        wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+    { wxCMD_LINE_SWITCH, "d", NULL, "suppress substitution of default outlines",
+        wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+    { wxCMD_LINE_SWITCH, "z", NULL, "suppress rendering of zero-height outlines",
+        wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+    { wxCMD_LINE_SWITCH, "m", NULL, "print object mapping to stdout for debugging",
+        wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+    { wxCMD_LINE_SWITCH, "h", NULL, "display this message",
+        wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
+    { wxCMD_LINE_NONE }
+};
+
+
+wxIMPLEMENT_APP( IDF2VRML );
+
+bool nozeroheights;
+bool showObjectMapping;
+
+bool IDF2VRML::OnInit()
+{
+    m_ScaleFactor = 1.0;
+    m_Compact = true;
+    m_NoOutlineSubs = false;
+    nozeroheights = false;
+    showObjectMapping = false;
+
+    if( !wxAppConsole::OnInit() )
+        return false;
+
+    return true;
+}
 
-#define CLEANUP do { \
-setlocale( LC_ALL, "C" ); \
-} while( 0 );
+
+void IDF2VRML::OnInitCmdLine( wxCmdLineParser& parser )
+{
+    parser.SetDesc( cmdLineDesc );
+    parser.SetSwitchChars( "-" );
+    return;
+}
+
+
+bool IDF2VRML::OnCmdLineParsed( wxCmdLineParser& parser )
+{
+    if( parser.Found( "k" ) )
+        m_Compact = false;
+
+    double scale;
+
+    if( parser.Found( "s", &scale ) )
+        m_ScaleFactor = scale;
+
+    wxString fname;
+
+    if( parser.Found( "f", &fname ) )
+        m_filename = fname;
+
+    if( parser.Found( "d" ) )
+        m_NoOutlineSubs = true;
+
+    if( parser.Found( "z" ) )
+        nozeroheights = true;
+
+    if( parser.Found( "m" ) )
+        showObjectMapping = true;
+
+    return true;
+}
+
+using namespace boost;
 
 // define colors
 struct VRML_COLOR
@@ -128,22 +215,7 @@ VRML_IDS* GetColor( boost::ptr_map<const std::string, VRML_IDS>& cmap,
                       int& index, const std::string& uid );
 
 
-void PrintUsage( void )
-{
-    cout << "-\nUsage: idf2vrml -f input_file.emn -s scale_factor {-k} {-d} {-z} {-m}\n";
-    cout << "flags:\n";
-    cout << "       -k: produce KiCad-friendly VRML output; default is compact VRML\n";
-    cout << "       -d: suppress substitution of default outlines\n";
-    cout << "       -z: suppress rendering of zero-height outlines\n";
-    cout << "       -m: print object mapping to stdout for debugging purposes\n";
-    cout << "example to produce a model for use by KiCad: idf2vrml -f input.emn -s 0.3937008 -k\n\n";
-    return;
-}
-
-bool nozeroheights;
-bool showObjectMapping;
-
-int main( int argc, char **argv )
+int IDF2VRML::OnRun()
 {
     // IDF implicitly requires the C locale
     setlocale( LC_ALL, "C" );
@@ -158,138 +230,53 @@ int main( int argc, char **argv )
     //      a KiCad friendly output then we must avoid DEF+USE;
     //      otherwise we employ DEF+USE to minimize file size
 
-    std::string inputFilename;
-    double scaleFactor = 1.0;
-    bool   compact = true;
-    bool   nooutlinesubs = false;
-    int    ichar;
-
-    nozeroheights = false;
-    showObjectMapping = false;
-
-    while( ( ichar = getopt( argc, argv, ":f:s:kdzm" ) ) != -1 )
+    if( m_ScaleFactor < 0.001 || m_ScaleFactor > 10.0 )
     {
-        switch( ichar )
-        {
-        case 'f':
-            inputFilename = optarg;
-            break;
-
-        case 's':
-            do
-            {
-                errno = 0;
-                char* cp = NULL;
-                scaleFactor = strtod( optarg, &cp );
-
-                if( errno || cp == optarg )
-                {
-                    cerr << "* invalid scale factor: '" << optarg << "'\n";
-                    return -1;
-                }
-
-                if( scaleFactor < 0.001 || scaleFactor > 10 )
-                {
-                    cerr << "* scale factor out of range (" << scaleFactor << "); range is 0.001 to 10.0\n";
-                    return -1;
-                }
-
-            } while( 0 );
-            break;
-
-        case 'k':
-            compact = false;
-            break;
-
-        case 'd':
-            nooutlinesubs = true;
-            break;
-
-        case 'z':
-            nozeroheights = true;
-            break;
-
-        case 'm':
-            showObjectMapping = true;
-            break;
-
-        case ':':
-            cerr << "* Missing parameter to option '-" << ((char) optopt) << "'\n";
-            PrintUsage();
-            return -1;
-            break;
-
-        default:
-            cerr << "* Unexpected option: '-";
-
-            if( ichar == '?' )
-                cerr << ((char) optopt) << "'\n";
-            else
-                cerr << ((char) ichar) << "'\n";
-
-            PrintUsage();
-            return -1;
-            break;
-        }
-    }
-
-    if( inputFilename.empty() )
-    {
-        cerr << "* no IDF filename supplied\n";
-        PrintUsage();
+        wxLogMessage("scale factor out of range (%d); range is 0.001 to 10.0", m_ScaleFactor);
         return -1;
     }
 
     IDF3_BOARD pcb( IDF3::CAD_ELEC );
 
-    cout << "** Reading file: " << inputFilename << "\n";
+    wxLogMessage( "Reading file: '%s'", m_filename );
 
-    if( !pcb.ReadFile( FROM_UTF8( inputFilename.c_str() ), nooutlinesubs ) )
+    if( !pcb.ReadFile( m_filename, m_NoOutlineSubs ) )
     {
-        cerr << "** Failed to read IDF data:\n";
-        cerr << pcb.GetError() << "\n\n";
-
+        wxLogMessage( "Failed to read IDF data: %s", pcb.GetError() );
         return -1;
     }
 
     // set the scale and output precision ( scale 1 == precision 5)
-    pcb.SetUserScale( scaleFactor );
+    pcb.SetUserScale( m_ScaleFactor );
 
-    if( scaleFactor < 0.01 )
+    if( m_ScaleFactor < 0.01 )
         pcb.SetUserPrecision( 8 );
-    else if( scaleFactor < 0.1 )
+    else if( m_ScaleFactor < 0.1 )
         pcb.SetUserPrecision( 7 );
-    else if( scaleFactor < 1.0 )
+    else if( m_ScaleFactor < 1.0 )
         pcb.SetUserPrecision( 6 );
-    else if( scaleFactor < 10.0 )
+    else if( m_ScaleFactor < 10.0 )
         pcb.SetUserPrecision( 5 );
     else
         pcb.SetUserPrecision( 4 );
 
     // Create the VRML file and write the header
-    char* bnp = (char*) malloc( inputFilename.size() + 1 );
-    strcpy( bnp, inputFilename.c_str() );
-
-    std::string fname = basename( bnp );
-    free( bnp );
-    std::string::iterator itf = fname.end();
-    *(--itf) = 'l';
-    *(--itf) = 'r';
-    *(--itf) = 'w';
-
-    cout << "Writing file: '" << fname << "'\n";
+    wxFileName fname( m_filename );
+    fname.SetExt( "wrl" );
+    fname.Normalize();
+    wxLogMessage( "Writing file: '%s'", fname.GetFullName() );
 
     std::ofstream ofile;
-    ofile.open( fname.c_str(), std::ios_base::out );
+    ofile.open( fname.GetFullPath().ToUTF8(), std::ios_base::out );
 
-    ofile << fixed; // do not use exponents in VRML output
+    ofile << std::fixed; // do not use exponents in VRML output
     WriteHeader( pcb, ofile );
 
     // STEP 1: Render the PCB alone
     MakeBoard( pcb, ofile );
 
     // STEP 2: Render the components
-    MakeComponents( pcb, ofile, compact );
+    MakeComponents( pcb, ofile, m_Compact );
 
     // STEP 3: Render the OTHER outlines
     MakeOtherOutlines( pcb, ofile );
@@ -341,8 +328,7 @@ bool MakeBoard( IDF3_BOARD& board, std::ofstream& file )
 
     if( board.GetBoardOutlinesSize() < 1 )
     {
-        ERROR_IDF << "\n";
-        cerr << "* Cannot proceed; no board outline in IDF object\n";
+        wxLogMessage( "Cannot proceed; no board outline in IDF object" );
         return false;
     }
 
@@ -436,14 +422,13 @@ bool PopulateVRML( VRML_LAYER& model, const std::list< IDF_OUTLINE* >* items, bo
 
         if( nvcont < 0 )
         {
-            ERROR_IDF << "\n";
-            cerr << "* cannot create an outline\n";
+            wxLogMessage( "Cannot create an outline" );
             return false;
         }
 
         if( (*scont)->size() < 1 )
         {
-            ERROR_IDF << "invalid contour: no vertices\n";
+            wxLogMessage( "Invalid contour: no vertices" );
             return false;
         }
 
@@ -481,7 +466,7 @@ bool AddSegment( VRML_LAYER& model, IDF_SEGMENT* seg, int icont, int iseg )
         {
             if( iseg != 0 )
             {
-                ERROR_IDF << "adding a circle to an existing vertex list\n";
+                wxLogMessage( "Adding a circle to an existing vertex list" );
                 return false;
             }
 
@@ -511,7 +496,7 @@ bool WriteTriangles( std::ofstream& file, VRML_IDS* vID, VRML_LAYER* layer, bool
 
     if( compact && !vID->objectName.empty() )
     {
-        file << "translation " << setprecision( precision ) << vID->dX;
+        file << "translation " << std::setprecision( precision ) << vID->dX;
         file << " " << vID->dY << " ";
 
         if( vID->bottom )
@@ -524,14 +509,14 @@ bool WriteTriangles( std::ofstream& file, VRML_IDS* vID, VRML_LAYER* layer, bool
             tx = cos( M_PI2 - vID->dA / 2.0 );
             ty = sin( M_PI2 - vID->dA / 2.0 );
 
-            file << "rotation " << setprecision( precision );
+            file << "rotation " << std::setprecision( precision );
             file << tx << " " << ty << " 0 ";
-            file << setprecision(5) << M_PI << "\n";
+            file << std::setprecision(5) << M_PI << "\n";
         }
         else
         {
             file << vID->dZ << "\n";
-            file << "rotation 0 0 1 " << setprecision(5) << vID->dA << "\n";
+            file << "rotation 0 0 1 " << std::setprecision(5) << vID->dA << "\n";
         }
 
         file << "children [\n";
@@ -569,7 +554,7 @@ bool WriteTriangles( std::ofstream& file, VRML_IDS* vID, VRML_LAYER* layer, bool
     file << "material Material {\n";
 
     // material definition
-    file << "diffuseColor " << setprecision(3) << color->diff[0] << " ";
+    file << "diffuseColor " << std::setprecision(3) << color->diff[0] << " ";
     file << color->diff[1] << " " << color->diff[2] << "\n";
     file << "specularColor " << color->spec[0] << " " << color->spec[1];
     file << " " << color->spec[2] << "\n";
@@ -591,16 +576,16 @@ bool WriteTriangles( std::ofstream& file, VRML_IDS* vID, VRML_LAYER* layer, bool
     {
         if( !layer->WriteVertices( top_z, file, precision ) )
         {
-            cerr << "* errors writing planar vertices to " << vID->objectName << "\n";
-            cerr << "** " << layer->GetError() << "\n";
+            wxLogMessage( "Errors writing planar vertices to %s\n%s",
+                vID->objectName, layer->GetError() );
         }
     }
     else
     {
         if( !layer->Write3DVertices( top_z, bottom_z, file, precision ) )
         {
-            cerr << "* errors writing 3D vertices to " << vID->objectName << "\n";
-            cerr << "** " << layer->GetError() << "\n";
+            wxLogMessage( "Errors writing 3D vertices to %s\n%s",
+                vID->objectName, layer->GetError() );
         }
     }
 
@@ -886,7 +871,7 @@ VRML_IDS* GetColor( boost::ptr_map<const std::string, VRML_IDS>& cmap, int& inde
         id->objectName = ostr.str();
 
         if( showObjectMapping )
-            cout << "* " << ostr.str() << " = '" << uid << "'\n";
+            wxLogMessage( "* %s = '%s'", ostr.str(), uid );
 
         cmap.insert( uid, id );
 

Follow ups

References