0030115: Implementation of import from XCAF to VRML.
[occt.git] / src / VrmlData / VrmlData_ShapeConvert.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 4c084e7..08b96b8
@@ -1,23 +1,17 @@
 // Created on: 2007-08-04
 // Created by: Alexander GRIGORIEV
-// Copyright (c) 2007-2012 OPEN CASCADE SAS
+// Copyright (c) 2007-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
-
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <VrmlData_ShapeConvert.hxx>
 #include <VrmlData_Scene.hxx>
 #include <Poly_PolygonOnTriangulation.hxx>
 #include <Poly_Polygon3D.hxx>
 #include <Precision.hxx>
+#include <Quantity_ColorRGBA.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
+#include <TDataStd_Name.hxx>
+#include <TDF_Label.hxx>
+//#include <TDF_LabelSequence.hxx>
+#include <TDocStd_Document.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TShort_Array1OfShortReal.hxx>
 #include <GeomLib.hxx>
 #include <TShort_HArray1OfShortReal.hxx>
+#include <VrmlData_Appearance.hxx>
+#include <XCAFDoc_ColorTool.hxx>
+#include <XCAFDoc_DocumentTool.hxx>
+#include <XCAFDoc_ShapeTool.hxx>
 
-//=======================================================================
-//function : IsEqual
-//purpose  : for NCollection_DataMap interface
-//=======================================================================
-
-inline Standard_Boolean IsEqual (const TopoDS_Shape& one,
-                                 const TopoDS_Shape& two) 
-{
-  return one == two;
-}
 
 //=======================================================================
 //function : AddShape
@@ -82,7 +75,7 @@ void VrmlData_ShapeConvert::AddShape (const TopoDS_Shape& theShape,
     char buf[2048], * optr = &buf[0];
     char * eptr = &buf[sizeof(buf)-1];
     for (const char * ptr = theName;; ptr++) {
-      int sym = *ptr;
+      char sym = *ptr;
       if (sym == '\0' || sym == '\n' || sym == '\r') {
         * optr = '\0';
         break;
@@ -103,6 +96,143 @@ void VrmlData_ShapeConvert::AddShape (const TopoDS_Shape& theShape,
   myShapes.Append (aData);
 }
 
+
+//=======================================================================
+//function : makeTShapeNode
+//purpose  : auxilary
+//=======================================================================
+Handle(VrmlData_Geometry) VrmlData_ShapeConvert::makeTShapeNode(const TopoDS_Shape& theShape,
+                                                                const TopAbs_ShapeEnum theShapeType,
+                                                                TopLoc_Location& theLoc)
+{
+  Handle(VrmlData_Geometry) aTShapeNode = 0L;
+  const Standard_Boolean isReverse = (theShape.Orientation() == TopAbs_REVERSED);
+
+  TopoDS_Shape aTestedShape;
+  aTestedShape.TShape(theShape.TShape());
+  aTestedShape.Orientation(isReverse ? TopAbs_REVERSED : TopAbs_FORWARD);
+  switch (theShapeType) {
+  case TopAbs_FACE:
+  {
+    const TopoDS_Face& aFace = TopoDS::Face(theShape);
+    if (aFace.IsNull() == Standard_False) {
+      Handle(Poly_Triangulation) aTri =
+        BRep_Tool::Triangulation(aFace, theLoc);
+
+      if (myRelMap.IsBound(aTestedShape)) {
+        aTShapeNode = myRelMap(aTestedShape);
+        break;
+      }
+
+      if (aTri.IsNull() == Standard_False) {
+        TopoDS_Shape aTestedShapeRev = aTestedShape;
+        aTestedShapeRev.Orientation(isReverse ?
+          TopAbs_FORWARD : TopAbs_REVERSED);
+        Handle(VrmlData_IndexedFaceSet) aFaceSetToReuse;
+        if (myRelMap.IsBound(aTestedShapeRev))
+          aFaceSetToReuse = Handle(VrmlData_IndexedFaceSet)::DownCast
+          (myRelMap(aTestedShapeRev));
+
+        Handle(VrmlData_Coordinate) aCoordToReuse;
+        if (aFaceSetToReuse.IsNull() == Standard_False)
+          aCoordToReuse = aFaceSetToReuse->Coordinates();
+
+        aTShapeNode = triToIndexedFaceSet(aTri, aFace, aCoordToReuse);
+        myScene.AddNode(aTShapeNode, Standard_False);
+        // Bind the converted face
+        myRelMap.Bind(aTestedShape, aTShapeNode);
+      }
+    }
+  }
+  break;
+  case TopAbs_WIRE:
+  {
+    const TopoDS_Wire& aWire = TopoDS::Wire(theShape);
+    if (aWire.IsNull() == Standard_False) {
+    }
+  }
+  break;
+  case TopAbs_EDGE:
+  {
+    const TopoDS_Edge& aEdge = TopoDS::Edge(theShape);
+    if (aEdge.IsNull() == Standard_False) {
+      if (myRelMap.IsBound(aTestedShape)) {
+        aTShapeNode = myRelMap(aTestedShape);
+        break;
+      }
+      // Check the presence of reversly oriented Edge. It can also be used
+      // because we do not distinguish the orientation for edges.
+      aTestedShape.Orientation(isReverse ?
+        TopAbs_FORWARD : TopAbs_REVERSED);
+      if (myRelMap.IsBound(aTestedShape)) {
+        aTShapeNode = myRelMap(aTestedShape);
+        break;
+      }
+
+      //try to find PolygonOnTriangulation
+      Handle(Poly_PolygonOnTriangulation) aPT;
+      Handle(Poly_Triangulation) aT;
+      TopLoc_Location aL;
+      BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL);
+
+      // If PolygonOnTriangulation was found -> get the Polygon3D
+      Handle(Poly_Polygon3D) aPol;
+      if (!aPT.IsNull() && !aT.IsNull() && aPT->HasParameters()) {
+        BRepAdaptor_Curve aCurve(aEdge);
+        Handle(TColStd_HArray1OfReal) aPrs = aPT->Parameters();
+        Standard_Integer nbNodes = aPT->NbNodes();
+        TColgp_Array1OfPnt arrNodes(1, nbNodes);
+        TColStd_Array1OfReal arrUVNodes(1, nbNodes);
+
+        for (Standard_Integer j = 1; j <= nbNodes; j++) {
+          arrUVNodes(j) = aPrs->Value(aPrs->Lower() + j - 1);
+          arrNodes(j) = aCurve.Value(arrUVNodes(j));
+        }
+        aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
+        aPol->Deflection(aPT->Deflection());
+      }
+      else {
+        aPol = BRep_Tool::Polygon3D(aEdge, aL);
+
+        // If polygon was not found -> generate it
+        if (aPol.IsNull()) {
+          BRepAdaptor_Curve aCurve(aEdge);
+          const Standard_Real aFirst = aCurve.FirstParameter();
+          const Standard_Real aLast = aCurve.LastParameter();
+
+          GCPnts_TangentialDeflection TD(aCurve, aFirst, aLast,
+            myDeflAngle, myDeflection, 2);
+          const Standard_Integer nbNodes = TD.NbPoints();
+
+          TColgp_Array1OfPnt arrNodes(1, nbNodes);
+          TColStd_Array1OfReal arrUVNodes(1, nbNodes);
+          for (Standard_Integer j = 1; j <= nbNodes; j++) {
+            arrNodes(j) = TD.Value(j);
+            arrUVNodes(j) = TD.Parameter(j);
+          }
+          aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
+          aPol->Deflection(myDeflection);
+        }
+      }
+
+      if (!aPol.IsNull())
+      {
+        aTShapeNode = polToIndexedLineSet(aPol);
+        myScene.AddNode(aTShapeNode, Standard_False);
+        // Bind the converted face
+        myRelMap.Bind(aTestedShape, aTShapeNode);
+      }
+    }
+  }
+  break;
+  default:
+    break;
+  }
+
+  return aTShapeNode;
+}
+
+
 //=======================================================================
 //function : Convert
 //purpose  : 
@@ -113,8 +243,11 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
                                      const Standard_Real    theDeflection,
                                      const Standard_Real    theDeflAngle)
 {
-  const Standard_Real aDeflection =
-    theDeflection < 0.0001 ? 0.0001 : theDeflection;
+  //const Standard_Real aDeflection =
+  //  theDeflection < 0.0001 ? 0.0001 : theDeflection;
+
+  myDeflection = theDeflection < 0.0001 ? 0.0001 : theDeflection;
+  myDeflAngle = theDeflAngle;
 
   Standard_Boolean Extract[2] = {theExtractFaces, theExtractEdges};
   TopAbs_ShapeEnum ShapeType[2] = {TopAbs_FACE, TopAbs_EDGE};
@@ -124,9 +257,9 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
 
   // Relocation map for converted shapes. We should distinguish both TShape
   // and Orientation in this map.
-  NCollection_DataMap <TopoDS_Shape,Handle(VrmlData_Geometry)>
-    aRelMap (100, anAlloc);
-
+  //NCollection_DataMap <TopoDS_Shape,Handle(VrmlData_Geometry)>
+  //  aRelMap (100, anAlloc);
+  myRelMap = NCollection_DataMap <TopoDS_Shape, Handle(VrmlData_Geometry)>(100, anAlloc);
 
   NCollection_List<ShapeData>::Iterator anIter (myShapes);
   for (; anIter.More(); anIter.Next()) {
@@ -144,159 +277,9 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
       for (; anExp.More(); anExp.Next()) {
         const TopoDS_Shape& aShape = anExp.Current();
         TopLoc_Location aLoc;
-        Handle(VrmlData_Geometry) aTShapeNode;
-        const Standard_Boolean isReverse=(aShape.Orientation()==TopAbs_REVERSED); 
-
-        TopoDS_Shape aTestedShape;
-        aTestedShape.TShape (aShape.TShape());
-        aTestedShape.Orientation (isReverse ? TopAbs_REVERSED : TopAbs_FORWARD);
-        Standard_Boolean isTessellate (Standard_False);
-        switch (ShapeType[i]) {
-        case TopAbs_FACE:
-          {
-            const TopoDS_Face& aFace = TopoDS::Face (aShape);
-            if (aFace.IsNull() == Standard_False) {
-              Handle(Poly_Triangulation) aTri =
-                BRep_Tool::Triangulation (aFace, aLoc);
-      
-              if (aRelMap.IsBound (aTestedShape)) {
-                aTShapeNode = aRelMap(aTestedShape);
-                break;
-              }
-
-              if (aTri.IsNull())
-                isTessellate = Standard_True;
-              // Check the existing deflection
-              else if (aTri->Deflection() > aDeflection+ Precision::Confusion())
-                isTessellate = Standard_True;
-              if (isTessellate) {
-                // Triangulate the face by the standard OCC mesher
-                BRepMesh_IncrementalMesh IM (aFace, aDeflection, Standard_False, theDeflAngle);
-                aTri = BRep_Tool::Triangulation (aFace, aLoc);
-              }
-              if (aTri.IsNull() == Standard_False) {
-                TopoDS_Shape aTestedShapeRev = aTestedShape;
-                aTestedShapeRev.Orientation (isReverse ?
-                                             TopAbs_FORWARD : TopAbs_REVERSED);
-                Handle(VrmlData_IndexedFaceSet) aFaceSetToReuse;
-                if (aRelMap.IsBound (aTestedShapeRev))
-                  aFaceSetToReuse = Handle(VrmlData_IndexedFaceSet)::DownCast
-                    (aRelMap(aTestedShapeRev));
-
-                Handle(VrmlData_Coordinate) aCoordToReuse;
-                if (aFaceSetToReuse.IsNull() == Standard_False)
-                  aCoordToReuse = aFaceSetToReuse->Coordinates();
-
-                aTShapeNode = triToIndexedFaceSet (aTri, aFace, aCoordToReuse);
-                myScene.AddNode (aTShapeNode, Standard_False);
-                // Bind the converted face
-                aRelMap.Bind (aTestedShape, aTShapeNode);
-              }
-            }
-          }
-          break;
-        case TopAbs_WIRE:
-          {
-            const TopoDS_Wire& aWire = TopoDS::Wire (aShape);
-            if (aWire.IsNull() == Standard_False) {
-            }
-          }
-          break;
-       case TopAbs_EDGE:
-         {
-           const TopoDS_Edge& aEdge = TopoDS::Edge (aShape);
-            if (aEdge.IsNull() == Standard_False) {
-              Handle(Poly_Polygon3D) aPol = BRep_Tool::Polygon3D (aEdge, aLoc);
-              
-              if (aRelMap.IsBound (aTestedShape)) {
-                aTShapeNode = aRelMap(aTestedShape);
-                break;
-              }
-              // Check the presence of reversly oriented Edge. It can also be used
-              // because we do not distinguish the orientation for edges.
-              aTestedShape.Orientation (isReverse ?
-                                        TopAbs_FORWARD : TopAbs_REVERSED);
-              if (aRelMap.IsBound (aTestedShape)) {
-                aTShapeNode = aRelMap(aTestedShape);
-                break;
-              }
-              
-              if (aPol.IsNull())
-                isTessellate = Standard_True;
-              // Check the existing deflection
-              else if (aPol->Deflection() > aDeflection+ Precision::Confusion()
-                       && BRep_Tool::IsGeometric(aEdge))
-                isTessellate = Standard_True;
-              
-              if (isTessellate && BRep_Tool::IsGeometric(aEdge)) {
-                //try to find PolygonOnTriangulation
-                Handle(Poly_PolygonOnTriangulation) aPT;
-                Handle(Poly_Triangulation) aT;
-                TopLoc_Location aL;
-
-                Standard_Boolean found = Standard_False;
-                for(i = 1; Standard_True; i++) {
-                  
-                  BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL, i);
-
-                  if(aPT.IsNull() || aT.IsNull()) break;
-
-                  if(aPT->Deflection() <= aDeflection + Precision::Confusion() &&
-                     aPT->HasParameters()) {
-                    found = Standard_True;
-                    break;
-                  }
-
-                }
-                
-                if(found) {
-
-                  BRepAdaptor_Curve aCurve(aEdge);
-                  Handle(TColStd_HArray1OfReal) aPrs = aPT->Parameters();
-                  Standard_Integer nbNodes = aPT->NbNodes();
-                  TColgp_Array1OfPnt arrNodes(1, nbNodes);
-                  TColStd_Array1OfReal arrUVNodes(1, nbNodes);
-
-                  for(i = 1; i <= nbNodes; i++) {
-                    arrUVNodes(i) = aPrs->Value(aPrs->Lower() + i - 1);
-                    arrNodes(i) = aCurve.Value(arrUVNodes(i));
-                  }
-                  aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
-                  aPol->Deflection (aPT->Deflection());
-                }
-                else{
-                  
-                  BRepAdaptor_Curve aCurve(aEdge);
-                  const Standard_Real aFirst = aCurve.FirstParameter();
-                  const Standard_Real aLast  = aCurve.LastParameter();
-                
-                  GCPnts_TangentialDeflection TD (aCurve, aFirst, aLast,
-                                                  theDeflAngle, aDeflection, 2);
-                  const Standard_Integer nbNodes = TD.NbPoints();
-                
-                  TColgp_Array1OfPnt arrNodes(1, nbNodes);
-                  TColStd_Array1OfReal arrUVNodes(1, nbNodes);
-                  for (i = 1; i <= nbNodes; i++) {
-                    arrNodes(i) = TD.Value(i);
-                    arrUVNodes(i) = TD.Parameter(i);
-                  }
-                  aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
-                  aPol->Deflection (aDeflection);
-                }
-                
-                BRep_Builder aBld;
-                aBld.UpdateEdge (aEdge, aPol);
-              }
-              aTShapeNode = polToIndexedLineSet (aPol);
-              myScene.AddNode (aTShapeNode, Standard_False);
-              // Bind the converted face
-              aRelMap.Bind (aTestedShape, aTShapeNode);
-            }
-          }
-          break;
-        }
-        
-        if (aTShapeNode.IsNull() == Standard_False) {
+        Handle(VrmlData_Geometry) aTShapeNode =
+          makeTShapeNode(aShape, ShapeType[i], aLoc);
+        if (!aTShapeNode.IsNull()) {
           const Handle(VrmlData_ShapeNode) aShapeNode =
             new VrmlData_ShapeNode (myScene, 0L);
           aShapeNode->SetAppearance (ShapeType[i] == TopAbs_FACE ?
@@ -334,10 +317,10 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
 //purpose  : 
 //=======================================================================
 
-Handle_VrmlData_Geometry VrmlData_ShapeConvert::triToIndexedFaceSet
-                                  (const Handle_Poly_Triangulation&  theTri,
+Handle(VrmlData_Geometry) VrmlData_ShapeConvert::triToIndexedFaceSet
+                                  (const Handle(Poly_Triangulation)&  theTri,
                                    const TopoDS_Face&                theFace,
-                                   const Handle_VrmlData_Coordinate& theCoord)
+                                   const Handle(VrmlData_Coordinate)& theCoord)
 {
   Standard_Integer i;
   const Standard_Integer nNodes         (theTri->NbNodes());
@@ -345,6 +328,21 @@ Handle_VrmlData_Geometry VrmlData_ShapeConvert::triToIndexedFaceSet
   const TColgp_Array1OfPnt&    arrPolyNodes = theTri->Nodes();
   const Poly_Array1OfTriangle& arrTriangles = theTri->Triangles();
 
+  // protection against creation degenerative triangles
+  Standard_Integer nbTri = 0;
+  Poly_Array1OfTriangle aTriangles(1, nTriangles);
+  for (i = 0; i < nTriangles; i++) {
+    Standard_Integer idx[3];
+    arrTriangles(i + 1).Get(idx[0], idx[1], idx[2]);
+    if (idx[0] == idx[1] || idx[0] == idx[2] || idx[1] == idx[2])
+    {
+      continue;
+    }
+    nbTri++;
+    aTriangles.SetValue(nbTri, arrTriangles(i + 1));
+  }
+  aTriangles.Resize(1, nbTri, Standard_True);
+
   const Handle(VrmlData_IndexedFaceSet) aFaceSet =
     new VrmlData_IndexedFaceSet (myScene,
                                  0L,                    // no name
@@ -356,15 +354,15 @@ Handle_VrmlData_Geometry VrmlData_ShapeConvert::triToIndexedFaceSet
 
   // Create the array of triangles
   const Standard_Integer ** arrPolygons = static_cast<const Standard_Integer **>
-    (anAlloc->Allocate (nTriangles * sizeof(const Standard_Integer *)));
-  aFaceSet->SetPolygons (nTriangles, arrPolygons);
+    (anAlloc->Allocate (nbTri * sizeof(const Standard_Integer *)));
+  aFaceSet->SetPolygons (nbTri, arrPolygons);
 
   // Store the triangles
-  for (i = 0; i < nTriangles; i++) {
+  for (i = 0; i < nbTri; i++) {
     Standard_Integer * aPolygon = static_cast<Standard_Integer *>
       (anAlloc->Allocate (4*sizeof(Standard_Integer)));
     aPolygon[0] = 3;
-    arrTriangles(i+1).Get (aPolygon[1],aPolygon[2],aPolygon[3]);
+    aTriangles(i + 1).Get(aPolygon[1], aPolygon[2], aPolygon[3]);
     aPolygon[1]--;
     if (isReverse) {
       const Standard_Integer aTmp = aPolygon[2]-1;
@@ -408,13 +406,13 @@ Handle_VrmlData_Geometry VrmlData_ShapeConvert::triToIndexedFaceSet
       new VrmlData_Normal (myScene, 0L, nNodes, arrVec);
     myScene.AddNode (aNormalNode, Standard_False);
     aFaceSet->SetNormals (aNormalNode);
-    return aFaceSet;
+    return Handle(VrmlData_Geometry) (aFaceSet);
   }
 
   Poly_Connect PC(theTri);
   // Create the Normals node (if UV- values are available)
   TopLoc_Location aLoc;
-  const Standard_Real aConf2 = Precision::Confusion()*Precision::Confusion();
+  const Standard_Real aConf2 = Precision::SquareConfusion();
   const Handle(Geom_Surface) aSurface = BRep_Tool::Surface (theFace, aLoc);
   if (theTri->HasUVNodes() && aSurface.IsNull() == Standard_False) {
     if (aSurface->IsCNu(1) && aSurface->IsCNv(1))
@@ -440,7 +438,7 @@ Handle_VrmlData_Geometry VrmlData_ShapeConvert::triToIndexedFaceSet
 
           gp_XYZ eqPlan(0., 0., 0.);
           for (PC.Initialize(i+1);  PC.More(); PC.Next()) {
-            arrTriangles(PC.Value()).Get(n[0], n[1], n[2]);
+            aTriangles(PC.Value()).Get(n[0], n[1], n[2]);
             gp_XYZ v1(arrPolyNodes(n[1]).Coord()-arrPolyNodes(n[0]).Coord());
             gp_XYZ v2(arrPolyNodes(n[2]).Coord()-arrPolyNodes(n[1]).Coord());
             gp_XYZ vv = v1^v2;
@@ -467,9 +465,9 @@ Handle_VrmlData_Geometry VrmlData_ShapeConvert::triToIndexedFaceSet
         arrVec[i] = aNormal.XYZ();
 
         Standard_Integer j = i * 3;
-        Normals->SetValue(j + 1, aNormal.X());
-        Normals->SetValue(j + 2, aNormal.Y());
-        Normals->SetValue(j + 3, aNormal.Z());
+        Normals->SetValue(j + 1, (Standard_ShortReal)aNormal.X());
+        Normals->SetValue(j + 2, (Standard_ShortReal)aNormal.Y());
+        Normals->SetValue(j + 3, (Standard_ShortReal)aNormal.Z());
 
       }
 
@@ -482,7 +480,7 @@ Handle_VrmlData_Geometry VrmlData_ShapeConvert::triToIndexedFaceSet
     }
   }
 
-  return aFaceSet;
+  return Handle(VrmlData_Geometry) (aFaceSet);
 }
 
 //=======================================================================
@@ -490,8 +488,8 @@ Handle_VrmlData_Geometry VrmlData_ShapeConvert::triToIndexedFaceSet
 //purpose  : single polygon3D => IndexedLineSet
 //=======================================================================
 
-Handle_VrmlData_Geometry VrmlData_ShapeConvert::polToIndexedLineSet
-                                        (const Handle_Poly_Polygon3D& thePol)
+Handle(VrmlData_Geometry) VrmlData_ShapeConvert::polToIndexedLineSet
+                                        (const Handle(Poly_Polygon3D)& thePol)
 {
   Standard_Integer i;
   const Standard_Integer    nNodes (thePol->NbNodes());
@@ -525,7 +523,7 @@ Handle_VrmlData_Geometry VrmlData_ShapeConvert::polToIndexedLineSet
   myScene.AddNode (aCoordNode, Standard_False);
   aLineSet->SetCoordinates (aCoordNode);
 
-  return aLineSet;
+  return Handle(VrmlData_Geometry) (aLineSet);
 }
 
 //=======================================================================
@@ -581,3 +579,331 @@ Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialEdge () const
   }
   return anAppearance;
 }
+
+
+//=======================================================================
+//function : addShape
+//purpose  : Adds the shape from the document
+//=======================================================================
+void VrmlData_ShapeConvert::addShape (const Handle(VrmlData_Group)& theParent,
+                                      const TDF_Label& theLabel,
+                                      const Handle(TDocStd_Document)& theDoc)
+{
+  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
+  Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(theDoc->Main());
+
+  NCollection_DataMap<TopoDS_Shape, TDF_Label> aChildShapeToLabels;
+  TDF_LabelSequence aChildLabels;
+  aShapeTool->GetSubShapes(theLabel, aChildLabels);
+  for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
+  {
+    const TDF_Label& aChildLabel = aChildIter.Value();
+    TopoDS_Shape aChildShape;
+    if (aShapeTool->GetShape(aChildLabel, aChildShape))
+    {
+      aChildShapeToLabels.Bind(aChildShape, aChildLabel);
+    }
+  }
+
+  const TopoDS_Shape aShape = aShapeTool->GetShape(theLabel);
+  Handle(VrmlData_Group) aGroup = 0L;
+  TopExp_Explorer anExp(aShape, TopAbs_FACE);
+  Standard_Integer nbFaces = 0;
+  for (; anExp.More(); anExp.Next()) {
+    nbFaces++;
+  }
+  Handle(TDataStd_Name) aNameAttribute;
+  theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
+  if (nbFaces > 1)
+  {
+    if (!aNameAttribute.IsNull())
+    {
+      TCollection_AsciiString aName = aNameAttribute->Get();
+      aGroup = new VrmlData_Group(myScene, aName.ToCString());
+    }
+    else
+    {
+      aGroup = new VrmlData_Group(myScene, 0L);
+    }
+    myScene.AddNode(aGroup, theParent.IsNull());
+    if (!theParent.IsNull())
+    {
+      theParent->AddNode(aGroup);
+    }
+  }
+
+  anExp.Init(aShape, TopAbs_FACE);
+  for (; anExp.More(); anExp.Next()) {
+    TopLoc_Location aLoc;
+    Handle(VrmlData_Geometry) aTShapeNode =
+      makeTShapeNode(anExp.Current(), TopAbs_FACE, aLoc);
+    if (!aTShapeNode.IsNull())
+    {
+      Handle(VrmlData_ShapeNode) aShapeNode = 0L;
+      if (aGroup.IsNull() && !aNameAttribute.IsNull())
+      {
+        TCollection_AsciiString aName = aNameAttribute->Get();
+        aName.ChangeAll(' ', '_');
+        aShapeNode = new VrmlData_ShapeNode(myScene, aName.ToCString());
+      }
+      else
+      {
+        aShapeNode = new VrmlData_ShapeNode(myScene, 0L);
+      }
+
+      // set color
+      TDF_Label aColorL;
+      Standard_Boolean findColor = Standard_False;
+      const TDF_Label* aLabel = aChildShapeToLabels.Seek(anExp.Current());
+      if (aLabel != NULL)
+      {
+        findColor = aColorTool->GetColor(*aLabel, XCAFDoc_ColorSurf, aColorL)
+          || aColorTool->GetColor(*aLabel, XCAFDoc_ColorGen, aColorL);
+      }
+      if (!findColor)
+      {
+        findColor = aColorTool->GetColor(theLabel, XCAFDoc_ColorSurf, aColorL)
+          || aColorTool->GetColor(theLabel, XCAFDoc_ColorGen, aColorL);
+      }
+      if (!findColor)
+      {
+        aShapeNode->SetAppearance(defaultMaterialFace());
+      }
+      else
+      {
+        aShapeNode->SetAppearance(makeMaterialFromColor(aColorL, aColorTool));
+      }
+
+      myScene.AddNode(aShapeNode, Standard_False);
+      aShapeNode->SetGeometry(aTShapeNode);
+      if (aLoc.IsIdentity())
+      {
+        // Store the shape node directly into the main Group.
+        if (!aGroup.IsNull())
+        {
+          aGroup->AddNode(aShapeNode);
+        }
+        else
+        {
+          theParent->AddNode(aShapeNode);
+        }
+      }
+      else
+      {
+        // Create a Transform grouping node
+        Handle(VrmlData_Group) aTrans = new VrmlData_Group(myScene, 0L,
+          Standard_True);
+        gp_Trsf aTrsf(aLoc);
+        if (fabs(myScale - 1.) > Precision::Confusion())
+        {
+          aTrsf.SetScaleFactor(myScale);
+        }
+        aTrans->SetTransform(aTrsf);
+        myScene.AddNode(aTrans, Standard_False);
+        if (!aGroup.IsNull())
+        {
+          aGroup->AddNode(aTrans);
+        }
+        else
+        {
+          theParent->AddNode(aTrans);
+        }
+        // Store the shape node under the transform.
+        aTrans->AddNode(aShapeNode);
+      }
+    }
+  }
+}
+
+
+//=======================================================================
+//function : addInstance
+//purpose  : Adds the reference from the document
+//=======================================================================
+void VrmlData_ShapeConvert::addInstance (const Handle(VrmlData_Group)& theParent,
+                                         const TDF_Label& theLabel,
+                                         const Handle(TDocStd_Document)& theDoc)
+{
+  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
+
+  const TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
+  Handle(VrmlData_Group) aTrans = 0L;
+  if (!aLoc.IsIdentity())
+  {
+    // Create a Transform grouping node
+    aTrans = new VrmlData_Group(myScene, 0L, Standard_True);
+    gp_Trsf aTrsf(aLoc);
+    if (fabs(myScale - 1.) > Precision::Confusion()) {
+      aTrsf.SetScaleFactor(myScale);
+    }
+    aTrans->SetTransform(aTrsf);
+    myScene.AddNode(aTrans, theParent.IsNull());
+    if (!theParent.IsNull())
+    {
+      theParent->AddNode(aTrans);
+    }
+  }
+
+  Handle(TDataStd_Name) aNameAttribute;
+  theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
+
+  TDF_Label aRefLabel;
+  aShapeTool->GetReferredShape(theLabel, aRefLabel);
+  Handle(TDataStd_Name) aRefNameAttribute;
+  aRefLabel.FindAttribute(TDataStd_Name::GetID(), aRefNameAttribute);
+
+  if (aShapeTool->IsSimpleShape(aRefLabel))
+  {
+    addShape((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc);
+  }
+  else if (aShapeTool->IsAssembly(aRefLabel))
+  {
+    addAssembly((aTrans.IsNull() ? theParent : aTrans), aRefLabel, theDoc, aTrans.IsNull());
+  }
+}
+
+
+//=======================================================================
+//function : addAssembly
+//purpose  : Adds the assembly from the document
+//=======================================================================
+void VrmlData_ShapeConvert::addAssembly (const Handle(VrmlData_Group)& theParent,
+                                         const TDF_Label& theLabel,
+                                         const Handle(TDocStd_Document)& theDoc,
+                                         const Standard_Boolean theNeedCreateGroup)
+{
+  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
+
+  Handle(VrmlData_Group) anAssembly = 0L;
+  if (theNeedCreateGroup)
+  {
+    Handle(TDataStd_Name) aNameAttribute;
+    theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
+    if (!aNameAttribute.IsNull())
+    {
+      TCollection_AsciiString aName = aNameAttribute->Get();
+      anAssembly = new VrmlData_Group(myScene, aName.ToCString());
+    }
+    else
+    {
+      anAssembly = new VrmlData_Group(myScene, 0L);
+    }
+    TopLoc_Location aLoc = aShapeTool->GetLocation(theLabel);
+    if (!aLoc.IsIdentity())
+    {
+      gp_Trsf aTrsf(aLoc);
+      if (fabs(myScale - 1.) > Precision::Confusion()) {
+        const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
+        aTrsf.SetTranslationPart(aTransl);
+      }
+      anAssembly->SetTransform(aTrsf);
+    }
+    myScene.AddNode(anAssembly, theParent.IsNull());
+    if (!theParent.IsNull())
+    {
+      theParent->AddNode(anAssembly);
+    }
+  }
+
+  TDF_LabelSequence aChildLabels;
+  aShapeTool->GetComponents(theLabel, aChildLabels);
+  for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
+  {
+    const TDF_Label& aChildLabel = aChildIter.Value();
+    if (aShapeTool->IsAssembly(aChildLabel))
+    {
+      addAssembly((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc, anAssembly.IsNull());
+    }
+    else if (aShapeTool->IsReference(aChildLabel))
+    {
+      addInstance((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
+    }
+    else if (aShapeTool->IsSimpleShape(aChildLabel))
+    {
+      addShape((anAssembly.IsNull() ? theParent : anAssembly), aChildLabel, theDoc);
+    }
+  }
+}
+
+
+//=======================================================================
+//function : ConvertDocument
+//purpose  : 
+//=======================================================================
+void VrmlData_ShapeConvert::ConvertDocument(const Handle(TDocStd_Document) &theDoc)
+{
+  Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
+
+  TDF_LabelSequence aFreeShapeLabels;
+  aShapeTool->GetFreeShapes(aFreeShapeLabels);
+
+  Handle(VrmlData_Group) aGroup = 0L;
+  if (aFreeShapeLabels.Size() > 1)
+  {
+    aGroup = new VrmlData_Group(myScene, 0L);
+    myScene.AddNode(aGroup);
+  }
+
+  for (TDF_LabelSequence::Iterator aRootIter(aFreeShapeLabels); aRootIter.More(); aRootIter.Next())
+  {
+    const TDF_Label& aFreeShapeLabel = aRootIter.Value();
+    if (aShapeTool->IsSimpleShape(aFreeShapeLabel))
+    {
+      addShape(aGroup, aFreeShapeLabel, theDoc);
+    }
+    else if (aShapeTool->IsAssembly(aFreeShapeLabel))
+    {
+      addAssembly(aGroup, aFreeShapeLabel, theDoc, Standard_True);
+    }
+  }
+}
+
+
+//=======================================================================
+//function : makeMaterialFromColor
+//purpose  : 
+//=======================================================================
+
+Handle(VrmlData_Appearance) VrmlData_ShapeConvert::makeMaterialFromColor(
+  const TDF_Label& theColorL,
+  const Handle(XCAFDoc_ColorTool)& theColorTool) const
+{
+  Quantity_ColorRGBA aColor;
+  theColorTool->GetColor(theColorL, aColor);
+
+  TCollection_AsciiString aNodeName = "_materialFace_";
+  Handle(TDataStd_Name) aNameAttribute;
+  if (theColorL.FindAttribute(TDataStd_Name::GetID(), aNameAttribute))
+  {
+    aNodeName.AssignCat(aNameAttribute->Get());
+    Standard_Integer n = aNodeName.Search(" ");
+    if (n > 0)
+    {
+      aNodeName = aNodeName.SubString(1, n - 1);
+    }
+  }
+  else
+  {
+    aNodeName.AssignCat(aColor.GetRGB().Red());
+    aNodeName.AssignCat("_");
+    aNodeName.AssignCat(aColor.GetRGB().Green());
+    aNodeName.AssignCat("_");
+    aNodeName.AssignCat(aColor.GetRGB().Blue());
+  }
+
+  Handle(VrmlData_Appearance) anAppearance =
+    Handle(VrmlData_Appearance)::DownCast(myScene.FindNode(aNodeName.ToCString()));
+  if (anAppearance.IsNull()) {
+    const Handle(VrmlData_Material) aMaterial =
+      new VrmlData_Material(myScene, 0L);
+    aMaterial->SetDiffuseColor(aColor.GetRGB());
+    myScene.AddNode(aMaterial, Standard_False);
+    anAppearance = new VrmlData_Appearance(myScene, aNodeName.ToCString());
+    anAppearance->SetMaterial(aMaterial);
+    myScene.AddNode(anAppearance, Standard_False);
+  }
+
+  return anAppearance;
+}
+
+