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 = 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 processSolidOrShell (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_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 processSolidOrShell().

◆ 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 processSolidOrShell().

◆ 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 processSolidOrShell().

◆ 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
Definition: loadmodel.cpp:284
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:927
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
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 1072 of file loadmodel.cpp.

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

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

◆ processSolidOrShell()

bool processSolidOrShell ( 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 resulting object
891 std::vector<SGNODE*> itemList;
892
893 TopAbs_ShapeEnum stype = shape.ShapeType();
894 if( stype == TopAbs_SHELL )
895 {
896 if( processShell( shape, data, pptr, &itemList, lcolor ) )
897 ret = true;
898 }
899 else
900 {
901
902 for( it.Initialize( shape, false, false ); it.More(); it.Next() )
903 {
904 const TopoDS_Shape& subShape = it.Value();
905
906 if( subShape.ShapeType() == TopAbs_SHELL )
907 {
908 if( processShell( subShape, data, pptr, &itemList, lcolor ) )
909 ret = true;
910 }
911 else
912 {
913 wxLogTrace( MASK_OCE, wxT( "Unsupported subshape in solid" ) );
914 }
915 }
916 }
917
918 if( !ret )
919 childNode.Destroy();
920 else if( nullptr != items )
921 items->push_back( pptr );
922
923 return ret;
924}
bool processShell(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
Definition: loadmodel.cpp:784
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().