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 "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)
 

Typedefs

typedef std::map< Standard_Real, 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_Color *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_Color &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_Color *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 87 of file loadmodel.cpp.

◆ MASK_OCE_EXTRA

#define MASK_OCE_EXTRA   wxT( "PLUGIN_OCE_EXTRA" )

Definition at line 88 of file loadmodel.cpp.

◆ USER_ANGLE

#define USER_ANGLE   (0.52359878)

Definition at line 97 of file loadmodel.cpp.

◆ USER_PREC

#define USER_PREC   (0.14)

Definition at line 91 of file loadmodel.cpp.

Typedef Documentation

◆ COLORMAP

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

Definition at line 99 of file loadmodel.cpp.

◆ FACEMAP

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

Definition at line 100 of file loadmodel.cpp.

◆ NODEITEM

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

Definition at line 102 of file loadmodel.cpp.

◆ NODEMAP

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

Definition at line 101 of file loadmodel.cpp.

Enumeration Type Documentation

◆ FormatType

enum FormatType
Enumerator
FMT_NONE 
FMT_STEP 
FMT_STPZ 
FMT_IGES 

Definition at line 269 of file loadmodel.cpp.

270 {
271  FMT_NONE = 0,
272  FMT_STEP,
273  FMT_STPZ,
274  FMT_IGES
275 };

Function Documentation

◆ addItems()

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

Definition at line 501 of file loadmodel.cpp.

502 {
503  if( nullptr == lp )
504  return;
505 
506  std::vector< SGNODE* >::iterator sL = lp->begin();
507  std::vector< SGNODE* >::iterator eL = lp->end();
508  SGNODE* item;
509 
510  while( sL != eL )
511  {
512  item = *sL;
513 
514  if( nullptr == S3D::GetSGNodeParent( item ) )
515  S3D::AddSGNodeChild( parent, item );
516  else
517  S3D::AddSGNodeRef( parent, item );
518 
519  ++sL;
520  }
521 }
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:494
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:503
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:512

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

Referenced by processSolid().

◆ colorFloatToDecimal()

static int colorFloatToDecimal ( float  aVal)
static

Definition at line 390 of file loadmodel.cpp.

391 {
392  return aVal * 255;
393 }

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 469 of file loadmodel.cpp.

471 {
472  std::string indent( aDepth * 2, ' ' );
473  printLabel( aLabel, aShapeTool, aColorTool, indent.c_str() );
474  TDF_ChildIterator it;
475  for( it.Initialize( aLabel ); it.More(); it.Next() )
476  dumpLabels( it.Value(), aShapeTool, aColorTool, aDepth + 1 );
477 }
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:469
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:416

References printLabel().

Referenced by LoadModel().

◆ fileType()

FormatType fileType ( const char *  aFileName)

Definition at line 278 of file loadmodel.cpp.

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

References FMT_IGES, FMT_NONE, FMT_STEP, and FMT_STPZ.

Referenced by PANEL_FP_LIB_TABLE::browseLibrariesHandler(), GRAPHICS_IMPORT_MGR::GetPluginByExt(), SCH_EDIT_FRAME::importFile(), FOOTPRINT_EDIT_FRAME::ImportFootprint(), LoadModel(), PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE(), GERBVIEW_CONTROL::ReloadAllLayers(), and SYMBOL_EDIT_FRAME::saveLibrary().

◆ getColor()

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

Definition at line 480 of file loadmodel.cpp.

481 {
482  while( true )
483  {
484  if( data.m_color->GetColor( label, XCAFDoc_ColorGen, color ) )
485  return true;
486  else if( data.m_color->GetColor( label, XCAFDoc_ColorSurf, color ) )
487  return true;
488  else if( data.m_color->GetColor( label, XCAFDoc_ColorCurv, color ) )
489  return true;
490 
491  label = label.Father();
492 
493  if( label.IsNull() )
494  break;
495  };
496 
497  return false;
498 }
SGNODE * GetColor(Quantity_Color *colorObj)
Definition: loadmodel.cpp:233
int color
Definition: DXF_plotter.cpp:57

References color, and DATA::GetColor().

Referenced by processSolid().

◆ getLabelName()

static wxString getLabelName ( const TDF_Label &  aLabel)
static

Definition at line 349 of file loadmodel.cpp.

350 {
351  wxString txt;
352  Handle( TDataStd_Name ) name;
353  if( !aLabel.IsNull() && aLabel.FindAttribute( TDataStd_Name::GetID(), name ) )
354  {
355  TCollection_ExtendedString extstr = name->Get();
356  char* str = new char[extstr.LengthOfCString() + 1];
357  extstr.ToUTF8CString( str );
358 
359  txt = wxString::FromUTF8( str );
360  delete[] str;
361  txt = txt.Trim();
362  }
363  return txt;
364 }
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 372 of file loadmodel.cpp.

373 {
374  switch( aShape )
375  {
376  case TopAbs_COMPOUND: return "COMPOUND";
377  case TopAbs_COMPSOLID: return "COMPSOLID";
378  case TopAbs_SOLID: return "SOLID";
379  case TopAbs_SHELL: return "SHELL";
380  case TopAbs_FACE: return "FACE";
381  case TopAbs_WIRE: return "WIRE";
382  case TopAbs_EDGE: return "EDGE";
383  case TopAbs_VERTEX: return "VERTEX";
384  case TopAbs_SHAPE: return "SHAPE";
385  }
386 
387  return "UNKNOWN";
388 }

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 325 of file loadmodel.cpp.

326 {
327  std::ostringstream ostr;
328 
329  if( aLabel.IsNull() )
330  {
331  wxLogTrace( MASK_OCE, wxT( "Null label passed to getTag" ) );
332  return;
333  }
334 
335  TColStd_ListOfInteger tagList;
336  TDF_Tool::TagList( aLabel, tagList );
337 
338  for( TColStd_ListOfInteger::Iterator it( tagList ); it.More(); it.Next() )
339  {
340  ostr << it.Value();
341  ostr << ":";
342  }
343 
344  aTag = ostr.str();
345  aTag.pop_back(); // kill the last colon
346 }
#define MASK_OCE
Definition: loadmodel.cpp:87

References MASK_OCE.

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

◆ LoadModel()

SCENEGRAPH* LoadModel ( char const *  filename)

Definition at line 660 of file loadmodel.cpp.

661 {
662  DATA data;
663 
664  Handle(XCAFApp_Application) m_app = XCAFApp_Application::GetApplication();
665  m_app->NewDocument( "MDTV-XCAF", data.m_doc );
666  FormatType modelFmt = fileType( filename );
667 
668  switch( modelFmt )
669  {
670  case FMT_IGES:
671  data.renderBoth = true;
672 
673  if( !readIGES( data.m_doc, filename ) )
674  {
675  m_app->Close( data.m_doc );
676  return nullptr;
677  }
678 
679  break;
680 
681  case FMT_STEP:
682  if( !readSTEP( data.m_doc, filename ) )
683  {
684  m_app->Close( data.m_doc );
685  return nullptr;
686  }
687 
688  break;
689 
690  case FMT_STPZ:
691  if( !readSTEPZ( data.m_doc, filename ) )
692  {
693  m_app->Close( data.m_doc );
694  return nullptr;
695  }
696 
697  break;
698 
699 
700  default:
701  m_app->Close( data.m_doc );
702  return nullptr;
703  break;
704  }
705 
706  data.m_assy = XCAFDoc_DocumentTool::ShapeTool( data.m_doc->Main() );
707  data.m_color = XCAFDoc_DocumentTool::ColorTool( data.m_doc->Main() );
708 
709  // Check if the log mask is enabled otherwise the dump routine may be expensive before the wxLog call
710  if( wxLog::IsAllowedTraceMask( MASK_OCE ) )
711  {
712  dumpLabels( data.m_doc->Main(), data.m_assy, data.m_color );
713  }
714 
715  // retrieve all free shapes
716  TDF_LabelSequence frshapes;
717  data.m_assy->GetFreeShapes( frshapes );
718 
719  bool ret = false;
720 
721  // create the top level SG node
722  IFSG_TRANSFORM topNode( true );
723  data.scene = topNode.GetRawPtr();
724 
725  for( Standard_Integer i = 1; i <= frshapes.Length(); i++ )
726  {
727  const TDF_Label& label = frshapes.Value( i );
728 
729  if( data.m_color->IsVisible( label ) )
730  {
731  if( processLabel( label, data, data.scene, nullptr ) )
732  ret = true;
733  }
734  }
735 
736  if( !ret )
737  {
738  m_app->Close( data.m_doc );
739  return nullptr;
740  }
741 
742  SCENEGRAPH* scene = (SCENEGRAPH*)data.scene;
743 
744  // DEBUG: WRITE OUT VRML2 FILE TO CONFIRM STRUCTURE
745 #if ( defined( DEBUG_OCE ) && DEBUG_OCE > 3 )
746  if( data.scene )
747  {
748  wxFileName fn( wxString::FromUTF8Unchecked( filename ) );
749  wxString output;
750 
751  if( FMT_STEP == modelFmt )
752  output = wxT( "_step-" );
753  else
754  output = wxT( "_iges-" );
755 
756  output.append( fn.GetName() );
757  output.append( wxT( ".wrl" ) );
758  S3D::WriteVRML( output.ToUTF8(), true, data.scene, true, true );
759  }
760 #endif
761 
762  // set to NULL to prevent automatic destruction of the scene data
763  data.scene = nullptr;
764 
765  m_app->Close( data.m_doc );
766 
767  return scene;
768 }
bool readSTEPZ(Handle(TDocStd_Document)&m_doc, const char *aFileName)
Definition: loadmodel.cpp:590
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:469
bool readSTEP(Handle(TDocStd_Document)&m_doc, const char *fname)
Definition: loadmodel.cpp:553
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 fileType(const char *aFileName)
Definition: loadmodel.cpp:278
FormatType
Definition: loadmodel.cpp:269
bool readIGES(Handle(TDocStd_Document) &m_doc, const char *fname)
Definition: loadmodel.cpp:524
bool processLabel(const TDF_Label &aLabel, DATA &aData, SGNODE *aParent, std::vector< SGNODE * > *aItems)
Definition: loadmodel.cpp:904
#define MASK_OCE
Definition: loadmodel.cpp:87
SGNODE * scene
Definition: loadmodel.cpp:119
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:44
bool renderBoth
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 396 of file loadmodel.cpp.

397 {
398  Quantity_Color rgb = aColor.GetRGB();
399 
400  return aOStream << "rgba(" << colorFloatToDecimal( rgb.Red() ) << ","
401  << colorFloatToDecimal( rgb.Green() ) << ","
402  << colorFloatToDecimal( rgb.Blue() ) << ","
403  << colorFloatToDecimal( aColor.Alpha() )
404  << ")";
405 }
static int colorFloatToDecimal(float aVal)
Definition: loadmodel.cpp:390

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 416 of file loadmodel.cpp.

418 {
419  if( aLabel.IsNull() )
420  return;
421 
422  if( !aPreMsg )
423  aPreMsg = "Label: ";
424 
425  TCollection_AsciiString entry;
426  TDF_Tool::Entry( aLabel, entry );
427  std::ostringstream ss;
428  ss << aPreMsg << entry << ", " << getLabelName( aLabel )
429  << ( aShapeTool->IsShape( aLabel ) ? ", shape" : "" )
430  << ( aShapeTool->IsTopLevel( aLabel ) ? ", topLevel" : "" )
431  << ( aShapeTool->IsFree( aLabel ) ? ", free" : "" )
432  << ( aShapeTool->IsAssembly( aLabel ) ? ", assembly" : "" )
433  << ( aShapeTool->IsSimpleShape( aLabel ) ? ", simple" : "" )
434  << ( aShapeTool->IsCompound( aLabel ) ? ", compound" : "" )
435  << ( aShapeTool->IsReference( aLabel ) ? ", reference" : "" )
436  << ( aShapeTool->IsComponent( aLabel ) ? ", component" : "" )
437  << ( aShapeTool->IsSubShape( aLabel ) ? ", subshape" : "" );
438 
439  if( aShapeTool->IsSubShape( aLabel ) )
440  {
441  auto shape = aShapeTool->GetShape( aLabel );
442  if( !shape.IsNull() )
443  ss << ", " << getShapeName( shape.ShapeType() );
444  }
445 
446  if( aShapeTool->IsShape( aLabel ) )
447  {
448  Quantity_ColorRGBA c;
449  if( aColorTool->GetColor( aLabel, XCAFDoc_ColorGen, c ) )
450  ss << ", gc: " << c;
451  if( aColorTool->GetColor( aLabel, XCAFDoc_ColorSurf, c ) )
452  ss << ", sc: " << c;
453  if( aColorTool->GetColor( aLabel, XCAFDoc_ColorCurv, c ) )
454  ss << ", cc: " << c;
455  }
456 
457  wxLogTrace( MASK_OCE, ss.str().c_str() );
458 }
static wxString getLabelName(const TDF_Label &aLabel)
Definition: loadmodel.cpp:349
#define MASK_OCE
Definition: loadmodel.cpp:87
std::string getShapeName(TopAbs_ShapeEnum aShape)
Gets a string for a given TopAbs_ShapeEnum element.
Definition: loadmodel.cpp:372

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_Color *  color 
)

Definition at line 1040 of file loadmodel.cpp.

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

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 904 of file loadmodel.cpp.

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

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

Referenced by LoadModel().

◆ processShell()

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

Definition at line 771 of file loadmodel.cpp.

773 {
774  TopoDS_Iterator it;
775  bool ret = false;
776 
777  wxLogTrace( MASK_OCE, wxT( "Processing shell" ) );
778  for( it.Initialize( shape, false, false ); it.More(); it.Next() )
779  {
780  const TopoDS_Face& face = TopoDS::Face( it.Value() );
781 
782  if( processFace( face, data, parent, items, color ) )
783  ret = true;
784  }
785 
786  return ret;
787 }
int color
Definition: DXF_plotter.cpp:57
bool processFace(const TopoDS_Face &face, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_Color *color)
Definition: loadmodel.cpp:1040
#define MASK_OCE
Definition: loadmodel.cpp:87

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 790 of file loadmodel.cpp.

792 {
793  TDF_Label label;
794  data.hasSolid = true;
795  std::string partID;
796  Quantity_Color col;
797  Quantity_Color* lcolor = nullptr;
798 
799  wxLogTrace( MASK_OCE, wxT( "Processing solid" ) );
800 
801  // Search the whole model first to make sure something exists (may or may not have color)
802  if( !data.m_assy->Search( shape, label ) )
803  {
804  static int i = 0;
805  std::ostringstream ostr;
806  ostr << "KMISC_" << i++;
807  partID = ostr.str();
808  }
809  else
810  {
811  bool found_color = false;
812 
813  if( getColor( data, label, col ) )
814  {
815  found_color = true;
816  lcolor = &col;
817  }
818 
819  // If the top-level label doesn't have the color information, search components
820  if( !found_color )
821  {
822  if( data.m_assy->Search( shape, label, Standard_False, Standard_True, Standard_True ) &&
823  getColor( data, label, col ) )
824  {
825  found_color = true;
826  lcolor = &col;
827  }
828  }
829 
830  // If the components do not have color information, search all components without location
831  if( !found_color )
832  {
833  if( data.m_assy->Search( shape, label, Standard_False, Standard_False,
834  Standard_True ) &&
835  getColor( data, label, col ) )
836  {
837  found_color = true;
838  lcolor = &col;
839  }
840  }
841 
842  // Our last chance to find the color looks for color as a subshape of top-level simple
843  // shapes.
844  if( !found_color )
845  {
846  if( data.m_assy->Search( shape, label, Standard_False, Standard_False,
847  Standard_False ) &&
848  getColor( data, label, col ) )
849  {
850  found_color = true;
851  lcolor = &col;
852  }
853  }
854 
855  getTag( label, partID );
856  }
857 
858  TopoDS_Iterator it;
859  IFSG_TRANSFORM childNode( parent );
860  SGNODE* pptr = childNode.GetRawPtr();
861  bool ret = false;
862 
863 
864  std::vector< SGNODE* >* component = nullptr;
865 
866  if( !partID.empty() )
867  data.GetShape( partID, component );
868 
869  if( component )
870  {
871  addItems( pptr, component );
872 
873  if( nullptr != items )
874  items->push_back( pptr );
875  }
876 
877  // instantiate the solid
878  std::vector< SGNODE* > itemList;
879 
880  for( it.Initialize( shape, false, false ); it.More(); it.Next() )
881  {
882  const TopoDS_Shape& subShape = it.Value();
883 
884  if( subShape.ShapeType() == TopAbs_SHELL )
885  {
886  if( processShell( subShape, data, pptr, &itemList, lcolor ) )
887  ret = true;
888  }
889  else
890  {
891  wxLogTrace( MASK_OCE, wxT( "Unsupported subshape in solid" ) );
892  }
893  }
894 
895  if( !ret )
896  childNode.Destroy();
897  else if( nullptr != items )
898  items->push_back( pptr );
899 
900  return ret;
901 }
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:325
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
bool getColor(DATA &data, TDF_Label label, Quantity_Color &color)
Definition: loadmodel.cpp:480
bool hasSolid
Definition: loadmodel.cpp:126
void addItems(SGNODE *parent, std::vector< SGNODE * > *lp)
Definition: loadmodel.cpp:501
#define MASK_OCE
Definition: loadmodel.cpp:87
IFSG_TRANSFORM is the wrapper for the VRML compatible TRANSFORM block class SCENEGRAPH.
bool GetShape(const std::string &id, std::vector< SGNODE * > *&listPtr)
Definition: loadmodel.cpp:207
bool processShell(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_Color *color)
Definition: loadmodel.cpp:771

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 524 of file loadmodel.cpp.

525 {
526  IGESCAFControl_Reader reader;
527  IFSelect_ReturnStatus stat = reader.ReadFile( fname );
528  reader.PrintCheckLoad( Standard_False, IFSelect_ItemsByEntity );
529 
530  if( stat != IFSelect_RetDone )
531  return false;
532 
533  // Enable file-defined shape precision
534  if( !Interface_Static::SetIVal( "read.precision.mode", 0 ) )
535  return false;
536 
537  // set other translation options
538  reader.SetColorMode(true); // use model colors
539  reader.SetNameMode(false); // don't use IGES label names
540  reader.SetLayerMode(false); // ignore LAYER data
541 
542  if ( !reader.Transfer( m_doc ) )
543  return false;
544 
545  // are there any shapes to translate?
546  if( reader.NbShapes() < 1 )
547  return false;
548 
549  return true;
550 }

Referenced by LoadModel().

◆ readSTEP()

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

Definition at line 553 of file loadmodel.cpp.

554 {
555  wxLogTrace( MASK_OCE, wxT( "Reading step file %s" ), fname );
556 
557  STEPCAFControl_Reader reader;
558  IFSelect_ReturnStatus stat = reader.ReadFile( fname );
559 
560  if( stat != IFSelect_RetDone )
561  return false;
562 
563  // Enable user-defined shape precision
564  if( !Interface_Static::SetIVal( "read.precision.mode", 1 ) )
565  return false;
566 
567  // Set the shape conversion precision to USER_PREC (default 0.0001 has too many triangles)
568  if( !Interface_Static::SetRVal( "read.precision.val", USER_PREC ) )
569  return false;
570 
571  // set other translation options
572  reader.SetColorMode( true ); // use model colors
573  reader.SetNameMode( false ); // don't use label names
574  reader.SetLayerMode( false ); // ignore LAYER data
575 
576  if ( !reader.Transfer( m_doc ) )
577  {
578  m_doc->Close();
579  return false;
580  }
581 
582  // are there any shapes to translate?
583  if( reader.NbRootsForTransfer() < 1 )
584  return false;
585 
586  return true;
587 }
#define USER_PREC
Definition: loadmodel.cpp:91
#define MASK_OCE
Definition: loadmodel.cpp:87

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 590 of file loadmodel.cpp.

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

References readSTEP().

Referenced by LoadModel().