35#include <wx/filename.h>
37#include <wx/stdpaths.h>
40#include <wx/wfstream.h>
41#include <wx/zipstrm.h>
43#include <decompress.hpp>
45#include <TDocStd_Document.hxx>
47#include <TopoDS_Shape.hxx>
48#include <Quantity_Color.hxx>
49#include <XCAFApp_Application.hxx>
51#include <AIS_Shape.hxx>
53#include <IGESControl_Reader.hxx>
54#include <IGESCAFControl_Reader.hxx>
55#include <Interface_Static.hxx>
57#include <STEPControl_Reader.hxx>
58#include <STEPCAFControl_Reader.hxx>
60#include <XCAFDoc_DocumentTool.hxx>
61#include <XCAFDoc_ColorTool.hxx>
62#include <XCAFDoc_ShapeTool.hxx>
64#include <BRep_Tool.hxx>
65#include <BRepMesh_IncrementalMesh.hxx>
68#include <TopoDS_Shape.hxx>
69#include <TopoDS_Face.hxx>
70#include <TopoDS_Compound.hxx>
71#include <TopExp_Explorer.hxx>
73#include <Quantity_Color.hxx>
74#include <Poly_Triangulation.hxx>
75#include <Poly_PolygonOnTriangulation.hxx>
76#include <Precision.hxx>
78#include <TDF_LabelSequence.hxx>
79#include <TDF_ChildIterator.hxx>
80#include <TDF_Tool.hxx>
81#include <TDataStd_Name.hxx>
82#include <Standard_Version.hxx>
88#define MASK_OCE wxT( "PLUGIN_OCE" )
89#define MASK_OCE_EXTRA wxT( "PLUGIN_OCE_EXTRA" )
92#define USER_PREC (0.14)
98#define USER_ANGLE (0.52359878)
101typedef std::map<std::string, SGNODE*>
FACEMAP;
102typedef std::map<std::string, std::vector<SGNODE*>>
NODEMAP;
103typedef std::pair<std::string, std::vector<SGNODE*>>
NODEITEM;
108 std::vector< SGNODE* >* aItems );
112 std::vector< SGNODE* >* items, Quantity_ColorRGBA*
color );
114#if OCC_VERSION_HEX >= 0x070500
115#define OCC_COLOR_SPACE Quantity_TOC_sRGB
117#define OCC_COLOR_SPACE Quantity_TOC_RGB
138 refColor.SetValues( Quantity_NOC_BLACK );
148 COLORMAP::iterator sC =
colors.begin();
149 COLORMAP::iterator eC =
colors.end();
168 FACEMAP::iterator sF =
faces.begin();
169 FACEMAP::iterator eF =
faces.end();
185 NODEMAP::iterator sS =
shapes.begin();
186 NODEMAP::iterator eS =
shapes.end();
190 std::vector< SGNODE* >::iterator sV = sS->second.begin();
191 std::vector< SGNODE* >::iterator eV = sS->second.end();
213 bool GetShape(
const std::string&
id, std::vector< SGNODE* >*& listPtr )
216 NODEMAP::iterator item;
219 if( item ==
shapes.end() )
222 listPtr = &item->second;
229 FACEMAP::iterator item;
230 item =
faces.find(
id );
232 if( item ==
faces.end() )
241 if(
nullptr == colorObj )
256 Quantity_Color colorRgb = colorObj->GetRGB();
258 Standard_Real r, g, b;
261 std::size_t hash = std::hash<double>{}( colorRgb.Distance(
refColor ) )
262 ^ ( std::hash<float>{}( colorObj->Alpha() ) << 1 );
264 std::map<std::size_t, SGNODE*>::iterator item;
265 item =
colors.find( hash );
267 if( item !=
colors.end() )
272 app.SetSpecular( 0.12f, 0.12f, 0.12f );
273 app.SetAmbient( 0.1f, 0.1f, 0.1f );
274 app.SetDiffuse( r, g, b );
275 app.SetTransparency( 1.0f - colorObj->Alpha() );
276 colors.emplace( hash, app.GetRawPtr() );
278 return app.GetRawPtr();
294 wxFileName fname( wxString::FromUTF8Unchecked( aFileName ) );
295 wxFFileInputStream ifile( fname.GetFullPath() );
300 if( fname.GetExt().MakeUpper().EndsWith( wxT(
"STPZ" ) )
301 || fname.GetExt().MakeUpper().EndsWith( wxT(
"GZ" ) ) )
307 memset( iline, 0, 82 );
308 ifile.Read( iline, 82 );
313 if( !strncmp( iline,
"ISO-10303-21;", 13 ) )
316 std::string fstr = iline;
320 if( fstr.find(
"urn:oid:1.0.10303." ) != std::string::npos )
326 if( iline[72] ==
'S' && ( iline[80] == 0 || iline[80] == 13 || iline[80] == 10 ) )
339void getTag(
const TDF_Label& aLabel, std::string& aTag )
341 std::ostringstream ostr;
343 if( aLabel.IsNull() )
345 wxLogTrace(
MASK_OCE, wxT(
"Null label passed to getTag" ) );
349 TColStd_ListOfInteger tagList;
350 TDF_Tool::TagList( aLabel, tagList );
352 for( TColStd_ListOfInteger::Iterator it( tagList ); it.More(); it.Next() )
366 Handle( TDataStd_Name )
name;
367 if( !aLabel.IsNull() && aLabel.FindAttribute( TDataStd_Name::GetID(),
name ) )
369 TCollection_ExtendedString extstr =
name->Get();
370 char* str =
new char[extstr.LengthOfCString() + 1];
371 extstr.ToUTF8CString( str );
373 txt = wxString::FromUTF8( str );
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";
410static inline std::ostream&
operator<<( std::ostream& aOStream,
const Quantity_ColorRGBA& aColor )
412 Quantity_Color rgb = aColor.GetRGB();
430static void printLabel( TDF_Label aLabel, Handle( XCAFDoc_ShapeTool ) aShapeTool,
431 Handle( XCAFDoc_ColorTool ) aColorTool,
const char* aPreMsg =
nullptr )
433 if( aLabel.IsNull() )
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" :
"" );
453 if( aShapeTool->IsSubShape( aLabel ) )
455 auto shape = aShapeTool->GetShape( aLabel );
456 if( !shape.IsNull() )
460 if( aShapeTool->IsShape( aLabel ) )
462 Quantity_ColorRGBA c;
463 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorGen, c ) )
465 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorSurf, c ) )
467 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorCurv, c ) )
471 wxLogTrace(
MASK_OCE, ss.str().c_str() );
483static void dumpLabels( TDF_Label aLabel, Handle( XCAFDoc_ShapeTool ) aShapeTool,
484 Handle( XCAFDoc_ColorTool ) aColorTool,
int aDepth = 0 )
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 );
498 if( data.m_color->
GetColor( label, XCAFDoc_ColorGen,
color ) )
500 else if( data.m_color->
GetColor( label, XCAFDoc_ColorSurf,
color ) )
502 else if( data.m_color->
GetColor( label, XCAFDoc_ColorCurv,
color ) )
505 label = label.Father();
520 std::vector< SGNODE* >::iterator sL = lp->begin();
521 std::vector< SGNODE* >::iterator eL = lp->end();
538bool readIGES( Handle( TDocStd_Document ) & m_doc,
const char* fname )
540 IGESCAFControl_Reader reader;
541 IFSelect_ReturnStatus stat = reader.ReadFile( fname );
542 reader.PrintCheckLoad( Standard_False, IFSelect_ItemsByEntity );
544 if( stat != IFSelect_RetDone )
548 if( !Interface_Static::SetIVal(
"read.precision.mode", 0 ) )
552 reader.SetColorMode(
true);
553 reader.SetNameMode(
false);
554 reader.SetLayerMode(
false);
556 if ( !reader.Transfer( m_doc ) )
560 if( reader.NbShapes() < 1 )
567bool readSTEP( Handle(TDocStd_Document)& m_doc,
const char* fname )
569 wxLogTrace(
MASK_OCE, wxT(
"Reading step file %s" ), fname );
571 STEPCAFControl_Reader reader;
572 IFSelect_ReturnStatus stat = reader.ReadFile( fname );
574 if( stat != IFSelect_RetDone )
578 if( !Interface_Static::SetIVal(
"read.precision.mode", 1 ) )
582 if( !Interface_Static::SetRVal(
"read.precision.val",
USER_PREC ) )
586 reader.SetColorMode(
true );
587 reader.SetNameMode(
false );
588 reader.SetLayerMode(
false );
590 if ( !reader.Transfer( m_doc ) )
597 if( reader.NbRootsForTransfer() < 1 )
604bool readSTEPZ( Handle(TDocStd_Document)& m_doc,
const char* aFileName )
606 wxFileName fname( wxString::FromUTF8Unchecked( aFileName ) );
607 wxFFileInputStream ifile( fname.GetFullPath() );
609 wxFileName outFile( fname );
611 outFile.SetPath( wxStandardPaths::Get().GetTempDir() );
612 outFile.SetExt( wxT(
"STEP" ) );
614 wxFileOffset size = ifile.GetLength();
615 wxBusyCursor busycursor;
617 if( size == wxInvalidOffset )
621 bool success =
false;
622 wxFFileOutputStream ofile( outFile.GetFullPath() );
627 char *buffer =
new char[size];
629 ifile.Read( buffer, size);
630 std::string expanded;
634 expanded = gzip::decompress( buffer, size );
640 if( expanded.empty() )
644 wxZipInputStream izipfile( ifile );
645 std::unique_ptr<wxZipEntry> zip_file( izipfile.GetNextEntry() );
647 if( zip_file && !zip_file->IsDir() && izipfile.CanRead() )
649 izipfile.Read( ofile );
655 ofile.Write( expanded.data(), expanded.size() );
665 bool retval =
readSTEP( m_doc, outFile.GetFullPath().mb_str() );
668 wxRemoveFile( outFile.GetFullPath() );
678 Handle(XCAFApp_Application) m_app = XCAFApp_Application::GetApplication();
679 m_app->NewDocument(
"MDTV-XCAF", data.m_doc );
687 if( !
readIGES( data.m_doc, filename ) )
689 m_app->Close( data.m_doc );
696 if( !
readSTEP( data.m_doc, filename ) )
698 m_app->Close( data.m_doc );
707 m_app->Close( data.m_doc );
715 m_app->Close( data.m_doc );
720 data.m_assy = XCAFDoc_DocumentTool::ShapeTool( data.m_doc->Main() );
721 data.m_color = XCAFDoc_DocumentTool::ColorTool( data.m_doc->Main() );
724 if( wxLog::IsAllowedTraceMask(
MASK_OCE ) )
726 dumpLabels( data.m_doc->Main(), data.m_assy, data.m_color );
730 TDF_LabelSequence frshapes;
731 data.m_assy->GetFreeShapes( frshapes );
739 for( Standard_Integer i = 1; i <= frshapes.Length(); i++ )
741 const TDF_Label& label = frshapes.Value( i );
743 if( data.m_color->IsVisible( label ) )
752 m_app->Close( data.m_doc );
759#if ( defined( DEBUG_OCE ) && DEBUG_OCE > 3 )
762 wxFileName fn( wxString::FromUTF8Unchecked( filename ) );
766 output = wxT(
"_step-" );
768 output = wxT(
"_iges-" );
770 output.append( fn.GetName() );
771 output.append( wxT(
".wrl" ) );
777 data.
scene =
nullptr;
779 m_app->Close( data.m_doc );
785 std::vector<SGNODE*>* items, Quantity_ColorRGBA*
color )
790 wxLogTrace(
MASK_OCE, wxT(
"Processing shell" ) );
791 for( it.Initialize( shape,
false,
false ); it.More(); it.Next() )
793 const TopoDS_Face& face = TopoDS::Face( it.Value() );
804 std::vector< SGNODE* >* items )
809 Quantity_ColorRGBA col;
810 Quantity_ColorRGBA* lcolor =
nullptr;
812 wxLogTrace(
MASK_OCE, wxT(
"Processing solid" ) );
815 if( !data.m_assy->Search( shape, label ) )
818 std::ostringstream ostr;
819 ostr <<
"KMISC_" << i++;
824 bool found_color =
false;
835 if( data.m_assy->Search( shape, label, Standard_False, Standard_True, Standard_True ) &&
846 if( data.m_assy->Search( shape, label, Standard_False, Standard_False,
859 if( data.m_assy->Search( shape, label, Standard_False, Standard_False,
877 std::vector< SGNODE* >* component =
nullptr;
879 if( !partID.empty() )
886 if(
nullptr != items )
887 items->push_back( pptr );
891 std::vector<SGNODE*> itemList;
893 TopAbs_ShapeEnum stype = shape.ShapeType();
894 if( stype == TopAbs_SHELL )
896 if(
processShell( shape, data, pptr, &itemList, lcolor ) )
902 for( it.Initialize( shape,
false,
false ); it.More(); it.Next() )
904 const TopoDS_Shape& subShape = it.Value();
906 if( subShape.ShapeType() == TopAbs_SHELL )
908 if(
processShell( subShape, data, pptr, &itemList, lcolor ) )
913 wxLogTrace(
MASK_OCE, wxT(
"Unsupported subshape in solid" ) );
920 else if(
nullptr != items )
921 items->push_back( pptr );
928 std::vector<SGNODE*>* aItems )
930 std::string labelTag;
932 if( wxLog::IsAllowedTraceMask(
MASK_OCE ) )
935 getTag( aLabel, labelTag );
938 wxLogTrace(
MASK_OCE, wxT(
"Processing label %s" ), labelTag );
940 TopoDS_Shape originalShape;
941 TDF_Label shapeLabel = aLabel;
943 if( !aData.m_assy->
GetShape( shapeLabel, originalShape ) )
948 TopoDS_Shape shape = originalShape;
950 if( aData.m_assy->IsReference( aLabel ) )
952 wxLogTrace(
MASK_OCE, wxT(
"Label %s is ref, trying to pull up referred label" ),
955 if( !aData.m_assy->GetReferredShape( aLabel, shapeLabel ) )
960 labelTag =
static_cast<int>( shapeLabel.Tag() );
963 if( !aData.m_assy->
GetShape( shapeLabel, shape ) )
973 const TopLoc_Location& loc = originalShape.Location();
975 if( !loc.IsIdentity() )
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();
981 wxLogTrace(
MASK_OCE, wxT(
"Translation %f, %f, %f" ), coord.X(), coord.Y(), coord.Z() );
985 if( T.GetRotation( axis, angle ) )
988 wxLogTrace(
MASK_OCE, wxT(
"Rotation %f, %f, %f, angle %f" ),
989 axis.X(), axis.Y(), axis.Z(), angle );
993 TopAbs_ShapeEnum stype = shape.ShapeType();
999 case TopAbs_COMPOUND:
1003 if( !aData.m_assy->IsAssembly( shapeLabel ) )
1007 for( xp.Init( shape, TopAbs_SOLID ); xp.More(); xp.Next() )
1014 for( xp.Init( shape, TopAbs_SHELL, TopAbs_SOLID ); xp.More(); xp.Next() )
1021 for( xp.Init( shape, TopAbs_FACE, TopAbs_SHELL ); xp.More(); xp.Next() )
1023 const TopoDS_Face& face = TopoDS::Face( xp.Current() );
1024 processFace( face, aData, pptr, aItems,
nullptr );
1044 if(
processFace( TopoDS::Face( shape ), aData, pptr, aItems,
nullptr ) )
1053 if(
nullptr != aItems )
1054 aItems->push_back( pptr );
1056 if( !aData.m_assy->IsSimpleShape( shapeLabel ) && shapeLabel.HasChild() )
1058 wxLogTrace(
MASK_OCE, wxT(
"Label %s has children" ), labelTag );
1059 TDF_ChildIterator it;
1061 for( it.Initialize( shapeLabel ); it.More(); it.Next() )
1073 Quantity_ColorRGBA*
color )
1075 if( Standard_True == face.IsNull() )
1078 bool reverse = ( face.Orientation() == TopAbs_REVERSED );
1079 SGNODE* ashape =
nullptr;
1083 bool useBothSides =
false;
1088 useBothSides =
true;
1090 if( data.m_assy->FindShape( face, label, Standard_False ) )
1093 if( !partID.empty() )
1094 ashape = data.
GetFace( partID );
1103 if(
nullptr != items )
1104 items->push_back( ashape );
1108 std::string id2 = partID;
1117 if(
nullptr != items )
1118 items->push_back( shapeB );
1124 TopLoc_Location loc;
1125 Standard_Boolean isTessellate (Standard_False);
1126 Handle( Poly_Triangulation ) triangulation = BRep_Tool::Triangulation( face, loc );
1128 if( triangulation.IsNull() || triangulation->Deflection() >
USER_PREC + Precision::Confusion() )
1129 isTessellate = Standard_True;
1134 triangulation = BRep_Tool::Triangulation( face, loc );
1137 if( triangulation.IsNull() == Standard_True )
1140 Quantity_ColorRGBA lcolor;
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 ) )
1162 std::vector< SGPOINT > vertices;
1163 std::vector< int > indices;
1164 std::vector< int > indices2;
1167 for(
int i = 1; i <= triangulation->NbNodes(); i++ )
1169 gp_XYZ v( triangulation->Node(i).Coord() );
1170 vertices.emplace_back( v.X(), v.Y(), v.Z() );
1173 for(
int i = 1; i <= triangulation->NbTriangles(); i++ )
1176 triangulation->Triangle(i).Get(a, b, c);
1191 indices.push_back( a );
1192 indices.push_back( b );
1193 indices.push_back( c );
1197 indices2.push_back( b );
1198 indices2.push_back( a );
1199 indices2.push_back( c );
1204 coordIdx.
SetIndices( indices.size(), &indices[0] );
1208 if( !partID.empty() )
1215 std::string id2 = partID;
1224 coordIdx2.
SetIndices( indices2.size(), &indices2[0] );
1228 if( !partID.empty() )
bool SetDiffuse(float aRVal, float aGVal, float aBVal)
bool SetSpecular(float aRVal, float aGVal, float aBVal)
bool SetShininess(float aShininess) noexcept
bool SetAmbient(float aRVal, float aGVal, float aBVal)
IFSG_COORDINDEX is the wrapper for SGCOORDINDEX.
IFSG_COORDS is the wrapper for SGCOORDS.
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
IFSG_FACESET is the wrapper for the SGFACESET class.
bool CalcNormals(SGNODE **aPtr)
bool SetIndices(size_t nIndices, int *aIndexList)
Function SetIndices sets the number of indices and creates a copy of the given index data.
bool SetParent(SGNODE *aParent)
Function SetParent sets the parent SGNODE of this object.
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
void Destroy(void)
Function Destroy deletes the object held by this wrapper.
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Define the basic data set required to represent a 3D model.
The base class of all Scene Graph nodes.
collects header files for all SG* wrappers and the API
bool processShell(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
std::map< std::string, std::vector< SGNODE * > > NODEMAP
std::map< std::size_t, SGNODE * > COLORMAP
bool processFace(const TopoDS_Face &face, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
std::pair< std::string, std::vector< SGNODE * > > NODEITEM
bool getColor(DATA &data, TDF_Label label, Quantity_ColorRGBA &color)
static int colorFloatToDecimal(float aVal)
void getTag(const TDF_Label &aLabel, std::string &aTag)
Gets the absolute tag string for a given label in the form of ##:##:##:##.
void addItems(SGNODE *parent, std::vector< SGNODE * > *lp)
std::string getShapeName(TopAbs_ShapeEnum aShape)
Gets a string for a given TopAbs_ShapeEnum element.
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.
SCENEGRAPH * LoadModel(char const *filename)
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.
FormatType fileType(const char *aFileName)
bool readSTEP(Handle(TDocStd_Document)&m_doc, const char *fname)
static std::ostream & operator<<(std::ostream &aOStream, const Quantity_ColorRGBA &aColor)
bool processSolidOrShell(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items)
static wxString getLabelName(const TDF_Label &aLabel)
bool processLabel(const TDF_Label &aLabel, DATA &aData, SGNODE *aParent, std::vector< SGNODE * > *aItems)
std::map< std::string, SGNODE * > FACEMAP
bool readSTEPZ(Handle(TDocStd_Document)&m_doc, const char *aFileName)
bool readIGES(Handle(TDocStd_Document) &m_doc, const char *fname)
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.
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Function DestroyNode deletes the given SG* class node.
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Handle(XCAFDoc_ColorTool) m_color
SGNODE * GetFace(const std::string &id)
Handle(TDocStd_Document) m_doc
bool GetShape(const std::string &id, std::vector< SGNODE * > *&listPtr)
Handle(XCAFDoc_ShapeTool) m_assy
SGNODE * GetColor(Quantity_ColorRGBA *colorObj)