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
103 //purpose : auxiliary
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());
334 // protection against creation degenerative triangles
335 Standard_Integer nbTri = 0;
336 Poly_Array1OfTriangle aTriangles(1, nTriangles);
337 for (i = 0; i < nTriangles; i++) {
338 Standard_Integer idx[3];
339 theTri->Triangle (i + 1).Get (idx[0], idx[1], idx[2]);
340 if (idx[0] == idx[1] || idx[0] == idx[2] || idx[1] == idx[2])
345 aTriangles.SetValue (nbTri, theTri->Triangle (i + 1));
347 aTriangles.Resize(1, nbTri, Standard_True);
349 const Handle(VrmlData_IndexedFaceSet) aFaceSet =
350 new VrmlData_IndexedFaceSet (myScene,
352 Standard_True, // IsCCW
353 Standard_False, // IsSolid
354 Standard_False); // IsConvex
355 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
356 const Standard_Boolean isReverse = (theFace.Orientation() == TopAbs_REVERSED);
358 // Create the array of triangles
359 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
360 (anAlloc->Allocate (nbTri * sizeof(const Standard_Integer *)));
361 aFaceSet->SetPolygons (nbTri, arrPolygons);
363 // Store the triangles
364 for (i = 0; i < nbTri; i++) {
365 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
366 (anAlloc->Allocate (4*sizeof(Standard_Integer)));
368 aTriangles(i + 1).Get(aPolygon[1], aPolygon[2], aPolygon[3]);
371 const Standard_Integer aTmp = aPolygon[2]-1;
372 aPolygon[2] = aPolygon[3]-1;
378 arrPolygons[i] = aPolygon;
381 // Create the Coordinates node
382 if (theCoord.IsNull() == Standard_False)
383 aFaceSet->SetCoordinates (theCoord);
385 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
386 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
387 for (i = 0; i < nNodes; i++)
389 arrNodes[i] = theTri->Node (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())
401 gp_XYZ* arrVec = static_cast<gp_XYZ*>(anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
403 for (i = 0; i < nNodes; i++)
405 theTri->Normal (i + 1, aVec3);
406 gp_XYZ aNormal (aVec3.x(), aVec3.y(), aVec3.z());
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)
427 if (aSurface->IsCNu(1) && aSurface->IsCNv(1))
429 gp_XYZ* arrVec = static_cast<gp_XYZ*> (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
431 // Compute the normal vectors
432 Standard_Real Tol = Sqrt(aConf2);
433 for (i = 0; i < nNodes; i++)
435 const gp_Pnt2d aUV = theTri->UVNode (i+1);
437 if (GeomLib::NormEstim(aSurface, aUV, Tol, aNormal) > 1) {
438 //Try to estimate as middle normal of adjacent triangles
439 Standard_Integer n[3];
441 gp_XYZ eqPlan(0., 0., 0.);
442 for (PC.Initialize(i+1); PC.More(); PC.Next()) {
443 aTriangles(PC.Value()).Get(n[0], n[1], n[2]);
444 gp_XYZ v1 (theTri->Node (n[1]).Coord()-theTri->Node (n[0]).Coord());
445 gp_XYZ v2 (theTri->Node (n[2]).Coord()-theTri->Node (n[1]).Coord());
448 Standard_Real mod = vv.Modulus();
455 if (eqPlan.SquareModulus() > gp::Resolution())
456 aNormal = gp_Dir(eqPlan);
461 if (aNormal.X()*aNormal.X() < aConf2)
463 if (aNormal.Y()*aNormal.Y() < aConf2)
465 if (aNormal.Z()*aNormal.Z() < aConf2)
468 arrVec[i] = aNormal.XYZ();
471 const Handle(VrmlData_Normal) aNormalNode =
472 new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
473 myScene.AddNode (aNormalNode, Standard_False);
474 aFaceSet->SetNormals (aNormalNode);
478 return Handle(VrmlData_Geometry) (aFaceSet);
481 //=======================================================================
482 //function : polToIndexedLineSet
483 //purpose : single polygon3D => IndexedLineSet
484 //=======================================================================
486 Handle(VrmlData_Geometry) VrmlData_ShapeConvert::polToIndexedLineSet
487 (const Handle(Poly_Polygon3D)& thePol)
490 const Standard_Integer nNodes (thePol->NbNodes());
491 const TColgp_Array1OfPnt& arrPolyNodes = thePol->Nodes();
492 const Handle(NCollection_IncAllocator)& anAlloc = myScene.Allocator();
494 const Handle(VrmlData_IndexedLineSet) aLineSet =
495 new VrmlData_IndexedLineSet (myScene, 0L);
497 // Create the array of polygons (1 member)
498 const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
499 (anAlloc->Allocate (sizeof(const Standard_Integer *)));
500 aLineSet->SetPolygons (1, arrPolygons);
503 Standard_Integer * aPolygon = static_cast<Standard_Integer *>
504 (anAlloc->Allocate ((nNodes+1)*sizeof(Standard_Integer)));
505 aPolygon[0] = nNodes;
506 for (i = 1; i <= nNodes; i++)
508 arrPolygons[0] = aPolygon;
510 // Create the Coordinates node
511 gp_XYZ * arrNodes = static_cast <gp_XYZ *>
512 (anAlloc->Allocate (nNodes * sizeof(gp_XYZ)));
513 for (i = 0; i < nNodes; i++)
514 arrNodes[i] = arrPolyNodes(i+1).XYZ() * myScale;
516 const Handle(VrmlData_Coordinate) aCoordNode =
517 new VrmlData_Coordinate (myScene, 0L, nNodes, arrNodes);
518 myScene.AddNode (aCoordNode, Standard_False);
519 aLineSet->SetCoordinates (aCoordNode);
521 return Handle(VrmlData_Geometry) (aLineSet);
524 //=======================================================================
525 //function : defaultMaterialFace
527 //=======================================================================
529 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialFace () const
531 static char aNodeName[] = "__defaultMaterialFace";
532 Handle(VrmlData_Appearance) anAppearance =
533 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
534 if (anAppearance.IsNull()) {
535 const Handle(VrmlData_Material) aMaterial =
536 new VrmlData_Material (myScene, 0L, 1.0, 0.022, 0.);
537 aMaterial->SetDiffuseColor (Quantity_Color(0.780392, 0.568627, 0.113725,
539 aMaterial->SetEmissiveColor(Quantity_Color(0.329412, 0.223529, 0.027451,
541 aMaterial->SetSpecularColor(Quantity_Color(0.992157, 0.941176, 0.807843,
543 myScene.AddNode (aMaterial, Standard_False);
544 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
545 anAppearance->SetMaterial (aMaterial);
546 myScene.AddNode (anAppearance, Standard_False);
551 //=======================================================================
552 //function : defaultMaterialEdge
554 //=======================================================================
556 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialEdge () const
558 static char aNodeName[] = "__defaultMaterialEdge";
559 Handle(VrmlData_Appearance) anAppearance =
560 Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName));
561 if (anAppearance.IsNull()) {
562 const Handle(VrmlData_Material) aMaterial =
563 new VrmlData_Material (myScene, 0L, 0.2, 0.2, 0.2);
564 aMaterial->SetDiffuseColor (Quantity_Color(0.2, 0.7, 0.2,
566 aMaterial->SetEmissiveColor(Quantity_Color(0.2, 0.7, 0.2,
568 aMaterial->SetSpecularColor(Quantity_Color(0.2, 0.7, 0.2,
570 myScene.AddNode (aMaterial, Standard_False);
571 anAppearance = new VrmlData_Appearance (myScene, aNodeName);
572 anAppearance->SetMaterial (aMaterial);
573 myScene.AddNode (anAppearance, Standard_False);
579 //=======================================================================
580 //function : addShape
581 //purpose : Adds the shape from the document
582 //=======================================================================
583 void VrmlData_ShapeConvert::addShape (const Handle(VrmlData_Group)& theParent,
584 const TDF_Label& theLabel,
585 const Handle(TDocStd_Document)& theDoc)
587 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
588 Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(theDoc->Main());
589 Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool(theDoc->Main());
591 NCollection_DataMap<TopoDS_Shape, TDF_Label> aChildShapeToLabels;
592 TDF_LabelSequence aChildLabels;
593 aShapeTool->GetSubShapes(theLabel, aChildLabels);
594 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
596 const TDF_Label& aChildLabel = aChildIter.Value();
597 TopoDS_Shape aChildShape;
598 if (aShapeTool->GetShape(aChildLabel, aChildShape))
600 aChildShapeToLabels.Bind(aChildShape, aChildLabel);
604 const TopoDS_Shape aShape = aShapeTool->GetShape(theLabel);
605 Handle(VrmlData_Group) aGroup = 0L;
606 TopExp_Explorer anExp(aShape, TopAbs_FACE);
607 Standard_Integer nbFaces = 0;
608 for (; anExp.More(); anExp.Next()) {
611 Handle(TDataStd_Name) aNameAttribute;
612 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
615 if (!aNameAttribute.IsNull())
617 TCollection_AsciiString aName = aNameAttribute->Get();
618 aName.ChangeAll(' ', '_');
619 aName.ChangeAll('#', '_');
620 aGroup = new VrmlData_Group(myScene, aName.ToCString());
624 aGroup = new VrmlData_Group(myScene, 0L);
626 myScene.AddNode(aGroup, theParent.IsNull());
627 if (!theParent.IsNull())
629 theParent->AddNode(aGroup);
633 anExp.Init(aShape, TopAbs_FACE);
634 for (; anExp.More(); anExp.Next()) {
635 TopLoc_Location aLoc;
636 Handle(VrmlData_Geometry) aTShapeNode =
637 makeTShapeNode(anExp.Current(), TopAbs_FACE, aLoc);
638 if (!aTShapeNode.IsNull())
640 Handle(VrmlData_ShapeNode) aShapeNode = 0L;
641 if (aGroup.IsNull() && !aNameAttribute.IsNull())
643 TCollection_AsciiString aName = aNameAttribute->Get();
644 aName.ChangeAll(' ', '_');
645 aName.ChangeAll('#', '_');
646 aShapeNode = new VrmlData_ShapeNode(myScene, aName.ToCString());
650 aShapeNode = new VrmlData_ShapeNode(myScene, 0L);
654 XCAFPrs_Style aStyle;
655 Quantity_ColorRGBA aColor;
656 TDF_Label aLabel, anAttribLab;
657 if (aChildShapeToLabels.Find (anExp.Current(), aLabel))
659 Handle(XCAFDoc_VisMaterial) aVisMat = aMatTool->GetShapeMaterial (aLabel);
660 if (!aVisMat.IsNull()
661 && !aVisMat->IsEmpty())
663 anAttribLab = aVisMat->Label();
664 aStyle.SetMaterial (aVisMat);
666 else if (aColorTool->GetColor (aLabel, XCAFDoc_ColorSurf, anAttribLab)
667 || aColorTool->GetColor (aLabel, XCAFDoc_ColorGen, anAttribLab))
669 aColorTool->GetColor (anAttribLab, aColor);
670 aStyle.SetColorSurf (aColor);
673 if (!aStyle.IsSetColorSurf()
674 && aStyle.Material().IsNull())
676 Handle(XCAFDoc_VisMaterial) aVisMat = aMatTool->GetShapeMaterial (theLabel);
677 if (!aVisMat.IsNull()
678 && !aVisMat->IsEmpty())
680 anAttribLab = aVisMat->Label();
681 aStyle.SetMaterial (aVisMat);
683 if (aColorTool->GetColor (theLabel, XCAFDoc_ColorSurf, anAttribLab)
684 || aColorTool->GetColor (theLabel, XCAFDoc_ColorGen, anAttribLab))
686 aColorTool->GetColor (anAttribLab, aColor);
687 aStyle.SetColorSurf (aColor);
690 if (!aStyle.IsSetColorSurf()
691 && aStyle.Material().IsNull())
693 aShapeNode->SetAppearance(defaultMaterialFace());
697 aShapeNode->SetAppearance (makeMaterialFromStyle (aStyle, anAttribLab));
700 myScene.AddNode(aShapeNode, theParent.IsNull() && aGroup.IsNull());
701 aShapeNode->SetGeometry(aTShapeNode);
702 if (aLoc.IsIdentity())
704 // Store the shape node directly into the main Group.
705 if (!aGroup.IsNull())
707 aGroup->AddNode(aShapeNode);
709 else if (!theParent.IsNull())
711 theParent->AddNode(aShapeNode);
716 // Create a Transform grouping node
717 Handle(VrmlData_Group) aTrans = new VrmlData_Group(myScene, 0L,
720 if (fabs(myScale - 1.) > Precision::Confusion())
722 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
723 aTrsf.SetTranslationPart(aTransl);
725 aTrans->SetTransform(aTrsf);
726 myScene.AddNode(aTrans, theParent.IsNull() && aGroup.IsNull());
727 if (!aGroup.IsNull())
729 aGroup->AddNode(aTrans);
731 else if (!theParent.IsNull())
733 theParent->AddNode(aTrans);
735 // Store the shape node under the transform.
736 aTrans->AddNode(aShapeNode);
743 //=======================================================================
744 //function : addInstance
745 //purpose : Adds the reference from the document
746 //=======================================================================
747 void VrmlData_ShapeConvert::addInstance (const Handle(VrmlData_Group)& theParent,
748 const TDF_Label& theLabel,
749 const Handle(TDocStd_Document)& theDoc)
751 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
753 const TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
754 Handle(VrmlData_Group) aTrans = 0L;
755 if (!aLoc.IsIdentity())
757 // Create a Transform grouping node
758 aTrans = new VrmlData_Group(myScene, 0L, Standard_True);
760 if (fabs(myScale - 1.) > Precision::Confusion())
762 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
763 aTrsf.SetTranslationPart(aTransl);
765 aTrans->SetTransform(aTrsf);
766 myScene.AddNode(aTrans, theParent.IsNull());
767 if (!theParent.IsNull())
769 theParent->AddNode(aTrans);
773 Handle(TDataStd_Name) aNameAttribute;
774 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
777 aShapeTool->GetReferredShape(theLabel, aRefLabel);
778 Handle(TDataStd_Name) aRefNameAttribute;
779 aRefLabel.FindAttribute(TDataStd_Name::GetID(), aRefNameAttribute);
781 if (aShapeTool->IsSimpleShape(aRefLabel))
783 addShape((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc);
785 else if (aShapeTool->IsAssembly(aRefLabel))
787 addAssembly((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc, aTrans.IsNull());
792 //=======================================================================
793 //function : addAssembly
794 //purpose : Adds the assembly from the document
795 //=======================================================================
796 void VrmlData_ShapeConvert::addAssembly (const Handle(VrmlData_Group)& theParent,
797 const TDF_Label& theLabel,
798 const Handle(TDocStd_Document)& theDoc,
799 const Standard_Boolean theNeedCreateGroup)
801 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
803 Handle(VrmlData_Group) anAssembly = 0L;
804 if (theNeedCreateGroup)
806 Handle(TDataStd_Name) aNameAttribute;
807 theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
808 if (!aNameAttribute.IsNull())
810 TCollection_AsciiString aName = aNameAttribute->Get();
811 aName.ChangeAll(' ', '_');
812 aName.ChangeAll('#', '_');
813 anAssembly = new VrmlData_Group(myScene, aName.ToCString());
817 anAssembly = new VrmlData_Group(myScene, 0L);
819 TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
820 if (!aLoc.IsIdentity())
823 if (fabs(myScale - 1.) > Precision::Confusion())
825 const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
826 aTrsf.SetTranslationPart(aTransl);
828 anAssembly->SetTransform(aTrsf);
830 myScene.AddNode(anAssembly, theParent.IsNull());
831 if (!theParent.IsNull())
833 theParent->AddNode(anAssembly);
837 TDF_LabelSequence aChildLabels;
838 aShapeTool->GetComponents(theLabel, aChildLabels);
839 for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
841 const TDF_Label& aChildLabel = aChildIter.Value();
842 if (aShapeTool->IsAssembly(aChildLabel))
844 addAssembly((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc, anAssembly.IsNull());
846 else if (aShapeTool->IsReference(aChildLabel))
848 addInstance((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
850 else if (aShapeTool->IsSimpleShape(aChildLabel))
852 addShape((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
858 //=======================================================================
859 //function : ConvertDocument
861 //=======================================================================
862 void VrmlData_ShapeConvert::ConvertDocument(const Handle(TDocStd_Document) &theDoc)
864 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
866 TDF_LabelSequence aFreeShapeLabels;
867 aShapeTool->GetFreeShapes(aFreeShapeLabels);
869 Handle(VrmlData_Group) aGroup = 0L;
870 if (aFreeShapeLabels.Size() > 1)
872 aGroup = new VrmlData_Group(myScene, 0L);
873 myScene.AddNode(aGroup);
876 for (TDF_LabelSequence::Iterator aRootIter(aFreeShapeLabels); aRootIter.More(); aRootIter.Next())
878 const TDF_Label& aFreeShapeLabel = aRootIter.Value();
879 if (aShapeTool->IsAssembly (aFreeShapeLabel))
881 addAssembly (aGroup, aFreeShapeLabel, theDoc, Standard_True);
883 else if (aShapeTool->IsReference (aFreeShapeLabel))
885 addInstance (aGroup, aFreeShapeLabel, theDoc);
887 else if (aShapeTool->IsSimpleShape (aFreeShapeLabel))
889 addShape (aGroup, aFreeShapeLabel, theDoc);
894 //=======================================================================
895 //function : makeMaterialFromStyle
897 //=======================================================================
898 Handle(VrmlData_Appearance) VrmlData_ShapeConvert::makeMaterialFromStyle (const XCAFPrs_Style& theStyle,
899 const TDF_Label& theAttribLab) const
901 const Quantity_ColorRGBA aColor = !theStyle.Material().IsNull()
902 ? theStyle.Material()->BaseColor()
903 : theStyle.GetColorSurfRGBA();
905 TCollection_AsciiString aNodeName = "_materialFace_";
906 Handle(TDataStd_Name) aNameAttribute;
907 if (theAttribLab.FindAttribute(TDataStd_Name::GetID(), aNameAttribute))
909 aNodeName.AssignCat(aNameAttribute->Get());
910 Standard_Integer n = aNodeName.Search(" ");
913 aNodeName = aNodeName.SubString(1, n - 1);
918 NCollection_Vec3<Standard_Real> aColor_sRGB;
919 aColor.GetRGB().Values (aColor_sRGB.r(), aColor_sRGB.g(), aColor_sRGB.b(), Quantity_TOC_sRGB);
920 aNodeName.AssignCat(aColor_sRGB.r());
921 aNodeName.AssignCat("_");
922 aNodeName.AssignCat(aColor_sRGB.g());
923 aNodeName.AssignCat("_");
924 aNodeName.AssignCat(aColor_sRGB.b());
927 Handle(VrmlData_Appearance) anAppearance = Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName.ToCString()));
928 if (anAppearance.IsNull())
930 Handle(VrmlData_Material) aMaterial = new VrmlData_Material (myScene, 0L);
931 aMaterial->SetDiffuseColor (aColor.GetRGB());
932 myScene.AddNode (aMaterial, Standard_False);
933 anAppearance = new VrmlData_Appearance (myScene, aNodeName.ToCString());
934 anAppearance->SetMaterial (aMaterial);
935 myScene.AddNode (anAppearance, Standard_False);