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   "PLUGIN_OCE"
 
#define MASK_OCE_EXTRA   "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   "PLUGIN_OCE"

Definition at line 87 of file loadmodel.cpp.

◆ MASK_OCE_EXTRA

#define MASK_OCE_EXTRA   "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 499 of file loadmodel.cpp.

500 {
501  if( nullptr == lp )
502  return;
503 
504  std::vector< SGNODE* >::iterator sL = lp->begin();
505  std::vector< SGNODE* >::iterator eL = lp->end();
506  SGNODE* item;
507 
508  while( sL != eL )
509  {
510  item = *sL;
511 
512  if( nullptr == S3D::GetSGNodeParent( item ) )
513  S3D::AddSGNodeChild( parent, item );
514  else
515  S3D::AddSGNodeRef( parent, item );
516 
517  ++sL;
518  }
519 }
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:492
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:501
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:510

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

Referenced by processSolid().

◆ colorFloatToDecimal()

static int colorFloatToDecimal ( float  aVal)
static

Definition at line 388 of file loadmodel.cpp.

389 {
390  return aVal * 255;
391 }

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

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

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

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

479 {
480  while( true )
481  {
482  if( data.m_color->GetColor( label, XCAFDoc_ColorGen, color ) )
483  return true;
484  else if( data.m_color->GetColor( label, XCAFDoc_ColorSurf, color ) )
485  return true;
486  else if( data.m_color->GetColor( label, XCAFDoc_ColorCurv, color ) )
487  return true;
488 
489  label = label.Father();
490 
491  if( label.IsNull() )
492  break;
493  };
494 
495  return false;
496 }
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 347 of file loadmodel.cpp.

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

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

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

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

References MASK_OCE.

Referenced by processFace(), and processSolid().

◆ LoadModel()

SCENEGRAPH* LoadModel ( char const *  filename)

Definition at line 658 of file loadmodel.cpp.

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

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

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

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

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

998 {
999  if( Standard_True == face.IsNull() )
1000  return false;
1001 
1002  bool reverse = ( face.Orientation() == TopAbs_REVERSED );
1003  SGNODE* ashape = nullptr;
1004  std::string partID;
1005  TDF_Label label;
1006 
1007  bool useBothSides = false;
1008 
1009  // for IGES renderBoth = TRUE; for STEP if a shell or face is not a descendant
1010  // of a SOLID then hasSolid = false and we must render both sides
1011  if( data.renderBoth || !data.hasSolid )
1012  useBothSides = true;
1013 
1014  if( data.m_assy->FindShape( face, label, Standard_False ) )
1015  getTag( label, partID );
1016 
1017  if( !partID.empty() )
1018  ashape = data.GetFace( partID );
1019 
1020  if( ashape )
1021  {
1022  if( nullptr == S3D::GetSGNodeParent( ashape ) )
1023  S3D::AddSGNodeChild( parent, ashape );
1024  else
1025  S3D::AddSGNodeRef( parent, ashape );
1026 
1027  if( nullptr != items )
1028  items->push_back( ashape );
1029 
1030  if( useBothSides )
1031  {
1032  std::string id2 = partID;
1033  id2.append( "b" );
1034  SGNODE* shapeB = data.GetFace( id2 );
1035 
1036  if( nullptr == S3D::GetSGNodeParent( shapeB ) )
1037  S3D::AddSGNodeChild( parent, shapeB );
1038  else
1039  S3D::AddSGNodeRef( parent, shapeB );
1040 
1041  if( nullptr != items )
1042  items->push_back( shapeB );
1043  }
1044 
1045  return true;
1046  }
1047 
1048  TopLoc_Location loc;
1049  Standard_Boolean isTessellate (Standard_False);
1050  Handle( Poly_Triangulation ) triangulation = BRep_Tool::Triangulation( face, loc );
1051 
1052  if( triangulation.IsNull() || triangulation->Deflection() > USER_PREC + Precision::Confusion() )
1053  isTessellate = Standard_True;
1054 
1055  if( isTessellate )
1056  {
1057  BRepMesh_IncrementalMesh IM(face, USER_PREC, Standard_False, USER_ANGLE );
1058  triangulation = BRep_Tool::Triangulation( face, loc );
1059  }
1060 
1061  if( triangulation.IsNull() == Standard_True )
1062  return false;
1063 
1064  Quantity_Color lcolor;
1065 
1066  // check for a face color; this has precedence over SOLID colors
1067  do
1068  {
1069  TDF_Label L;
1070 
1071  if( data.m_color->ShapeTool()->Search( face, L ) )
1072  {
1073  if( data.m_color->GetColor( L, XCAFDoc_ColorGen, lcolor )
1074  || data.m_color->GetColor( L, XCAFDoc_ColorCurv, lcolor )
1075  || data.m_color->GetColor( L, XCAFDoc_ColorSurf, lcolor ) )
1076  color = &lcolor;
1077  }
1078  } while( 0 );
1079 
1080  SGNODE* ocolor = data.GetColor( color );
1081 
1082  // create a SHAPE and attach the color and data,
1083  // then attach the shape to the parent and return TRUE
1084  IFSG_SHAPE vshape( true );
1085  IFSG_FACESET vface( vshape );
1086  IFSG_COORDS vcoords( vface );
1087  IFSG_COORDINDEX coordIdx( vface );
1088 
1089  if( nullptr == S3D::GetSGNodeParent( ocolor ) )
1090  S3D::AddSGNodeChild( vshape.GetRawPtr(), ocolor );
1091  else
1092  S3D::AddSGNodeRef( vshape.GetRawPtr(), ocolor );
1093 
1094  const TColgp_Array1OfPnt& arrPolyNodes = triangulation->Nodes();
1095  const Poly_Array1OfTriangle& arrTriangles = triangulation->Triangles();
1096 
1097  std::vector< SGPOINT > vertices;
1098  std::vector< int > indices;
1099  std::vector< int > indices2;
1100  gp_Trsf tx;
1101 
1102  for( int i = 1; i <= triangulation->NbNodes(); i++ )
1103  {
1104  gp_XYZ v( arrPolyNodes(i).Coord() );
1105  vertices.emplace_back( v.X(), v.Y(), v.Z() );
1106  }
1107 
1108  for( int i = 1; i <= triangulation->NbTriangles(); i++ )
1109  {
1110  int a, b, c;
1111  arrTriangles( i ).Get( a, b, c );
1112  a--;
1113 
1114  if( reverse )
1115  {
1116  int tmp = b - 1;
1117  b = c - 1;
1118  c = tmp;
1119  }
1120  else
1121  {
1122  b--;
1123  c--;
1124  }
1125 
1126  indices.push_back( a );
1127  indices.push_back( b );
1128  indices.push_back( c );
1129 
1130  if( useBothSides )
1131  {
1132  indices2.push_back( b );
1133  indices2.push_back( a );
1134  indices2.push_back( c );
1135  }
1136  }
1137 
1138  vcoords.SetCoordsList( vertices.size(), &vertices[0] );
1139  coordIdx.SetIndices( indices.size(), &indices[0] );
1140  vface.CalcNormals( nullptr );
1141  vshape.SetParent( parent );
1142 
1143  if( !partID.empty() )
1144  data.faces.insert( std::pair< std::string, SGNODE* >( partID, vshape.GetRawPtr() ) );
1145 
1146  // The outer surface of an IGES model is indeterminate so
1147  // we must render both sides of a surface.
1148  if( useBothSides )
1149  {
1150  std::string id2 = partID;
1151  id2.append( "b" );
1152  IFSG_SHAPE vshape2( true );
1153  IFSG_FACESET vface2( vshape2 );
1154  IFSG_COORDS vcoords2( vface2 );
1155  IFSG_COORDINDEX coordIdx2( vface2 );
1156  S3D::AddSGNodeRef( vshape2.GetRawPtr(), ocolor );
1157 
1158  vcoords2.SetCoordsList( vertices.size(), &vertices[0] );
1159  coordIdx2.SetIndices( indices2.size(), &indices2[0] );
1160  vface2.CalcNormals( nullptr );
1161  vshape2.SetParent( parent );
1162 
1163  if( !partID.empty() )
1164  data.faces.insert( std::pair< std::string, SGNODE* >( id2, vshape2.GetRawPtr() ) );
1165  }
1166 
1167  return true;
1168 }
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:323
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:492
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:501
#define USER_ANGLE
Definition: loadmodel.cpp:97
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:510
#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 887 of file loadmodel.cpp.

889 {
890  int labelTag = static_cast<int>( aLabel.Tag() );
891  wxLogTrace( MASK_OCE, "Processing label %d", labelTag );
892 
893  TopoDS_Shape originalShape;
894  TDF_Label shapeLabel = aLabel;
895 
896  if( !aData.m_assy->GetShape( shapeLabel, originalShape ) )
897  {
898  return false;
899  }
900 
901  TopoDS_Shape shape = originalShape;
902 
903  if( aData.m_assy->IsReference( aLabel ) )
904  {
905  wxLogTrace( MASK_OCE, "Label %d is ref, trying to pull up referred label", labelTag );
906 
907  if( !aData.m_assy->GetReferredShape( aLabel, shapeLabel ) )
908  {
909  return false;
910  }
911 
912  labelTag = static_cast<int>( shapeLabel.Tag() );
913  wxLogTrace( MASK_OCE, "Label %d referred", labelTag );
914 
915  if( !aData.m_assy->GetShape( shapeLabel, shape ) )
916  {
917  return false;
918  }
919  }
920 
921  // Now let's see if the original label has a location
922  // Labels can be used to place copies of other labels at a specific location
923  IFSG_TRANSFORM childNode( aParent );
924  SGNODE* pptr = childNode.GetRawPtr();
925  const TopLoc_Location& loc = originalShape.Location();
926 
927  if( !loc.IsIdentity() )
928  {
929  wxLogTrace( MASK_OCE, "Label %d has location", static_cast<int>( aLabel.Tag() ) );
930  gp_Trsf T = loc.Transformation();
931  gp_XYZ coord = T.TranslationPart();
932  childNode.SetTranslation( SGPOINT( coord.X(), coord.Y(), coord.Z() ) );
933  wxLogTrace( MASK_OCE, "Translation %f, %f, %f", coord.X(), coord.Y(), coord.Z() );
934  gp_XYZ axis;
935  Standard_Real angle;
936 
937  if( T.GetRotation( axis, angle ) )
938  {
939  childNode.SetRotation( SGVECTOR( axis.X(), axis.Y(), axis.Z() ), angle );
940  wxLogTrace( MASK_OCE, "Rotation %f, %f, %f, angle %f", axis.X(), axis.Y(), axis.Z(),
941  angle );
942  }
943  }
944 
945  TopAbs_ShapeEnum stype = shape.ShapeType();
946  bool ret = false;
947  aData.hasSolid = false;
948 
949  switch( stype )
950  {
951  case TopAbs_COMPOUND:
952  case TopAbs_COMPSOLID:
953  ret = true;
954  break;
955 
956  case TopAbs_SOLID:
957  if( processSolid( shape, aData, pptr, aItems ) )
958  ret = true;
959 
960  break;
961 
962  case TopAbs_SHELL:
963  if( processShell( shape, aData, pptr, aItems, nullptr ) )
964  ret = true;
965 
966  break;
967 
968  case TopAbs_FACE:
969  if( processFace( TopoDS::Face( shape ), aData, pptr, aItems, nullptr ) )
970  ret = true;
971 
972  break;
973 
974  default:
975  break;
976  }
977 
978  if( nullptr != aItems )
979  aItems->push_back( pptr );
980 
981  if( shapeLabel.HasChild() )
982  {
983  wxLogTrace( MASK_OCE, "Label %d has children", labelTag );
984  TDF_ChildIterator it;
985  for( it.Initialize( shapeLabel ); it.More(); it.Next() )
986  {
987  if( processLabel( it.Value(), aData, pptr, aItems ) )
988  ret = true;
989  }
990  }
991 
992  return ret;
993 }
bool processSolid(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items)
Definition: loadmodel.cpp:773
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:996
bool hasSolid
Definition: loadmodel.cpp:126
bool processLabel(const TDF_Label &aLabel, DATA &aData, SGNODE *aParent, std::vector< SGNODE * > *aItems)
Definition: loadmodel.cpp:887
#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:754

References PNS::angle(), IFSG_NODE::GetRawPtr(), DATA::GetShape(), 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 754 of file loadmodel.cpp.

756 {
757  TopoDS_Iterator it;
758  bool ret = false;
759 
760  wxLogTrace( MASK_OCE, "Processing shell" );
761  for( it.Initialize( shape, false, false ); it.More(); it.Next() )
762  {
763  const TopoDS_Face& face = TopoDS::Face( it.Value() );
764 
765  if( processFace( face, data, parent, items, color ) )
766  ret = true;
767  }
768 
769  return ret;
770 }
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:996
#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 773 of file loadmodel.cpp.

775 {
776  TDF_Label label;
777  data.hasSolid = true;
778  std::string partID;
779  Quantity_Color col;
780  Quantity_Color* lcolor = nullptr;
781 
782  wxLogTrace( MASK_OCE, "Processing solid" );
783 
784  // Search the whole model first to make sure something exists (may or may not have color)
785  if( !data.m_assy->Search( shape, label ) )
786  {
787  static int i = 0;
788  std::ostringstream ostr;
789  ostr << "KMISC_" << i++;
790  partID = ostr.str();
791  }
792  else
793  {
794  bool found_color = false;
795 
796  if( getColor( data, label, col ) )
797  {
798  found_color = true;
799  lcolor = &col;
800  }
801 
802  // If the top-level label doesn't have the color information, search components
803  if( !found_color )
804  {
805  if( data.m_assy->Search( shape, label, Standard_False, Standard_True, Standard_True ) &&
806  getColor( data, label, col ) )
807  {
808  found_color = true;
809  lcolor = &col;
810  }
811  }
812 
813  // If the components do not have color information, search all components without location
814  if( !found_color )
815  {
816  if( data.m_assy->Search( shape, label, Standard_False, Standard_False,
817  Standard_True ) &&
818  getColor( data, label, col ) )
819  {
820  found_color = true;
821  lcolor = &col;
822  }
823  }
824 
825  // Our last chance to find the color looks for color as a subshape of top-level simple
826  // shapes.
827  if( !found_color )
828  {
829  if( data.m_assy->Search( shape, label, Standard_False, Standard_False,
830  Standard_False ) &&
831  getColor( data, label, col ) )
832  {
833  found_color = true;
834  lcolor = &col;
835  }
836  }
837 
838  getTag( label, partID );
839  }
840 
841  TopoDS_Iterator it;
842  IFSG_TRANSFORM childNode( parent );
843  SGNODE* pptr = childNode.GetRawPtr();
844  bool ret = false;
845 
846 
847  std::vector< SGNODE* >* component = nullptr;
848 
849  if( !partID.empty() )
850  data.GetShape( partID, component );
851 
852  if( component )
853  {
854  addItems( pptr, component );
855 
856  if( nullptr != items )
857  items->push_back( pptr );
858  }
859 
860  // instantiate the solid
861  std::vector< SGNODE* > itemList;
862 
863  for( it.Initialize( shape, false, false ); it.More(); it.Next() )
864  {
865  const TopoDS_Shape& subShape = it.Value();
866 
867  if( subShape.ShapeType() == TopAbs_SHELL )
868  {
869  if( processShell( subShape, data, pptr, &itemList, lcolor ) )
870  ret = true;
871  }
872  else
873  {
874  wxLogTrace( MASK_OCE, "Unsupported subshape in solid" );
875  }
876  }
877 
878  if( !ret )
879  childNode.Destroy();
880  else if( nullptr != items )
881  items->push_back( pptr );
882 
883  return ret;
884 }
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:323
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:478
bool hasSolid
Definition: loadmodel.cpp:126
void addItems(SGNODE *parent, std::vector< SGNODE * > *lp)
Definition: loadmodel.cpp:499
#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:754

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

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

Referenced by LoadModel().

◆ readSTEP()

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

Definition at line 551 of file loadmodel.cpp.

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

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

References readSTEP().

Referenced by LoadModel().