static void export_vrml_module( MODEL_VRML& aModel, BOARD* aPcb, MODULE* aModule,
                                std::ofstream& aOutputFile, double aVRMLModelsToBiu,
                                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() )
    {
        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;
        }
    }

    // Export pads
    for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
        export_vrml_pad( aModel, aPcb, pad );

    bool isFlipped = aModule->GetLayer() == B_Cu;

    // Export the object VRML model(s)
    for( S3D_MASTER* vrmlm = aModule->Models();  vrmlm;  vrmlm = vrmlm->Next() )
    {
        if( !vrmlm->Is3DType( S3D_MASTER::FILE3D_VRML ) )
            continue;

        wxFileName modelFileName = vrmlm->GetShape3DFullFilename();
        wxFileName destFileName( a3D_Subdir, modelFileName.GetName(), modelFileName.GetExt() );

        // Only copy VRML files.
        if( modelFileName.FileExists() && modelFileName.GetExt() == wxT( "wrl" ) )
        {
            if( aExport3DFiles )
            {
                wxDateTime srcModTime = modelFileName.GetModificationTime();
                wxDateTime destModTime = srcModTime;

                destModTime.SetToCurrent();

                if( destFileName.FileExists() )
                    destModTime = destFileName.GetModificationTime();

                // Only copy the file if it doesn't exist or has been modified.  This eliminates
                // the redundant file copies.
                if( srcModTime != destModTime )
                {
                    wxLogDebug( wxT( "Copying 3D model %s to %s." ),
                                GetChars( modelFileName.GetFullPath() ),
                                GetChars( destFileName.GetFullPath() ) );

                    if( !wxCopyFile( modelFileName.GetFullPath(), destFileName.GetFullPath() ) )
                        continue;
                }
            }

            /* 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)
             */
            double rotx = -vrmlm->m_MatRotation.x;
            double roty = -vrmlm->m_MatRotation.y;
            double rotz = -vrmlm->m_MatRotation.z;

            if( isFlipped )
            {
                rotx += 180.0;
                NEGATE( roty );
                NEGATE( rotz );
            }

            // Do some quaternion munching
            double q1[4], q2[4], rot[4];
            build_quat( 1, 0, 0, DEG2RAD( rotx ), q1 );
            build_quat( 0, 1, 0, DEG2RAD( roty ), q2 );
            compose_quat( q1, q2, q1 );
            build_quat( 0, 0, 1, DEG2RAD( rotz ), q2 );
            compose_quat( q1, q2, q1 );

            // Note here aModule->GetOrientation() is in 0.1 degrees,
            // so module rotation has to be converted to radians
            build_quat( 0, 0, 1, DECIDEG2RAD( aModule->GetOrientation() ), q2 );
            compose_quat( q1, q2, q1 );
            from_quat( q1, rot );

            aOutputFile << "Transform {\n";

            // A null rotation would fail the acos!
            if( rot[3] != 0.0 )
            {
                aOutputFile << "  rotation " << std::setprecision( 3 );
                aOutputFile << rot[0] << " " << rot[1] << " " << rot[2] << " " << rot[3] << "\n";
            }

            // adjust 3D shape local offset position
            // they are given in inch, so they are converted in board IU.
            double offsetx = vrmlm->m_MatPosition.x * IU_PER_MILS * 1000.0;
            double offsety = vrmlm->m_MatPosition.y * IU_PER_MILS * 1000.0;
            double offsetz = vrmlm->m_MatPosition.z * IU_PER_MILS * 1000.0;

            if( isFlipped )
                NEGATE( offsetz );
            else // In normal mode, Y axis is reversed in Pcbnew.
                NEGATE( offsety );

            RotatePoint( &offsetx, &offsety, aModule->GetOrientation() );

            aOutputFile << "  translation " << std::setprecision( aModel.precision );
            aOutputFile << ( ( offsetx + aModule->GetPosition().x ) *
                             aModel.scale + aModel.tx ) << " ";
            aOutputFile << ( -(offsety + aModule->GetPosition().y) *
                             aModel.scale - aModel.ty ) << " ";
            aOutputFile << ( (offsetz * aModel.scale ) +
                             aModel.GetLayerZ( aModule->GetLayer() ) ) << "\n";
            aOutputFile << "  scale ";
            aOutputFile << ( vrmlm->m_MatScale.x * aVRMLModelsToBiu ) << " ";
            aOutputFile << ( vrmlm->m_MatScale.y * aVRMLModelsToBiu ) << " ";
            aOutputFile << ( vrmlm->m_MatScale.z * aVRMLModelsToBiu ) << "\n";
            aOutputFile << "  children [\n    Inline {\n      url \"";

            if( aUseRelativePaths )
            {
                wxFileName tmp = destFileName;
                tmp.SetExt( wxT( "" ) );
                tmp.SetName( wxT( "" ) );
                tmp.RemoveLastDir();
                destFileName.MakeRelativeTo( tmp.GetPath() );
            }

            wxString fn = destFileName.GetFullPath();
            fn.Replace( wxT( "\\" ), wxT( "/" ) );
            aOutputFile << TO_UTF8( fn ) << "\"\n    } ]\n";
            aOutputFile << "  }\n";
        }
    }
}
static void export_vrml_module( MODEL_VRML& aModel, BOARD* aPcb, MODULE* aModule,
        std::ofstream& aOutputFile,
        double aVRMLModelsToBiu,
        bool aExport3DFiles, 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() )
    {
        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;
        }
    }

    // Export pads
    for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
        export_vrml_pad( aModel, aPcb, pad );

    bool isFlipped = aModule->GetLayer() == B_Cu;

    // Export the object VRML model(s)
    for( S3D_MASTER* vrmlm = aModule->Models();  vrmlm;  vrmlm = vrmlm->Next() )
    {
        if( !vrmlm->Is3DType( S3D_MASTER::FILE3D_VRML ) )
            continue;

        wxString fname = vrmlm->GetShape3DFullFilename();

        fname.Replace( wxT( "\\" ), wxT( "/" ) );
        wxString source_fname = fname;

        if( aExport3DFiles )
        {
            // Change illegal characters in filenames
            ChangeIllegalCharacters( fname, true );
            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)
         */
        double rotx = -vrmlm->m_MatRotation.x;
        double roty = -vrmlm->m_MatRotation.y;
        double rotz = -vrmlm->m_MatRotation.z;

        if( isFlipped )
        {
            rotx += 180.0;
            NEGATE( roty );
            NEGATE( rotz );
        }

        // Do some quaternion munching
        double q1[4], q2[4], rot[4];
        build_quat( 1, 0, 0, DEG2RAD( rotx ), q1 );
        build_quat( 0, 1, 0, DEG2RAD( roty ), q2 );
        compose_quat( q1, q2, q1 );
        build_quat( 0, 0, 1, DEG2RAD( rotz ), q2 );
        compose_quat( q1, q2, q1 );

        // Note here aModule->GetOrientation() is in 0.1 degrees,
        // so module rotation has to be converted to radians
        build_quat( 0, 0, 1, DECIDEG2RAD( aModule->GetOrientation() ), q2 );
        compose_quat( q1, q2, q1 );
        from_quat( q1, rot );

        aOutputFile << "Transform {\n";

        // A null rotation would fail the acos!
        if( rot[3] != 0.0 )
        {
            aOutputFile << "  rotation " << std::setprecision( 3 );
            aOutputFile << rot[0] << " " << rot[1] << " " << rot[2] << " " << rot[3] << "\n";
        }

        // adjust 3D shape local offset position
        // they are given in inch, so they are converted in board IU.
        double offsetx = vrmlm->m_MatPosition.x * IU_PER_MILS * 1000.0;
        double offsety = vrmlm->m_MatPosition.y * IU_PER_MILS * 1000.0;
        double offsetz = vrmlm->m_MatPosition.z * IU_PER_MILS * 1000.0;

        if( isFlipped )
            NEGATE( offsetz );
        else // In normal mode, Y axis is reversed in Pcbnew.
            NEGATE( offsety );

        RotatePoint( &offsetx, &offsety, aModule->GetOrientation() );

        aOutputFile << "  translation " << std::setprecision( aModel.precision );
        aOutputFile << (( offsetx + aModule->GetPosition().x) * aModel.scale + aModel.tx ) << " ";
        aOutputFile << ( -(offsety + aModule->GetPosition().y) * aModel.scale - aModel.ty ) << " ";
        aOutputFile << ( (offsetz * aModel.scale ) + aModel.GetLayerZ( aModule->GetLayer() ) ) << "\n";

        aOutputFile << "  scale ";
        aOutputFile << ( vrmlm->m_MatScale.x * aVRMLModelsToBiu ) << " ";
        aOutputFile << ( vrmlm->m_MatScale.y * aVRMLModelsToBiu ) << " ";
        aOutputFile << ( vrmlm->m_MatScale.z * aVRMLModelsToBiu ) << "\n";

        if( fname.EndsWith( wxT( "x3d" ) ) )
        {
            X3D_MODEL_PARSER* parser = new X3D_MODEL_PARSER( vrmlm );

            if( parser )
            {
                // embed x3d model in vrml format
                double vrml_to_x3d = aVRMLModelsToBiu;
                parser->Load( fname, vrml_to_x3d );

                try
                {
                    aOutputFile << "  children [\n ";
                    aOutputFile << TO_UTF8( parser->VRML2_representation() ) << " ]\n";
                    aOutputFile << "  }\n";
                }
                catch( const std::exception& e )
                {
                    delete parser;
                    throw;
                }
            }
        }
        else
        {
            aOutputFile << "  children [\n    Inline {\n      url \"";
            aOutputFile << TO_UTF8( fname ) << "\"\n    } ]\n";
            aOutputFile << "  }\n";
        }
    }
}
Esempio n. 3
0
static void export_vrml_module( BOARD* aPcb, MODULE* aModule,
                                FILE* aOutputFile,
                                double aVRMLModelsToBiu,
                                bool aExport3DFiles, const wxString & a3D_Subdir,
                                double boardIU2WRML )
{
    // Reference and value
    export_vrml_text_module( aModule->m_Reference );
    export_vrml_text_module( aModule->m_Value );

    // Export module edges
    for( EDA_ITEM* item = aModule->m_Drawings;  item != NULL;  item = item->Next() )
    {
        switch( item->Type() )
        {
        case PCB_MODULE_TEXT_T:
            export_vrml_text_module( dynamic_cast<TEXTE_MODULE*>(item) );
            break;

        case PCB_MODULE_EDGE_T:
            export_vrml_edge_module( dynamic_cast<EDGE_MODULE*>(item) );
            break;

        default:
            break;
        }
    }

    // Export pads
    for( D_PAD* pad = aModule->m_Pads;  pad; 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 )    // Change illegal characters in short filename
        {
            ChangeIllegalCharacters( fname, true );
            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)
         */
        double rotx = - vrmlm->m_MatRotation.x;
        double roty = - vrmlm->m_MatRotation.y;
        double rotz = - vrmlm->m_MatRotation.z;

        if ( isFlipped )
        {
            rotx += 180.0;
            NEGATE(roty);
            NEGATE(rotz);
        }

        // Do some quaternion munching
        double q1[4], q2[4], rot[4];
        build_quat( 1, 0, 0, rotx / 180.0 * M_PI, q1 );
        build_quat( 0, 1, 0, roty / 180.0 * M_PI, q2 );
        compose_quat( q1, q2, q1 );
        build_quat( 0, 0, 1, rotz / 180.0 * M_PI, q2 );
        compose_quat( q1, q2, q1 );
        // Note here aModule->GetOrientation() is in 0.1 degrees,
        // so module rotation is aModule->GetOrientation() / 1800.0
        build_quat( 0, 0, 1, aModule->GetOrientation() / 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] );
        }

        // adjust 3D shape offset position
        int offsetx = vrmlm->m_MatPosition.x;
        int offsety = vrmlm->m_MatPosition.y;
        double offsetz = vrmlm->m_MatPosition.z;

        if ( isFlipped )
            NEGATE(offsetz);
        else    // In normal mode, Y axis is reversed in Pcbnew.
            NEGATE(offsety);

        RotatePoint(&offsetx, &offsety, aModule->GetOrientation());

        fprintf( aOutputFile, "  translation %g %g %g\n",
                 (double) (offsetx + aModule->m_Pos.x) * boardIU2WRML,
                 - (double)(offsety + aModule->m_Pos.y) * boardIU2WRML,    // Y axis is reversed in Pcbnew
                 offsetz + layer_z[aModule->GetLayer()] * boardIU2WRML);

        fprintf( aOutputFile, "  scale %g %g %g\n",
                 vrmlm->m_MatScale.x * aVRMLModelsToBiu,
                 vrmlm->m_MatScale.y * aVRMLModelsToBiu,
                 vrmlm->m_MatScale.z * aVRMLModelsToBiu );

        fprintf( aOutputFile,
//                 "  children [\n    Inline {\n      url \"file://%s\"\n    } ]\n",
                 "  children [\n    Inline {\n      url \"%s\"\n    } ]\n",
                 TO_UTF8( fname ) );
        fprintf( aOutputFile, "  }\n" );
    }
}