KiCad PCB EDA Suite
loadmodel.cpp
Go to the documentation of this file.
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 
24 #include <iostream>
25 #include <fstream>
26 #include <sstream>
27 #include <string>
28 #include <cstring>
29 #include <map>
30 #include <vector>
31 #include <wx/string.h>
32 #include <wx/wfstream.h>
33 
34 #if ( defined( DEBUG_OCE ) && DEBUG_OCE > 3 )
35 #include <wx/filename.h>
36 #endif
37 
38 #include <TDocStd_Document.hxx>
39 #include <TopoDS.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <Quantity_Color.hxx>
42 #include <XCAFApp_Application.hxx>
43 
44 #include <AIS_Shape.hxx>
45 
46 #include <IGESControl_Reader.hxx>
47 #include <IGESCAFControl_Reader.hxx>
48 #include <Interface_Static.hxx>
49 
50 #include <STEPControl_Reader.hxx>
51 #include <STEPCAFControl_Reader.hxx>
52 
53 #include <XCAFDoc_DocumentTool.hxx>
54 #include <XCAFDoc_ColorTool.hxx>
55 #include <XCAFDoc_ShapeTool.hxx>
56 
57 #include <BRep_Tool.hxx>
58 #include <BRepMesh_IncrementalMesh.hxx>
59 
60 #include <TopoDS.hxx>
61 #include <TopoDS_Shape.hxx>
62 #include <TopoDS_Face.hxx>
63 #include <TopoDS_Compound.hxx>
64 #include <TopExp_Explorer.hxx>
65 
66 #include <Quantity_Color.hxx>
67 #include <Poly_Triangulation.hxx>
68 #include <Poly_PolygonOnTriangulation.hxx>
69 #include <Precision.hxx>
70 
71 #include <TDF_LabelSequence.hxx>
72 #include <TDF_ChildIterator.hxx>
73 
74 #include "plugins/3dapi/ifsg_all.h"
75 
76 // log mask for wxLogTrace
77 #define MASK_OCE "PLUGIN_OCE"
78 
79 // precision for mesh creation; 0.07 should be good enough for ECAD viewing
80 #define USER_PREC (0.14)
81 
82 // angular deflection for meshing
83 // 10 deg (36 faces per circle) = 0.17453293
84 // 20 deg (18 faces per circle) = 0.34906585
85 // 30 deg (12 faces per circle) = 0.52359878
86 #define USER_ANGLE (0.52359878)
87 
88 typedef std::map< Standard_Real, SGNODE* > COLORMAP;
89 typedef std::map< std::string, SGNODE* > FACEMAP;
90 typedef std::map< std::string, std::vector< SGNODE* > > NODEMAP;
91 typedef std::pair< std::string, std::vector< SGNODE* > > NODEITEM;
92 
93 struct DATA;
94 
95 bool processNode( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
96  std::vector< SGNODE* >* items );
97 
98 bool processComp( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
99  std::vector< SGNODE* >* items );
100 
101 bool processFace( const TopoDS_Face& face, DATA& data, SGNODE* parent,
102  std::vector< SGNODE* >* items, Quantity_Color* color );
103 
104 struct DATA
105 {
106  Handle( TDocStd_Document ) m_doc;
107  Handle( XCAFDoc_ColorTool ) m_color;
108  Handle( XCAFDoc_ShapeTool ) m_assy;
111  Quantity_Color refColor;
112  NODEMAP shapes; // SGNODE lists representing a TopoDS_SOLID / COMPOUND
113  COLORMAP colors; // SGAPPEARANCE nodes
114  FACEMAP faces; // SGSHAPE items representing a TopoDS_FACE
115  bool renderBoth; // set TRUE if we're processing IGES
116  bool hasSolid; // set TRUE if there is no parent SOLID
117 
119  {
120  scene = NULL;
121  defaultColor = NULL;
122  refColor.SetValues( Quantity_NOC_BLACK );
123  renderBoth = false;
124  hasSolid = false;
125  }
126 
128  {
129  // destroy any colors with no parent
130  if( !colors.empty() )
131  {
132  COLORMAP::iterator sC = colors.begin();
133  COLORMAP::iterator eC = colors.end();
134 
135  while( sC != eC )
136  {
137  if( NULL == S3D::GetSGNodeParent( sC->second ) )
138  S3D::DestroyNode( sC->second );
139 
140  ++sC;
141  }
142 
143  colors.clear();
144  }
145 
148 
149  // destroy any faces with no parent
150  if( !faces.empty() )
151  {
152  FACEMAP::iterator sF = faces.begin();
153  FACEMAP::iterator eF = faces.end();
154 
155  while( sF != eF )
156  {
157  if( NULL == S3D::GetSGNodeParent( sF->second ) )
158  S3D::DestroyNode( sF->second );
159 
160  ++sF;
161  }
162 
163  faces.clear();
164  }
165 
166  // destroy any shapes with no parent
167  if( !shapes.empty() )
168  {
169  NODEMAP::iterator sS = shapes.begin();
170  NODEMAP::iterator eS = shapes.end();
171 
172  while( sS != eS )
173  {
174  std::vector< SGNODE* >::iterator sV = sS->second.begin();
175  std::vector< SGNODE* >::iterator eV = sS->second.end();
176 
177  while( sV != eV )
178  {
179  if( NULL == S3D::GetSGNodeParent( *sV ) )
180  S3D::DestroyNode( *sV );
181 
182  ++sV;
183  }
184 
185  sS->second.clear();
186  ++sS;
187  }
188 
189  shapes.clear();
190  }
191 
192  if( scene )
194 
195  return;
196  }
197 
198  // find collection of tagged nodes
199  bool GetShape( const std::string& id, std::vector< SGNODE* >*& listPtr )
200  {
201  listPtr = NULL;
202  NODEMAP::iterator item;
203  item = shapes.find( id );
204 
205  if( item == shapes.end() )
206  return false;
207 
208  listPtr = &item->second;
209  return true;
210  }
211 
212  // find collection of tagged nodes
213  SGNODE* GetFace( const std::string& id )
214  {
215  FACEMAP::iterator item;
216  item = faces.find( id );
217 
218  if( item == faces.end() )
219  return NULL;
220 
221  return item->second;
222  }
223 
224  // return color if found; if not found, create SGAPPEARANCE
225  SGNODE* GetColor( Quantity_Color* colorObj )
226  {
227  if( NULL == colorObj )
228  {
229  if( defaultColor )
230  return defaultColor;
231 
232  IFSG_APPEARANCE app( true );
233  app.SetShininess( 0.05 );
234  app.SetSpecular( 0.04, 0.04, 0.04 );
235  app.SetAmbient( 0.1, 0.1, 0.1 );
236  app.SetDiffuse( 0.6,0.6, 0.6 );
237 
238  defaultColor = app.GetRawPtr();
239  return defaultColor;
240  }
241 
242  Standard_Real id = colorObj->Distance( refColor );
243  std::map< Standard_Real, SGNODE* >::iterator item;
244  item = colors.find( id );
245 
246  if( item != colors.end() )
247  return item->second;
248 
249  IFSG_APPEARANCE app( true );
250  app.SetShininess( 0.1 );
251  app.SetSpecular( 0.12, 0.12, 0.12 );
252  app.SetAmbient( 0.1, 0.1, 0.1 );
253  app.SetDiffuse( colorObj->Red(), colorObj->Green(), colorObj->Blue() );
254  colors.insert( std::pair< Standard_Real, SGNODE* >( id, app.GetRawPtr() ) );
255 
256  return app.GetRawPtr();
257  }
258 };
259 
260 
262 {
263  FMT_NONE = 0,
264  FMT_STEP = 1,
266 };
267 
268 
269 FormatType fileType( const char* aFileName )
270 {
271  wxString fname( wxString::FromUTF8Unchecked( aFileName ) );
272  wxFileInputStream ifile( fname );
273 
274  if( !ifile.IsOk() )
275  return FMT_NONE;
276 
277  char iline[82];
278  memset( iline, 0, 82 );
279  ifile.Read( iline, 82 );
280  iline[81] = 0; // ensure NULL termination when string is too long
281 
282  // check for STEP in Part 21 format
283  // (this can give false positives since Part 21 is not exclusively STEP)
284  if( !strncmp( iline, "ISO-10303-21;", 13 ) )
285  return FMT_STEP;
286 
287  std::string fstr = iline;
288 
289  // check for STEP in XML format
290  // (this can give both false positive and false negatives)
291  if( fstr.find( "urn:oid:1.0.10303." ) != std::string::npos )
292  return FMT_STEP;
293 
294  // Note: this is a very simple test which can yield false positives; the only
295  // sure method for determining if a file *not* an IGES model is to attempt
296  // to load it.
297  if( iline[72] == 'S' && ( iline[80] == 0 || iline[80] == 13 || iline[80] == 10 ) )
298  return FMT_IGES;
299 
300  return FMT_NONE;
301 }
302 
303 
304 void getTag( TDF_Label& label, std::string& aTag )
305 {
306  if( label.IsNull() )
307  return;
308 
309  std::string rtag; // tag in reverse
310  aTag.clear();
311  int id = label.Tag();
312  std::ostringstream ostr;
313  ostr << id;
314  rtag = ostr.str();
315  ostr.str( "" );
316  ostr.clear();
317 
318  TDF_Label nlab = label.Father();
319 
320  while( !nlab.IsNull() )
321  {
322  rtag.append( 1, ':' );
323  id = nlab.Tag();
324  ostr << id;
325  rtag.append( ostr.str() );
326  ostr.str( "" );
327  ostr.clear();
328  nlab = nlab.Father();
329  };
330 
331  std::string::reverse_iterator bI = rtag.rbegin();
332  std::string::reverse_iterator eI = rtag.rend();
333 
334  while( bI != eI )
335  {
336  aTag.append( 1, *bI );
337  ++bI;
338  }
339 
340  return;
341 }
342 
343 
344 bool getColor( DATA& data, TDF_Label label, Quantity_Color& color )
345 {
346  while( true )
347  {
348  if( data.m_color->GetColor( label, XCAFDoc_ColorGen, color ) )
349  return true;
350  else if( data.m_color->GetColor( label, XCAFDoc_ColorSurf, color ) )
351  return true;
352  else if( data.m_color->GetColor( label, XCAFDoc_ColorCurv, color ) )
353  return true;
354 
355  label = label.Father();
356 
357  if( label.IsNull() )
358  break;
359  };
360 
361  return false;
362 }
363 
364 
365 void addItems( SGNODE* parent, std::vector< SGNODE* >* lp )
366 {
367  if( NULL == lp )
368  return;
369 
370  std::vector< SGNODE* >::iterator sL = lp->begin();
371  std::vector< SGNODE* >::iterator eL = lp->end();
372  SGNODE* item;
373 
374  while( sL != eL )
375  {
376  item = *sL;
377 
378  if( NULL == S3D::GetSGNodeParent( item ) )
379  S3D::AddSGNodeChild( parent, item );
380  else
381  S3D::AddSGNodeRef( parent, item );
382 
383  ++sL;
384  }
385 
386  return;
387 }
388 
389 
390 bool readIGES( Handle(TDocStd_Document)& m_doc, const char* fname )
391 {
392  IGESCAFControl_Reader reader;
393  IFSelect_ReturnStatus stat = reader.ReadFile( fname );
394  reader.PrintCheckLoad( Standard_False, IFSelect_ItemsByEntity );
395 
396  if( stat != IFSelect_RetDone )
397  return false;
398 
399  // Enable file-defined shape precision
400  if( !Interface_Static::SetIVal( "read.precision.mode", 0 ) )
401  return false;
402 
403  // set other translation options
404  reader.SetColorMode(true); // use model colors
405  reader.SetNameMode(false); // don't use IGES label names
406  reader.SetLayerMode(false); // ignore LAYER data
407 
408  if ( !reader.Transfer( m_doc ) )
409  return false;
410 
411  // are there any shapes to translate?
412  if( reader.NbShapes() < 1 )
413  return false;
414 
415  return true;
416 }
417 
418 
419 bool readSTEP( Handle(TDocStd_Document)& m_doc, const char* fname )
420 {
421  STEPCAFControl_Reader reader;
422  IFSelect_ReturnStatus stat = reader.ReadFile( fname );
423 
424  if( stat != IFSelect_RetDone )
425  return false;
426 
427  // Enable user-defined shape precision
428  if( !Interface_Static::SetIVal( "read.precision.mode", 1 ) )
429  return false;
430 
431  // Set the shape conversion precision to USER_PREC (default 0.0001 has too many triangles)
432  if( !Interface_Static::SetRVal( "read.precision.val", USER_PREC ) )
433  return false;
434 
435  // set other translation options
436  reader.SetColorMode(true); // use model colors
437  reader.SetNameMode(false); // don't use label names
438  reader.SetLayerMode(false); // ignore LAYER data
439 
440  if ( !reader.Transfer( m_doc ) )
441  {
442  m_doc->Close();
443  return false;
444  }
445 
446  // are there any shapes to translate?
447  if( reader.NbRootsForTransfer() < 1 )
448  return false;
449 
450  return true;
451 }
452 
453 
454 SCENEGRAPH* LoadModel( char const* filename )
455 {
456  DATA data;
457 
458  Handle(XCAFApp_Application) m_app = XCAFApp_Application::GetApplication();
459  m_app->NewDocument( "MDTV-XCAF", data.m_doc );
460  FormatType modelFmt = fileType( filename );
461 
462  switch( modelFmt )
463  {
464  case FMT_IGES:
465  data.renderBoth = true;
466 
467  if( !readIGES( data.m_doc, filename ) )
468  return NULL;
469  break;
470 
471  case FMT_STEP:
472  if( !readSTEP( data.m_doc, filename ) )
473  return NULL;
474  break;
475 
476  default:
477  return NULL;
478  break;
479  }
480 
481  data.m_assy = XCAFDoc_DocumentTool::ShapeTool( data.m_doc->Main() );
482  data.m_color = XCAFDoc_DocumentTool::ColorTool( data.m_doc->Main() );
483 
484  // retrieve all free shapes
485  TDF_LabelSequence frshapes;
486  data.m_assy->GetFreeShapes( frshapes );
487 
488  int nshapes = frshapes.Length();
489  int id = 1;
490  bool ret = false;
491 
492  // create the top level SG node
493  IFSG_TRANSFORM topNode( true );
494  data.scene = topNode.GetRawPtr();
495 
496  while( id <= nshapes )
497  {
498  TopoDS_Shape shape = data.m_assy->GetShape( frshapes.Value(id) );
499 
500  if ( !shape.IsNull() && processNode( shape, data, data.scene, NULL ) )
501  ret = true;
502 
503  ++id;
504  };
505 
506  if( !ret )
507  return NULL;
508 
509  SCENEGRAPH* scene = (SCENEGRAPH*)data.scene;
510 
511  // DEBUG: WRITE OUT VRML2 FILE TO CONFIRM STRUCTURE
512  #if ( defined( DEBUG_OCE ) && DEBUG_OCE > 3 )
513  if( data.scene )
514  {
515  wxFileName fn( wxString::FromUTF8Unchecked( filename ) );
516  wxString output;
517 
518  if( FMT_STEP == modelFmt )
519  output = wxT( "_step-" );
520  else
521  output = wxT( "_iges-" );
522 
523  output.append( fn.GetName() );
524  output.append( wxT(".wrl") );
525  S3D::WriteVRML( output.ToUTF8(), true, data.scene, true, true );
526  }
527  #endif
528 
529  // set to NULL to prevent automatic destruction of the scene data
530  data.scene = NULL;
531 
532  return scene;
533 }
534 
535 
536 bool processShell( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
537  std::vector< SGNODE* >* items, Quantity_Color* color )
538 {
539  TopoDS_Iterator it;
540  bool ret = false;
541 
542  for( it.Initialize( shape, false, false ); it.More(); it.Next() )
543  {
544  const TopoDS_Face& face = TopoDS::Face( it.Value() );
545 
546  if( processFace( face, data, parent, items, color ) )
547  ret = true;
548  }
549 
550  return ret;
551 }
552 
553 
554 bool processSolid( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
555  std::vector< SGNODE* >* items )
556 {
557  TDF_Label label = data.m_assy->FindShape( shape, Standard_False );
558 
559  data.hasSolid = true;
560  std::string partID;
561  Quantity_Color col;
562  Quantity_Color* lcolor = NULL;
563 
564  if( label.IsNull() )
565  {
566  static int i = 0;
567  std::ostringstream ostr;
568  ostr << "KMISC_" << i++;
569  partID = ostr.str();
570  }
571  else
572  {
573  getTag( label, partID );
574 
575 
576  if( getColor( data, label, col ) )
577  lcolor = &col;
578  }
579 
580  TopoDS_Iterator it;
581  IFSG_TRANSFORM childNode( parent );
582  SGNODE* pptr = childNode.GetRawPtr();
583  const TopLoc_Location& loc = shape.Location();
584  bool ret = false;
585 
586  if( !loc.IsIdentity() )
587  {
588  gp_Trsf T = loc.Transformation();
589  gp_XYZ coord = T.TranslationPart();
590  childNode.SetTranslation( SGPOINT( coord.X(), coord.Y(), coord.Z() ) );
591  gp_XYZ axis;
592  Standard_Real angle;
593 
594  if( T.GetRotation( axis, angle ) )
595  childNode.SetRotation( SGVECTOR( axis.X(), axis.Y(), axis.Z() ), angle );
596  }
597 
598  std::vector< SGNODE* >* component = NULL;
599 
600  if( !partID.empty() )
601  data.GetShape( partID, component );
602 
603  if( component )
604  {
605  addItems( pptr, component );
606 
607  if( NULL != items )
608  items->push_back( pptr );
609  }
610 
611  // instantiate the solid
612  std::vector< SGNODE* > itemList;
613 
614  for( it.Initialize( shape, false, false ); it.More(); it.Next() )
615  {
616  const TopoDS_Shape& subShape = it.Value();
617 
618  if( processShell( subShape, data, pptr, &itemList, lcolor ) )
619  ret = true;
620  }
621 
622  if( !ret )
623  childNode.Destroy();
624  else if( NULL != items )
625  items->push_back( pptr );
626 
627  return ret;
628 }
629 
630 
631 bool processComp( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
632  std::vector< SGNODE* >* items )
633 {
634  TopoDS_Iterator it;
635  IFSG_TRANSFORM childNode( parent );
636  SGNODE* pptr = childNode.GetRawPtr();
637  const TopLoc_Location& loc = shape.Location();
638  bool ret = false;
639 
640  if( !loc.IsIdentity() )
641  {
642  gp_Trsf T = loc.Transformation();
643  gp_XYZ coord = T.TranslationPart();
644  childNode.SetTranslation( SGPOINT( coord.X(), coord.Y(), coord.Z() ) );
645  gp_XYZ axis;
646  Standard_Real angle;
647 
648  if( T.GetRotation( axis, angle ) )
649  childNode.SetRotation( SGVECTOR( axis.X(), axis.Y(), axis.Z() ), angle );
650  }
651 
652  for( it.Initialize( shape, false, false ); it.More(); it.Next() )
653  {
654  const TopoDS_Shape& subShape = it.Value();
655  TopAbs_ShapeEnum stype = subShape.ShapeType();
656  data.hasSolid = false;
657 
658  switch( stype )
659  {
660  case TopAbs_COMPOUND:
661  case TopAbs_COMPSOLID:
662  if( processComp( subShape, data, pptr, items ) )
663  ret = true;
664  break;
665 
666  case TopAbs_SOLID:
667  if( processSolid( subShape, data, pptr, items ) )
668  ret = true;
669  break;
670 
671  case TopAbs_SHELL:
672  if( processShell( subShape, data, pptr, items, NULL ) )
673  ret = true;
674  break;
675 
676  case TopAbs_FACE:
677  if( processFace( TopoDS::Face( subShape ), data, pptr, items, NULL ) )
678  ret = true;
679  break;
680 
681  default:
682  break;
683  }
684  }
685 
686  if( !ret )
687  childNode.Destroy();
688  else if( NULL != items )
689  items->push_back( pptr );
690 
691  return ret;
692 }
693 
694 
695 bool processNode( const TopoDS_Shape& shape, DATA& data, SGNODE* parent,
696  std::vector< SGNODE* >* items )
697 {
698  TopAbs_ShapeEnum stype = shape.ShapeType();
699  bool ret = false;
700  data.hasSolid = false;
701 
702  switch( stype )
703  {
704  case TopAbs_COMPOUND:
705  case TopAbs_COMPSOLID:
706  if( processComp( shape, data, parent, items ) )
707  ret = true;
708  break;
709 
710  case TopAbs_SOLID:
711  if( processSolid( shape, data, parent, items ) )
712  ret = true;
713  break;
714 
715  case TopAbs_SHELL:
716  if( processShell( shape, data, parent, items, NULL ) )
717  ret = true;
718  break;
719 
720  case TopAbs_FACE:
721  if( processFace( TopoDS::Face( shape ), data, parent, items, NULL ) )
722  ret = true;
723  break;
724 
725  default:
726  break;
727  }
728 
729  return ret;
730 }
731 
732 
733 bool processFace( const TopoDS_Face& face, DATA& data, SGNODE* parent,
734  std::vector< SGNODE* >* items, Quantity_Color* color )
735 {
736  if( Standard_True == face.IsNull() )
737  return false;
738 
739  bool reverse = ( face.Orientation() == TopAbs_REVERSED );
740  SGNODE* ashape = NULL;
741  std::string partID;
742  TDF_Label label;
743 
744  bool useBothSides = false;
745 
746  // for IGES renderBoth = TRUE; for STEP if a shell or face is not a descendant
747  // of a SOLID then hasSolid = false and we must render both sides
748  if( data.renderBoth || !data.hasSolid )
749  useBothSides = true;
750 
751  if( data.m_assy->FindShape( face, label, Standard_False ) )
752  getTag( label, partID );
753 
754  if( !partID.empty() )
755  ashape = data.GetFace( partID );
756 
757  if( ashape )
758  {
759  if( NULL == S3D::GetSGNodeParent( ashape ) )
760  S3D::AddSGNodeChild( parent, ashape );
761  else
762  S3D::AddSGNodeRef( parent, ashape );
763 
764  if( NULL != items )
765  items->push_back( ashape );
766 
767  if( useBothSides )
768  {
769  std::string id2 = partID;
770  id2.append( "b" );
771  SGNODE* shapeB = data.GetFace( id2 );
772 
773  if( NULL == S3D::GetSGNodeParent( shapeB ) )
774  S3D::AddSGNodeChild( parent, shapeB );
775  else
776  S3D::AddSGNodeRef( parent, shapeB );
777 
778  if( NULL != items )
779  items->push_back( shapeB );
780  }
781 
782  return true;
783  }
784 
785  TopLoc_Location loc;
786  Standard_Boolean isTessellate (Standard_False);
787  Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation( face, loc );
788 
789  if( triangulation.IsNull() || triangulation->Deflection() > USER_PREC + Precision::Confusion() )
790  isTessellate = Standard_True;
791 
792  if (isTessellate)
793  {
794  BRepMesh_IncrementalMesh IM(face, USER_PREC, Standard_False, USER_ANGLE );
795  triangulation = BRep_Tool::Triangulation( face, loc );
796  }
797 
798  if( triangulation.IsNull() == Standard_True )
799  return false;
800 
801  Quantity_Color lcolor;
802 
803  // check for a face color; this has precedence over SOLID colors
804  do
805  {
806  TDF_Label L;
807 
808  if( data.m_color->ShapeTool()->Search( face, L ) )
809  {
810  if( data.m_color->GetColor( L, XCAFDoc_ColorGen, lcolor )
811  || data.m_color->GetColor( L, XCAFDoc_ColorCurv, lcolor )
812  || data.m_color->GetColor( L, XCAFDoc_ColorSurf, lcolor ) )
813  color = &lcolor;
814  }
815  } while( 0 );
816 
817  SGNODE* ocolor = data.GetColor( color );
818 
819  // create a SHAPE and attach the color and data,
820  // then attach the shape to the parent and return TRUE
821  IFSG_SHAPE vshape( true );
822  IFSG_FACESET vface( vshape );
823  IFSG_COORDS vcoords( vface );
824  IFSG_COORDINDEX coordIdx( vface );
825 
826  if( NULL == S3D::GetSGNodeParent( ocolor ) )
827  S3D::AddSGNodeChild( vshape.GetRawPtr(), ocolor );
828  else
829  S3D::AddSGNodeRef( vshape.GetRawPtr(), ocolor );
830 
831  const TColgp_Array1OfPnt& arrPolyNodes = triangulation->Nodes();
832  const Poly_Array1OfTriangle& arrTriangles = triangulation->Triangles();
833 
834  std::vector< SGPOINT > vertices;
835  std::vector< int > indices;
836  std::vector< int > indices2;
837  gp_Trsf tx;
838 
839  for(int i = 1; i <= triangulation->NbNodes(); i++)
840  {
841  gp_XYZ v( arrPolyNodes(i).Coord() );
842  vertices.emplace_back( v.X(), v.Y(), v.Z() );
843  }
844 
845  for(int i = 1; i <= triangulation->NbTriangles(); i++)
846  {
847  int a, b, c;
848  arrTriangles( i ).Get( a, b, c );
849  a--;
850 
851  if( reverse )
852  {
853  int tmp = b - 1;
854  b = c - 1;
855  c = tmp;
856  } else {
857  b--;
858  c--;
859  }
860 
861  indices.push_back( a );
862  indices.push_back( b );
863  indices.push_back( c );
864 
865  if( useBothSides )
866  {
867  indices2.push_back( b );
868  indices2.push_back( a );
869  indices2.push_back( c );
870  }
871  }
872 
873  vcoords.SetCoordsList( vertices.size(), &vertices[0] );
874  coordIdx.SetIndices( indices.size(), &indices[0] );
875  vface.CalcNormals( NULL );
876  vshape.SetParent( parent );
877 
878  if( !partID.empty() )
879  data.faces.insert( std::pair< std::string,
880  SGNODE* >( partID, vshape.GetRawPtr() ) );
881 
882  // The outer surface of an IGES model is indeterminate so
883  // we must render both sides of a surface.
884  if( useBothSides )
885  {
886  std::string id2 = partID;
887  id2.append( "b" );
888  IFSG_SHAPE vshape2( true );
889  IFSG_FACESET vface2( vshape2 );
890  IFSG_COORDS vcoords2( vface2 );
891  IFSG_COORDINDEX coordIdx2( vface2 );
892  S3D::AddSGNodeRef( vshape2.GetRawPtr(), ocolor );
893 
894  vcoords2.SetCoordsList( vertices.size(), &vertices[0] );
895  coordIdx2.SetIndices( indices2.size(), &indices2[0] );
896  vface2.CalcNormals( NULL );
897  vshape2.SetParent( parent );
898 
899  if( !partID.empty() )
900  data.faces.insert( std::pair< std::string,
901  SGNODE* >( id2, vshape2.GetRawPtr() ) );
902  }
903 
904  return true;
905 }
SGNODE * GetColor(Quantity_Color *colorObj)
Definition: loadmodel.cpp:225
DATA()
Definition: loadmodel.cpp:118
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:213
FACEMAP faces
Definition: loadmodel.cpp:114
~DATA()
Definition: loadmodel.cpp:127
int color
Definition: DXF_plotter.cpp:61
bool SetDiffuse(float aRVal, float aGVal, float aBVal)
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:636
bool processSolid(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items)
Definition: loadmodel.cpp:554
T
enum T contains all this lexer's tokens.
bool SetParent(SGNODE *aParent)
Function SetParent sets the parent SGNODE of this object.
Definition: ifsg_node.cpp:108
SGNODE represents the base class of all Scene Graph nodes.
Definition: sg_node.h:76
collects header files for all SG* wrappers and the API
COLORMAP colors
Definition: loadmodel.cpp:113
bool readSTEP(Handle(TDocStd_Document)&m_doc, const char *fname)
Definition: loadmodel.cpp:419
bool processNode(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items)
Definition: loadmodel.cpp:695
std::pair< std::string, std::vector< SGNODE * > > NODEITEM
Definition: loadmodel.cpp:91
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
Definition: ifsg_node.cpp:66
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:645
std::map< std::string, SGNODE * > FACEMAP
Definition: loadmodel.cpp:89
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:81
std::map< std::string, std::vector< SGNODE * > > NODEMAP
Definition: loadmodel.cpp:90
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Function DestroyNode deletes the given SG* class node.
Definition: ifsg_api.cpp:210
#define NULL
bool SetAmbient(float aRVal, float aGVal, float aBVal)
bool processFace(const TopoDS_Face &face, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_Color *color)
Definition: loadmodel.cpp:733
bool readIGES(Handle(TDocStd_Document)&m_doc, const char *fname)
Definition: loadmodel.cpp:390
void getTag(TDF_Label &label, std::string &aTag)
Definition: loadmodel.cpp:304
Quantity_Color refColor
Definition: loadmodel.cpp:111
#define USER_ANGLE
Definition: loadmodel.cpp:86
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:654
bool SetRotation(const SGVECTOR &aRotationAxis, double aAngle)
bool getColor(DATA &data, TDF_Label label, Quantity_Color &color)
Definition: loadmodel.cpp:344
FormatType fileType(const char *aFileName)
Definition: loadmodel.cpp:269
bool SetShininess(float aShininess) noexcept
bool CalcNormals(SGNODE **aPtr)
FormatType
Definition: loadmodel.cpp:261
#define USER_PREC
Definition: loadmodel.cpp:80
bool SetIndices(size_t nIndices, int *aIndexList)
Function SetIndices sets the number of indices and creates a copy of the given index data.
Definition: ifsg_index.cpp:63
SCENEGRAPH * LoadModel(char const *filename)
Definition: loadmodel.cpp:454
bool hasSolid
Definition: loadmodel.cpp:116
void addItems(SGNODE *parent, std::vector< SGNODE * > *lp)
Definition: loadmodel.cpp:365
bool SetSpecular(float aRVal, float aGVal, float aBVal)
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
SGNODE * scene
Definition: loadmodel.cpp:109
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:40
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 SetTranslation(const SGPOINT &aTranslation) noexcept
SGNODE * defaultColor
Definition: loadmodel.cpp:110
Handle(TDocStd_Document) m_doc
void Destroy(void)
Function Destroy deletes the object held by this wrapper.
Definition: ifsg_node.cpp:54
std::map< Standard_Real, SGNODE * > COLORMAP
Definition: loadmodel.cpp:88
NODEMAP shapes
Definition: loadmodel.cpp:112
bool renderBoth
Definition: loadmodel.cpp:115
bool GetShape(const std::string &id, std::vector< SGNODE * > *&listPtr)
Definition: loadmodel.cpp:199
bool processComp(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items)
Definition: loadmodel.cpp:631
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Definition: ifsg_shape.h:40
bool processShell(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_Color *color)
Definition: loadmodel.cpp:536