1 // Created on: 2007-08-04
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2007-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <VrmlData_ShapeConvert.hxx>
17 #include <VrmlData_Scene.hxx>
18 #include <VrmlData_Group.hxx>
19 #include <VrmlData_Coordinate.hxx>
20 #include <VrmlData_IndexedFaceSet.hxx>
21 #include <VrmlData_IndexedLineSet.hxx>
22 #include <VrmlData_ShapeNode.hxx>
23 #include <BRep_Builder.hxx>
24 #include <BRep_Tool.hxx>
25 #include <Geom_Surface.hxx>
26 #include <NCollection_DataMap.hxx>
27 #include <Poly_Triangulation.hxx>
28 #include <Poly_Connect.hxx>
29 #include <Poly_PolygonOnTriangulation.hxx>
30 #include <Poly_Polygon3D.hxx>
31 #include <Precision.hxx>
32 #include <Quantity_ColorRGBA.hxx>
33 #include <TColgp_Array1OfPnt2d.hxx>
34 #include <TDataStd_Name.hxx>
35 #include <TDF_Label.hxx>
36 //#include <TDF_LabelSequence.hxx>
37 #include <TDocStd_Document.hxx>
38 #include <TopExp_Explorer.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Wire.hxx>
44 #include <GCPnts_TangentialDeflection.hxx>
45 #include <BRepAdaptor_Curve.hxx>
46 #include <TColStd_Array1OfReal.hxx>
47 #include <TColStd_HArray1OfReal.hxx>
48 #include <TShort_Array1OfShortReal.hxx>
49 #include <GeomLib.hxx>
50 #include <TShort_HArray1OfShortReal.hxx>
51 #include <VrmlData_Appearance.hxx>
52 #include <XCAFDoc_ColorTool.hxx>
53 #include <XCAFDoc_DocumentTool.hxx>
54 #include <XCAFDoc_ShapeTool.hxx>
57 //=======================================================================
60 //=======================================================================
62 void VrmlData_ShapeConvert::AddShape (const TopoDS_Shape& theShape,
65 ShapeData aData;/* = { - compilation problem on SUN
66 TCollection_AsciiString(),
70 aData.Shape = theShape;
74 char buf[2048], * optr = &buf[0];
75 char * eptr = &buf[sizeof(buf)-1];
76 for (const char * ptr = theName;; ptr++) {
78 if (sym == '\0' || sym == '\n' || sym == '\r') {
82 if (sym == '\"' || sym == '\\')
95 myShapes.Append (aData);
99 //=======================================================================
100 //function : makeTShapeNode
102 //=======================================================================
103 Handle(VrmlData_Geometry) VrmlData_ShapeConvert::makeTShapeNode(const TopoDS_Shape& theShape,
104 const TopAbs_ShapeEnum theShapeType,
105 TopLoc_Location& theLoc)
107 Handle(VrmlData_Geometry) aTShapeNode = 0L;
108 const Standard_Boolean isReverse = (theShape.Orientation() == TopAbs_REVERSED);
110 TopoDS_Shape aTestedShape;
111 aTestedShape.TShape(theShape.TShape());
112 aTestedShape.Orientation(isReverse ? TopAbs_REVERSED : TopAbs_FORWARD);
113 switch (theShapeType) {
116 const TopoDS_Face& aFace = TopoDS::Face(theShape);
117 if (aFace.IsNull() == Standard_False) {
118 Handle(Poly_Triangulation) aTri =
119 BRep_Tool::Triangulation(aFace, theLoc);
121 if (myRelMap.IsBound(aTestedShape)) {
122 aTShapeNode = myRelMap(aTestedShape);
126 if (aTri.IsNull() == Standard_False) {
127 TopoDS_Shape aTestedShapeRev = aTestedShape;
128 aTestedShapeRev.Orientation(isReverse ?
129 TopAbs_FORWARD : TopAbs_REVERSED);
130 Handle(VrmlData_IndexedFaceSet) aFaceSetToReuse;
131 if (myRelMap.IsBound(aTestedShapeRev))
132 aFaceSetToReuse = Handle(VrmlData_IndexedFaceSet)::DownCast
133 (myRelMap(aTestedShapeRev));
135 Handle(VrmlData_Coordinate) aCoordToReuse;
136 if (aFaceSetToReuse.IsNull() == Standard_False)
137 aCoordToReuse = aFaceSetToReuse->Coordinates();
139 aTShapeNode = triToIndexedFaceSet(aTri, aFace, aCoordToReuse);
140 myScene.AddNode(aTShapeNode, Standard_False);
141 // Bind the converted face
142 myRelMap.Bind(aTestedShape, aTShapeNode);
149 const TopoDS_Wire& aWire = TopoDS::Wire(theShape);
150 if (aWire.IsNull() == Standard_False) {
156 const TopoDS_Edge& aEdge = TopoDS::Edge(theShape);
157 if (aEdge.IsNull() == Standard_False) {
158 if (myRelMap.IsBound(aTestedShape)) {
159 aTShapeNode = myRelMap(aTestedShape);
162 // Check the presence of reversly oriented Edge. It can also be used
163 // because we do not distinguish the orientation for edges.
164 aTestedShape.Orientation(isReverse ?
165 TopAbs_FORWARD : TopAbs_REVERSED);
166 if (myRelMap.IsBound(aTestedShape)) {
167 aTShapeNode = myRelMap(aTestedShape);
171 //try to find PolygonOnTriangulation
172 Handle(Poly_PolygonOnTriangulation) aPT;
173 Handle(Poly_Triangulation) aT;
175 BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL);
177 // If PolygonOnTriangulation was found -> get the Polygon3D
178 Handle(Poly_Polygon3D) aPol;
179 if (!aPT.IsNull() && !aT.IsNull() && aPT->HasParameters()) {
180 BRepAdaptor_Curve aCurve(aEdge);
181 Handle(TColStd_HArray1OfReal) aPrs = aPT->Parameters();
182 Standard_Integer nbNodes = aPT->NbNodes();
183 TColgp_Array1OfPnt arrNodes(1, nbNodes);
184 TColStd_Array1OfReal arrUVNodes(1, nbNodes);
186 for (Standard_Integer j = 1; j <= nbNodes; j++) {
187 arrUVNodes(j) = aPrs->Value(aPrs->Lower() + j - 1);
188 arrNodes(j) = aCurve.Value(arrUVNodes(j));
190 aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
191 aPol->Deflection(aPT->Deflection());
194 aPol = BRep_Tool::Polygon3D(aEdge, aL);
196 // If polygon was not found -> generate it
198 BRepAdaptor_Curve aCurve(aEdge);
199 const Standard_Real aFirst = aCurve.FirstParameter();
200 const Standard_Real aLast = aCurve.LastParameter();
202 GCPnts_TangentialDeflection TD(aCurve, aFirst, aLast,
203 myDeflAngle, myDeflection, 2);
204 const Standard_Integer nbNodes = TD.NbPoints();
206 TColgp_Array1OfPnt arrNodes(1, nbNodes);
207 TColStd_Array1OfReal arrUVNodes(1, nbNodes);
208 for (Standard_Integer j = 1; j <= nbNodes; j++) {
209 arrNodes(j) = TD.Value(j);
210 arrUVNodes(j) = TD.Parameter(j);
212 aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
213 aPol->Deflection(myDeflection);
219 aTShapeNode = polToIndexedLineSet(aPol);
220 myScene.AddNode(aTShapeNode, Standard_False);
221 // Bind the converted face
222 myRelMap.Bind(aTestedShape, aTShapeNode);
235 //=======================================================================
238 //=======================================================================
240 void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
241 const Standard_Boolean theExtractEdges,
242 const Standard_Real theDeflection,
243 const Standard_Real theDeflAngle)
245 //const Standard_Real aDeflection =
246 // theDeflection < 0.0001 ? 0.0001 : theDeflection;
248 myDeflection = theDeflection < 0.0001 ? 0.0001 : theDeflection;
249 myDeflAngle = theDeflAngle;
251 Standard_Boolean Extract[2] = {theExtractFaces, theExtractEdges};
252 TopAbs_ShapeEnum ShapeType[2] = {TopAbs_FACE, TopAbs_EDGE};
255 const Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
257 // Relocation map for converted shapes. We should distinguish both TShape
258 // and Orientation in this map.
259 //NCollection_DataMap <TopoDS_Shape,Handle(VrmlData_Geometry)>
260 // aRelMap (100, anAlloc);
261 myRelMap = NCollection_DataMap <TopoDS_Shape, Handle(VrmlData_Geometry)>(100, anAlloc);
263 NCollection_List<ShapeData>::Iterator anIter (myShapes);
264 for (; anIter.More(); anIter.Next())
266 ShapeData& aData = anIter.ChangeValue();
267 TCollection_AsciiString aGrName = aData.Name;
268 aGrName.ChangeAll(' ', '_');
269 aGrName.ChangeAll('#', '_');
270 Handle(VrmlData_Group) aGroup =
271 new VrmlData_Group (myScene, aGrName.ToCString());
272 myScene.AddNode (aGroup);
274 for(i = 0; i < 2; ++i) {
276 if(!Extract[i]) continue;
278 TopExp_Explorer anExp (aData.Shape, ShapeType[i]);
279 for (; anExp.More(); anExp.Next()) {
280 const TopoDS_Shape& aShape = anExp.Current();
281 TopLoc_Location aLoc;
282 Handle(VrmlData_Geometry) aTShapeNode =
283 makeTShapeNode(aShape, ShapeType[i], aLoc);
284 if (!aTShapeNode.IsNull()) {
285 const Handle(VrmlData_ShapeNode) aShapeNode =
286 new VrmlData_ShapeNode (myScene, 0L);
287 aShapeNode->SetAppearance (ShapeType[i] == TopAbs_FACE ?
288 defaultMaterialFace():defaultMaterialEdge());
289 myScene.AddNode (aShapeNode, Standard_False);
290 aShapeNode->SetGeometry (aTShapeNode);
291 if (aLoc.IsIdentity())
292 // Store the shape node directly into the main Group.
293 aGroup->AddNode (aShapeNode);
295 // Create a Transform grouping node
296 Handle(VrmlData_Group) aTrans = new VrmlData_Group (myScene, 0L,
298 gp_Trsf aTrsf (aLoc);
299 if (fabs(myScale - 1.) > Precision::Confusion()) {
300 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
301 aTrsf.SetTranslationPart (aTransl);
303 aTrans->SetTransform (aTrsf);
304 myScene.AddNode (aTrans, Standard_False);
305 aGroup->AddNode (aTrans);
307 // Store the shape node under the transform.
308 aTrans->AddNode (aShapeNode);
317 //=======================================================================
318 //function : triToIndexedFaceSet
320 //=======================================================================
322 Handle(VrmlData_Geometry) VrmlData_ShapeConvert::triToIndexedFaceSet
323 (const Handle(Poly_Triangulation)& theTri,
324 const TopoDS_Face& theFace,
325 const Handle(VrmlData_Coordinate)& theCoord)
328 const Standard_Integer nNodes (theTri->NbNodes());
329 const Standard_Integer nTriangles (theTri->NbTriangles());
330 const TColgp_Array1OfPnt& arrPolyNodes = theTri->Nodes();
331 const Poly_Array1OfTriangle& arrTriangles = theTri->Triangles();
333 // protection against creation degenerative triangles
334 Standard_Integer nbTri = 0;
335 Poly_Array1OfTriangle aTriangles(1, nTriangles);
336 for (i = 0; i < nTriangles; i++) {
337 Standard_Integer idx[3];
338 arrTriangles(i + 1).Get(idx[0], idx[1], idx[2]);
339 if (idx[0] == idx[1] || idx[0] == idx[2] || idx[1] == idx[2])
344 aTriangles.SetValue(nbTri, arrTriangles(i + 1));
346 aTriangles.Resize(1, nbTri, Standard_True);
348 const Handle(VrmlData_IndexedFaceSet) aFaceSet =
349 new VrmlData_IndexedFaceSet (myScene,
351 Standard_True, // IsCCW
352 Standard_False, // IsSolid
353 Standard_False); // IsConvex
354 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
355 const Standard_Boolean isReverse = (theFace.Orientation() == TopAbs_REVERSED);
357 // Create the array of triangles
358 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
359 (anAlloc->Allocate (nbTri * sizeof(const Standard_Integer *)));
360 aFaceSet->SetPolygons (nbTri, arrPolygons);
362 // Store the triangles
363 for (i = 0; i < nbTri; i++) {
364 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
365 (anAlloc->Allocate (4*sizeof(Standard_Integer)));
367 aTriangles(i + 1).Get(aPolygon[1], aPolygon[2], aPolygon[3]);
370 const Standard_Integer aTmp = aPolygon[2]-1;
371 aPolygon[2] = aPolygon[3]-1;
377 arrPolygons[i] = aPolygon;
380 // Create the Coordinates node
381 if (theCoord.IsNull() == Standard_False)
382 aFaceSet->SetCoordinates (theCoord);
384 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
385 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
386 for (i = 0; i < nNodes; i++)
387 arrNodes[i] = arrPolyNodes(i+1).XYZ() * myScale;
389 const Handle(VrmlData_Coordinate) aCoordNode =
390 new VrmlData_Coordinate (myScene, 0L, nNodes, arrNodes);
391 myScene.AddNode (aCoordNode, Standard_False);
392 aFaceSet->SetCoordinates (aCoordNode);
395 // Create the Normals node if theTri has normals
396 if(theTri->HasNormals()) {
397 gp_XYZ * arrVec = static_cast <gp_XYZ *>
398 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
399 const TShort_Array1OfShortReal& Norm = theTri->Normals();
401 for (i = 0, j = 1; i < nNodes; i++, j += 3)
403 gp_XYZ aNormal(Norm(j), Norm(j+1), Norm(j+2));
410 const Handle(VrmlData_Normal) aNormalNode =
411 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
412 myScene.AddNode (aNormalNode, Standard_False);
413 aFaceSet->SetNormals (aNormalNode);
414 return Handle(VrmlData_Geometry) (aFaceSet);
417 Poly_Connect PC(theTri);
418 // Create the Normals node (if UV- values are available)
419 TopLoc_Location aLoc;
420 const Standard_Real aConf2 = Precision::SquareConfusion();
421 const Handle(Geom_Surface) aSurface = BRep_Tool::Surface (theFace, aLoc);
422 if (theTri->HasUVNodes() && aSurface.IsNull() == Standard_False) {
423 if (aSurface->IsCNu(1) && aSurface->IsCNv(1))
425 Standard_Integer nbNormVal = nNodes * 3;
426 Handle(TShort_HArray1OfShortReal) Normals =
427 new TShort_HArray1OfShortReal(1, nbNormVal);
429 const TColgp_Array1OfPnt2d& arrUV = theTri->UVNodes();
430 gp_XYZ * arrVec = static_cast <gp_XYZ *>
431 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
433 // Compute the normal vectors
434 Standard_Real Tol = Sqrt(aConf2);
435 for (i = 0; i < nNodes; i++) {
436 const gp_Pnt2d& aUV = arrUV(i+1);
440 if (GeomLib::NormEstim(aSurface, aUV, Tol, aNormal) > 1) {
441 //Try to estimate as middle normal of adjacent triangles
442 Standard_Integer n[3];
444 gp_XYZ eqPlan(0., 0., 0.);
445 for (PC.Initialize(i+1); PC.More(); PC.Next()) {
446 aTriangles(PC.Value()).Get(n[0], n[1], n[2]);
447 gp_XYZ v1(arrPolyNodes(n[1]).Coord()-arrPolyNodes(n[0]).Coord());
448 gp_XYZ v2(arrPolyNodes(n[2]).Coord()-arrPolyNodes(n[1]).Coord());
451 Standard_Real mod = vv.Modulus();
458 if (eqPlan.SquareModulus() > gp::Resolution())
459 aNormal = gp_Dir(eqPlan);
464 if (aNormal.X()*aNormal.X() < aConf2)
466 if (aNormal.Y()*aNormal.Y() < aConf2)
468 if (aNormal.Z()*aNormal.Z() < aConf2)
470 arrVec[i] = aNormal.XYZ();
472 Standard_Integer j = i * 3;
473 Normals->SetValue(j + 1, (Standard_ShortReal)aNormal.X());
474 Normals->SetValue(j + 2, (Standard_ShortReal)aNormal.Y());
475 Normals->SetValue(j + 3, (Standard_ShortReal)aNormal.Z());
479 theTri->SetNormals(Normals);
481 const Handle(VrmlData_Normal) aNormalNode =
482 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
483 myScene.AddNode (aNormalNode, Standard_False);
484 aFaceSet->SetNormals (aNormalNode);
488 return Handle(VrmlData_Geometry) (aFaceSet);
491 //=======================================================================
492 //function : polToIndexedLineSet
493 //purpose : single polygon3D => IndexedLineSet
494 //=======================================================================
496 Handle(VrmlData_Geometry) VrmlData_ShapeConvert::polToIndexedLineSet
497 (const Handle(Poly_Polygon3D)& thePol)
500 const Standard_Integer nNodes (thePol->NbNodes());
501 const TColgp_Array1OfPnt& arrPolyNodes = thePol->Nodes();
502 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
504 const Handle(VrmlData_IndexedLineSet) aLineSet =
505 new VrmlData_IndexedLineSet (myScene, 0L);
507 // Create the array of polygons (1 member)
508 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
509 (anAlloc->Allocate (sizeof(const Standard_Integer *)));
510 aLineSet->SetPolygons (1, arrPolygons);
513 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
514 (anAlloc->Allocate ((nNodes+1)*sizeof(Standard_Integer)));
515 aPolygon[0] = nNodes;
516 for (i = 1; i <= nNodes; i++)
518 arrPolygons[0] = aPolygon;
520 // Create the Coordinates node
521 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
522 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
523 for (i = 0; i < nNodes; i++)
524 arrNodes[i] = arrPolyNodes(i+1).XYZ() * myScale;
526 const Handle(VrmlData_Coordinate) aCoordNode =
527 new VrmlData_Coordinate (myScene, 0L, nNodes, arrNodes);
528 myScene.AddNode (aCoordNode, Standard_False);
529 aLineSet->SetCoordinates (aCoordNode);
531 return Handle(VrmlData_Geometry) (aLineSet);
534 //=======================================================================
535 //function : defaultMaterialFace
537 //=======================================================================
539 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialFace () const
541 static char aNodeName[] = "__defaultMaterialFace";
542 Handle(VrmlData_Appearance) anAppearance =
543 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
544 if (anAppearance.IsNull()) {
545 const Handle(VrmlData_Material) aMaterial =
546 new VrmlData_Material (myScene, 0L, 1.0, 0.022, 0.);
547 aMaterial->SetDiffuseColor (Quantity_Color(0.780392, 0.568627, 0.113725,
549 aMaterial->SetEmissiveColor(Quantity_Color(0.329412, 0.223529, 0.027451,
551 aMaterial->SetSpecularColor(Quantity_Color(0.992157, 0.941176, 0.807843,
553 myScene.AddNode (aMaterial, Standard_False);
554 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
555 anAppearance->SetMaterial (aMaterial);
556 myScene.AddNode (anAppearance, Standard_False);
561 //=======================================================================
562 //function : defaultMaterialEdge
564 //=======================================================================
566 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialEdge () const
568 static char aNodeName[] = "__defaultMaterialEdge";
569 Handle(VrmlData_Appearance) anAppearance =
570 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
571 if (anAppearance.IsNull()) {
572 const Handle(VrmlData_Material) aMaterial =
573 new VrmlData_Material (myScene, 0L, 0.2, 0.2, 0.2);
574 aMaterial->SetDiffuseColor (Quantity_Color(0.2, 0.7, 0.2,
576 aMaterial->SetEmissiveColor(Quantity_Color(0.2, 0.7, 0.2,
578 aMaterial->SetSpecularColor(Quantity_Color(0.2, 0.7, 0.2,
580 myScene.AddNode (aMaterial, Standard_False);
581 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
582 anAppearance->SetMaterial (aMaterial);
583 myScene.AddNode (anAppearance, Standard_False);
589 //=======================================================================
590 //function : addShape
591 //purpose : Adds the shape from the document
592 //=======================================================================
593 void VrmlData_ShapeConvert::addShape (const Handle(VrmlData_Group)& theParent,
594 const TDF_Label& theLabel,
595 const Handle(TDocStd_Document)& theDoc)
597 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
598 Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(theDoc->Main());
600 NCollection_DataMap<TopoDS_Shape, TDF_Label> aChildShapeToLabels;
601 TDF_LabelSequence aChildLabels;
602 aShapeTool->GetSubShapes(theLabel, aChildLabels);
603 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
605 const TDF_Label& aChildLabel = aChildIter.Value();
606 TopoDS_Shape aChildShape;
607 if (aShapeTool->GetShape(aChildLabel, aChildShape))
609 aChildShapeToLabels.Bind(aChildShape, aChildLabel);
613 const TopoDS_Shape aShape = aShapeTool->GetShape(theLabel);
614 Handle(VrmlData_Group) aGroup = 0L;
615 TopExp_Explorer anExp(aShape, TopAbs_FACE);
616 Standard_Integer nbFaces = 0;
617 for (; anExp.More(); anExp.Next()) {
620 Handle(TDataStd_Name) aNameAttribute;
621 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
624 if (!aNameAttribute.IsNull())
626 TCollection_AsciiString aName = aNameAttribute->Get();
627 aName.ChangeAll(' ', '_');
628 aName.ChangeAll('#', '_');
629 aGroup = new VrmlData_Group(myScene, aName.ToCString());
633 aGroup = new VrmlData_Group(myScene, 0L);
635 myScene.AddNode(aGroup, theParent.IsNull());
636 if (!theParent.IsNull())
638 theParent->AddNode(aGroup);
642 anExp.Init(aShape, TopAbs_FACE);
643 for (; anExp.More(); anExp.Next()) {
644 TopLoc_Location aLoc;
645 Handle(VrmlData_Geometry) aTShapeNode =
646 makeTShapeNode(anExp.Current(), TopAbs_FACE, aLoc);
647 if (!aTShapeNode.IsNull())
649 Handle(VrmlData_ShapeNode) aShapeNode = 0L;
650 if (aGroup.IsNull() && !aNameAttribute.IsNull())
652 TCollection_AsciiString aName = aNameAttribute->Get();
653 aName.ChangeAll(' ', '_');
654 aName.ChangeAll('#', '_');
655 aShapeNode = new VrmlData_ShapeNode(myScene, aName.ToCString());
659 aShapeNode = new VrmlData_ShapeNode(myScene, 0L);
664 Standard_Boolean findColor = Standard_False;
665 const TDF_Label* aLabel = aChildShapeToLabels.Seek(anExp.Current());
668 findColor = aColorTool->GetColor(*aLabel, XCAFDoc_ColorSurf, aColorL)
669 || aColorTool->GetColor(*aLabel, XCAFDoc_ColorGen, aColorL);
673 findColor = aColorTool->GetColor(theLabel, XCAFDoc_ColorSurf, aColorL)
674 || aColorTool->GetColor(theLabel, XCAFDoc_ColorGen, aColorL);
678 aShapeNode->SetAppearance(defaultMaterialFace());
682 aShapeNode->SetAppearance(makeMaterialFromColor(aColorL, aColorTool));
685 myScene.AddNode(aShapeNode, Standard_False);
686 aShapeNode->SetGeometry(aTShapeNode);
687 if (aLoc.IsIdentity())
689 // Store the shape node directly into the main Group.
690 if (!aGroup.IsNull())
692 aGroup->AddNode(aShapeNode);
696 theParent->AddNode(aShapeNode);
701 // Create a Transform grouping node
702 Handle(VrmlData_Group) aTrans = new VrmlData_Group(myScene, 0L,
705 if (fabs(myScale - 1.) > Precision::Confusion())
707 aTrsf.SetScaleFactor(myScale);
709 aTrans->SetTransform(aTrsf);
710 myScene.AddNode(aTrans, Standard_False);
711 if (!aGroup.IsNull())
713 aGroup->AddNode(aTrans);
717 theParent->AddNode(aTrans);
719 // Store the shape node under the transform.
720 aTrans->AddNode(aShapeNode);
727 //=======================================================================
728 //function : addInstance
729 //purpose : Adds the reference from the document
730 //=======================================================================
731 void VrmlData_ShapeConvert::addInstance (const Handle(VrmlData_Group)& theParent,
732 const TDF_Label& theLabel,
733 const Handle(TDocStd_Document)& theDoc)
735 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
737 const TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
738 Handle(VrmlData_Group) aTrans = 0L;
739 if (!aLoc.IsIdentity())
741 // Create a Transform grouping node
742 aTrans = new VrmlData_Group(myScene, 0L, Standard_True);
744 if (fabs(myScale - 1.) > Precision::Confusion()) {
745 aTrsf.SetScaleFactor(myScale);
747 aTrans->SetTransform(aTrsf);
748 myScene.AddNode(aTrans, theParent.IsNull());
749 if (!theParent.IsNull())
751 theParent->AddNode(aTrans);
755 Handle(TDataStd_Name) aNameAttribute;
756 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
759 aShapeTool->GetReferredShape(theLabel, aRefLabel);
760 Handle(TDataStd_Name) aRefNameAttribute;
761 aRefLabel.FindAttribute(TDataStd_Name::GetID(), aRefNameAttribute);
763 if (aShapeTool->IsSimpleShape(aRefLabel))
765 addShape((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc);
767 else if (aShapeTool->IsAssembly(aRefLabel))
769 addAssembly((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc, aTrans.IsNull());
774 //=======================================================================
775 //function : addAssembly
776 //purpose : Adds the assembly from the document
777 //=======================================================================
778 void VrmlData_ShapeConvert::addAssembly (const Handle(VrmlData_Group)& theParent,
779 const TDF_Label& theLabel,
780 const Handle(TDocStd_Document)& theDoc,
781 const Standard_Boolean theNeedCreateGroup)
783 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
785 Handle(VrmlData_Group) anAssembly = 0L;
786 if (theNeedCreateGroup)
788 Handle(TDataStd_Name) aNameAttribute;
789 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
790 if (!aNameAttribute.IsNull())
792 TCollection_AsciiString aName = aNameAttribute->Get();
793 aName.ChangeAll(' ', '_');
794 aName.ChangeAll('#', '_');
795 anAssembly = new VrmlData_Group(myScene, aName.ToCString());
799 anAssembly = new VrmlData_Group(myScene, 0L);
801 TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
802 if (!aLoc.IsIdentity())
805 if (fabs(myScale - 1.) > Precision::Confusion()) {
806 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
807 aTrsf.SetTranslationPart(aTransl);
809 anAssembly->SetTransform(aTrsf);
811 myScene.AddNode(anAssembly, theParent.IsNull());
812 if (!theParent.IsNull())
814 theParent->AddNode(anAssembly);
818 TDF_LabelSequence aChildLabels;
819 aShapeTool->GetComponents(theLabel, aChildLabels);
820 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
822 const TDF_Label& aChildLabel = aChildIter.Value();
823 if (aShapeTool->IsAssembly(aChildLabel))
825 addAssembly((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc, anAssembly.IsNull());
827 else if (aShapeTool->IsReference(aChildLabel))
829 addInstance((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
831 else if (aShapeTool->IsSimpleShape(aChildLabel))
833 addShape((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
839 //=======================================================================
840 //function : ConvertDocument
842 //=======================================================================
843 void VrmlData_ShapeConvert::ConvertDocument(const Handle(TDocStd_Document) &theDoc)
845 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
847 TDF_LabelSequence aFreeShapeLabels;
848 aShapeTool->GetFreeShapes(aFreeShapeLabels);
850 Handle(VrmlData_Group) aGroup = 0L;
851 if (aFreeShapeLabels.Size() > 1)
853 aGroup = new VrmlData_Group(myScene, 0L);
854 myScene.AddNode(aGroup);
857 for (TDF_LabelSequence::Iterator aRootIter(aFreeShapeLabels); aRootIter.More(); aRootIter.Next())
859 const TDF_Label& aFreeShapeLabel = aRootIter.Value();
860 if (aShapeTool->IsSimpleShape(aFreeShapeLabel))
862 addShape(aGroup, aFreeShapeLabel, theDoc);
864 else if (aShapeTool->IsAssembly(aFreeShapeLabel))
866 addAssembly(aGroup, aFreeShapeLabel, theDoc, Standard_True);
872 //=======================================================================
873 //function : makeMaterialFromColor
875 //=======================================================================
877 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::makeMaterialFromColor(
878 const TDF_Label& theColorL,
879 const Handle(XCAFDoc_ColorTool)& theColorTool) const
881 Quantity_ColorRGBA aColor;
882 theColorTool->GetColor(theColorL, aColor);
884 TCollection_AsciiString aNodeName = "_materialFace_";
885 Handle(TDataStd_Name) aNameAttribute;
886 if (theColorL.FindAttribute(TDataStd_Name::GetID(), aNameAttribute))
888 aNodeName.AssignCat(aNameAttribute->Get());
889 Standard_Integer n = aNodeName.Search(" ");
892 aNodeName = aNodeName.SubString(1, n - 1);
897 aNodeName.AssignCat(aColor.GetRGB().Red());
898 aNodeName.AssignCat("_");
899 aNodeName.AssignCat(aColor.GetRGB().Green());
900 aNodeName.AssignCat("_");
901 aNodeName.AssignCat(aColor.GetRGB().Blue());
904 Handle(VrmlData_Appearance) anAppearance =
905 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName.ToCString()));
906 if (anAppearance.IsNull()) {
907 const Handle(VrmlData_Material) aMaterial =
908 new VrmlData_Material(myScene, 0L);
909 aMaterial->SetDiffuseColor(aColor.GetRGB());
910 myScene.AddNode(aMaterial, Standard_False);
911 anAppearance = new VrmlData_Appearance(myScene, aNodeName.ToCString());
912 anAppearance->SetMaterial(aMaterial);
913 myScene.AddNode(anAppearance, Standard_False);