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>
55 #include <XCAFPrs_Style.hxx>
56 #include <XCAFDoc_VisMaterial.hxx>
57 #include <XCAFDoc_VisMaterialTool.hxx>
59 //=======================================================================
62 //=======================================================================
64 void VrmlData_ShapeConvert::AddShape (const TopoDS_Shape& theShape,
67 ShapeData aData;/* = { - compilation problem on SUN
68 TCollection_AsciiString(),
72 aData.Shape = theShape;
76 char buf[2048], * optr = &buf[0];
77 char * eptr = &buf[sizeof(buf)-1];
78 for (const char * ptr = theName;; ptr++) {
80 if (sym == '\0' || sym == '\n' || sym == '\r') {
84 if (sym == '\"' || sym == '\\')
97 myShapes.Append (aData);
101 //=======================================================================
102 //function : makeTShapeNode
104 //=======================================================================
105 Handle(VrmlData_Geometry) VrmlData_ShapeConvert::makeTShapeNode(const TopoDS_Shape& theShape,
106 const TopAbs_ShapeEnum theShapeType,
107 TopLoc_Location& theLoc)
109 Handle(VrmlData_Geometry) aTShapeNode = 0L;
110 const Standard_Boolean isReverse = (theShape.Orientation() == TopAbs_REVERSED);
112 TopoDS_Shape aTestedShape;
113 aTestedShape.TShape(theShape.TShape());
114 aTestedShape.Orientation(isReverse ? TopAbs_REVERSED : TopAbs_FORWARD);
115 switch (theShapeType) {
118 const TopoDS_Face& aFace = TopoDS::Face(theShape);
119 if (aFace.IsNull() == Standard_False) {
120 Handle(Poly_Triangulation) aTri =
121 BRep_Tool::Triangulation(aFace, theLoc);
123 if (myRelMap.IsBound(aTestedShape)) {
124 aTShapeNode = myRelMap(aTestedShape);
128 if (aTri.IsNull() == Standard_False) {
129 TopoDS_Shape aTestedShapeRev = aTestedShape;
130 aTestedShapeRev.Orientation(isReverse ?
131 TopAbs_FORWARD : TopAbs_REVERSED);
132 Handle(VrmlData_IndexedFaceSet) aFaceSetToReuse;
133 if (myRelMap.IsBound(aTestedShapeRev))
134 aFaceSetToReuse = Handle(VrmlData_IndexedFaceSet)::DownCast
135 (myRelMap(aTestedShapeRev));
137 Handle(VrmlData_Coordinate) aCoordToReuse;
138 if (aFaceSetToReuse.IsNull() == Standard_False)
139 aCoordToReuse = aFaceSetToReuse->Coordinates();
141 aTShapeNode = triToIndexedFaceSet(aTri, aFace, aCoordToReuse);
142 myScene.AddNode(aTShapeNode, Standard_False);
143 // Bind the converted face
144 myRelMap.Bind(aTestedShape, aTShapeNode);
151 const TopoDS_Wire& aWire = TopoDS::Wire(theShape);
152 if (aWire.IsNull() == Standard_False) {
158 const TopoDS_Edge& aEdge = TopoDS::Edge(theShape);
159 if (aEdge.IsNull() == Standard_False) {
160 if (myRelMap.IsBound(aTestedShape)) {
161 aTShapeNode = myRelMap(aTestedShape);
164 // Check the presence of reversly oriented Edge. It can also be used
165 // because we do not distinguish the orientation for edges.
166 aTestedShape.Orientation(isReverse ?
167 TopAbs_FORWARD : TopAbs_REVERSED);
168 if (myRelMap.IsBound(aTestedShape)) {
169 aTShapeNode = myRelMap(aTestedShape);
173 //try to find PolygonOnTriangulation
174 Handle(Poly_PolygonOnTriangulation) aPT;
175 Handle(Poly_Triangulation) aT;
177 BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL);
179 // If PolygonOnTriangulation was found -> get the Polygon3D
180 Handle(Poly_Polygon3D) aPol;
181 if (!aPT.IsNull() && !aT.IsNull() && aPT->HasParameters()) {
182 BRepAdaptor_Curve aCurve(aEdge);
183 Handle(TColStd_HArray1OfReal) aPrs = aPT->Parameters();
184 Standard_Integer nbNodes = aPT->NbNodes();
185 TColgp_Array1OfPnt arrNodes(1, nbNodes);
186 TColStd_Array1OfReal arrUVNodes(1, nbNodes);
188 for (Standard_Integer j = 1; j <= nbNodes; j++) {
189 arrUVNodes(j) = aPrs->Value(aPrs->Lower() + j - 1);
190 arrNodes(j) = aCurve.Value(arrUVNodes(j));
192 aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
193 aPol->Deflection(aPT->Deflection());
196 aPol = BRep_Tool::Polygon3D(aEdge, aL);
198 // If polygon was not found -> generate it
200 BRepAdaptor_Curve aCurve(aEdge);
201 const Standard_Real aFirst = aCurve.FirstParameter();
202 const Standard_Real aLast = aCurve.LastParameter();
204 GCPnts_TangentialDeflection TD(aCurve, aFirst, aLast,
205 myDeflAngle, myDeflection, 2);
206 const Standard_Integer nbNodes = TD.NbPoints();
208 TColgp_Array1OfPnt arrNodes(1, nbNodes);
209 TColStd_Array1OfReal arrUVNodes(1, nbNodes);
210 for (Standard_Integer j = 1; j <= nbNodes; j++) {
211 arrNodes(j) = TD.Value(j);
212 arrUVNodes(j) = TD.Parameter(j);
214 aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
215 aPol->Deflection(myDeflection);
221 aTShapeNode = polToIndexedLineSet(aPol);
222 myScene.AddNode(aTShapeNode, Standard_False);
223 // Bind the converted face
224 myRelMap.Bind(aTestedShape, aTShapeNode);
237 //=======================================================================
240 //=======================================================================
242 void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
243 const Standard_Boolean theExtractEdges,
244 const Standard_Real theDeflection,
245 const Standard_Real theDeflAngle)
247 //const Standard_Real aDeflection =
248 // theDeflection < 0.0001 ? 0.0001 : theDeflection;
250 myDeflection = theDeflection < 0.0001 ? 0.0001 : theDeflection;
251 myDeflAngle = theDeflAngle;
253 Standard_Boolean Extract[2] = {theExtractFaces, theExtractEdges};
254 TopAbs_ShapeEnum ShapeType[2] = {TopAbs_FACE, TopAbs_EDGE};
257 const Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
259 // Relocation map for converted shapes. We should distinguish both TShape
260 // and Orientation in this map.
261 //NCollection_DataMap <TopoDS_Shape,Handle(VrmlData_Geometry)>
262 // aRelMap (100, anAlloc);
263 myRelMap = NCollection_DataMap <TopoDS_Shape, Handle(VrmlData_Geometry)>(100, anAlloc);
265 NCollection_List<ShapeData>::Iterator anIter (myShapes);
266 for (; anIter.More(); anIter.Next())
268 ShapeData& aData = anIter.ChangeValue();
269 TCollection_AsciiString aGrName = aData.Name;
270 aGrName.ChangeAll(' ', '_');
271 aGrName.ChangeAll('#', '_');
272 Handle(VrmlData_Group) aGroup =
273 new VrmlData_Group (myScene, aGrName.ToCString());
274 myScene.AddNode (aGroup);
276 for(i = 0; i < 2; ++i) {
278 if(!Extract[i]) continue;
280 TopExp_Explorer anExp (aData.Shape, ShapeType[i]);
281 for (; anExp.More(); anExp.Next()) {
282 const TopoDS_Shape& aShape = anExp.Current();
283 TopLoc_Location aLoc;
284 Handle(VrmlData_Geometry) aTShapeNode =
285 makeTShapeNode(aShape, ShapeType[i], aLoc);
286 if (!aTShapeNode.IsNull()) {
287 const Handle(VrmlData_ShapeNode) aShapeNode =
288 new VrmlData_ShapeNode (myScene, 0L);
289 aShapeNode->SetAppearance (ShapeType[i] == TopAbs_FACE ?
290 defaultMaterialFace():defaultMaterialEdge());
291 myScene.AddNode (aShapeNode, Standard_False);
292 aShapeNode->SetGeometry (aTShapeNode);
293 if (aLoc.IsIdentity())
294 // Store the shape node directly into the main Group.
295 aGroup->AddNode (aShapeNode);
297 // Create a Transform grouping node
298 Handle(VrmlData_Group) aTrans = new VrmlData_Group (myScene, 0L,
300 gp_Trsf aTrsf (aLoc);
301 if (fabs(myScale - 1.) > Precision::Confusion())
303 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
304 aTrsf.SetTranslationPart (aTransl);
306 aTrans->SetTransform (aTrsf);
307 myScene.AddNode (aTrans, Standard_False);
308 aGroup->AddNode (aTrans);
310 // Store the shape node under the transform.
311 aTrans->AddNode (aShapeNode);
320 //=======================================================================
321 //function : triToIndexedFaceSet
323 //=======================================================================
325 Handle(VrmlData_Geometry) VrmlData_ShapeConvert::triToIndexedFaceSet
326 (const Handle(Poly_Triangulation)& theTri,
327 const TopoDS_Face& theFace,
328 const Handle(VrmlData_Coordinate)& theCoord)
331 const Standard_Integer nNodes (theTri->NbNodes());
332 const Standard_Integer nTriangles (theTri->NbTriangles());
333 const TColgp_Array1OfPnt& arrPolyNodes = theTri->Nodes();
334 const Poly_Array1OfTriangle& arrTriangles = theTri->Triangles();
336 // protection against creation degenerative triangles
337 Standard_Integer nbTri = 0;
338 Poly_Array1OfTriangle aTriangles(1, nTriangles);
339 for (i = 0; i < nTriangles; i++) {
340 Standard_Integer idx[3];
341 arrTriangles(i + 1).Get(idx[0], idx[1], idx[2]);
342 if (idx[0] == idx[1] || idx[0] == idx[2] || idx[1] == idx[2])
347 aTriangles.SetValue(nbTri, arrTriangles(i + 1));
349 aTriangles.Resize(1, nbTri, Standard_True);
351 const Handle(VrmlData_IndexedFaceSet) aFaceSet =
352 new VrmlData_IndexedFaceSet (myScene,
354 Standard_True, // IsCCW
355 Standard_False, // IsSolid
356 Standard_False); // IsConvex
357 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
358 const Standard_Boolean isReverse = (theFace.Orientation() == TopAbs_REVERSED);
360 // Create the array of triangles
361 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
362 (anAlloc->Allocate (nbTri * sizeof(const Standard_Integer *)));
363 aFaceSet->SetPolygons (nbTri, arrPolygons);
365 // Store the triangles
366 for (i = 0; i < nbTri; i++) {
367 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
368 (anAlloc->Allocate (4*sizeof(Standard_Integer)));
370 aTriangles(i + 1).Get(aPolygon[1], aPolygon[2], aPolygon[3]);
373 const Standard_Integer aTmp = aPolygon[2]-1;
374 aPolygon[2] = aPolygon[3]-1;
380 arrPolygons[i] = aPolygon;
383 // Create the Coordinates node
384 if (theCoord.IsNull() == Standard_False)
385 aFaceSet->SetCoordinates (theCoord);
387 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
388 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
389 for (i = 0; i < nNodes; i++)
390 arrNodes[i] = arrPolyNodes(i+1).XYZ() * myScale;
392 const Handle(VrmlData_Coordinate) aCoordNode =
393 new VrmlData_Coordinate (myScene, 0L, nNodes, arrNodes);
394 myScene.AddNode (aCoordNode, Standard_False);
395 aFaceSet->SetCoordinates (aCoordNode);
398 // Create the Normals node if theTri has normals
399 if(theTri->HasNormals()) {
400 gp_XYZ * arrVec = static_cast <gp_XYZ *>
401 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
402 const TShort_Array1OfShortReal& Norm = theTri->Normals();
404 for (i = 0, j = 1; i < nNodes; i++, j += 3)
406 gp_XYZ aNormal(Norm(j), Norm(j+1), Norm(j+2));
413 const Handle(VrmlData_Normal) aNormalNode =
414 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
415 myScene.AddNode (aNormalNode, Standard_False);
416 aFaceSet->SetNormals (aNormalNode);
417 return Handle(VrmlData_Geometry) (aFaceSet);
420 Poly_Connect PC(theTri);
421 // Create the Normals node (if UV- values are available)
422 TopLoc_Location aLoc;
423 const Standard_Real aConf2 = Precision::SquareConfusion();
424 const Handle(Geom_Surface) aSurface = BRep_Tool::Surface (theFace, aLoc);
425 if (theTri->HasUVNodes() && aSurface.IsNull() == Standard_False) {
426 if (aSurface->IsCNu(1) && aSurface->IsCNv(1))
428 Standard_Integer nbNormVal = nNodes * 3;
429 Handle(TShort_HArray1OfShortReal) Normals =
430 new TShort_HArray1OfShortReal(1, nbNormVal);
432 const TColgp_Array1OfPnt2d& arrUV = theTri->UVNodes();
433 gp_XYZ * arrVec = static_cast <gp_XYZ *>
434 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
436 // Compute the normal vectors
437 Standard_Real Tol = Sqrt(aConf2);
438 for (i = 0; i < nNodes; i++) {
439 const gp_Pnt2d& aUV = arrUV(i+1);
443 if (GeomLib::NormEstim(aSurface, aUV, Tol, aNormal) > 1) {
444 //Try to estimate as middle normal of adjacent triangles
445 Standard_Integer n[3];
447 gp_XYZ eqPlan(0., 0., 0.);
448 for (PC.Initialize(i+1); PC.More(); PC.Next()) {
449 aTriangles(PC.Value()).Get(n[0], n[1], n[2]);
450 gp_XYZ v1(arrPolyNodes(n[1]).Coord()-arrPolyNodes(n[0]).Coord());
451 gp_XYZ v2(arrPolyNodes(n[2]).Coord()-arrPolyNodes(n[1]).Coord());
454 Standard_Real mod = vv.Modulus();
461 if (eqPlan.SquareModulus() > gp::Resolution())
462 aNormal = gp_Dir(eqPlan);
467 if (aNormal.X()*aNormal.X() < aConf2)
469 if (aNormal.Y()*aNormal.Y() < aConf2)
471 if (aNormal.Z()*aNormal.Z() < aConf2)
473 arrVec[i] = aNormal.XYZ();
475 Standard_Integer j = i * 3;
476 Normals->SetValue(j + 1, (Standard_ShortReal)aNormal.X());
477 Normals->SetValue(j + 2, (Standard_ShortReal)aNormal.Y());
478 Normals->SetValue(j + 3, (Standard_ShortReal)aNormal.Z());
482 theTri->SetNormals(Normals);
484 const Handle(VrmlData_Normal) aNormalNode =
485 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
486 myScene.AddNode (aNormalNode, Standard_False);
487 aFaceSet->SetNormals (aNormalNode);
491 return Handle(VrmlData_Geometry) (aFaceSet);
494 //=======================================================================
495 //function : polToIndexedLineSet
496 //purpose : single polygon3D => IndexedLineSet
497 //=======================================================================
499 Handle(VrmlData_Geometry) VrmlData_ShapeConvert::polToIndexedLineSet
500 (const Handle(Poly_Polygon3D)& thePol)
503 const Standard_Integer nNodes (thePol->NbNodes());
504 const TColgp_Array1OfPnt& arrPolyNodes = thePol->Nodes();
505 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
507 const Handle(VrmlData_IndexedLineSet) aLineSet =
508 new VrmlData_IndexedLineSet (myScene, 0L);
510 // Create the array of polygons (1 member)
511 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
512 (anAlloc->Allocate (sizeof(const Standard_Integer *)));
513 aLineSet->SetPolygons (1, arrPolygons);
516 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
517 (anAlloc->Allocate ((nNodes+1)*sizeof(Standard_Integer)));
518 aPolygon[0] = nNodes;
519 for (i = 1; i <= nNodes; i++)
521 arrPolygons[0] = aPolygon;
523 // Create the Coordinates node
524 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
525 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
526 for (i = 0; i < nNodes; i++)
527 arrNodes[i] = arrPolyNodes(i+1).XYZ() * myScale;
529 const Handle(VrmlData_Coordinate) aCoordNode =
530 new VrmlData_Coordinate (myScene, 0L, nNodes, arrNodes);
531 myScene.AddNode (aCoordNode, Standard_False);
532 aLineSet->SetCoordinates (aCoordNode);
534 return Handle(VrmlData_Geometry) (aLineSet);
537 //=======================================================================
538 //function : defaultMaterialFace
540 //=======================================================================
542 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialFace () const
544 static char aNodeName[] = "__defaultMaterialFace";
545 Handle(VrmlData_Appearance) anAppearance =
546 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
547 if (anAppearance.IsNull()) {
548 const Handle(VrmlData_Material) aMaterial =
549 new VrmlData_Material (myScene, 0L, 1.0, 0.022, 0.);
550 aMaterial->SetDiffuseColor (Quantity_Color(0.780392, 0.568627, 0.113725,
552 aMaterial->SetEmissiveColor(Quantity_Color(0.329412, 0.223529, 0.027451,
554 aMaterial->SetSpecularColor(Quantity_Color(0.992157, 0.941176, 0.807843,
556 myScene.AddNode (aMaterial, Standard_False);
557 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
558 anAppearance->SetMaterial (aMaterial);
559 myScene.AddNode (anAppearance, Standard_False);
564 //=======================================================================
565 //function : defaultMaterialEdge
567 //=======================================================================
569 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialEdge () const
571 static char aNodeName[] = "__defaultMaterialEdge";
572 Handle(VrmlData_Appearance) anAppearance =
573 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
574 if (anAppearance.IsNull()) {
575 const Handle(VrmlData_Material) aMaterial =
576 new VrmlData_Material (myScene, 0L, 0.2, 0.2, 0.2);
577 aMaterial->SetDiffuseColor (Quantity_Color(0.2, 0.7, 0.2,
579 aMaterial->SetEmissiveColor(Quantity_Color(0.2, 0.7, 0.2,
581 aMaterial->SetSpecularColor(Quantity_Color(0.2, 0.7, 0.2,
583 myScene.AddNode (aMaterial, Standard_False);
584 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
585 anAppearance->SetMaterial (aMaterial);
586 myScene.AddNode (anAppearance, Standard_False);
592 //=======================================================================
593 //function : addShape
594 //purpose : Adds the shape from the document
595 //=======================================================================
596 void VrmlData_ShapeConvert::addShape (const Handle(VrmlData_Group)& theParent,
597 const TDF_Label& theLabel,
598 const Handle(TDocStd_Document)& theDoc)
600 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
601 Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(theDoc->Main());
602 Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool(theDoc->Main());
604 NCollection_DataMap<TopoDS_Shape, TDF_Label> aChildShapeToLabels;
605 TDF_LabelSequence aChildLabels;
606 aShapeTool->GetSubShapes(theLabel, aChildLabels);
607 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
609 const TDF_Label& aChildLabel = aChildIter.Value();
610 TopoDS_Shape aChildShape;
611 if (aShapeTool->GetShape(aChildLabel, aChildShape))
613 aChildShapeToLabels.Bind(aChildShape, aChildLabel);
617 const TopoDS_Shape aShape = aShapeTool->GetShape(theLabel);
618 Handle(VrmlData_Group) aGroup = 0L;
619 TopExp_Explorer anExp(aShape, TopAbs_FACE);
620 Standard_Integer nbFaces = 0;
621 for (; anExp.More(); anExp.Next()) {
624 Handle(TDataStd_Name) aNameAttribute;
625 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
628 if (!aNameAttribute.IsNull())
630 TCollection_AsciiString aName = aNameAttribute->Get();
631 aName.ChangeAll(' ', '_');
632 aName.ChangeAll('#', '_');
633 aGroup = new VrmlData_Group(myScene, aName.ToCString());
637 aGroup = new VrmlData_Group(myScene, 0L);
639 myScene.AddNode(aGroup, theParent.IsNull());
640 if (!theParent.IsNull())
642 theParent->AddNode(aGroup);
646 anExp.Init(aShape, TopAbs_FACE);
647 for (; anExp.More(); anExp.Next()) {
648 TopLoc_Location aLoc;
649 Handle(VrmlData_Geometry) aTShapeNode =
650 makeTShapeNode(anExp.Current(), TopAbs_FACE, aLoc);
651 if (!aTShapeNode.IsNull())
653 Handle(VrmlData_ShapeNode) aShapeNode = 0L;
654 if (aGroup.IsNull() && !aNameAttribute.IsNull())
656 TCollection_AsciiString aName = aNameAttribute->Get();
657 aName.ChangeAll(' ', '_');
658 aName.ChangeAll('#', '_');
659 aShapeNode = new VrmlData_ShapeNode(myScene, aName.ToCString());
663 aShapeNode = new VrmlData_ShapeNode(myScene, 0L);
667 XCAFPrs_Style aStyle;
668 Quantity_ColorRGBA aColor;
669 TDF_Label aLabel, anAttribLab;
670 if (aChildShapeToLabels.Find (anExp.Current(), aLabel))
672 Handle(XCAFDoc_VisMaterial) aVisMat = aMatTool->GetShapeMaterial (aLabel);
673 if (!aVisMat.IsNull()
674 && !aVisMat->IsEmpty())
676 anAttribLab = aVisMat->Label();
677 aStyle.SetMaterial (aVisMat);
679 else if (aColorTool->GetColor (aLabel, XCAFDoc_ColorSurf, anAttribLab)
680 || aColorTool->GetColor (aLabel, XCAFDoc_ColorGen, anAttribLab))
682 aColorTool->GetColor (anAttribLab, aColor);
683 aStyle.SetColorSurf (aColor);
686 if (!aStyle.IsSetColorSurf()
687 && aStyle.Material().IsNull())
689 Handle(XCAFDoc_VisMaterial) aVisMat = aMatTool->GetShapeMaterial (theLabel);
690 if (!aVisMat.IsNull()
691 && !aVisMat->IsEmpty())
693 anAttribLab = aVisMat->Label();
694 aStyle.SetMaterial (aVisMat);
696 if (aColorTool->GetColor (theLabel, XCAFDoc_ColorSurf, anAttribLab)
697 || aColorTool->GetColor (theLabel, XCAFDoc_ColorGen, anAttribLab))
699 aColorTool->GetColor (anAttribLab, aColor);
700 aStyle.SetColorSurf (aColor);
703 if (!aStyle.IsSetColorSurf()
704 && aStyle.Material().IsNull())
706 aShapeNode->SetAppearance(defaultMaterialFace());
710 aShapeNode->SetAppearance (makeMaterialFromStyle (aStyle, anAttribLab));
713 myScene.AddNode(aShapeNode, theParent.IsNull() && aGroup.IsNull());
714 aShapeNode->SetGeometry(aTShapeNode);
715 if (aLoc.IsIdentity())
717 // Store the shape node directly into the main Group.
718 if (!aGroup.IsNull())
720 aGroup->AddNode(aShapeNode);
722 else if (!theParent.IsNull())
724 theParent->AddNode(aShapeNode);
729 // Create a Transform grouping node
730 Handle(VrmlData_Group) aTrans = new VrmlData_Group(myScene, 0L,
733 if (fabs(myScale - 1.) > Precision::Confusion())
735 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
736 aTrsf.SetTranslationPart(aTransl);
738 aTrans->SetTransform(aTrsf);
739 myScene.AddNode(aTrans, theParent.IsNull() && aGroup.IsNull());
740 if (!aGroup.IsNull())
742 aGroup->AddNode(aTrans);
744 else if (!theParent.IsNull())
746 theParent->AddNode(aTrans);
748 // Store the shape node under the transform.
749 aTrans->AddNode(aShapeNode);
756 //=======================================================================
757 //function : addInstance
758 //purpose : Adds the reference from the document
759 //=======================================================================
760 void VrmlData_ShapeConvert::addInstance (const Handle(VrmlData_Group)& theParent,
761 const TDF_Label& theLabel,
762 const Handle(TDocStd_Document)& theDoc)
764 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
766 const TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
767 Handle(VrmlData_Group) aTrans = 0L;
768 if (!aLoc.IsIdentity())
770 // Create a Transform grouping node
771 aTrans = new VrmlData_Group(myScene, 0L, Standard_True);
773 if (fabs(myScale - 1.) > Precision::Confusion())
775 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
776 aTrsf.SetTranslationPart(aTransl);
778 aTrans->SetTransform(aTrsf);
779 myScene.AddNode(aTrans, theParent.IsNull());
780 if (!theParent.IsNull())
782 theParent->AddNode(aTrans);
786 Handle(TDataStd_Name) aNameAttribute;
787 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
790 aShapeTool->GetReferredShape(theLabel, aRefLabel);
791 Handle(TDataStd_Name) aRefNameAttribute;
792 aRefLabel.FindAttribute(TDataStd_Name::GetID(), aRefNameAttribute);
794 if (aShapeTool->IsSimpleShape(aRefLabel))
796 addShape((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc);
798 else if (aShapeTool->IsAssembly(aRefLabel))
800 addAssembly((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc, aTrans.IsNull());
805 //=======================================================================
806 //function : addAssembly
807 //purpose : Adds the assembly from the document
808 //=======================================================================
809 void VrmlData_ShapeConvert::addAssembly (const Handle(VrmlData_Group)& theParent,
810 const TDF_Label& theLabel,
811 const Handle(TDocStd_Document)& theDoc,
812 const Standard_Boolean theNeedCreateGroup)
814 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
816 Handle(VrmlData_Group) anAssembly = 0L;
817 if (theNeedCreateGroup)
819 Handle(TDataStd_Name) aNameAttribute;
820 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
821 if (!aNameAttribute.IsNull())
823 TCollection_AsciiString aName = aNameAttribute->Get();
824 aName.ChangeAll(' ', '_');
825 aName.ChangeAll('#', '_');
826 anAssembly = new VrmlData_Group(myScene, aName.ToCString());
830 anAssembly = new VrmlData_Group(myScene, 0L);
832 TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
833 if (!aLoc.IsIdentity())
836 if (fabs(myScale - 1.) > Precision::Confusion())
838 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
839 aTrsf.SetTranslationPart(aTransl);
841 anAssembly->SetTransform(aTrsf);
843 myScene.AddNode(anAssembly, theParent.IsNull());
844 if (!theParent.IsNull())
846 theParent->AddNode(anAssembly);
850 TDF_LabelSequence aChildLabels;
851 aShapeTool->GetComponents(theLabel, aChildLabels);
852 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
854 const TDF_Label& aChildLabel = aChildIter.Value();
855 if (aShapeTool->IsAssembly(aChildLabel))
857 addAssembly((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc, anAssembly.IsNull());
859 else if (aShapeTool->IsReference(aChildLabel))
861 addInstance((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
863 else if (aShapeTool->IsSimpleShape(aChildLabel))
865 addShape((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
871 //=======================================================================
872 //function : ConvertDocument
874 //=======================================================================
875 void VrmlData_ShapeConvert::ConvertDocument(const Handle(TDocStd_Document) &theDoc)
877 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
879 TDF_LabelSequence aFreeShapeLabels;
880 aShapeTool->GetFreeShapes(aFreeShapeLabels);
882 Handle(VrmlData_Group) aGroup = 0L;
883 if (aFreeShapeLabels.Size() > 1)
885 aGroup = new VrmlData_Group(myScene, 0L);
886 myScene.AddNode(aGroup);
889 for (TDF_LabelSequence::Iterator aRootIter(aFreeShapeLabels); aRootIter.More(); aRootIter.Next())
891 const TDF_Label& aFreeShapeLabel = aRootIter.Value();
892 if (aShapeTool->IsAssembly (aFreeShapeLabel))
894 addAssembly (aGroup, aFreeShapeLabel, theDoc, Standard_True);
896 else if (aShapeTool->IsReference (aFreeShapeLabel))
898 addInstance (aGroup, aFreeShapeLabel, theDoc);
900 else if (aShapeTool->IsSimpleShape (aFreeShapeLabel))
902 addShape (aGroup, aFreeShapeLabel, theDoc);
907 //=======================================================================
908 //function : makeMaterialFromStyle
910 //=======================================================================
911 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::makeMaterialFromStyle (const XCAFPrs_Style& theStyle,
912 const TDF_Label& theAttribLab) const
914 const Quantity_ColorRGBA aColor = !theStyle.Material().IsNull()
915 ? theStyle.Material()->BaseColor()
916 : theStyle.GetColorSurfRGBA();
918 TCollection_AsciiString aNodeName = "_materialFace_";
919 Handle(TDataStd_Name) aNameAttribute;
920 if (theAttribLab.FindAttribute(TDataStd_Name::GetID(), aNameAttribute))
922 aNodeName.AssignCat(aNameAttribute->Get());
923 Standard_Integer n = aNodeName.Search(" ");
926 aNodeName = aNodeName.SubString(1, n - 1);
931 NCollection_Vec3<Standard_Real> aColor_sRGB;
932 aColor.GetRGB().Values (aColor_sRGB.r(), aColor_sRGB.g(), aColor_sRGB.b(), Quantity_TOC_sRGB);
933 aNodeName.AssignCat(aColor_sRGB.r());
934 aNodeName.AssignCat("_");
935 aNodeName.AssignCat(aColor_sRGB.g());
936 aNodeName.AssignCat("_");
937 aNodeName.AssignCat(aColor_sRGB.b());
940 Handle(VrmlData_Appearance) anAppearance = Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName.ToCString()));
941 if (anAppearance.IsNull())
943 Handle(VrmlData_Material) aMaterial = new VrmlData_Material (myScene, 0L);
944 aMaterial->SetDiffuseColor (aColor.GetRGB());
945 myScene.AddNode (aMaterial, Standard_False);
946 anAppearance = new VrmlData_Appearance (myScene, aNodeName.ToCString());
947 anAppearance->SetMaterial (aMaterial);
948 myScene.AddNode (anAppearance, Standard_False);