You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

912 lines
24 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <iostream>
  24. #include <fstream>
  25. #include <sstream>
  26. #include <string>
  27. #include <cstring>
  28. #include <map>
  29. #include <vector>
  30. #if ( defined( DEBUG_OCE ) && DEBUG_OCE > 3 )
  31. #include <wx/filename.h>
  32. #include <wx/string.h>
  33. #endif
  34. #include <TDocStd_Document.hxx>
  35. #include <TopoDS.hxx>
  36. #include <TopoDS_Shape.hxx>
  37. #include <Quantity_Color.hxx>
  38. #include <XCAFApp_Application.hxx>
  39. #include <Handle_XCAFApp_Application.hxx>
  40. #include <AIS_Shape.hxx>
  41. #include <IGESControl_Reader.hxx>
  42. #include <IGESCAFControl_Reader.hxx>
  43. #include <Interface_Static.hxx>
  44. #include <STEPControl_Reader.hxx>
  45. #include <STEPCAFControl_Reader.hxx>
  46. #include <XCAFDoc_DocumentTool.hxx>
  47. #include <XCAFDoc_ColorTool.hxx>
  48. #include <Handle_XCAFDoc_ColorTool.hxx>
  49. #include <XCAFDoc_ShapeTool.hxx>
  50. #include <BRep_Tool.hxx>
  51. #include <BRepMesh_IncrementalMesh.hxx>
  52. #include <TopoDS.hxx>
  53. #include <TopoDS_Shape.hxx>
  54. #include <TopoDS_Face.hxx>
  55. #include <TopoDS_Compound.hxx>
  56. #include <TopExp_Explorer.hxx>
  57. #include <Quantity_Color.hxx>
  58. #include <Poly_Triangulation.hxx>
  59. #include <Poly_PolygonOnTriangulation.hxx>
  60. #include <Precision.hxx>
  61. #include <TDF_LabelSequence.hxx>
  62. #include <TDF_ChildIterator.hxx>
  63. #include "plugins/3dapi/ifsg_all.h"
  64. // log mask for wxLogTrace
  65. #define MASK_OCE "PLUGIN_OCE"
  66. // precision for mesh creation; 0.07 should be good enough for ECAD viewing
  67. #define USER_PREC (0.14)
  68. // angular deflection for meshing
  69. // 10 deg (36 faces per circle) = 0.17453293
  70. // 20 deg (18 faces per circle) = 0.34906585
  71. // 30 deg (12 faces per circle) = 0.52359878
  72. #define USER_ANGLE (0.52359878)
  73. typedef std::map< Standard_Real, SGNODE* > COLORMAP;
  74. typedef std::map< std::string, SGNODE* > FACEMAP;
  75. typedef std::map< std::string, std::vector< SGNODE* > > NODEMAP;
  76. typedef std::pair< std::string, std::vector< SGNODE* > > NODEITEM;
  77. struct DATA;
  78. bool processNode( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
  79. std::vector< SGNODE* >* items );
  80. bool processComp( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
  81. std::vector< SGNODE* >* items );
  82. bool processFace( const TopoDS_Face& face, DATA& data, SGNODE* parent,
  83. std::vector< SGNODE* >* items, Quantity_Color* color );
  84. struct DATA
  85. {
  86. Handle( TDocStd_Document ) m_doc;
  87. Handle( XCAFDoc_ColorTool ) m_color;
  88. Handle( XCAFDoc_ShapeTool ) m_assy;
  89. SGNODE* scene;
  90. SGNODE* defaultColor;
  91. Quantity_Color refColor;
  92. NODEMAP shapes; // SGNODE lists representing a TopoDS_SOLID / COMPOUND
  93. COLORMAP colors; // SGAPPEARANCE nodes
  94. FACEMAP faces; // SGSHAPE items representing a TopoDS_FACE
  95. bool renderBoth; // set TRUE if we're processing IGES
  96. bool hasSolid; // set TRUE if there is no parent SOLID
  97. DATA()
  98. {
  99. scene = NULL;
  100. defaultColor = NULL;
  101. refColor.SetValues( Quantity_NOC_BLACK );
  102. renderBoth = false;
  103. hasSolid = false;
  104. }
  105. ~DATA()
  106. {
  107. // destroy any colors with no parent
  108. if( !colors.empty() )
  109. {
  110. COLORMAP::iterator sC = colors.begin();
  111. COLORMAP::iterator eC = colors.end();
  112. while( sC != eC )
  113. {
  114. if( NULL == S3D::GetSGNodeParent( sC->second ) )
  115. S3D::DestroyNode( sC->second );
  116. ++sC;
  117. }
  118. colors.clear();
  119. }
  120. if( defaultColor && NULL == S3D::GetSGNodeParent( defaultColor ) )
  121. S3D::DestroyNode(defaultColor);
  122. // destroy any faces with no parent
  123. if( !faces.empty() )
  124. {
  125. FACEMAP::iterator sF = faces.begin();
  126. FACEMAP::iterator eF = faces.end();
  127. while( sF != eF )
  128. {
  129. if( NULL == S3D::GetSGNodeParent( sF->second ) )
  130. S3D::DestroyNode( sF->second );
  131. ++sF;
  132. }
  133. faces.clear();
  134. }
  135. // destroy any shapes with no parent
  136. if( !shapes.empty() )
  137. {
  138. NODEMAP::iterator sS = shapes.begin();
  139. NODEMAP::iterator eS = shapes.end();
  140. while( sS != eS )
  141. {
  142. std::vector< SGNODE* >::iterator sV = sS->second.begin();
  143. std::vector< SGNODE* >::iterator eV = sS->second.end();
  144. while( sV != eV )
  145. {
  146. if( NULL == S3D::GetSGNodeParent( *sV ) )
  147. S3D::DestroyNode( *sV );
  148. ++sV;
  149. }
  150. sS->second.clear();
  151. ++sS;
  152. }
  153. shapes.clear();
  154. }
  155. if( scene )
  156. S3D::DestroyNode(scene);
  157. return;
  158. }
  159. // find collection of tagged nodes
  160. bool GetShape( const std::string& id, std::vector< SGNODE* >*& listPtr )
  161. {
  162. listPtr = NULL;
  163. NODEMAP::iterator item;
  164. item = shapes.find( id );
  165. if( item == shapes.end() )
  166. return false;
  167. listPtr = &item->second;
  168. return true;
  169. }
  170. // find collection of tagged nodes
  171. SGNODE* GetFace( const std::string& id )
  172. {
  173. FACEMAP::iterator item;
  174. item = faces.find( id );
  175. if( item == faces.end() )
  176. return NULL;
  177. return item->second;
  178. }
  179. // return color if found; if not found, create SGAPPEARANCE
  180. SGNODE* GetColor( Quantity_Color* colorObj )
  181. {
  182. if( NULL == colorObj )
  183. {
  184. if( defaultColor )
  185. return defaultColor;
  186. IFSG_APPEARANCE app( true );
  187. app.SetShininess( 0.05 );
  188. app.SetSpecular( 0.04, 0.04, 0.04 );
  189. app.SetAmbient( 0.1, 0.1, 0.1 );
  190. app.SetDiffuse( 0.6,0.6, 0.6 );
  191. defaultColor = app.GetRawPtr();
  192. return defaultColor;
  193. }
  194. Standard_Real id = colorObj->Distance( refColor );
  195. std::map< Standard_Real, SGNODE* >::iterator item;
  196. item = colors.find( id );
  197. if( item != colors.end() )
  198. return item->second;
  199. IFSG_APPEARANCE app( true );
  200. app.SetShininess( 0.1 );
  201. app.SetSpecular( 0.12, 0.12, 0.12 );
  202. app.SetAmbient( 0.1, 0.1, 0.1 );
  203. app.SetDiffuse( colorObj->Red(), colorObj->Green(), colorObj->Blue() );
  204. colors.insert( std::pair< Standard_Real, SGNODE* >( id, app.GetRawPtr() ) );
  205. return app.GetRawPtr();
  206. }
  207. };
  208. enum FormatType
  209. {
  210. FMT_NONE = 0,
  211. FMT_STEP = 1,
  212. FMT_IGES = 2
  213. };
  214. FormatType fileType( const char* aFileName )
  215. {
  216. std::ifstream ifile;
  217. ifile.open( aFileName );
  218. if( !ifile.is_open() )
  219. return FMT_NONE;
  220. char iline[82];
  221. memset( iline, 0, 82 );
  222. ifile.getline( iline, 82 );
  223. ifile.close();
  224. iline[81] = 0; // ensure NULL termination when string is too long
  225. // check for STEP in Part 21 format
  226. // (this can give false positives since Part 21 is not exclusively STEP)
  227. if( !strncmp( iline, "ISO-10303-21;", 13 ) )
  228. return FMT_STEP;
  229. std::string fstr = iline;
  230. // check for STEP in XML format
  231. // (this can give both false positive and false negatives)
  232. if( fstr.find( "urn:oid:1.0.10303." ) != std::string::npos )
  233. return FMT_STEP;
  234. // Note: this is a very simple test which can yield false positives; the only
  235. // sure method for determining if a file *not* an IGES model is to attempt
  236. // to load it.
  237. if( iline[72] == 'S' && ( iline[80] == 0 || iline[80] == 13 || iline[80] == 10 ) )
  238. return FMT_IGES;
  239. return FMT_NONE;
  240. }
  241. void getTag( TDF_Label& label, std::string& aTag )
  242. {
  243. aTag.clear();
  244. if( label.IsNull() )
  245. return;
  246. std::string rtag; // tag in reverse
  247. aTag.clear();
  248. int id = label.Tag();
  249. std::ostringstream ostr;
  250. ostr << id;
  251. rtag = ostr.str();
  252. ostr.str( "" );
  253. ostr.clear();
  254. TDF_Label nlab = label.Father();
  255. while( !nlab.IsNull() )
  256. {
  257. rtag.append( 1, ':' );
  258. id = nlab.Tag();
  259. ostr << id;
  260. rtag.append( ostr.str() );
  261. ostr.str( "" );
  262. ostr.clear();
  263. nlab = nlab.Father();
  264. };
  265. std::string::reverse_iterator bI = rtag.rbegin();
  266. std::string::reverse_iterator eI = rtag.rend();
  267. while( bI != eI )
  268. {
  269. aTag.append( 1, *bI );
  270. ++bI;
  271. }
  272. return;
  273. }
  274. bool getColor( DATA& data, TDF_Label label, Quantity_Color& color )
  275. {
  276. while( true )
  277. {
  278. if( data.m_color->GetColor( label, XCAFDoc_ColorGen, color ) )
  279. return true;
  280. else if( data.m_color->GetColor( label, XCAFDoc_ColorSurf, color ) )
  281. return true;
  282. else if( data.m_color->GetColor( label, XCAFDoc_ColorCurv, color ) )
  283. return true;
  284. label = label.Father();
  285. if( label.IsNull() )
  286. break;
  287. };
  288. return false;
  289. }
  290. void addItems( SGNODE* parent, std::vector< SGNODE* >* lp )
  291. {
  292. if( NULL == lp )
  293. return;
  294. std::vector< SGNODE* >::iterator sL = lp->begin();
  295. std::vector< SGNODE* >::iterator eL = lp->end();
  296. SGNODE* item;
  297. while( sL != eL )
  298. {
  299. item = *sL;
  300. if( NULL == S3D::GetSGNodeParent( item ) )
  301. S3D::AddSGNodeChild( parent, item );
  302. else
  303. S3D::AddSGNodeRef( parent, item );
  304. ++sL;
  305. }
  306. return;
  307. }
  308. bool readIGES( Handle(TDocStd_Document)& m_doc, const char* fname )
  309. {
  310. IGESCAFControl_Reader reader;
  311. IFSelect_ReturnStatus stat = reader.ReadFile( fname );
  312. reader.PrintCheckLoad( Standard_False, IFSelect_ItemsByEntity );
  313. if( stat != IFSelect_RetDone )
  314. return false;
  315. // Enable user-defined shape precision
  316. if( !Interface_Static::SetIVal( "read.precision.mode", 1 ) )
  317. return false;
  318. // Set the shape conversion precision to USER_PREC (default 0.0001 has too many triangles)
  319. if( !Interface_Static::SetRVal( "read.precision.val", USER_PREC ) )
  320. return false;
  321. // set other translation options
  322. reader.SetColorMode(true); // use model colors
  323. reader.SetNameMode(false); // don't use IGES label names
  324. reader.SetLayerMode(false); // ignore LAYER data
  325. if ( !reader.Transfer( m_doc ) )
  326. return false;
  327. // are there any shapes to translate?
  328. if( reader.NbShapes() < 1 )
  329. return false;
  330. return true;
  331. }
  332. bool readSTEP( Handle(TDocStd_Document)& m_doc, const char* fname )
  333. {
  334. STEPCAFControl_Reader reader;
  335. IFSelect_ReturnStatus stat = reader.ReadFile( fname );
  336. if( stat != IFSelect_RetDone )
  337. return false;
  338. // Enable user-defined shape precision
  339. if( !Interface_Static::SetIVal( "read.precision.mode", 1 ) )
  340. return false;
  341. // Set the shape conversion precision to USER_PREC (default 0.0001 has too many triangles)
  342. if( !Interface_Static::SetRVal( "read.precision.val", USER_PREC ) )
  343. return false;
  344. // set other translation options
  345. reader.SetColorMode(true); // use model colors
  346. reader.SetNameMode(false); // don't use label names
  347. reader.SetLayerMode(false); // ignore LAYER data
  348. if ( !reader.Transfer( m_doc ) )
  349. {
  350. m_doc->Close();
  351. return false;
  352. }
  353. // are there any shapes to translate?
  354. if( reader.NbRootsForTransfer() < 1 )
  355. return false;
  356. return true;
  357. }
  358. SCENEGRAPH* LoadModel( char const* filename )
  359. {
  360. DATA data;
  361. Handle(XCAFApp_Application) m_app = XCAFApp_Application::GetApplication();
  362. m_app->NewDocument( "MDTV-XCAF", data.m_doc );
  363. FormatType modelFmt = fileType( filename );
  364. switch( modelFmt )
  365. {
  366. case FMT_IGES:
  367. data.renderBoth = true;
  368. if( !readIGES( data.m_doc, filename ) )
  369. return NULL;
  370. break;
  371. case FMT_STEP:
  372. if( !readSTEP( data.m_doc, filename ) )
  373. return NULL;
  374. break;
  375. default:
  376. return NULL;
  377. break;
  378. }
  379. data.m_assy = XCAFDoc_DocumentTool::ShapeTool( data.m_doc->Main() );
  380. data.m_color = XCAFDoc_DocumentTool::ColorTool( data.m_doc->Main() );
  381. // retrieve all free shapes
  382. TDF_LabelSequence frshapes;
  383. data.m_assy->GetFreeShapes( frshapes );
  384. int nshapes = frshapes.Length();
  385. int id = 1;
  386. bool ret = false;
  387. // create the top level SG node
  388. IFSG_TRANSFORM topNode( true );
  389. data.scene = topNode.GetRawPtr();
  390. while( id <= nshapes )
  391. {
  392. TopoDS_Shape shape = data.m_assy->GetShape( frshapes.Value(id) );
  393. if ( !shape.IsNull() && processNode( shape, data, data.scene, NULL ) )
  394. ret = true;
  395. ++id;
  396. };
  397. if( !ret )
  398. return NULL;
  399. SCENEGRAPH* scene = (SCENEGRAPH*)data.scene;
  400. // DEBUG: WRITE OUT VRML2 FILE TO CONFIRM STRUCTURE
  401. #if ( defined( DEBUG_OCE ) && DEBUG_OCE > 3 )
  402. if( data.scene )
  403. {
  404. wxFileName fn( wxString::FromUTF8Unchecked( filename ) );
  405. wxString output;
  406. if( FMT_STEP == modelFmt )
  407. output = wxT( "_step-" );
  408. else
  409. output = wxT( "_iges-" );
  410. output.append( fn.GetName() );
  411. output.append( wxT(".wrl") );
  412. S3D::WriteVRML( output.ToUTF8(), true, data.scene, true, true );
  413. }
  414. #endif
  415. // set to NULL to prevent automatic destruction of the scene data
  416. data.scene = NULL;
  417. return scene;
  418. }
  419. bool processShell( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
  420. std::vector< SGNODE* >* items, Quantity_Color* color )
  421. {
  422. TopoDS_Iterator it;
  423. bool ret = false;
  424. for( it.Initialize( shape, false, false ); it.More(); it.Next() )
  425. {
  426. const TopoDS_Face& face = TopoDS::Face( it.Value() );
  427. if( processFace( face, data, parent, items, color ) )
  428. ret = true;
  429. }
  430. return ret;
  431. }
  432. bool processSolid( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
  433. std::vector< SGNODE* >* items )
  434. {
  435. TDF_Label label = data.m_assy->FindShape( shape, Standard_False );
  436. data.hasSolid = true;
  437. std::string partID;
  438. Quantity_Color col;
  439. Quantity_Color* lcolor = NULL;
  440. if( label.IsNull() )
  441. {
  442. static int i = 0;
  443. std::ostringstream ostr;
  444. ostr << "KMISC_" << i++;
  445. partID = ostr.str();
  446. }
  447. else
  448. {
  449. getTag( label, partID );
  450. if( getColor( data, label, col ) )
  451. lcolor = &col;
  452. }
  453. TopoDS_Iterator it;
  454. IFSG_TRANSFORM childNode( parent );
  455. SGNODE* pptr = childNode.GetRawPtr();
  456. TopLoc_Location loc = shape.Location();
  457. bool ret = false;
  458. if( !loc.IsIdentity() )
  459. {
  460. gp_Trsf T = loc.Transformation();
  461. gp_XYZ coord = T.TranslationPart();
  462. childNode.SetTranslation( SGPOINT( coord.X(), coord.Y(), coord.Z() ) );
  463. gp_XYZ axis;
  464. Standard_Real angle;
  465. if( T.GetRotation( axis, angle ) )
  466. childNode.SetRotation( SGVECTOR( axis.X(), axis.Y(), axis.Z() ), angle );
  467. }
  468. std::vector< SGNODE* >* component = NULL;
  469. if( !partID.empty() )
  470. data.GetShape( partID, component );
  471. if( component )
  472. {
  473. addItems( pptr, component );
  474. if( NULL != items )
  475. items->push_back( pptr );
  476. }
  477. // instantiate the solid
  478. std::vector< SGNODE* > itemList;
  479. for( it.Initialize( shape, false, false ); it.More(); it.Next() )
  480. {
  481. const TopoDS_Shape& subShape = it.Value();
  482. if( processShell( subShape, data, pptr, &itemList, lcolor ) )
  483. ret = true;
  484. }
  485. if( !ret )
  486. childNode.Destroy();
  487. else if( NULL != items )
  488. items->push_back( pptr );
  489. return ret;
  490. }
  491. bool processComp( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
  492. std::vector< SGNODE* >* items )
  493. {
  494. TopoDS_Iterator it;
  495. IFSG_TRANSFORM childNode( parent );
  496. SGNODE* pptr = childNode.GetRawPtr();
  497. TopLoc_Location loc = shape.Location();
  498. bool ret = false;
  499. if( !loc.IsIdentity() )
  500. {
  501. gp_Trsf T = loc.Transformation();
  502. gp_XYZ coord = T.TranslationPart();
  503. childNode.SetTranslation( SGPOINT( coord.X(), coord.Y(), coord.Z() ) );
  504. gp_XYZ axis;
  505. Standard_Real angle;
  506. if( T.GetRotation( axis, angle ) )
  507. childNode.SetRotation( SGVECTOR( axis.X(), axis.Y(), axis.Z() ), angle );
  508. }
  509. for( it.Initialize( shape, false, false ); it.More(); it.Next() )
  510. {
  511. const TopoDS_Shape& subShape = it.Value();
  512. TopAbs_ShapeEnum stype = subShape.ShapeType();
  513. data.hasSolid = false;
  514. switch( stype )
  515. {
  516. case TopAbs_COMPOUND:
  517. case TopAbs_COMPSOLID:
  518. if( processComp( subShape, data, pptr, items ) )
  519. ret = true;
  520. break;
  521. case TopAbs_SOLID:
  522. if( processSolid( subShape, data, pptr, items ) )
  523. ret = true;
  524. break;
  525. case TopAbs_SHELL:
  526. if( processShell( subShape, data, pptr, items, NULL ) )
  527. ret = true;
  528. break;
  529. case TopAbs_FACE:
  530. if( processFace( TopoDS::Face( subShape ), data, pptr, items, NULL ) )
  531. ret = true;
  532. break;
  533. default:
  534. break;
  535. }
  536. }
  537. if( !ret )
  538. childNode.Destroy();
  539. else if( NULL != items )
  540. items->push_back( pptr );
  541. return ret;
  542. }
  543. bool processNode( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
  544. std::vector< SGNODE* >* items )
  545. {
  546. TopAbs_ShapeEnum stype = shape.ShapeType();
  547. bool ret = false;
  548. data.hasSolid = false;
  549. switch( stype )
  550. {
  551. case TopAbs_COMPOUND:
  552. case TopAbs_COMPSOLID:
  553. if( processComp( shape, data, parent, items ) )
  554. ret = true;
  555. break;
  556. case TopAbs_SOLID:
  557. if( processSolid( shape, data, parent, items ) )
  558. ret = true;
  559. break;
  560. case TopAbs_SHELL:
  561. if( processShell( shape, data, parent, items, NULL ) )
  562. ret = true;
  563. break;
  564. case TopAbs_FACE:
  565. if( processFace( TopoDS::Face( shape ), data, parent, items, NULL ) )
  566. ret = true;
  567. break;
  568. default:
  569. break;
  570. }
  571. return ret;
  572. }
  573. bool processFace( const TopoDS_Face& face, DATA& data, SGNODE* parent,
  574. std::vector< SGNODE* >* items, Quantity_Color* color )
  575. {
  576. if( Standard_True == face.IsNull() )
  577. return false;
  578. bool reverse = ( face.Orientation() == TopAbs_REVERSED );
  579. SGNODE* ashape = NULL;
  580. std::string partID;
  581. TDF_Label label;
  582. bool useBothSides = false;
  583. // for IGES renderBoth = TRUE; for STEP if a shell or face is not a descendant
  584. // of a SOLID then hasSolid = false and we must render both sides
  585. if( data.renderBoth || !data.hasSolid )
  586. useBothSides = true;
  587. if( data.m_assy->FindShape( face, label, Standard_False ) )
  588. getTag( label, partID );
  589. if( !partID.empty() )
  590. ashape = data.GetFace( partID );
  591. if( ashape )
  592. {
  593. if( NULL == S3D::GetSGNodeParent( ashape ) )
  594. S3D::AddSGNodeChild( parent, ashape );
  595. else
  596. S3D::AddSGNodeRef( parent, ashape );
  597. if( NULL != items )
  598. items->push_back( ashape );
  599. if( useBothSides )
  600. {
  601. std::string id2 = partID;
  602. id2.append( "b" );
  603. SGNODE* shapeB = data.GetFace( id2 );
  604. if( NULL == S3D::GetSGNodeParent( shapeB ) )
  605. S3D::AddSGNodeChild( parent, shapeB );
  606. else
  607. S3D::AddSGNodeRef( parent, shapeB );
  608. if( NULL != items )
  609. items->push_back( shapeB );
  610. }
  611. return true;
  612. }
  613. TopLoc_Location loc;
  614. Standard_Boolean isTessellate (Standard_False);
  615. Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation( face, loc );
  616. if( triangulation.IsNull() || triangulation->Deflection() > USER_PREC + Precision::Confusion() )
  617. isTessellate = Standard_True;
  618. if (isTessellate)
  619. {
  620. BRepMesh_IncrementalMesh IM(face, USER_PREC, Standard_False, USER_ANGLE );
  621. triangulation = BRep_Tool::Triangulation( face, loc );
  622. }
  623. if( triangulation.IsNull() == Standard_True )
  624. return false;
  625. Quantity_Color lcolor;
  626. // check for a face color; this has precedence over SOLID colors
  627. do
  628. {
  629. TDF_Label L;
  630. if( data.m_color->ShapeTool()->Search( face, L ) )
  631. {
  632. if( data.m_color->GetColor( L, XCAFDoc_ColorGen, lcolor )
  633. || data.m_color->GetColor( L, XCAFDoc_ColorCurv, lcolor )
  634. || data.m_color->GetColor( L, XCAFDoc_ColorSurf, lcolor ) )
  635. color = &lcolor;
  636. }
  637. } while( 0 );
  638. SGNODE* ocolor = data.GetColor( color );
  639. // create a SHAPE and attach the color and data,
  640. // then attach the shape to the parent and return TRUE
  641. IFSG_SHAPE vshape( true );
  642. IFSG_FACESET vface( vshape );
  643. IFSG_COORDS vcoords( vface );
  644. IFSG_COORDINDEX coordIdx( vface );
  645. if( NULL == S3D::GetSGNodeParent( ocolor ) )
  646. S3D::AddSGNodeChild( vshape.GetRawPtr(), ocolor );
  647. else
  648. S3D::AddSGNodeRef( vshape.GetRawPtr(), ocolor );
  649. const TColgp_Array1OfPnt& arrPolyNodes = triangulation->Nodes();
  650. const Poly_Array1OfTriangle& arrTriangles = triangulation->Triangles();
  651. std::vector< SGPOINT > vertices;
  652. std::vector< int > indices;
  653. std::vector< int > indices2;
  654. gp_Trsf tx;
  655. for(int i = 1; i <= triangulation->NbNodes(); i++)
  656. {
  657. gp_XYZ v( arrPolyNodes(i).Coord() );
  658. vertices.push_back( SGPOINT( v.X(), v.Y(), v.Z() ) );
  659. }
  660. for(int i = 1; i <= triangulation->NbTriangles(); i++)
  661. {
  662. int a, b, c;
  663. arrTriangles( i ).Get( a, b, c );
  664. a--;
  665. if( reverse )
  666. {
  667. int tmp = b - 1;
  668. b = c - 1;
  669. c = tmp;
  670. } else {
  671. b--;
  672. c--;
  673. }
  674. indices.push_back( a );
  675. indices.push_back( b );
  676. indices.push_back( c );
  677. if( useBothSides )
  678. {
  679. indices2.push_back( b );
  680. indices2.push_back( a );
  681. indices2.push_back( c );
  682. }
  683. }
  684. vcoords.SetCoordsList( vertices.size(), &vertices[0] );
  685. coordIdx.SetIndices( indices.size(), &indices[0] );
  686. vface.CalcNormals( NULL );
  687. vshape.SetParent( parent );
  688. if( !partID.empty() )
  689. data.faces.insert( std::pair< std::string,
  690. SGNODE* >( partID, vshape.GetRawPtr() ) );
  691. // The outer surface of an IGES model is indeterminate so
  692. // we must render both sides of a surface.
  693. if( useBothSides )
  694. {
  695. std::string id2 = partID;
  696. id2.append( "b" );
  697. IFSG_SHAPE vshape2( true );
  698. IFSG_FACESET vface2( vshape2 );
  699. IFSG_COORDS vcoords2( vface2 );
  700. IFSG_COORDINDEX coordIdx2( vface2 );
  701. S3D::AddSGNodeRef( vshape2.GetRawPtr(), ocolor );
  702. vcoords2.SetCoordsList( vertices.size(), &vertices[0] );
  703. coordIdx2.SetIndices( indices2.size(), &indices2[0] );
  704. vface2.CalcNormals( NULL );
  705. vshape2.SetParent( parent );
  706. if( !partID.empty() )
  707. data.faces.insert( std::pair< std::string,
  708. SGNODE* >( id2, vshape2.GetRawPtr() ) );
  709. }
  710. return true;
  711. }