diff --git a/3d-viewer/3d_cache/sg/ifsg_node.cpp b/3d-viewer/3d_cache/sg/ifsg_node.cpp index 746cebb337..f4113e66e5 100644 --- a/3d-viewer/3d_cache/sg/ifsg_node.cpp +++ b/3d-viewer/3d_cache/sg/ifsg_node.cpp @@ -48,6 +48,18 @@ IFSG_NODE::~IFSG_NODE() } +void IFSG_NODE::Destroy( void ) +{ + if( m_node ) + m_node->DisassociateWrapper( &m_node ); + + delete m_node; + m_node = NULL; + + return; +} + + SGNODE* IFSG_NODE::GetRawPtr( void ) { return m_node; diff --git a/3d-viewer/3d_cache/sg/scenegraph.cpp b/3d-viewer/3d_cache/sg/scenegraph.cpp index 9abea7042d..72e730d396 100644 --- a/3d-viewer/3d_cache/sg/scenegraph.cpp +++ b/3d-viewer/3d_cache/sg/scenegraph.cpp @@ -21,6 +21,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#define GLM_FORCE_RADIANS #include #include @@ -580,7 +581,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, // calculate the accumulated transform double rX, rY, rZ; rotation_axis.GetVector( rX, rY, rZ ); - glm::dmat4 rM = glm::rotate( glm::degrees( rotation_angle ), glm::dvec3( rX, rY, rZ ) ); + glm::dmat4 rM = glm::rotate( rotation_angle, glm::dvec3( rX, rY, rZ ) ); glm::dmat4 tM = glm::translate( glm::dvec3( translation.x, translation.y, translation.z ) ); glm::dmat4 tx0; diff --git a/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp b/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp index 94065c07b7..45f492321d 100644 --- a/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp +++ b/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp @@ -253,6 +253,7 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event ) // Render Model if( m_ogl_3dmodel ) { + /* ogl_set_arrow_material(); glColor3f( 0.9f, 0.0f, 0.0f ); @@ -269,6 +270,7 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event ) OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 1.0f ), 0.2f ); + */ glPushMatrix(); diff --git a/plugins/3d/idf/s3d_plugin_idf.cpp b/plugins/3d/idf/s3d_plugin_idf.cpp index 5ab6d8bbe6..ecb6a633de 100644 --- a/plugins/3d/idf/s3d_plugin_idf.cpp +++ b/plugins/3d/idf/s3d_plugin_idf.cpp @@ -21,6 +21,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +// Note: the board's bottom side is at Z = 0 + #include #include #include @@ -36,67 +38,105 @@ #define PLUGIN_3D_IDF_PATCH 0 #define PLUGIN_3D_IDF_REVNO 0 +// number of colors in the palette; cycles from 1..NCOLORS; +// number 0 is special (the PCB board color) +#define NCOLORS 6 + +// read and instantiate an IDF component outline static SCENEGRAPH* loadIDFOutline( const wxString& aFileName ); +// read and render an IDF board assembly static SCENEGRAPH* loadIDFBoard( const wxString& aFileName ); +// model a single extruded outline +// idxColor = color index to use +// aParent = parent SCENEGRAPH object, if any +static SCENEGRAPH* addOutline( IDF3_COMP_OUTLINE* outline, int idxColor, SGNODE* aParent ); +// model the board extrusion +static SCENEGRAPH* makeBoard( IDF3_BOARD& brd, SGNODE* aParent ); +// model all included components +static bool makeComponents( IDF3_BOARD& brd, SGNODE* aParent ); +// model any .OTHER_OUTLINE items +static bool makeOtherOutlines( IDF3_BOARD& brd, SGNODE* aParent ); +// convert the IDF outline to VRML intermediate data +static bool getOutlineModel( VRML_LAYER& model, const std::list< IDF_OUTLINE* >* items ); +// convert IDF segment data to VRML segment data +static bool addSegment( VRML_LAYER& model, IDF_SEGMENT* seg, int icont, int iseg ); +// convert the VRML intermediate data into SG* data +static SCENEGRAPH* vrmlToSG( VRML_LAYER& vpcb, int idxColor, SGNODE* aParent, double top, double bottom ); -static SGNODE* getColor( IFSG_SHAPE& shape ) +class LOCALESWITCH +{ +public: + LOCALESWITCH() + { + setlocale( LC_NUMERIC, "C" ); + } + + ~LOCALESWITCH() + { + setlocale( LC_NUMERIC, "" ); + } +}; + + +static SGNODE* getColor( IFSG_SHAPE& shape, int colorIdx ) { IFSG_APPEARANCE material( shape ); - static int idx = 0; + static int cidx = 1; + int idx; + + if( colorIdx == -1 ) + idx = cidx; + else + idx = colorIdx; switch( idx ) { case 0: + // green for PCB + material.SetSpecular( 0.13, 0.81, 0.22 ); + material.SetDiffuse( 0.13, 0.81, 0.22 ); + material.SetAmbient( 0.9 ); + material.SetShininess( 0.3 ); + + break; + + case 1: // magenta material.SetSpecular( 0.8, 0.0, 0.8 ); material.SetDiffuse( 0.6, 0.0, 0.6 ); material.SetAmbient( 0.9 ); material.SetShininess( 0.3 ); - ++idx; break; - case 1: + case 2: // red material.SetSpecular( 0.69, 0.14, 0.14 ); material.SetDiffuse( 0.69, 0.14, 0.14 ); material.SetAmbient( 0.9 ); material.SetShininess( 0.3 ); - ++idx; break; - case 2: + case 3: // orange material.SetSpecular( 1.0, 0.44, 0.0 ); material.SetDiffuse( 1.0, 0.44, 0.0 ); material.SetAmbient( 0.9 ); material.SetShininess( 0.3 ); - ++idx; break; - case 3: + case 4: // yellow material.SetSpecular( 0.93, 0.94, 0.16 ); material.SetDiffuse( 0.93, 0.94, 0.16 ); material.SetAmbient( 0.9 ); material.SetShininess( 0.3 ); - ++idx; - break; - - case 4: - // green - material.SetSpecular( 0.13, 0.81, 0.22 ); - material.SetDiffuse( 0.13, 0.81, 0.22 ); - material.SetAmbient( 0.9 ); - material.SetShininess( 0.3 ); - - ++idx; break; case 5: @@ -106,7 +146,6 @@ static SGNODE* getColor( IFSG_SHAPE& shape ) material.SetAmbient( 0.9 ); material.SetShininess( 0.3 ); - ++idx; break; default: @@ -116,10 +155,12 @@ static SGNODE* getColor( IFSG_SHAPE& shape ) material.SetAmbient( 0.9 ); material.SetShininess( 0.3 ); - idx = 0; break; } + if( ( colorIdx == -1 ) && ( ++cidx > NCOLORS ) ) + cidx = 1; + return material.GetRawPtr(); }; @@ -194,10 +235,6 @@ static struct FILE_DATA } file_data; -static bool getOutlineModel( VRML_LAYER& model, const std::list< IDF_OUTLINE* >* items ); -static bool addSegment( VRML_LAYER& model, IDF_SEGMENT* seg, int icont, int iseg ); - - int GetNExtensions( void ) { return NEXTS; @@ -245,17 +282,30 @@ SCENEGRAPH* Load( char const* aFileName ) wxString ext = fname.GetExt(); + SCENEGRAPH* data = NULL; + if( !ext.Cmp( wxT( "idf" ) ) || !ext.Cmp( wxT( "IDF" ) ) ) { - return loadIDFOutline( fname.GetFullPath() ); + data = loadIDFOutline( fname.GetFullPath() ); } if( !ext.Cmp( wxT( "emn" ) ) || !ext.Cmp( wxT( "EMN" ) ) ) { - return loadIDFBoard( fname.GetFullPath() ); + data = loadIDFBoard( fname.GetFullPath() ); } - return NULL; + // DEBUG: WRITE OUT IDF FILE TO CONFIRM NORMALS + #ifdef DEBUG + if( data ) + { + wxFileName fn( aFileName ); + wxString output = fn.GetName(); + output.append( wxT(".wrl") ); + S3D::WriteVRML( output, true, (SGNODE*)(data), true, true ); + } + #endif + + return data; } @@ -363,169 +413,178 @@ static bool addSegment( VRML_LAYER& model, IDF_SEGMENT* seg, int icont, int iseg } +static SCENEGRAPH* vrmlToSG( VRML_LAYER& vpcb, int idxColor, SGNODE* aParent, double top, double bottom ) +{ + vpcb.Tesselate( NULL ); + std::vector< double > vertices; + std::vector< int > idxPlane; + std::vector< int > idxSide; + + if( top < bottom ) + { + double tmp = top; + top = bottom; + bottom = tmp; + } + + if( !vpcb.Get3DTriangles( vertices, idxPlane, idxSide, top, bottom ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] no vertex data\n"; + #endif + return NULL; + } + + if( ( idxPlane.size() % 3 ) || ( idxSide.size() % 3 ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] index lists are not a multiple of 3 (not a triangle list)\n"; + #endif + return NULL; + } + + std::vector< SGPOINT > vlist; + size_t nvert = vertices.size() / 3; + size_t j = 0; + + for( size_t i = 0; i < nvert; ++i, j+= 3 ) + vlist.push_back( SGPOINT( vertices[j], vertices[j+1], vertices[j+2] ) ); + + // create the intermediate scenegraph + IFSG_TRANSFORM* tx0 = new IFSG_TRANSFORM( aParent ); // tx0 = Transform for this outline + IFSG_SHAPE* shape = new IFSG_SHAPE( *tx0 ); // shape will hold (a) all vertices and (b) a local list of normals + IFSG_FACESET* face = new IFSG_FACESET( *shape ); // this face shall represent the top and bottom planes + IFSG_COORDS* cp = new IFSG_COORDS( *face ); // coordinates for all faces + cp->SetCoordsList( nvert, &vlist[0] ); + IFSG_COORDINDEX* coordIdx = new IFSG_COORDINDEX( *face ); // coordinate indices for top and bottom planes only + coordIdx->SetIndices( idxPlane.size(), &idxPlane[0] ); + IFSG_NORMALS* norms = new IFSG_NORMALS( *face ); // normals for the top and bottom planes + + // number of TOP (and bottom) vertices + j = nvert / 2; + + // set the TOP normals + for( size_t i = 0; i < j; ++i ) + norms->AddNormal( 0.0, 0.0, 1.0 ); + + // set the BOTTOM normals + for( size_t i = 0; i < j; ++i ) + norms->AddNormal( 0.0, 0.0, -1.0 ); + + // assign a color from the palette + SGNODE* modelColor = getColor( *shape, idxColor ); + + // create a second shape describing the vertical walls of the IDF extrusion + // using per-vertex-per-face-normals + shape->NewNode( *tx0 ); + shape->AddRefNode( modelColor ); // set the color to be the same as the top/bottom + face->NewNode( *shape ); + cp->NewNode( *face ); // new vertex list + norms->NewNode( *face ); // new normals list + coordIdx->NewNode( *face ); // new index list + + // populate the new per-face vertex list and its indices and normals + std::vector< int >::iterator sI = idxSide.begin(); + std::vector< int >::iterator eI = idxSide.end(); + + size_t sidx = 0; // index to the new coord set + SGPOINT p1, p2, p3; + SGVECTOR vnorm; + + while( sI != eI ) + { + p1 = vlist[*sI]; + cp->AddCoord( p1 ); + ++sI; + + p2 = vlist[*sI]; + cp->AddCoord( p2 ); + ++sI; + + p3 = vlist[*sI]; + cp->AddCoord( p3 ); + ++sI; + + vnorm.SetVector( S3D::CalcTriNorm( p1, p2, p3 ) ); + norms->AddNormal( vnorm ); + norms->AddNormal( vnorm ); + norms->AddNormal( vnorm ); + + coordIdx->AddIndex( (int)sidx ); + ++sidx; + coordIdx->AddIndex( (int)sidx ); + ++sidx; + coordIdx->AddIndex( (int)sidx ); + ++sidx; + } + + SCENEGRAPH* data = (SCENEGRAPH*)tx0->GetRawPtr(); + + // delete the API wrappers + delete shape; + delete face; + delete coordIdx; + delete cp; + delete tx0; + + return data; +} + + +static SCENEGRAPH* addOutline( IDF3_COMP_OUTLINE* outline, int idxColor, SGNODE* aParent ) +{ + VRML_LAYER vpcb; + + if( !getOutlineModel( vpcb, outline->GetOutlines() ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] no valid outline data\n"; + #endif + return NULL; + } + + vpcb.EnsureWinding( 0, false ); + + double top = outline->GetThickness(); + double bot = 0.0; + + // note: some IDF entities permit negative heights + if( top < bot ) + { + bot = top; + top = 0.0; + } + + SCENEGRAPH* data = vrmlToSG( vpcb, idxColor, aParent, top, bot ); + + return data; +} + + static SCENEGRAPH* loadIDFOutline( const wxString& aFileName ) { - // load and render the file + LOCALESWITCH switcher; IDF3_BOARD brd( IDF3::CAD_ELEC ); - SCENEGRAPH* data = NULL; + IDF3_COMP_OUTLINE* outline = NULL; - try + outline = brd.GetComponentOutline( aFileName ); + + if( NULL == outline ) { - IDF3_COMP_OUTLINE* outline = - brd.GetComponentOutline( aFileName ); - - if( NULL == outline ) - { - #ifdef DEBUG - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] no outline for file '"; - std::cerr << aFileName << "'\n"; - #endif - return NULL; - } - - VRML_LAYER vpcb; - - if( !getOutlineModel( vpcb, outline->GetOutlines() ) ) - { - #ifdef DEBUG - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] no valid outline data in '"; - std::cerr << aFileName << "'\n"; - #endif - return NULL; - } - - vpcb.Tesselate( NULL ); - std::vector< double > vertices; - std::vector< int > idxPlane; - std::vector< int > idxSide; - double thick = outline->GetThickness(); - - if( !vpcb.Get3DTriangles( vertices, idxPlane, idxSide, thick, 0.0 ) ) - { - #ifdef DEBUG - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] no vertex data in '"; - std::cerr << aFileName << "'\n"; - #endif - return NULL; - } - - if( ( idxPlane.size() % 3 ) || ( idxSide.size() % 3 ) ) - { - #ifdef DEBUG - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [BUG] index lists are not a multiple of 3 (not a triangle list)\n"; - #endif - return NULL; - } - - std::vector< SGPOINT > vlist; - size_t nvert = vertices.size() / 3; - size_t j = 0; - - for( size_t i = 0; i < nvert; ++i, j+= 3 ) - vlist.push_back( SGPOINT( vertices[j], vertices[j+1], vertices[j+2] ) ); - - // create the intermediate scenegraph - IFSG_TRANSFORM* tx0 = new IFSG_TRANSFORM( true ); // tx0 = top level Transform - IFSG_SHAPE* shape = new IFSG_SHAPE( *tx0 ); // shape will hold (a) all vertices and (b) a local list of normals - IFSG_FACESET* face = new IFSG_FACESET( *shape ); // this face shall represent the top and bottom planes - IFSG_COORDS* cp = new IFSG_COORDS( *face ); // coordinates for all faces - cp->SetCoordsList( nvert, &vlist[0] ); - IFSG_COORDINDEX* coordIdx = new IFSG_COORDINDEX( *face ); // coordinate indices for top and bottom planes only - coordIdx->SetIndices( idxPlane.size(), &idxPlane[0] ); - IFSG_NORMALS* norms = new IFSG_NORMALS( *face ); // normals for the top and bottom planes - - // number of TOP (and bottom) vertices - j = nvert / 2; - - // set the TOP normals - for( size_t i = 0; i < j; ++i ) - norms->AddNormal( 0.0, 0.0, 1.0 ); - - // set the BOTTOM normals - for( size_t i = 0; i < j; ++i ) - norms->AddNormal( 0.0, 0.0, -1.0 ); - - // assign a color from the rotating palette - SGNODE* modelColor = getColor( *shape ); - - // create a second shape describing the vertical walls of the IDF extrusion - // using per-vertex-per-face-normals - shape->NewNode( *tx0 ); - shape->AddRefNode( modelColor ); // set the color to be the same as the top/bottom - face->NewNode( *shape ); - cp->NewNode( *face ); // new vertex list - norms->NewNode( *face ); // new normals list - coordIdx->NewNode( *face ); // new index list - - // populate the new per-face vertex list and its indices and normals - std::vector< int >::iterator sI = idxSide.begin(); - std::vector< int >::iterator eI = idxSide.end(); - - size_t sidx = 0; // index to the new coord set - SGPOINT p1, p2, p3; - SGVECTOR vnorm; - - while( sI != eI ) - { - p1 = vlist[*sI]; - cp->AddCoord( p1 ); - ++sI; - - p2 = vlist[*sI]; - cp->AddCoord( p2 ); - ++sI; - - p3 = vlist[*sI]; - cp->AddCoord( p3 ); - ++sI; - - vnorm.SetVector( S3D::CalcTriNorm( p1, p2, p3 ) ); - norms->AddNormal( vnorm ); - norms->AddNormal( vnorm ); - norms->AddNormal( vnorm ); - - coordIdx->AddIndex( (int)sidx ); - ++sidx; - coordIdx->AddIndex( (int)sidx ); - ++sidx; - coordIdx->AddIndex( (int)sidx ); - ++sidx; - } - - data = (SCENEGRAPH*)tx0->GetRawPtr(); - - // delete the API wrappers - delete shape; - delete face; - delete coordIdx; - delete cp; - delete tx0; - } - catch( const IDF_ERROR& e ) - { - std::cerr << e.what() << "\n"; + #ifdef DEBUG std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] cannot load the outline '" << aFileName.ToUTF8() << "'\n"; - return NULL; - } - catch( ... ) - { - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [INFO] cannot load the outline '" << aFileName.ToUTF8() << "'\n"; + std::cerr << " * [INFO] Failed to read IDF data:\n"; + std::cerr << brd.GetError() << "\n\n"; + std::cerr << " * [INFO] no outline for file '"; + std::cerr << aFileName << "'\n"; + #endif return NULL; } - // DEBUG: WRITE OUT IDF FILE TO CONFIRM NORMALS - #ifdef DEBUG - wxFileName fn( aFileName ); - wxString output = fn.GetName(); - output.append( wxT(".wrl") ); - S3D::WriteVRML( output, true, (SGNODE*)(data), true, true ); - #endif + SCENEGRAPH* data = addOutline( outline, -1, NULL ); return data; } @@ -533,6 +592,301 @@ static SCENEGRAPH* loadIDFOutline( const wxString& aFileName ) static SCENEGRAPH* loadIDFBoard( const wxString& aFileName ) { - // XXX - TO BE IMPLEMENTED - return NULL; + LOCALESWITCH switcher; + IDF3_BOARD brd( IDF3::CAD_ELEC ); + + // note: if the IDF model is defective no outline substitutes shall be made + if( !brd.ReadFile( aFileName, true ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] Failed to read IDF file:\n"; + std::cerr << brd.GetError() << "\n\n"; + std::cerr << " * [INFO] IDF file '" << aFileName.ToUTF8() << "'\n"; + + return NULL; + } + + IFSG_TRANSFORM tx0( true ); + SGNODE* topNode = tx0.GetRawPtr(); + + bool noBoard = false; + bool noComp = false; + bool noOther = false; + + if( NULL == makeBoard( brd, topNode ) ) + noBoard = true; + + if( !makeComponents( brd, topNode ) ) + noComp = true; + + if( !makeOtherOutlines( brd, topNode ) ) + noOther = true; + + if( noBoard && noComp && noOther ) + { + tx0.Destroy(); + return NULL; + } + + return (SCENEGRAPH*) topNode; +} + + +static SCENEGRAPH* makeBoard( IDF3_BOARD& brd, SGNODE* aParent ) +{ + if( NULL == aParent ) + return NULL; + + VRML_LAYER vpcb; + + // check if no board outline + if( brd.GetBoardOutlinesSize() < 1 ) + return NULL; + + + if( !getOutlineModel( vpcb, brd.GetBoardOutline()->GetOutlines() ) ) + return NULL; + + vpcb.EnsureWinding( 0, false ); + + int nvcont = vpcb.GetNContours() - 1; + + while( nvcont > 0 ) + vpcb.EnsureWinding( nvcont--, true ); + + // Add the drill holes + const std::list* drills = &brd.GetBoardDrills(); + + std::list::const_iterator sd = drills->begin(); + std::list::const_iterator ed = drills->end(); + + while( sd != ed ) + { + vpcb.AddCircle( (*sd)->GetDrillXPos(), (*sd)->GetDrillYPos(), + (*sd)->GetDrillDia() / 2.0, true ); + ++sd; + } + + std::map< std::string, IDF3_COMPONENT* >*const comp = brd.GetComponents(); + std::map< std::string, IDF3_COMPONENT* >::const_iterator sc = comp->begin(); + std::map< std::string, IDF3_COMPONENT* >::const_iterator ec = comp->end(); + + while( sc != ec ) + { + drills = sc->second->GetDrills(); + sd = drills->begin(); + ed = drills->end(); + + while( sd != ed ) + { + vpcb.AddCircle( (*sd)->GetDrillXPos(), (*sd)->GetDrillYPos(), + (*sd)->GetDrillDia() / 2.0, true ); + ++sd; + } + + ++sc; + } + + double top = brd.GetBoardThickness(); + + SCENEGRAPH* data = vrmlToSG( vpcb, 0, aParent, top, 0.0 ); + + return data; +} + + +static bool makeComponents( IDF3_BOARD& brd, SGNODE* aParent ) +{ + if( NULL == aParent ) + return false; + + int ncomponents = 0; + + double brdTop = brd.GetBoardThickness(); + + // Add the component outlines + const std::map< std::string, IDF3_COMPONENT* >*const comp = brd.GetComponents(); + std::map< std::string, IDF3_COMPONENT* >::const_iterator sc = comp->begin(); + std::map< std::string, IDF3_COMPONENT* >::const_iterator ec = comp->end(); + + std::list< IDF3_COMP_OUTLINE_DATA* >::const_iterator so; + std::list< IDF3_COMP_OUTLINE_DATA* >::const_iterator eo; + + double vX, vY, vA; + double tX, tY, tZ, tA; + bool bottom; + IDF3::IDF_LAYER lyr; + + std::map< std::string, SGNODE* > dataMap; // map data by UID + std::map< std::string, SGNODE* >::iterator dataItem; + IDF3_COMP_OUTLINE* pout; + + while( sc != ec ) + { + sc->second->GetPosition( vX, vY, vA, lyr ); + + if( lyr == IDF3::LYR_BOTTOM ) + bottom = true; + else + bottom = false; + + so = sc->second->GetOutlinesData()->begin(); + eo = sc->second->GetOutlinesData()->end(); + + while( so != eo ) + { + if( abs( (*so)->GetOutline()->GetThickness() ) < 0.001 ) + { + ++so; + continue; + } + + (*so)->GetOffsets( tX, tY, tZ, tA ); + tX += vX; + tY += vY; + tA += vA; + + pout = (IDF3_COMP_OUTLINE*)((*so)->GetOutline()); + + if( NULL == pout ) + { + ++so; + continue; + } + + dataItem = dataMap.find( pout->GetUID() ); + SCENEGRAPH* sg = NULL; + + if( dataItem == dataMap.end() ) + { + sg = addOutline( pout, -1, NULL ); + + if( NULL == sg ) + { + ++so; + continue; + } + + ++ncomponents; + dataMap.insert( std::pair< std::string, SGNODE* > + ( pout->GetUID(), (SGNODE*)sg ) ); + } + else + { + sg = (SCENEGRAPH*) dataItem->second; + } + + IFSG_TRANSFORM tx0( aParent ); + IFSG_TRANSFORM txN( false ); + txN.Attach( (SGNODE*)sg ); + + if( NULL == txN.GetParent() ) + tx0.AddChildNode( txN ); + else + tx0.AddRefNode( txN ); + + if( bottom ) + { + tx0.SetTranslation( SGPOINT( tX, tY, -tZ ) ); + // for an item on the back of the board we have a compounded rotation, + // first a flip on the Y axis as per the IDF spec and then a rotation + // of -tA degrees on the Z axis. The resultant rotation axis is an + // XY vector equivalent to (0,1) rotated by -(tA/2) degrees + // + double ang = -tA * M_PI / 360.0; + double sinA = sin( ang ); + double cosA = cos( ang ); + tx0.SetRotation( SGVECTOR( -sinA, cosA , 0 ), M_PI ); + } + else + { + tx0.SetTranslation( SGPOINT( tX, tY, tZ + brdTop ) ); + tx0.SetRotation( SGVECTOR( 0, 0, 1 ), tA * M_PI / 180.0 ); + } + + ++so; + } + + ++sc; + } + + if( 0 == ncomponents ) + return false; + + return true; +} + + +static bool makeOtherOutlines( IDF3_BOARD& brd, SGNODE* aParent ) +{ + if( NULL == aParent ) + return false; + + VRML_LAYER vpcb; + int ncomponents = 0; + + double brdTop = brd.GetBoardThickness(); + double top, bot; + + // Add the component outlines + const std::map< std::string, OTHER_OUTLINE* >*const comp = brd.GetOtherOutlines(); + std::map< std::string, OTHER_OUTLINE* >::const_iterator sc = comp->begin(); + std::map< std::string, OTHER_OUTLINE* >::const_iterator ec = comp->end(); + + int nvcont; + + OTHER_OUTLINE* pout; + + while( sc != ec ) + { + pout = sc->second; + + if( abs( pout->GetThickness() ) < 0.001 ) + { + ++sc; + continue; + } + + if( !getOutlineModel( vpcb, pout->GetOutlines() ) ) + { + vpcb.Clear(); + ++sc; + continue; + } + + vpcb.EnsureWinding( 0, false ); + + nvcont = vpcb.GetNContours() - 1; + + while( nvcont > 0 ) + vpcb.EnsureWinding( nvcont--, true ); + + if( pout->GetSide() == IDF3::LYR_BOTTOM ) + { + top = 0.0; + bot = -pout->GetThickness(); + } + else + { + bot = brdTop; + top = bot + pout->GetThickness(); + } + + if( NULL == vrmlToSG( vpcb, -1, aParent, top, bot ) ) + { + vpcb.Clear(); + ++sc; + continue; + } + + ++ncomponents; + + vpcb.Clear(); + ++sc; + } + + if( 0 == ncomponents ) + return false; + + return true; } diff --git a/plugins/3d/vrml/vrml.cpp b/plugins/3d/vrml/vrml.cpp index b75c20dcc7..b40b50e9ca 100644 --- a/plugins/3d/vrml/vrml.cpp +++ b/plugins/3d/vrml/vrml.cpp @@ -31,6 +31,7 @@ * #VRML V2.0 utf8 */ +#include #include #include #include diff --git a/utils/idftools/idf_parser.cpp b/utils/idftools/idf_parser.cpp index 69356b996b..c3c63b03f2 100644 --- a/utils/idftools/idf_parser.cpp +++ b/utils/idftools/idf_parser.cpp @@ -2737,9 +2737,10 @@ bool IDF3_BOARD::ReadFile( const wxString& aFullFileName, bool aNoSubstituteOutl else { ostringstream ostr; - ostr << "\n* invalid file name: '" << aFullFileName.ToUTF8() << "'"; + ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + ostr << "* [INFO] invalid file name: '" << aFullFileName.ToUTF8() << "'"; - throw( IDF_ERROR( __FILE__, __FUNCTION__, __LINE__, ostr.str() ) ); + errormsg = ostr.str(); }