KiCad PCB EDA Suite
loadmodel.cpp File Reference
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <wx/filename.h>
#include <wx/log.h>
#include <wx/stdpaths.h>
#include <wx/string.h>
#include <wx/utils.h>
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
#include <decompress.hpp>
#include <TDocStd_Document.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <Quantity_Color.hxx>
#include <XCAFApp_Application.hxx>
#include <AIS_Shape.hxx>
#include <IGESControl_Reader.hxx>
#include <IGESCAFControl_Reader.hxx>
#include <Interface_Static.hxx>
#include <STEPControl_Reader.hxx>
#include <STEPCAFControl_Reader.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <BRep_Tool.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Compound.hxx>
#include <TopExp_Explorer.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <Precision.hxx>
#include <TDF_LabelSequence.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_Tool.hxx>
#include <TDataStd_Name.hxx>
#include <Standard_Version.hxx>
#include "plugins/3dapi/ifsg_all.h"

Go to the source code of this file.

Classes

struct  DATA
 

Macros

#define MASK_OCE   wxT( "PLUGIN_OCE" )
 
#define MASK_OCE_EXTRA   wxT( "PLUGIN_OCE_EXTRA" )
 
#define USER_PREC   (0.14)
 
#define USER_ANGLE   (0.52359878)
 
#define OCC_COLOR_SPACE   Quantity_TOC_RGB
 

Typedefs

typedef std::map< std::size_t, SGNODE * > COLORMAP
 
typedef std::map< std::string, SGNODE * > FACEMAP
 
typedef std::map< std::string, std::vector< SGNODE * > > NODEMAP
 
typedef std::pair< std::string, std::vector< SGNODE * > > NODEITEM
 

Enumerations

enum  FormatType {
  FMT_NONE , FMT_STEP , FMT_STEPZ , FMT_IGES ,
  FMT_EMN , FMT_IDF , FMT_WRL , FMT_WRZ ,
  FMT_NONE = 0 , FMT_STEP , FMT_STPZ , FMT_IGES
}
 

Functions

bool processLabel (const TDF_Label &aLabel, DATA &aData, SGNODE *aParent, std::vector< SGNODE * > *aItems)
 
bool processFace (const TopoDS_Face &face, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
 
FormatType fileType (const char *aFileName)
 
void getTag (const TDF_Label &aLabel, std::string &aTag)
 Gets the absolute tag string for a given label in the form of ##:##:##:##. More...
 
static wxString getLabelName (const TDF_Label &aLabel)
 
std::string getShapeName (TopAbs_ShapeEnum aShape)
 Gets a string for a given TopAbs_ShapeEnum element. More...
 
static int colorFloatToDecimal (float aVal)
 
static std::ostream & operator<< (std::ostream &aOStream, const Quantity_ColorRGBA &aColor)
 
static void printLabel (TDF_Label aLabel, Handle(XCAFDoc_ShapeTool) aShapeTool, Handle(XCAFDoc_ColorTool) aColorTool, const char *aPreMsg=nullptr)
 Gets a string for a given TopAbs_ShapeEnum element. More...
 
static void dumpLabels (TDF_Label aLabel, Handle(XCAFDoc_ShapeTool) aShapeTool, Handle(XCAFDoc_ColorTool) aColorTool, int aDepth=0)
 Dumps a label and the entire tree underneath it. More...
 
bool getColor (DATA &data, TDF_Label label, Quantity_ColorRGBA &color)
 
void addItems (SGNODE *parent, std::vector< SGNODE * > *lp)
 
bool readIGES (Handle(TDocStd_Document) &m_doc, const char *fname)
 
bool readSTEP (Handle(TDocStd_Document)&m_doc, const char *fname)
 
bool readSTEPZ (Handle(TDocStd_Document)&m_doc, const char *aFileName)
 
SCENEGRAPHLoadModel (char const *filename)
 
bool processShell (const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
 
bool processSolid (const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items)
 

Macro Definition Documentation

◆ MASK_OCE

#define MASK_OCE   wxT( "PLUGIN_OCE" )

Definition at line 88 of file loadmodel.cpp.

◆ MASK_OCE_EXTRA

#define MASK_OCE_EXTRA   wxT( "PLUGIN_OCE_EXTRA" )

Definition at line 89 of file loadmodel.cpp.

◆ OCC_COLOR_SPACE

#define OCC_COLOR_SPACE   Quantity_TOC_RGB

Definition at line 117 of file loadmodel.cpp.

◆ USER_ANGLE

#define USER_ANGLE   (0.52359878)

Definition at line 98 of file loadmodel.cpp.

◆ USER_PREC

#define USER_PREC   (0.14)

Definition at line 92 of file loadmodel.cpp.

Typedef Documentation

◆ COLORMAP

typedef std::map<std::size_t, SGNODE*> COLORMAP

Definition at line 100 of file loadmodel.cpp.

◆ FACEMAP

typedef std::map<std::string, SGNODE*> FACEMAP

Definition at line 101 of file loadmodel.cpp.

◆ NODEITEM

typedef std::pair<std::string, std::vector<SGNODE*> > NODEITEM

Definition at line 103 of file loadmodel.cpp.

◆ NODEMAP

typedef std::map<std::string, std::vector<SGNODE*> > NODEMAP

Definition at line 102 of file loadmodel.cpp.

Enumeration Type Documentation

◆ FormatType

enum FormatType
Enumerator
FMT_NONE 
FMT_STEP 
FMT_STEPZ 
FMT_IGES 
FMT_EMN 
FMT_IDF 
FMT_WRL 
FMT_WRZ 
FMT_NONE 
FMT_STEP 
FMT_STPZ 
FMT_IGES 

Definition at line 283 of file loadmodel.cpp.

284{
285 FMT_NONE = 0,
286 FMT_STEP,
287 FMT_STPZ,
289};
@ FMT_STEP
Definition: loadmodel.cpp:286
@ FMT_IGES
Definition: loadmodel.cpp:288
@ FMT_NONE
Definition: loadmodel.cpp:285
@ FMT_STPZ
Definition: loadmodel.cpp:287

Function Documentation

◆ addItems()

void addItems ( SGNODE parent,
std::vector< SGNODE * > *  lp 
)

Definition at line 515 of file loadmodel.cpp.

516{
517 if( nullptr == lp )
518 return;
519
520 std::vector< SGNODE* >::iterator sL = lp->begin();
521 std::vector< SGNODE* >::iterator eL = lp->end();
522 SGNODE* item;
523
524 while( sL != eL )
525 {
526 item = *sL;
527
528 if( nullptr == S3D::GetSGNodeParent( item ) )
529 S3D::AddSGNodeChild( parent, item );
530 else
531 S3D::AddSGNodeRef( parent, item );
532
533 ++sL;
534 }
535}
The base class of all Scene Graph nodes.
Definition: sg_node.h:75
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:494
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:512
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:503

References S3D::AddSGNodeChild(), S3D::AddSGNodeRef(), and S3D::GetSGNodeParent().

Referenced by processSolid().

◆ colorFloatToDecimal()

static int colorFloatToDecimal ( float  aVal)
static

Definition at line 404 of file loadmodel.cpp.

405{
406 return aVal * 255;
407}

Referenced by operator<<().

◆ dumpLabels()

static void dumpLabels ( TDF_Label  aLabel,
Handle(XCAFDoc_ShapeTool)  aShapeTool,
Handle(XCAFDoc_ColorTool)  aColorTool,
int  aDepth = 0 
)
static

Dumps a label and the entire tree underneath it.

Parameters
aLabelLabel to convert
aShapeToolHandle to shape tool being used
aColorToolHandle to color tool being used
aDepthIndentation level to offset labels (used recursively by dumpLabels)

Definition at line 483 of file loadmodel.cpp.

485{
486 std::string indent( aDepth * 2, ' ' );
487 printLabel( aLabel, aShapeTool, aColorTool, indent.c_str() );
488 TDF_ChildIterator it;
489 for( it.Initialize( aLabel ); it.More(); it.Next() )
490 dumpLabels( it.Value(), aShapeTool, aColorTool, aDepth + 1 );
491}
static void printLabel(TDF_Label aLabel, Handle(XCAFDoc_ShapeTool) aShapeTool, Handle(XCAFDoc_ColorTool) aColorTool, const char *aPreMsg=nullptr)
Gets a string for a given TopAbs_ShapeEnum element.
Definition: loadmodel.cpp:430
static void dumpLabels(TDF_Label aLabel, Handle(XCAFDoc_ShapeTool) aShapeTool, Handle(XCAFDoc_ColorTool) aColorTool, int aDepth=0)
Dumps a label and the entire tree underneath it.
Definition: loadmodel.cpp:483

References dumpLabels(), and printLabel().

Referenced by dumpLabels(), and LoadModel().

◆ fileType()

FormatType fileType ( const char *  aFileName)

Definition at line 292 of file loadmodel.cpp.

293{
294 wxFileName fname( wxString::FromUTF8Unchecked( aFileName ) );
295 wxFFileInputStream ifile( fname.GetFullPath() );
296
297 if( !ifile.IsOk() )
298 return FMT_NONE;
299
300 if( fname.GetExt().MakeUpper().EndsWith( wxT( "STPZ" ) )
301 || fname.GetExt().MakeUpper().EndsWith( wxT( "GZ" ) ) )
302 {
303 return FMT_STPZ;
304 }
305
306 char iline[82];
307 memset( iline, 0, 82 );
308 ifile.Read( iline, 82 );
309 iline[81] = 0; // ensure NULL termination when string is too long
310
311 // check for STEP in Part 21 format
312 // (this can give false positives since Part 21 is not exclusively STEP)
313 if( !strncmp( iline, "ISO-10303-21;", 13 ) )
314 return FMT_STEP;
315
316 std::string fstr = iline;
317
318 // check for STEP in XML format
319 // (this can give both false positive and false negatives)
320 if( fstr.find( "urn:oid:1.0.10303." ) != std::string::npos )
321 return FMT_STEP;
322
323 // Note: this is a very simple test which can yield false positives; the only
324 // sure method for determining if a file *not* an IGES model is to attempt
325 // to load it.
326 if( iline[72] == 'S' && ( iline[80] == 0 || iline[80] == 13 || iline[80] == 10 ) )
327 return FMT_IGES;
328
329 return FMT_NONE;
330}

References FMT_IGES, FMT_NONE, FMT_STEP, and FMT_STPZ.

Referenced by LoadModel().

◆ getColor()

bool getColor ( DATA data,
TDF_Label  label,
Quantity_ColorRGBA &  color 
)

Definition at line 494 of file loadmodel.cpp.

495{
496 while( true )
497 {
498 if( data.m_color->GetColor( label, XCAFDoc_ColorGen, color ) )
499 return true;
500 else if( data.m_color->GetColor( label, XCAFDoc_ColorSurf, color ) )
501 return true;
502 else if( data.m_color->GetColor( label, XCAFDoc_ColorCurv, color ) )
503 return true;
504
505 label = label.Father();
506
507 if( label.IsNull() )
508 break;
509 };
510
511 return false;
512}
int color
Definition: DXF_plotter.cpp:57
SGNODE * GetColor(Quantity_ColorRGBA *colorObj)
Definition: loadmodel.cpp:239

References color, and DATA::GetColor().

Referenced by processSolid().

◆ getLabelName()

static wxString getLabelName ( const TDF_Label &  aLabel)
static

Definition at line 363 of file loadmodel.cpp.

364{
365 wxString txt;
366 Handle( TDataStd_Name ) name;
367 if( !aLabel.IsNull() && aLabel.FindAttribute( TDataStd_Name::GetID(), name ) )
368 {
369 TCollection_ExtendedString extstr = name->Get();
370 char* str = new char[extstr.LengthOfCString() + 1];
371 extstr.ToUTF8CString( str );
372
373 txt = wxString::FromUTF8( str );
374 delete[] str;
375 txt = txt.Trim();
376 }
377 return txt;
378}
const char * name
Definition: DXF_plotter.cpp:56

References name.

Referenced by printLabel().

◆ getShapeName()

std::string getShapeName ( TopAbs_ShapeEnum  aShape)

Gets a string for a given TopAbs_ShapeEnum element.

Parameters
aShapeenum value to convert

Definition at line 386 of file loadmodel.cpp.

387{
388 switch( aShape )
389 {
390 case TopAbs_COMPOUND: return "COMPOUND";
391 case TopAbs_COMPSOLID: return "COMPSOLID";
392 case TopAbs_SOLID: return "SOLID";
393 case TopAbs_SHELL: return "SHELL";
394 case TopAbs_FACE: return "FACE";
395 case TopAbs_WIRE: return "WIRE";
396 case TopAbs_EDGE: return "EDGE";
397 case TopAbs_VERTEX: return "VERTEX";
398 case TopAbs_SHAPE: return "SHAPE";
399 }
400
401 return "UNKNOWN";
402}

Referenced by printLabel().

◆ getTag()

void getTag ( const TDF_Label &  aLabel,
std::string &  aTag 
)

Gets the absolute tag string for a given label in the form of ##:##:##:##.

Parameters
aLabelis the label to get the string for
aTagis the resulting tag string based by reference

Definition at line 339 of file loadmodel.cpp.

340{
341 std::ostringstream ostr;
342
343 if( aLabel.IsNull() )
344 {
345 wxLogTrace( MASK_OCE, wxT( "Null label passed to getTag" ) );
346 return;
347 }
348
349 TColStd_ListOfInteger tagList;
350 TDF_Tool::TagList( aLabel, tagList );
351
352 for( TColStd_ListOfInteger::Iterator it( tagList ); it.More(); it.Next() )
353 {
354 ostr << it.Value();
355 ostr << ":";
356 }
357
358 aTag = ostr.str();
359 aTag.pop_back(); // kill the last colon
360}
#define MASK_OCE
Definition: loadmodel.cpp:88

References MASK_OCE.

Referenced by processFace(), processLabel(), and processSolid().

◆ LoadModel()

SCENEGRAPH * LoadModel ( char const *  filename)

Definition at line 674 of file loadmodel.cpp.

675{
676 DATA data;
677
678 Handle(XCAFApp_Application) m_app = XCAFApp_Application::GetApplication();
679 m_app->NewDocument( "MDTV-XCAF", data.m_doc );
680 FormatType modelFmt = fileType( filename );
681
682 switch( modelFmt )
683 {
684 case FMT_IGES:
685 data.renderBoth = true;
686
687 if( !readIGES( data.m_doc, filename ) )
688 {
689 m_app->Close( data.m_doc );
690 return nullptr;
691 }
692
693 break;
694
695 case FMT_STEP:
696 if( !readSTEP( data.m_doc, filename ) )
697 {
698 m_app->Close( data.m_doc );
699 return nullptr;
700 }
701
702 break;
703
704 case FMT_STPZ:
705 if( !readSTEPZ( data.m_doc, filename ) )
706 {
707 m_app->Close( data.m_doc );
708 return nullptr;
709 }
710
711 break;
712
713
714 default:
715 m_app->Close( data.m_doc );
716 return nullptr;
717 break;
718 }
719
720 data.m_assy = XCAFDoc_DocumentTool::ShapeTool( data.m_doc->Main() );
721 data.m_color = XCAFDoc_DocumentTool::ColorTool( data.m_doc->Main() );
722
723 // Check if the log mask is enabled otherwise the dump routine may be expensive before the wxLog call
724 if( wxLog::IsAllowedTraceMask( MASK_OCE ) )
725 {
726 dumpLabels( data.m_doc->Main(), data.m_assy, data.m_color );
727 }
728
729 // retrieve all free shapes
730 TDF_LabelSequence frshapes;
731 data.m_assy->GetFreeShapes( frshapes );
732
733 bool ret = false;
734
735 // create the top level SG node
736 IFSG_TRANSFORM topNode( true );
737 data.scene = topNode.GetRawPtr();
738
739 for( Standard_Integer i = 1; i <= frshapes.Length(); i++ )
740 {
741 const TDF_Label& label = frshapes.Value( i );
742
743 if( data.m_color->IsVisible( label ) )
744 {
745 if( processLabel( label, data, data.scene, nullptr ) )
746 ret = true;
747 }
748 }
749
750 if( !ret )
751 {
752 m_app->Close( data.m_doc );
753 return nullptr;
754 }
755
756 SCENEGRAPH* scene = (SCENEGRAPH*)data.scene;
757
758 // DEBUG: WRITE OUT VRML2 FILE TO CONFIRM STRUCTURE
759#if ( defined( DEBUG_OCE ) && DEBUG_OCE > 3 )
760 if( data.scene )
761 {
762 wxFileName fn( wxString::FromUTF8Unchecked( filename ) );
763 wxString output;
764
765 if( FMT_STEP == modelFmt )
766 output = wxT( "_step-" );
767 else
768 output = wxT( "_iges-" );
769
770 output.append( fn.GetName() );
771 output.append( wxT( ".wrl" ) );
772 S3D::WriteVRML( output.ToUTF8(), true, data.scene, true, true );
773 }
774#endif
775
776 // set to NULL to prevent automatic destruction of the scene data
777 data.scene = nullptr;
778
779 m_app->Close( data.m_doc );
780 return scene;
781}
IFSG_TRANSFORM is the wrapper for the VRML compatible TRANSFORM block class SCENEGRAPH.
Define the basic data set required to represent a 3D model.
Definition: scenegraph.h:45
FormatType fileType(const char *aFileName)
Definition: loadmodel.cpp:292
bool readSTEP(Handle(TDocStd_Document)&m_doc, const char *fname)
Definition: loadmodel.cpp:567
bool processLabel(const TDF_Label &aLabel, DATA &aData, SGNODE *aParent, std::vector< SGNODE * > *aItems)
Definition: loadmodel.cpp:917
bool readSTEPZ(Handle(TDocStd_Document)&m_doc, const char *aFileName)
Definition: loadmodel.cpp:604
bool readIGES(Handle(TDocStd_Document) &m_doc, const char *fname)
Definition: loadmodel.cpp:538
SGLIB_API bool WriteVRML(const char *filename, bool overwrite, SGNODE *aTopNode, bool reuse, bool renameNodes)
Function WriteVRML writes out the given node and its subnodes to a VRML2 file.
Definition: ifsg_api.cpp:77
FormatType
bool renderBoth
Definition: loadmodel.cpp:131
SGNODE * scene
Definition: loadmodel.cpp:125

References dumpLabels(), fileType(), FMT_IGES, FMT_STEP, FMT_STPZ, IFSG_NODE::GetRawPtr(), MASK_OCE, processLabel(), readIGES(), readSTEP(), readSTEPZ(), DATA::renderBoth, DATA::scene, and S3D::WriteVRML().

Referenced by Load().

◆ operator<<()

static std::ostream & operator<< ( std::ostream &  aOStream,
const Quantity_ColorRGBA &  aColor 
)
inlinestatic

Definition at line 410 of file loadmodel.cpp.

411{
412 Quantity_Color rgb = aColor.GetRGB();
413
414 return aOStream << "rgba(" << colorFloatToDecimal( rgb.Red() ) << ","
415 << colorFloatToDecimal( rgb.Green() ) << ","
416 << colorFloatToDecimal( rgb.Blue() ) << ","
417 << colorFloatToDecimal( aColor.Alpha() )
418 << ")";
419}
static int colorFloatToDecimal(float aVal)
Definition: loadmodel.cpp:404

References colorFloatToDecimal().

◆ printLabel()

static void printLabel ( TDF_Label  aLabel,
Handle(XCAFDoc_ShapeTool)  aShapeTool,
Handle(XCAFDoc_ColorTool)  aColorTool,
const char *  aPreMsg = nullptr 
)
static

Gets a string for a given TopAbs_ShapeEnum element.

Parameters
aLabelLabel to convert
aShapeToolHandle to shape tool being used
aColorToolHandle to color tool being used
aPregMsgAny prefixed message to insert (used for indentation in dump)

Definition at line 430 of file loadmodel.cpp.

432{
433 if( aLabel.IsNull() )
434 return;
435
436 if( !aPreMsg )
437 aPreMsg = "Label: ";
438
439 TCollection_AsciiString entry;
440 TDF_Tool::Entry( aLabel, entry );
441 std::ostringstream ss;
442 ss << aPreMsg << entry << ", " << getLabelName( aLabel )
443 << ( aShapeTool->IsShape( aLabel ) ? ", shape" : "" )
444 << ( aShapeTool->IsTopLevel( aLabel ) ? ", topLevel" : "" )
445 << ( aShapeTool->IsFree( aLabel ) ? ", free" : "" )
446 << ( aShapeTool->IsAssembly( aLabel ) ? ", assembly" : "" )
447 << ( aShapeTool->IsSimpleShape( aLabel ) ? ", simple" : "" )
448 << ( aShapeTool->IsCompound( aLabel ) ? ", compound" : "" )
449 << ( aShapeTool->IsReference( aLabel ) ? ", reference" : "" )
450 << ( aShapeTool->IsComponent( aLabel ) ? ", component" : "" )
451 << ( aShapeTool->IsSubShape( aLabel ) ? ", subshape" : "" );
452
453 if( aShapeTool->IsSubShape( aLabel ) )
454 {
455 auto shape = aShapeTool->GetShape( aLabel );
456 if( !shape.IsNull() )
457 ss << ", " << getShapeName( shape.ShapeType() );
458 }
459
460 if( aShapeTool->IsShape( aLabel ) )
461 {
462 Quantity_ColorRGBA c;
463 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorGen, c ) )
464 ss << ", gc: " << c;
465 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorSurf, c ) )
466 ss << ", sc: " << c;
467 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorCurv, c ) )
468 ss << ", cc: " << c;
469 }
470
471 wxLogTrace( MASK_OCE, ss.str().c_str() );
472}
std::string getShapeName(TopAbs_ShapeEnum aShape)
Gets a string for a given TopAbs_ShapeEnum element.
Definition: loadmodel.cpp:386
static wxString getLabelName(const TDF_Label &aLabel)
Definition: loadmodel.cpp:363

References getLabelName(), getShapeName(), and MASK_OCE.

Referenced by dumpLabels().

◆ processFace()

bool processFace ( const TopoDS_Face &  face,
DATA data,
SGNODE parent,
std::vector< SGNODE * > *  items,
Quantity_ColorRGBA *  color 
)

Definition at line 1053 of file loadmodel.cpp.

1055{
1056 if( Standard_True == face.IsNull() )
1057 return false;
1058
1059 bool reverse = ( face.Orientation() == TopAbs_REVERSED );
1060 SGNODE* ashape = nullptr;
1061 std::string partID;
1062 TDF_Label label;
1063
1064 bool useBothSides = false;
1065
1066 // for IGES renderBoth = TRUE; for STEP if a shell or face is not a descendant
1067 // of a SOLID then hasSolid = false and we must render both sides
1068 if( data.renderBoth || !data.hasSolid )
1069 useBothSides = true;
1070
1071 if( data.m_assy->FindShape( face, label, Standard_False ) )
1072 getTag( label, partID );
1073
1074 if( !partID.empty() )
1075 ashape = data.GetFace( partID );
1076
1077 if( ashape )
1078 {
1079 if( nullptr == S3D::GetSGNodeParent( ashape ) )
1080 S3D::AddSGNodeChild( parent, ashape );
1081 else
1082 S3D::AddSGNodeRef( parent, ashape );
1083
1084 if( nullptr != items )
1085 items->push_back( ashape );
1086
1087 if( useBothSides )
1088 {
1089 std::string id2 = partID;
1090 id2.append( "b" );
1091 SGNODE* shapeB = data.GetFace( id2 );
1092
1093 if( nullptr == S3D::GetSGNodeParent( shapeB ) )
1094 S3D::AddSGNodeChild( parent, shapeB );
1095 else
1096 S3D::AddSGNodeRef( parent, shapeB );
1097
1098 if( nullptr != items )
1099 items->push_back( shapeB );
1100 }
1101
1102 return true;
1103 }
1104
1105 TopLoc_Location loc;
1106 Standard_Boolean isTessellate (Standard_False);
1107 Handle( Poly_Triangulation ) triangulation = BRep_Tool::Triangulation( face, loc );
1108
1109 if( triangulation.IsNull() || triangulation->Deflection() > USER_PREC + Precision::Confusion() )
1110 isTessellate = Standard_True;
1111
1112 if( isTessellate )
1113 {
1114 BRepMesh_IncrementalMesh IM(face, USER_PREC, Standard_False, USER_ANGLE );
1115 triangulation = BRep_Tool::Triangulation( face, loc );
1116 }
1117
1118 if( triangulation.IsNull() == Standard_True )
1119 return false;
1120
1121 Quantity_ColorRGBA lcolor;
1122
1123 // check for a face color; this has precedence over SOLID colors
1124 do
1125 {
1126 TDF_Label L;
1127
1128 if( data.m_color->ShapeTool()->Search( face, L ) )
1129 {
1130 if( data.m_color->GetColor( L, XCAFDoc_ColorGen, lcolor )
1131 || data.m_color->GetColor( L, XCAFDoc_ColorCurv, lcolor )
1132 || data.m_color->GetColor( L, XCAFDoc_ColorSurf, lcolor ) )
1133 color = &lcolor;
1134 }
1135 } while( 0 );
1136
1137 SGNODE* ocolor = data.GetColor( color );
1138
1139 // create a SHAPE and attach the color and data,
1140 // then attach the shape to the parent and return TRUE
1141 IFSG_SHAPE vshape( true );
1142 IFSG_FACESET vface( vshape );
1143 IFSG_COORDS vcoords( vface );
1144 IFSG_COORDINDEX coordIdx( vface );
1145
1146 if( nullptr == S3D::GetSGNodeParent( ocolor ) )
1147 S3D::AddSGNodeChild( vshape.GetRawPtr(), ocolor );
1148 else
1149 S3D::AddSGNodeRef( vshape.GetRawPtr(), ocolor );
1150
1151 std::vector< SGPOINT > vertices;
1152 std::vector< int > indices;
1153 std::vector< int > indices2;
1154 gp_Trsf tx;
1155
1156 for( int i = 1; i <= triangulation->NbNodes(); i++ )
1157 {
1158 gp_XYZ v( triangulation->Node(i).Coord() );
1159 vertices.emplace_back( v.X(), v.Y(), v.Z() );
1160 }
1161
1162 for( int i = 1; i <= triangulation->NbTriangles(); i++ )
1163 {
1164 int a, b, c;
1165 triangulation->Triangle(i).Get(a, b, c);
1166 a--;
1167
1168 if( reverse )
1169 {
1170 int tmp = b - 1;
1171 b = c - 1;
1172 c = tmp;
1173 }
1174 else
1175 {
1176 b--;
1177 c--;
1178 }
1179
1180 indices.push_back( a );
1181 indices.push_back( b );
1182 indices.push_back( c );
1183
1184 if( useBothSides )
1185 {
1186 indices2.push_back( b );
1187 indices2.push_back( a );
1188 indices2.push_back( c );
1189 }
1190 }
1191
1192 vcoords.SetCoordsList( vertices.size(), &vertices[0] );
1193 coordIdx.SetIndices( indices.size(), &indices[0] );
1194 vface.CalcNormals( nullptr );
1195 vshape.SetParent( parent );
1196
1197 if( !partID.empty() )
1198 data.faces.emplace( partID, vshape.GetRawPtr() );
1199
1200 // The outer surface of an IGES model is indeterminate so
1201 // we must render both sides of a surface.
1202 if( useBothSides )
1203 {
1204 std::string id2 = partID;
1205 id2.append( "b" );
1206 IFSG_SHAPE vshape2( true );
1207 IFSG_FACESET vface2( vshape2 );
1208 IFSG_COORDS vcoords2( vface2 );
1209 IFSG_COORDINDEX coordIdx2( vface2 );
1210 S3D::AddSGNodeRef( vshape2.GetRawPtr(), ocolor );
1211
1212 vcoords2.SetCoordsList( vertices.size(), &vertices[0] );
1213 coordIdx2.SetIndices( indices2.size(), &indices2[0] );
1214 vface2.CalcNormals( nullptr );
1215 vshape2.SetParent( parent );
1216
1217 if( !partID.empty() )
1218 data.faces.emplace( id2, vshape2.GetRawPtr() );
1219 }
1220
1221 return true;
1222}
IFSG_COORDINDEX is the wrapper for SGCOORDINDEX.
IFSG_COORDS is the wrapper for SGCOORDS.
Definition: ifsg_coords.h:41
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:41
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Definition: ifsg_shape.h:41
#define USER_ANGLE
Definition: loadmodel.cpp:98
void getTag(const TDF_Label &aLabel, std::string &aTag)
Gets the absolute tag string for a given label in the form of ##:##:##:##.
Definition: loadmodel.cpp:339
#define USER_PREC
Definition: loadmodel.cpp:92
SGNODE * GetFace(const std::string &id)
Definition: loadmodel.cpp:227
bool hasSolid
Definition: loadmodel.cpp:132
FACEMAP faces
Definition: loadmodel.cpp:130

References S3D::AddSGNodeChild(), S3D::AddSGNodeRef(), IFSG_FACESET::CalcNormals(), color, DATA::faces, DATA::GetColor(), DATA::GetFace(), IFSG_NODE::GetRawPtr(), S3D::GetSGNodeParent(), getTag(), DATA::hasSolid, DATA::renderBoth, IFSG_COORDS::SetCoordsList(), IFSG_INDEX::SetIndices(), IFSG_NODE::SetParent(), USER_ANGLE, and USER_PREC.

Referenced by processLabel(), and processShell().

◆ processLabel()

bool processLabel ( const TDF_Label &  aLabel,
DATA aData,
SGNODE aParent,
std::vector< SGNODE * > *  aItems 
)

Definition at line 917 of file loadmodel.cpp.

919{
920 std::string labelTag;
921
922 if( wxLog::IsAllowedTraceMask( MASK_OCE ) )
923 {
924 // can be expensive, guard it if we aren't logging
925 getTag( aLabel, labelTag );
926 }
927
928 wxLogTrace( MASK_OCE, wxT( "Processing label %s" ), labelTag );
929
930 TopoDS_Shape originalShape;
931 TDF_Label shapeLabel = aLabel;
932
933 if( !aData.m_assy->GetShape( shapeLabel, originalShape ) )
934 {
935 return false;
936 }
937
938 TopoDS_Shape shape = originalShape;
939
940 if( aData.m_assy->IsReference( aLabel ) )
941 {
942 wxLogTrace( MASK_OCE, wxT( "Label %s is ref, trying to pull up referred label" ),
943 labelTag );
944
945 if( !aData.m_assy->GetReferredShape( aLabel, shapeLabel ) )
946 {
947 return false;
948 }
949
950 labelTag = static_cast<int>( shapeLabel.Tag() );
951 // wxLogTrace( MASK_OCE, wxT( "Label %s referred" ), labelTag );
952
953 if( !aData.m_assy->GetShape( shapeLabel, shape ) )
954 {
955 return false;
956 }
957 }
958
959 // Now let's see if the original label has a location
960 // Labels can be used to place copies of other labels at a specific location
961 IFSG_TRANSFORM childNode( aParent );
962 SGNODE* pptr = childNode.GetRawPtr();
963 const TopLoc_Location& loc = originalShape.Location();
964
965 if( !loc.IsIdentity() )
966 {
967 wxLogTrace( MASK_OCE, wxT( "Label %d has location" ), static_cast<int>( aLabel.Tag() ) );
968 gp_Trsf T = loc.Transformation();
969 gp_XYZ coord = T.TranslationPart();
970 childNode.SetTranslation( SGPOINT( coord.X(), coord.Y(), coord.Z() ) );
971 wxLogTrace( MASK_OCE, wxT( "Translation %f, %f, %f" ), coord.X(), coord.Y(), coord.Z() );
972 gp_XYZ axis;
973 Standard_Real angle;
974
975 if( T.GetRotation( axis, angle ) )
976 {
977 childNode.SetRotation( SGVECTOR( axis.X(), axis.Y(), axis.Z() ), angle );
978 wxLogTrace( MASK_OCE, wxT( "Rotation %f, %f, %f, angle %f" ),
979 axis.X(), axis.Y(), axis.Z(), angle );
980 }
981 }
982
983 TopAbs_ShapeEnum stype = shape.ShapeType();
984 bool ret = false;
985 aData.hasSolid = false;
986
987 switch( stype )
988 {
989 case TopAbs_COMPOUND:
990 {
991 // assemblies will report a shape type of compound which isn't what we are after
992 // we will still process the children of assemblies but they should just be label references to the actual shapes
993 if( !aData.m_assy->IsAssembly( shapeLabel ) )
994 {
995 TopExp_Explorer xp;
996
997 for( xp.Init( shape, TopAbs_SOLID ); xp.More(); xp.Next() )
998 {
999 processSolid( xp.Current(), aData, pptr, aItems );
1000 ret = true;
1001 }
1002
1003 for( xp.Init( shape, TopAbs_SHELL, TopAbs_SOLID ); xp.More(); xp.Next() )
1004 {
1005 processShell( xp.Current(), aData, pptr, aItems, nullptr );
1006 ret = true;
1007 }
1008 }
1009 }
1010 break;
1011
1012 case TopAbs_SOLID:
1013 if( processSolid( shape, aData, pptr, aItems ) )
1014 ret = true;
1015
1016 break;
1017
1018 case TopAbs_SHELL:
1019 if( processShell( shape, aData, pptr, aItems, nullptr ) )
1020 ret = true;
1021
1022 break;
1023
1024 case TopAbs_FACE:
1025 if( processFace( TopoDS::Face( shape ), aData, pptr, aItems, nullptr ) )
1026 ret = true;
1027
1028 break;
1029
1030 default:
1031 break;
1032 }
1033
1034 if( nullptr != aItems )
1035 aItems->push_back( pptr );
1036
1037 if( !aData.m_assy->IsSimpleShape( shapeLabel ) && shapeLabel.HasChild() )
1038 {
1039 wxLogTrace( MASK_OCE, wxT( "Label %s has children" ), labelTag );
1040 TDF_ChildIterator it;
1041
1042 for( it.Initialize( shapeLabel ); it.More(); it.Next() )
1043 {
1044 if( processLabel( it.Value(), aData, pptr, aItems ) )
1045 ret = true;
1046 }
1047 }
1048
1049 return ret;
1050}
bool processShell(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
Definition: loadmodel.cpp:784
bool processFace(const TopoDS_Face &face, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
Definition: loadmodel.cpp:1053
bool processSolid(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items)
Definition: loadmodel.cpp:803
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
bool GetShape(const std::string &id, std::vector< SGNODE * > *&listPtr)
Definition: loadmodel.cpp:213

References PNS::angle(), IFSG_NODE::GetRawPtr(), DATA::GetShape(), getTag(), DATA::hasSolid, MASK_OCE, processFace(), processLabel(), processShell(), processSolid(), IFSG_TRANSFORM::SetRotation(), and IFSG_TRANSFORM::SetTranslation().

Referenced by LoadModel(), and processLabel().

◆ processShell()

bool processShell ( const TopoDS_Shape &  shape,
DATA data,
SGNODE parent,
std::vector< SGNODE * > *  items,
Quantity_ColorRGBA *  color 
)

Definition at line 784 of file loadmodel.cpp.

786{
787 TopoDS_Iterator it;
788 bool ret = false;
789
790 wxLogTrace( MASK_OCE, wxT( "Processing shell" ) );
791 for( it.Initialize( shape, false, false ); it.More(); it.Next() )
792 {
793 const TopoDS_Face& face = TopoDS::Face( it.Value() );
794
795 if( processFace( face, data, parent, items, color ) )
796 ret = true;
797 }
798
799 return ret;
800}

References color, MASK_OCE, and processFace().

Referenced by processLabel(), and processSolid().

◆ processSolid()

bool processSolid ( const TopoDS_Shape &  shape,
DATA data,
SGNODE parent,
std::vector< SGNODE * > *  items 
)

Definition at line 803 of file loadmodel.cpp.

805{
806 TDF_Label label;
807 data.hasSolid = true;
808 std::string partID;
809 Quantity_ColorRGBA col;
810 Quantity_ColorRGBA* lcolor = nullptr;
811
812 wxLogTrace( MASK_OCE, wxT( "Processing solid" ) );
813
814 // Search the whole model first to make sure something exists (may or may not have color)
815 if( !data.m_assy->Search( shape, label ) )
816 {
817 static int i = 0;
818 std::ostringstream ostr;
819 ostr << "KMISC_" << i++;
820 partID = ostr.str();
821 }
822 else
823 {
824 bool found_color = false;
825
826 if( getColor( data, label, col ) )
827 {
828 found_color = true;
829 lcolor = &col;
830 }
831
832 // If the top-level label doesn't have the color information, search components
833 if( !found_color )
834 {
835 if( data.m_assy->Search( shape, label, Standard_False, Standard_True, Standard_True ) &&
836 getColor( data, label, col ) )
837 {
838 found_color = true;
839 lcolor = &col;
840 }
841 }
842
843 // If the components do not have color information, search all components without location
844 if( !found_color )
845 {
846 if( data.m_assy->Search( shape, label, Standard_False, Standard_False,
847 Standard_True ) &&
848 getColor( data, label, col ) )
849 {
850 found_color = true;
851 lcolor = &col;
852 }
853 }
854
855 // Our last chance to find the color looks for color as a subshape of top-level simple
856 // shapes.
857 if( !found_color )
858 {
859 if( data.m_assy->Search( shape, label, Standard_False, Standard_False,
860 Standard_False ) &&
861 getColor( data, label, col ) )
862 {
863 found_color = true;
864 lcolor = &col;
865 }
866 }
867
868 getTag( label, partID );
869 }
870
871 TopoDS_Iterator it;
872 IFSG_TRANSFORM childNode( parent );
873 SGNODE* pptr = childNode.GetRawPtr();
874 bool ret = false;
875
876
877 std::vector< SGNODE* >* component = nullptr;
878
879 if( !partID.empty() )
880 data.GetShape( partID, component );
881
882 if( component )
883 {
884 addItems( pptr, component );
885
886 if( nullptr != items )
887 items->push_back( pptr );
888 }
889
890 // instantiate the solid
891 std::vector< SGNODE* > itemList;
892
893 for( it.Initialize( shape, false, false ); it.More(); it.Next() )
894 {
895 const TopoDS_Shape& subShape = it.Value();
896
897 if( subShape.ShapeType() == TopAbs_SHELL )
898 {
899 if( processShell( subShape, data, pptr, &itemList, lcolor ) )
900 ret = true;
901 }
902 else
903 {
904 wxLogTrace( MASK_OCE, wxT( "Unsupported subshape in solid" ) );
905 }
906 }
907
908 if( !ret )
909 childNode.Destroy();
910 else if( nullptr != items )
911 items->push_back( pptr );
912
913 return ret;
914}
bool getColor(DATA &data, TDF_Label label, Quantity_ColorRGBA &color)
Definition: loadmodel.cpp:494
void addItems(SGNODE *parent, std::vector< SGNODE * > *lp)
Definition: loadmodel.cpp:515

References addItems(), IFSG_NODE::Destroy(), getColor(), IFSG_NODE::GetRawPtr(), DATA::GetShape(), getTag(), DATA::hasSolid, MASK_OCE, and processShell().

Referenced by processLabel().

◆ readIGES()

bool readIGES ( Handle(TDocStd_Document) &  m_doc,
const char *  fname 
)

Definition at line 538 of file loadmodel.cpp.

539{
540 IGESCAFControl_Reader reader;
541 IFSelect_ReturnStatus stat = reader.ReadFile( fname );
542 reader.PrintCheckLoad( Standard_False, IFSelect_ItemsByEntity );
543
544 if( stat != IFSelect_RetDone )
545 return false;
546
547 // Enable file-defined shape precision
548 if( !Interface_Static::SetIVal( "read.precision.mode", 0 ) )
549 return false;
550
551 // set other translation options
552 reader.SetColorMode(true); // use model colors
553 reader.SetNameMode(false); // don't use IGES label names
554 reader.SetLayerMode(false); // ignore LAYER data
555
556 if ( !reader.Transfer( m_doc ) )
557 return false;
558
559 // are there any shapes to translate?
560 if( reader.NbShapes() < 1 )
561 return false;
562
563 return true;
564}

Referenced by LoadModel().

◆ readSTEP()

bool readSTEP ( Handle(TDocStd_Document)&  m_doc,
const char *  fname 
)

Definition at line 567 of file loadmodel.cpp.

568{
569 wxLogTrace( MASK_OCE, wxT( "Reading step file %s" ), fname );
570
571 STEPCAFControl_Reader reader;
572 IFSelect_ReturnStatus stat = reader.ReadFile( fname );
573
574 if( stat != IFSelect_RetDone )
575 return false;
576
577 // Enable user-defined shape precision
578 if( !Interface_Static::SetIVal( "read.precision.mode", 1 ) )
579 return false;
580
581 // Set the shape conversion precision to USER_PREC (default 0.0001 has too many triangles)
582 if( !Interface_Static::SetRVal( "read.precision.val", USER_PREC ) )
583 return false;
584
585 // set other translation options
586 reader.SetColorMode( true ); // use model colors
587 reader.SetNameMode( false ); // don't use label names
588 reader.SetLayerMode( false ); // ignore LAYER data
589
590 if ( !reader.Transfer( m_doc ) )
591 {
592 m_doc->Close();
593 return false;
594 }
595
596 // are there any shapes to translate?
597 if( reader.NbRootsForTransfer() < 1 )
598 return false;
599
600 return true;
601}

References MASK_OCE, and USER_PREC.

Referenced by LoadModel(), and readSTEPZ().

◆ readSTEPZ()

bool readSTEPZ ( Handle(TDocStd_Document)&  m_doc,
const char *  aFileName 
)

Definition at line 604 of file loadmodel.cpp.

605{
606 wxFileName fname( wxString::FromUTF8Unchecked( aFileName ) );
607 wxFFileInputStream ifile( fname.GetFullPath() );
608
609 wxFileName outFile( fname );
610
611 outFile.SetPath( wxStandardPaths::Get().GetTempDir() );
612 outFile.SetExt( wxT( "STEP" ) );
613
614 wxFileOffset size = ifile.GetLength();
615 wxBusyCursor busycursor;
616
617 if( size == wxInvalidOffset )
618 return false;
619
620 {
621 bool success = false;
622 wxFFileOutputStream ofile( outFile.GetFullPath() );
623
624 if( !ofile.IsOk() )
625 return false;
626
627 char *buffer = new char[size];
628
629 ifile.Read( buffer, size);
630 std::string expanded;
631
632 try
633 {
634 expanded = gzip::decompress( buffer, size );
635 success = true;
636 }
637 catch(...)
638 {}
639
640 if( expanded.empty() )
641 {
642 ifile.Reset();
643 ifile.SeekI( 0 );
644 wxZipInputStream izipfile( ifile );
645 std::unique_ptr<wxZipEntry> zip_file( izipfile.GetNextEntry() );
646
647 if( zip_file && !zip_file->IsDir() && izipfile.CanRead() )
648 {
649 izipfile.Read( ofile );
650 success = true;
651 }
652 }
653 else
654 {
655 ofile.Write( expanded.data(), expanded.size() );
656 }
657
658 delete[] buffer;
659 ofile.Close();
660
661 if( !success )
662 return false;
663 }
664
665 bool retval = readSTEP( m_doc, outFile.GetFullPath().mb_str() );
666
667 // Cleanup our temporary file
668 wxRemoveFile( outFile.GetFullPath() );
669
670 return retval;
671}

References readSTEP().

Referenced by LoadModel().