0031136: Modeling Data - BinXCAF persistence loses normals from triangulation-only...
authorasuraven <asuraven@opencascade.com>
Tue, 17 Nov 2020 17:37:01 +0000 (20:37 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 20 Jan 2021 18:20:43 +0000 (21:20 +0300)
Information about normals are stored in BinOCAF, XmlOCAF, BRep and BBRep (in case of triangulation-only Faces).
Versions of formats have been changed (11 for TDocStd, 4 for BRep Shape and 3 for Binary BRep Shape)
theWithNormals parameter added to BRepTools::Write()
IsWithNormals()/SetWithNormals() function added to BRepTools_ShapeSet
-normals/-noNormals option added to StoreTriangulation DRAW command
-normals/-noNormals option added to writebrep DRAW command
Tests for writing to brep/binary brep/BinXCaf/XmlXCaf added
Test for StoreTriangulation options -normals/-noNormals added

40 files changed:
dox/specification/brep_format.md
dox/upgrade/upgrade.md
src/BRepTools/BRepTools.cxx
src/BRepTools/BRepTools.hxx
src/BRepTools/BRepTools_ShapeSet.cxx
src/BRepTools/BRepTools_ShapeSet.hxx
src/BinDrivers/BinDrivers_DocumentStorageDriver.cxx
src/BinDrivers/BinDrivers_DocumentStorageDriver.hxx
src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.cxx
src/BinLDrivers/BinLDrivers_DocumentSection.cxx
src/BinLDrivers/BinLDrivers_DocumentSection.hxx
src/BinLDrivers/BinLDrivers_DocumentStorageDriver.cxx
src/BinLDrivers/BinLDrivers_DocumentStorageDriver.hxx
src/BinMNaming/BinMNaming_NamedShapeDriver.cxx
src/BinMNaming/BinMNaming_NamedShapeDriver.hxx
src/BinMNaming/BinMNaming_NamedShapeDriver.lxx
src/BinTools/BinTools.cxx
src/BinTools/BinTools.hxx
src/BinTools/BinTools_FormatVersion.hxx
src/BinTools/BinTools_ShapeSet.cxx
src/BinTools/BinTools_ShapeSet.hxx
src/DBRep/DBRep.cxx
src/DDocStd/DDocStd_DocumentCommands.cxx
src/Poly/Poly_Triangulation.cxx
src/Poly/Poly_Triangulation.hxx
src/TDocStd/TDocStd_FormatVersion.hxx
src/TopTools/TopTools_FormatVersion.hxx
src/TopTools/TopTools_ShapeSet.cxx
src/TopTools/TopTools_ShapeSet.hxx
src/XmlDrivers/XmlDrivers_DocumentStorageDriver.cxx
src/XmlDrivers/XmlDrivers_DocumentStorageDriver.hxx
src/XmlLDrivers/XmlLDrivers_DocumentStorageDriver.cxx
src/XmlLDrivers/XmlLDrivers_DocumentStorageDriver.hxx
src/XmlMNaming/XmlMNaming_NamedShapeDriver.cxx
src/XmlMNaming/XmlMNaming_NamedShapeDriver.hxx
tests/bugs/moddata_3/bug31136_1 [new file with mode: 0644]
tests/bugs/moddata_3/bug31136_2 [new file with mode: 0644]
tests/bugs/moddata_3/bug31136_3 [new file with mode: 0644]
tests/bugs/moddata_3/bug31136_4 [new file with mode: 0644]
tests/bugs/moddata_3/bug31136_5 [new file with mode: 0644]

index 6fa6f00..767a59d 100644 (file)
@@ -54,6 +54,7 @@ The following sample code reads a shape from ASCII file and writes it to a binar
   * \<flag\>: = "0" | "1";
   * \<int\>: It is an integer number from -2<sup>31</sup> to 2<sup>31</sup>-1 which is written in  denary system;  
   * \<real\>: It is a real from -1.7976931348623158 @f$\cdot@f$ 10<sup>308</sup> to 1.7976931348623158 @f$\cdot@f$ 10<sup>308</sup> which is written in decimal or E form with base 10.The point is used as a delimiter of the integer and  fractional parts;
+  * \<short real\>: It is a real from -3.402823 @f$\cdot@f$ 10<sup>38</sup> to 3.402823 @f$\cdot@f$ 10<sup>38</sup> which is written in decimal or E form with base 10.The point is used as a delimiter of the integer and  fractional parts;
   * \<2D point\>: = \<real\>\<_\>\<real\>;  
   * \<3D point\>: = \<real\>(\<_\>\<real)\><sup>2</sup>;  
   * \<2D direction\>: It is a \<2D point\> *x y* so that *x<sup>2</sup> + y<sup>2</sup>* = 1;  
@@ -71,7 +72,7 @@ The following sample code reads a shape from ASCII file and writes it to a binar
   \<content type\> = "DBRep_DrawableShape" \<_\\n\>\<_\\n\>;  
   \<content type\> have other values [1].  
  
-  \<version\> = ("CASCADE Topology V1, (c)  Matra-Datavision" | "CASCADE Topology V2, (c) Matra-Datavision")\<_\\n\>;  
+  \<version\> = ("CASCADE Topology V1, (c)  Matra-Datavision" | "CASCADE Topology V2, (c) Matra-Datavision" | "CASCADE Topology V3, (c) Open Cascade")\<_\\n\>;
   The difference of the versions is described in the  document.  
  
   Sections \<locations\>, \<geometry\> and \<shapes\> are described below in separate chapters of the document.  
@@ -1436,8 +1437,8 @@ The example record describes a polyline from *m*=2 nodes with a parameter prese
 
        <triangulation records> = <triangulation record> ^ <triangulation count>;
 
-       <triangulation record> = <triangulation node count> <_> <triangulation triangle count> <_> <triangulation parameter presence flag> <_> <triangulation deflection> <_\n> 
-       <triangulation nodes> [<_> <triangulation u v parameters>] <_> <triangulation triangles> <_\n>;
+       <triangulation record> = <triangulation node count> <_> <triangulation triangle count> <_> <triangulation parameter presence flag> [<_> <need to write normals flag>] <_> <triangulation deflection> <_\n>
+       <triangulation nodes> [<_> <triangulation u v parameters>] <_> <triangulation triangles> [<_> <triangulation normals>] <_\n>;
 
        <triangulation node count> = <int>;
 
@@ -1445,6 +1446,8 @@ The example record describes a polyline from *m*=2 nodes with a parameter prese
 
        <triangulation parameter presence flag> = <flag>;
 
+       <need to write normals flag> = <flag>;
+
        <triangulation deflection> = <real>;
 
        <triangulation nodes> = (<triangulation node> <_>) ^ <triangulation node count>;
@@ -1458,10 +1461,17 @@ The example record describes a polyline from *m*=2 nodes with a parameter prese
 
        <triangulation triangles> = (<triangulation triangle> <_>) ^ <triangulation triangle count>;
 
-       <triangulation triangle> = <int> <_> <int> <_> <int>.  
+       <triangulation triangle> = <int> <_> <int> <_> <int>;
+
+       <triangulation normals> = (<triangulation normal> <_>) ^ <triangulation node count> ^ 3;
+
+       <triangulation normal> = <short real>.
 ~~~~
  
 **Description**  
+
+\<triangulation u v parameters\> are used in version 2 or later.
+\<need to write normals flag\> and \<triangulation normals\> are used in version 3.
  
 \<triangulation record\> describes a triangulation  *T* which  approximates a surface *S*. The triangulation data consist of a node  count @f$ m \geq 3 @f$, a triangle count @f$ k \geq 1 @f$, a parameter  presence flag *p*, a deflection @f$ d \geq 0 @f$, nodes @f$ N_{i}\; (1\leq i \leq m) @f$, parameter pairs @f$ u_{i}\; v_{i}\; (1\leq i \leq m) @f$, triangles @f$ n_{j,1}\; n_{j,2}\; n_{j,3}\; (1\leq j \leq k,\; n_{j,l} \in \left \{1,...,m \right \}\; (1\leq l\leq 3)) @f$. The parameters are present  only if *p*=1. The deflection describes the triangulation deflection from the surface:  
  
@@ -1640,7 +1650,7 @@ An example of section shapes and a whole  *.brep file are given in chapter 7 @re
 
   *  @f$ f_{1} @f$ -- free;  
   *  @f$ f_{2} @f$ -- modified;  
-  *  @f$ f_{3} @f$ -- IGNORED(version 1) \\ checked (version 2);  
+  *  @f$ f_{3} @f$ -- IGNORED(version 1 only) \\ checked (version 2 or later);  
   *  @f$ f_{4} @f$ -- orientable;  
   *  @f$ f_{5} @f$ -- closed;  
   *  @f$ f_{6} @f$ -- infinite;  
@@ -1827,10 +1837,10 @@ Flags \<edge data same parameter flag\>, \<edge data same range flag\> and \<edg
 \<edge data representation data 1\> describes a 3D curve.  
  
 \<edge data representation data 2\> describes a 2D curve on a surface.  
-\<curve values for parameter minimal and maximal  values\> are used only in version 2.  
+\<curve values for parameter minimal and maximal  values\> are used in version 2 or later.  
  
 \<edge data representation data 3\> describes a 2D  curve on a closed surface.  
-\<curve values for parameter minimal and maximal  values\> are used only in version 2.  
+\<curve values for parameter minimal and maximal  values\> are used in version 2 or later.  
  
 \<edge data representation data 5\> describes a 3D polyline.  
  
index 45a75e8..269d1c8 100644 (file)
@@ -2202,3 +2202,11 @@ This way an application based on an old version of Open CASCADE Technology may r
 @subsection upgrade_760_createdocument New OCAF document
 
 A new OCAF document may be created only by means of the method *NewDocument()* from CDF_Application (redefined in TDocStd_Application). The methods *CreateDocument()* are deleted in all retrieval drivers.
+
+@subsection upgrade_760_changesInStorageOfShapes Changes in storage of shapes
+
+Information about per-vertex triangulations normals is now stored in BinOCAF and XmlOCAF document,
+BRep and Binary BRep Shape formats (only in case of triangulation-only Faces, with no analytical geometry to restore normals).
+
+Versions of formats have been changed (11 for BinOCAF, 10 for XmlOCAF, 4 for BRep Shape and 3 for Binary BRep Shape).
+Files written with the new version will not be readable by applications of old versions.
index b6e2139..b5c9b39 100644 (file)
@@ -668,10 +668,11 @@ void  BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S)
 void BRepTools::Write (const TopoDS_Shape& theShape,
                        Standard_OStream& theStream,
                        const Standard_Boolean theWithTriangles,
+                       const Standard_Boolean theWithNormals,
                        const TopTools_FormatVersion theVersion,
                        const Message_ProgressRange& theProgress)
 {
-  BRepTools_ShapeSet aShapeSet (theWithTriangles);
+  BRepTools_ShapeSet aShapeSet (theWithTriangles, theWithNormals);
   aShapeSet.SetFormatNb (theVersion);
   aShapeSet.Add (theShape);
   aShapeSet.Write (theStream, theProgress);
@@ -700,6 +701,7 @@ void  BRepTools::Read(TopoDS_Shape& Sh,
 Standard_Boolean  BRepTools::Write (const TopoDS_Shape& theShape,
                                     const Standard_CString theFile,
                                     const Standard_Boolean theWithTriangles,
+                                    const Standard_Boolean theWithNormals,
                                     const TopTools_FormatVersion theVersion,
                                     const Message_ProgressRange& theProgress)
 {
@@ -712,7 +714,7 @@ Standard_Boolean  BRepTools::Write (const TopoDS_Shape& theShape,
   if(!isGood)
     return isGood;
 
-  BRepTools_ShapeSet SS (theWithTriangles);
+  BRepTools_ShapeSet SS (theWithTriangles, theWithNormals);
   SS.SetFormatNb (theVersion);
   SS.Add (theShape);
 
index 48e93ac..1a8b80f 100644 (file)
@@ -214,8 +214,8 @@ public:
                      Standard_OStream& theStream,
                      const Message_ProgressRange& theProgress = Message_ProgressRange())
   {
-    Write (theShape, theStream, Standard_True,
-           TopTools_FormatVersion_VERSION_1, theProgress);
+    Write (theShape, theStream, Standard_True, Standard_False,
+           TopTools_FormatVersion_CURRENT, theProgress);
   }
 
   //! Writes the shape to the stream in an ASCII format of specified version.
@@ -223,11 +223,14 @@ public:
   //! @param theStream [in][out]   the stream to output shape into
   //! @param theWithTriangles [in] flag which specifies whether to save shape with (TRUE) or without (FALSE) triangles;
   //!                              has no effect on triangulation-only geometry
+  //! @param theWithNormals [in]   flag which specifies whether to save triangulation with (TRUE) or without (FALSE) normals;
+  //!                              has no effect on triangulation-only geometry
   //! @param theVersion [in]       the TopTools format version
   //! @param theRange              the range of progress indicator to fill in
   Standard_EXPORT static void Write (const TopoDS_Shape& theShape,
                                      Standard_OStream& theStream,
                                      const Standard_Boolean theWithTriangles,
+                                     const Standard_Boolean theWithNormals,
                                      const TopTools_FormatVersion theVersion,
                                      const Message_ProgressRange& theProgress = Message_ProgressRange());
 
@@ -245,8 +248,8 @@ public:
                                  const Standard_CString theFile,
                                  const Message_ProgressRange& theProgress = Message_ProgressRange())
   {
-    return Write (theShape, theFile, Standard_True,
-                  TopTools_FormatVersion_VERSION_1, theProgress);
+    return Write (theShape, theFile, Standard_True, Standard_False,
+                  TopTools_FormatVersion_CURRENT, theProgress);
   }
 
   //! Writes the shape to the file in an ASCII format of specified version.
@@ -254,11 +257,14 @@ public:
   //! @param theFile [in]          the path to file to output shape into
   //! @param theWithTriangles [in] flag which specifies whether to save shape with (TRUE) or without (FALSE) triangles;
   //!                              has no effect on triangulation-only geometry
+  //! @param theWithNormals [in]   flag which specifies whether to save triangulation with (TRUE) or without (FALSE) normals;
+  //!                              has no effect on triangulation-only geometry
   //! @param theVersion [in]       the TopTools format version
   //! @param theRange              the range of progress indicator to fill in
   Standard_EXPORT static Standard_Boolean Write (const TopoDS_Shape& theShape,
                                                  const Standard_CString theFile,
                                                  const Standard_Boolean theWithTriangles,
+                                                 const Standard_Boolean theWithNormals,
                                                  const TopTools_FormatVersion theVersion,
                                                  const Message_ProgressRange& theProgress = Message_ProgressRange());
 
index bdb87cd..5bb69bc 100644 (file)
 //function : BRepTools_ShapeSet
 //purpose  :
 //=======================================================================
-BRepTools_ShapeSet::BRepTools_ShapeSet (const Standard_Boolean theWithTriangles)
-: myWithTriangles (theWithTriangles)
+BRepTools_ShapeSet::BRepTools_ShapeSet (const Standard_Boolean theWithTriangles,
+                                        const Standard_Boolean theWithNormals)
+: myWithTriangles (theWithTriangles),
+  myWithNormals (theWithNormals)
 {
 }
 
@@ -94,9 +96,11 @@ BRepTools_ShapeSet::BRepTools_ShapeSet (const Standard_Boolean theWithTriangles)
 //purpose  :
 //=======================================================================
 BRepTools_ShapeSet::BRepTools_ShapeSet (const BRep_Builder& theBuilder,
-                                        const Standard_Boolean theWithTriangles)
+                                        const Standard_Boolean theWithTriangles,
+                                        const Standard_Boolean theWithNormals)
 : myBuilder (theBuilder),
-  myWithTriangles (theWithTriangles)
+  myWithTriangles (theWithTriangles),
+  myWithNormals(theWithNormals)
 {
 }
 
@@ -197,7 +201,11 @@ void BRepTools_ShapeSet::AddGeometry(const TopoDS_Shape& S)
           }
         }
         else if (CR->IsPolygonOnTriangulation()) {
-          myTriangulations.Add(CR->Triangulation());
+          // NCollection_IndexedDataMap::Add() function use is correct because
+          // Bin(Brep)Tools_ShapeSet::AddGeometry() is called from Bin(Brep)Tools_ShapeSet::Add()
+          // that processes shapes recursively from complex to elementary ones.
+          // As a result, the TopAbs_FACE's will be processed earlier than the TopAbs_EDGE's.
+          myTriangulations.Add(CR->Triangulation(), Standard_False); // edge triangulation does not need normals
           myNodes.Add(CR->PolygonOnTriangulation());
           ChangeLocations().Add(CR->Location());
           if (CR->IsPolygonOnClosedTriangulation())
@@ -218,12 +226,19 @@ void BRepTools_ShapeSet::AddGeometry(const TopoDS_Shape& S)
   else if (S.ShapeType() == TopAbs_FACE) {
 
     // Add the surface geometry
+    Standard_Boolean needNormals(myWithNormals);
     Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(S.TShape());
-    if (!TF->Surface().IsNull())  mySurfaces.Add(TF->Surface());
-
+    if (!TF->Surface().IsNull())
+    {
+      mySurfaces.Add(TF->Surface());
+    }
+    else
+    {
+      needNormals = Standard_True;
+    }
     if (myWithTriangles || TF->Surface().IsNull()) { // for XML Persistence
       Handle(Poly_Triangulation) Tr = TF->Triangulation();
-      if (!Tr.IsNull()) myTriangulations.Add(Tr);
+      if (!Tr.IsNull()) myTriangulations.Add(Tr, needNormals);
     }
 
     ChangeLocations().Add(TF->Location());
@@ -1002,7 +1017,7 @@ void  BRepTools_ShapeSet::ReadGeometry (const TopAbs_ShapeEnum T,
                 myBuilder.UpdateEdge
                   (E, Handle(Poly_PolygonOnTriangulation)::DownCast(myNodes(pt)),
                    Handle(Poly_PolygonOnTriangulation)::DownCast(myNodes(pt2)),
-                   Handle(Poly_Triangulation)::DownCast(myTriangulations(t)),
+                   myTriangulations.FindKey(t),
                    Locations().Location(l));
             }
             else {
@@ -1010,7 +1025,7 @@ void  BRepTools_ShapeSet::ReadGeometry (const TopAbs_ShapeEnum T,
                                  pt > 0 && pt <= myNodes.Extent())
                 myBuilder.UpdateEdge
                   (E,Handle(Poly_PolygonOnTriangulation)::DownCast(myNodes(pt)),
-                   Handle(Poly_Triangulation)::DownCast(myTriangulations(t)),
+                   myTriangulations.FindKey(t),
                    Locations().Location(l));
             }
             // range
@@ -1062,7 +1077,7 @@ void  BRepTools_ShapeSet::ReadGeometry (const TopAbs_ShapeEnum T,
       //only triangulation
       IS >> s;
       myBuilder.UpdateFace(TopoDS::Face(S),
-                           Handle(Poly_Triangulation)::DownCast(myTriangulations(s)));
+                           myTriangulations.FindKey(s));
     }
 //    else pos = IS.tellg();
     
@@ -1079,7 +1094,7 @@ void  BRepTools_ShapeSet::ReadGeometry (const TopAbs_ShapeEnum T,
       s = atoi ( &string[2] );
          if (s > 0 && s <= myTriangulations.Extent())
         myBuilder.UpdateFace(TopoDS::Face(S),
-                             Handle(Poly_Triangulation)::DownCast(myTriangulations(s)));
+                             myTriangulations.FindKey(s));
     }
 //    else IS.seekg(pos);
     }
@@ -1422,16 +1437,24 @@ void BRepTools_ShapeSet::WriteTriangulation(Standard_OStream&      OS,
   Handle(Poly_Triangulation) T;
   for (i = 1; i <= nbtri && aPS.More(); i++, aPS.Next()) {
 
-    T = Handle(Poly_Triangulation)::DownCast(myTriangulations(i));
+    T = myTriangulations.FindKey(i);
+    const Standard_Boolean toWriteNormals = myTriangulations(i);
     if (Compact) {
       OS << T->NbNodes() << " " << T->NbTriangles() << " ";
       OS << ((T->HasUVNodes()) ? "1" : "0") << " ";
+      if (FormatNb() >= TopTools_FormatVersion_VERSION_3)
+      {
+        OS << ((T->HasNormals() && toWriteNormals) ? "1" : "0") << " ";
+      }
     }
     else {
       OS << "  "<< i << " : Triangulation with " << T->NbNodes() << " Nodes and "
          << T->NbTriangles() <<" Triangles\n";
       OS << "      "<<((T->HasUVNodes()) ? "with" : "without") << " UV nodes\n";
-
+      if (FormatNb() >= TopTools_FormatVersion_VERSION_3)
+      {
+        OS << "      " << ((T->HasNormals() && toWriteNormals) ? "with" : "without") << " normals\n";
+      }
     }
     
     // write the deflection
@@ -1486,6 +1509,32 @@ void BRepTools_ShapeSet::WriteTriangulation(Standard_OStream&      OS,
       if (!Compact) OS << "\n";
       else OS << " ";
     }
+
+    if (FormatNb() >= TopTools_FormatVersion_VERSION_3)
+    {
+      if (T->HasNormals() && toWriteNormals)
+      {
+        if (!Compact) OS << "\nNormals :\n";
+        const TShort_Array1OfShortReal& Normals = T->Normals();
+        for (j = 1; j <= nbNodes * 3; j++)
+        {
+          if (!Compact)
+          {
+            OS << std::setw(10) << j << " : ";
+            OS << std::setw(17);
+          }
+          OS << Normals(j) << " ";
+          if (!Compact)
+          {
+            OS << "\n";
+          }
+          else
+          {
+            OS << " ";
+          }
+        }
+      }
+    }
     OS << "\n";
   }
 }
@@ -1512,8 +1561,10 @@ void BRepTools_ShapeSet::ReadTriangulation(Standard_IStream& IS, const Message_P
   //  Standard_Integer i, j, val, nbtri;
   Standard_Integer i, j, nbtri =0;
   Standard_Real d, x, y, z;
+  Standard_Real normal;
   Standard_Integer nbNodes =0, nbTriangles=0;
   Standard_Boolean hasUV= Standard_False;
+  Standard_Boolean hasNormals= Standard_False;
 
   Handle(Poly_Triangulation) T;
 
@@ -1526,11 +1577,19 @@ void BRepTools_ShapeSet::ReadTriangulation(Standard_IStream& IS, const Message_P
   for (i=1; i<=nbtri && aPS.More();i++, aPS.Next()) {
 
     IS >> nbNodes >> nbTriangles >> hasUV;
+    if (FormatNb() >= TopTools_FormatVersion_VERSION_3)
+    {
+      IS >> hasNormals;
+    }
     GeomTools::GetReal(IS, d);
 
     TColgp_Array1OfPnt Nodes(1, nbNodes);
     TColgp_Array1OfPnt2d UVNodes(1, nbNodes);
-
+    Handle(TShort_HArray1OfShortReal) Normals;
+    if (hasNormals)
+    {
+      Normals = new TShort_HArray1OfShortReal(1, nbNodes * 3);
+    }
     for (j = 1; j <= nbNodes; j++) {
       GeomTools::GetReal(IS, x);
       GeomTools::GetReal(IS, y);
@@ -1553,12 +1612,24 @@ void BRepTools_ShapeSet::ReadTriangulation(Standard_IStream& IS, const Message_P
       IS >> n1 >> n2 >> n3;
       Triangles(j).Set(n1,n2,n3);
     }
-      
+
+    if (hasNormals)
+    {
+      for (j = 1; j <= nbNodes * 3; j++)
+      {
+        GeomTools::GetReal(IS, normal);
+        Normals->SetValue(j, static_cast<Standard_ShortReal>(normal));
+      }
+    }
+
     if (hasUV) T =  new Poly_Triangulation(Nodes,UVNodes,Triangles);
     else T = new Poly_Triangulation(Nodes,Triangles);
       
     T->Deflection(d);
-      
-    myTriangulations.Add(T);
+    if (hasNormals)
+    {
+      T->SetNormals(Normals);
+    }
+    myTriangulations.Add(T, hasNormals);
   }
 }
index 3406666..2d1bfe3 100644 (file)
@@ -48,21 +48,28 @@ public:
 
   //! Builds an empty ShapeSet.
   //! @param theWithTriangles flag to write triangulation data
-  Standard_EXPORT BRepTools_ShapeSet (const Standard_Boolean theWithTriangles = Standard_True);
+  Standard_EXPORT BRepTools_ShapeSet (const Standard_Boolean theWithTriangles = Standard_True,
+                                      const Standard_Boolean theWithNormals = Standard_False);
   
   //! Builds an empty ShapeSet.
   //! @param theWithTriangles flag to write triangulation data
   Standard_EXPORT BRepTools_ShapeSet (const BRep_Builder& theBuilder,
-                                      const Standard_Boolean theWithTriangles = Standard_True);
+                                      const Standard_Boolean theWithTriangles = Standard_True,
+                                      const Standard_Boolean theWithNormals = Standard_False);
 
   Standard_EXPORT virtual ~BRepTools_ShapeSet();
 
   //! Return true if shape should be stored with triangles.
   Standard_Boolean IsWithTriangles() const { return myWithTriangles; }
+  //! Return true if shape should be stored triangulation with normals.
+  Standard_Boolean IsWithNormals() const { return myWithNormals; }
 
   //! Define if shape will be stored with triangles.
   //! Ignored (always written) if face defines only triangulation (no surface).
   void SetWithTriangles (const Standard_Boolean theWithTriangles) { myWithTriangles = theWithTriangles; }
+  //! Define if shape will be stored triangulation with normals.
+  //! Ignored (always written) if face defines only triangulation (no surface).
+  void SetWithNormals (const Standard_Boolean theWithNormals) { myWithNormals = theWithNormals; }
 
   //! Clears the content of the set.
   Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
@@ -167,9 +174,12 @@ private:
   GeomTools_Curve2dSet myCurves2d;
   TColStd_IndexedMapOfTransient myPolygons2D;
   TColStd_IndexedMapOfTransient myPolygons3D;
-  TColStd_IndexedMapOfTransient myTriangulations;
+  NCollection_IndexedDataMap<Handle(Poly_Triangulation),
+                             Standard_Boolean> myTriangulations; //!< Contains a boolean flag with information
+                                                                 //!  to save normals for triangulation
   TColStd_IndexedMapOfTransient myNodes;
   Standard_Boolean myWithTriangles;
+  Standard_Boolean myWithNormals;
 
 };
 
index fda11df..492ef6d 100644 (file)
@@ -93,6 +93,51 @@ void BinDrivers_DocumentStorageDriver::SetWithTriangles (const Handle(Message_Me
   aShapesDriver->SetWithTriangles (theWithTriangulation);
 }
 
+//=======================================================================
+//function : IsWithNormals
+//purpose  :
+//=======================================================================
+Standard_Boolean BinDrivers_DocumentStorageDriver::IsWithNormals() const
+{
+  if (myDrivers.IsNull())
+  {
+    return Standard_False;
+  }
+
+  Handle(BinMDF_ADriver) aDriver;
+  myDrivers->GetDriver(STANDARD_TYPE(TNaming_NamedShape), aDriver);
+  Handle(BinMNaming_NamedShapeDriver) aShapesDriver = Handle(BinMNaming_NamedShapeDriver)::DownCast(aDriver);
+  return !aShapesDriver.IsNull()
+    && aShapesDriver->IsWithNormals();
+}
+
+//=======================================================================
+//function : SetWithNormals
+//purpose  :
+//=======================================================================
+void BinDrivers_DocumentStorageDriver::SetWithNormals(const Handle(Message_Messenger)& theMessageDriver,
+  const Standard_Boolean theWithNormals)
+{
+  if (myDrivers.IsNull())
+  {
+    myDrivers = AttributeDrivers(theMessageDriver);
+  }
+  if (myDrivers.IsNull())
+  {
+    return;
+  }
+
+  Handle(BinMDF_ADriver) aDriver;
+  myDrivers->GetDriver(STANDARD_TYPE(TNaming_NamedShape), aDriver);
+  Handle(BinMNaming_NamedShapeDriver) aShapesDriver = Handle(BinMNaming_NamedShapeDriver)::DownCast(aDriver);
+  if (aShapesDriver.IsNull())
+  {
+    throw Standard_NotImplemented("Internal Error - TNaming_NamedShape is not found!");
+  }
+
+  aShapesDriver->SetWithNormals(theWithNormals);
+}
+
 //=======================================================================
 //function : WriteShapeSection
 //purpose  : Implements WriteShapeSection
@@ -100,7 +145,7 @@ void BinDrivers_DocumentStorageDriver::SetWithTriangles (const Handle(Message_Me
 void BinDrivers_DocumentStorageDriver::WriteShapeSection
                                (BinLDrivers_DocumentSection&   theSection,
                                 Standard_OStream&              theOS,
-                                const Standard_Integer         theDocVer,
+                                const TDocStd_FormatVersion    theDocVer,
                                 const Message_ProgressRange&   theRange)
 {
   const Standard_Size aShapesSectionOffset = (Standard_Size) theOS.tellp();
@@ -112,7 +157,7 @@ void BinDrivers_DocumentStorageDriver::WriteShapeSection
       OCC_CATCH_SIGNALS
       Handle(BinMNaming_NamedShapeDriver) aNamedShapeDriver =
         Handle(BinMNaming_NamedShapeDriver)::DownCast (aDriver);
-      aNamedShapeDriver->WriteShapeSection (theOS, theRange);
+      aNamedShapeDriver->WriteShapeSection (theOS, theDocVer, theRange);
     }
     catch(Standard_Failure const& anException) {
       TCollection_ExtendedString anErrorStr ("BinDrivers_DocumentStorageDriver, Shape Section :");
index b230145..d02fa87 100644 (file)
@@ -46,15 +46,20 @@ public:
   Standard_EXPORT virtual void WriteShapeSection
     (BinLDrivers_DocumentSection& theDocSection, 
      Standard_OStream& theOS, 
-     const Standard_Integer theDocVer,
+     const TDocStd_FormatVersion theDocVer,
      const Message_ProgressRange& theRange = Message_ProgressRange()) Standard_OVERRIDE;
 
   //! Return true if shape should be stored with triangles.
   Standard_EXPORT Standard_Boolean IsWithTriangles() const;
+  //! Return true if shape should be stored with triangulation normals.
+  Standard_EXPORT Standard_Boolean IsWithNormals() const;
 
   //! Set if triangulation should be stored or not.
   Standard_EXPORT void SetWithTriangles (const Handle(Message_Messenger)& theMessageDriver,
                                          const Standard_Boolean theWithTriangulation);
+  //! Set if triangulation should be stored with normals or not.
+  Standard_EXPORT void SetWithNormals(const Handle(Message_Messenger)& theMessageDriver,
+                                         const Standard_Boolean theWithTriangulation);
 
   DEFINE_STANDARD_RTTIEXT(BinDrivers_DocumentStorageDriver,BinLDrivers_DocumentStorageDriver)
 
index a36a41a..7bf2a1d 100644 (file)
@@ -158,8 +158,8 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&
     myReaderStatus = PCDM_RS_FormatFailure;
     return;
   }
-  Standard_Integer aFileVer = aHeaderData->StorageVersion().IntegerValue();
-  Standard_Integer aCurrVer = TDocStd_Document::CurrentStorageFormatVersion();
+  TDocStd_FormatVersion aFileVer = static_cast<TDocStd_FormatVersion>(aHeaderData->StorageVersion().IntegerValue());
+  TDocStd_FormatVersion aCurrVer = TDocStd_Document::CurrentStorageFormatVersion();
   // maintain one-way compatibility starting from version 2+
   if (!CheckDocumentVersion(aFileVer, aCurrVer)) {
     myReaderStatus = PCDM_RS_NoVersion;
@@ -560,7 +560,7 @@ Standard_Boolean BinLDrivers_DocumentRetrievalDriver::CheckDocumentVersion(
                                                           const Standard_Integer theFileVersion,
                                                           const Standard_Integer theCurVersion)
 {
-  if (theFileVersion < TDocStd_FormatVersion_VERSION_2 || theFileVersion > theCurVersion) {
+  if (theFileVersion < TDocStd_FormatVersion_LOWER || theFileVersion > theCurVersion) {
     // file was written with another version
     return Standard_False;
   }
index b51ba2f..d82ef56 100644 (file)
@@ -111,7 +111,7 @@ void BinLDrivers_DocumentSection::SetLength (const uint64_t theLength)
 //=======================================================================
 
 void BinLDrivers_DocumentSection::WriteTOC (Standard_OStream& theStream,
-                                            const Standard_Integer theDocFormatVersion)
+                                            const TDocStd_FormatVersion theDocFormatVersion)
 {
   char aBuf[512];
 
@@ -167,7 +167,7 @@ void BinLDrivers_DocumentSection::WriteTOC (Standard_OStream& theStream,
 
 void BinLDrivers_DocumentSection::Write (Standard_OStream&   theStream,
                                          const uint64_t theOffset,
-                                         const Standard_Integer theDocFormatVersion)
+                                         const TDocStd_FormatVersion theDocFormatVersion)
 {
   const uint64_t aSectionEnd = (uint64_t) theStream.tellp();
   theStream.seekp((std::streamsize)myValue[0]);
@@ -218,7 +218,7 @@ void BinLDrivers_DocumentSection::Write (Standard_OStream&   theStream,
 void BinLDrivers_DocumentSection::ReadTOC
                                 (BinLDrivers_DocumentSection& theSection,
                                  Standard_IStream&            theStream,
-                                 const Standard_Integer       theDocFormatVersion)
+                                 const TDocStd_FormatVersion  theDocFormatVersion)
 {
   char aBuf[512];
   Standard_Integer aNameBufferSize;
index b3cf472..b206057 100644 (file)
@@ -25,6 +25,7 @@
 #include <Standard_OStream.hxx>
 #include <Standard_IStream.hxx>
 #include <Message_ProgressIndicator.hxx>
+#include <TDocStd_FormatVersion.hxx>
 
 class TCollection_AsciiString;
 
@@ -67,17 +68,17 @@ public:
   
   //! Create a Section entry in the Document TOC (list of sections)
   Standard_EXPORT void WriteTOC (Standard_OStream& theOS,
-                                 const Standard_Integer theDocFormatVersion);
+                                 const TDocStd_FormatVersion theDocFormatVersion);
   
   //! Save Offset and Length data into the Section entry
   //! in the Document TOC (list of sections)
   Standard_EXPORT void Write (Standard_OStream& theOS, const uint64_t theOffset,
-                              const Standard_Integer theDocFormatVersion);
+                              const TDocStd_FormatVersion theDocFormatVersion);
   
   //! Fill a DocumentSection instance from the data that are read
   //! from TOC.
   Standard_EXPORT static void ReadTOC (BinLDrivers_DocumentSection& theSection, Standard_IStream& theIS,
-                                       const Standard_Integer theDocFormatVersion);
+                                       const TDocStd_FormatVersion theDocFormatVersion);
 
 
 
index aa67de6..b5b9006 100644 (file)
@@ -124,7 +124,7 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)&  theD
     }
 
 //  2. Write the Table of Contents of Sections
-    const Standard_Integer aDocVer = aDoc->StorageFormatVersion();
+    const TDocStd_FormatVersion aDocVer = aDoc->StorageFormatVersion();
     BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
     for (; anIterS.More(); anIterS.Next())
       anIterS.ChangeValue().WriteTOC (theOStream, aDocVer);
@@ -547,7 +547,7 @@ void BinLDrivers_DocumentStorageDriver::WriteSection
 void BinLDrivers_DocumentStorageDriver::WriteShapeSection
                                 (BinLDrivers_DocumentSection&   theSection,
                                  Standard_OStream&              theOS,
-                                 const Standard_Integer         theDocVer,
+                                 const TDocStd_FormatVersion    theDocVer,
                                  const Message_ProgressRange& /*theRange*/)
 {
   const Standard_Size aShapesSectionOffset = (Standard_Size) theOS.tellp();
index 9862219..e91d56c 100644 (file)
@@ -29,6 +29,7 @@
 #include <Standard_OStream.hxx>
 #include <Standard_Boolean.hxx>
 #include <Standard_Type.hxx>
+#include <TDocStd_FormatVersion.hxx>
 class BinMDF_ADriverTable;
 class Message_Messenger;
 class TCollection_ExtendedString;
@@ -87,7 +88,7 @@ protected:
   //! defines the procedure of writing a shape  section to file
   Standard_EXPORT virtual void WriteShapeSection (BinLDrivers_DocumentSection& theDocSection,
                                                   Standard_OStream& theOS,
-                                                  const Standard_Integer theDocVer,
+                                                  const TDocStd_FormatVersion theDocVer,
                                                   const Message_ProgressRange& theRange = Message_ProgressRange());
 
   Handle(BinMDF_ADriverTable) myDrivers;
index 98e3bab..651facd 100644 (file)
@@ -24,6 +24,7 @@
 #include <TCollection_AsciiString.hxx>
 #include <TDF_Attribute.hxx>
 #include <TDF_Label.hxx>
+#include <TDocStd_FormatVersion.hxx>
 #include <TNaming_Builder.hxx>
 #include <TNaming_Evolution.hxx>
 #include <TNaming_Iterator.hxx>
@@ -141,9 +142,7 @@ static int TranslateFrom  (const BinObjMgt_Persistent&  theSource,
 
 BinMNaming_NamedShapeDriver::BinMNaming_NamedShapeDriver
                         (const Handle(Message_Messenger)& theMsgDriver)
-: BinMDF_ADriver (theMsgDriver, STANDARD_TYPE(TNaming_NamedShape)->Name()),
-  myShapeSet (Standard_False),
-  myFormatNb (BinTools_FormatVersion_VERSION_1)
+: BinMDF_ADriver (theMsgDriver, STANDARD_TYPE(TNaming_NamedShape)->Name())
 {
 }
 
@@ -278,10 +277,19 @@ void BinMNaming_NamedShapeDriver::Paste (const Handle(TDF_Attribute)& theSource,
 //=======================================================================
 
 void BinMNaming_NamedShapeDriver::WriteShapeSection (Standard_OStream& theOS,
+                                                     const Standard_Integer theDocVer,
                                                      const Message_ProgressRange& theRange)
 {
   theOS << SHAPESET; 
-  myShapeSet.SetFormatNb(myFormatNb);
+  if (theDocVer >= TDocStd_FormatVersion_VERSION_11)
+  {
+    myShapeSet.SetFormatNb(BinTools_FormatVersion_VERSION_4);
+  }
+  else
+  {
+    myShapeSet.SetFormatNb(BinTools_FormatVersion_VERSION_1);
+  }
+
   myShapeSet.Write (theOS, theRange);
   myShapeSet.Clear();
 }
@@ -312,7 +320,6 @@ void BinMNaming_NamedShapeDriver::ReadShapeSection (Standard_IStream& theIS,
   if(aSectionTitle.Length() > 0 && aSectionTitle == SHAPESET) {
     myShapeSet.Clear();
     myShapeSet.Read (theIS, theRange);
-    SetFormatNb(myShapeSet.FormatNb());
   }
   else
     theIS.seekg(aPos); // no shape section is present, try to return to initial point
index 4e15ab7..c5b3788 100644 (file)
@@ -56,29 +56,26 @@ public:
                                          const Message_ProgressRange& therange = Message_ProgressRange());
   
   //! Output the shapes into Bin Document file
-  Standard_EXPORT void WriteShapeSection (Standard_OStream& theOS,
-                                          const Message_ProgressRange& therange = Message_ProgressRange());
+  Standard_EXPORT void WriteShapeSection(Standard_OStream& theOS,
+                                         const Standard_Integer theDocVer,
+                                         const Message_ProgressRange& therange = Message_ProgressRange());
   
   //! Clear myShapeSet
   Standard_EXPORT void Clear();
 
   //! Return true if shape should be stored with triangles.
   Standard_Boolean IsWithTriangles() const { return myShapeSet.IsWithTriangles(); }
+  //! Return true if shape should be stored with triangulation normals.
+  Standard_Boolean IsWithNormals() const { return myShapeSet.IsWithNormals(); }
 
   //! set whether to store triangulation
-  void SetWithTriangles (const Standard_Boolean isWithTriangles);
-  
-  //! set the format of topology
-  //! First : does not write CurveOnSurface UV Points into the file
-  //! on reading calls Check() method.
-  //! Second: stores CurveOnSurface UV Points.
-    void SetFormatNb (const Standard_Integer theFormat);
+  void SetWithTriangles (const Standard_Boolean isWithTriangles) { myShapeSet.SetWithTriangles(isWithTriangles); }
+  //! set whether to store triangulation with normals
+  void SetWithNormals (const Standard_Boolean isWithNormals) { myShapeSet.SetWithNormals(isWithNormals); }
   
-  //! get the format of topology
-    Standard_Integer GetFormatNb() const;
   
-  //! get the format of topology
-    BinTools_LocationSet& GetShapesLocations();
+  //! get the shapes locations
+  BinTools_LocationSet& GetShapesLocations();
 
 
 
@@ -94,8 +91,6 @@ private:
 
 
   BinTools_ShapeSet myShapeSet;
-  Standard_Integer myFormatNb;
-
 
 };
 
index da9a59d..c313d6f 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-//=======================================================================
-//function : GetFormat
-//purpose  : 
-//=======================================================================
-
-inline Standard_Integer BinMNaming_NamedShapeDriver::GetFormatNb() const
-{
-  return myFormatNb;
-}
-
-//=======================================================================
-//function : SetFormat
-//purpose  : 
-//=======================================================================
-
-inline void BinMNaming_NamedShapeDriver::SetFormatNb(const Standard_Integer theFormatNb) 
-{
-  myFormatNb = theFormatNb;
-}
-
-//=======================================================================
-//function : SetWithTriangles
-//purpose  : 
-//=======================================================================
-
-inline void BinMNaming_NamedShapeDriver::SetWithTriangles(const Standard_Boolean isWithTriangles) 
-{
-  myShapeSet.SetWithTriangles(isWithTriangles);
-}
 
 //=======================================================================
 //function : GetShapesLocations
index 741be0e..d17d490 100644 (file)
@@ -176,10 +176,13 @@ Standard_IStream& BinTools::GetBool(Standard_IStream& IS, Standard_Boolean& aVal
 void BinTools::Write (const TopoDS_Shape& theShape,
                       Standard_OStream& theStream,
                       const Standard_Boolean theWithTriangles,
+                      const Standard_Boolean theWithNormals,
                       const BinTools_FormatVersion theVersion,
                       const Message_ProgressRange& theRange)
 {
-  BinTools_ShapeSet aShapeSet (theWithTriangles);
+  BinTools_ShapeSet aShapeSet;
+  aShapeSet.SetWithTriangles(theWithTriangles);
+  aShapeSet.SetWithNormals(theWithNormals);
   aShapeSet.SetFormatNb (theVersion);
   aShapeSet.Add (theShape);
   aShapeSet.Write (theStream, theRange);
@@ -194,7 +197,8 @@ void BinTools::Write (const TopoDS_Shape& theShape,
 void BinTools::Read (TopoDS_Shape& theShape, Standard_IStream& theStream,
                      const Message_ProgressRange& theRange)
 {
-  BinTools_ShapeSet aShapeSet(Standard_True);
+  BinTools_ShapeSet aShapeSet;
+  aShapeSet.SetWithTriangles(Standard_True);
   aShapeSet.Read (theStream, theRange);
   aShapeSet.Read (theShape, theStream, aShapeSet.NbShapes());
 }
@@ -206,6 +210,7 @@ void BinTools::Read (TopoDS_Shape& theShape, Standard_IStream& theStream,
 Standard_Boolean BinTools::Write (const TopoDS_Shape& theShape,
                                   const Standard_CString theFile,
                                   const Standard_Boolean theWithTriangles,
+                                  const Standard_Boolean theWithNormals,
                                   const BinTools_FormatVersion theVersion,
                                   const Message_ProgressRange& theRange)
 {
@@ -215,7 +220,7 @@ Standard_Boolean BinTools::Write (const TopoDS_Shape& theShape,
   if (!aStream.good())
     return Standard_False;
 
-  Write (theShape, aStream, theWithTriangles, theVersion, theRange);
+  Write (theShape, aStream, theWithTriangles, theWithNormals, theVersion, theRange);
   aStream.close();
   return aStream.good();
 }
index efbf823..e6fe7e7 100644 (file)
@@ -73,7 +73,7 @@ public:
                      Standard_OStream& theStream,
                      const Message_ProgressRange& theRange = Message_ProgressRange())
   {
-    Write (theShape, theStream, Standard_True,
+    Write (theShape, theStream, Standard_True, Standard_False,
            BinTools_FormatVersion_CURRENT, theRange);
   }
 
@@ -82,10 +82,13 @@ public:
   //! @param theStream [in][out]   the stream to output shape into
   //! @param theWithTriangles [in] flag which specifies whether to save shape with (TRUE) or without (FALSE) triangles;
   //!                              has no effect on triangulation-only geometry
+  //! @param theWithNormals [in]   flag which specifies whether to save triangulation with (TRUE) or without (FALSE) normals;
+  //!                              has no effect on triangulation-only geometry
   //! @param theVersion [in]       the BinTools format version
   //! @param theRange              the range of progress indicator to fill in
   Standard_EXPORT static void Write(const TopoDS_Shape& theShape, Standard_OStream& theStream,
                                     const Standard_Boolean theWithTriangles,
+                                    const Standard_Boolean theWithNormals,
                                     const BinTools_FormatVersion theVersion,
                                     const Message_ProgressRange& theRange = Message_ProgressRange());
 
@@ -101,7 +104,7 @@ public:
                                  const Standard_CString theFile,
                                  const Message_ProgressRange& theRange = Message_ProgressRange())
   {
-    return Write (theShape, theFile, Standard_True,
+    return Write (theShape, theFile, Standard_True, Standard_False,
                   BinTools_FormatVersion_CURRENT, theRange);
   }
 
@@ -110,11 +113,14 @@ public:
   //! @param theFile [in]          the path to file to output shape into
   //! @param theWithTriangles [in] flag which specifies whether to save shape with (TRUE) or without (FALSE) triangles;
   //!                              has no effect on triangulation-only geometry
+  //! @param theWithNormals [in]   flag which specifies whether to save triangulation with (TRUE) or without (FALSE) normals;
+  //!                              has no effect on triangulation-only geometry
   //! @param theVersion [in]       the BinTools format version
   //! @param theRange              the range of progress indicator to fill in
   Standard_EXPORT static Standard_Boolean Write (const TopoDS_Shape& theShape,
                                                  const Standard_CString theFile,
                                                  const Standard_Boolean theWithTriangles,
+                                                 const Standard_Boolean theWithNormals,
                                                  const BinTools_FormatVersion theVersion,
                                                  const Message_ProgressRange& theRange = Message_ProgressRange());
 
index faced8f..66724ee 100644 (file)
@@ -23,8 +23,16 @@ enum BinTools_FormatVersion
                                         //!  On reading format is recognized from Version string.
   BinTools_FormatVersion_VERSION_3 = 3, //!< (OCCT 6.2.1) Correctly processes geometry with points on Curve,
                                         //!  or point on Surface, or points on curve of surface [#0009745]
+  BinTools_FormatVersion_VERSION_4 = 4, //!< Stores per-vertex normal information in case
+                                        //!  of triangulation-only Faces, because
+                                        //!  no analytical geometry to restore normals
+  BinTools_FormatVersion_CURRENT = BinTools_FormatVersion_VERSION_4 //!< Current version
+};
 
-  BinTools_FormatVersion_CURRENT = BinTools_FormatVersion_VERSION_1 //!< The current version.
+enum
+{
+  BinTools_FormatVersion_LOWER   = BinTools_FormatVersion_VERSION_1,
+  BinTools_FormatVersion_UPPER   = BinTools_FormatVersion_VERSION_4
 };
 
 #endif
index 2709dd2..6af7ad3 100644 (file)
 
 #include <string.h>
 //#define MDTV_DEB 1
-Standard_CString BinTools_ShapeSet::Version_1 = "Open CASCADE Topology V1 (c)";
-Standard_CString BinTools_ShapeSet::Version_2 = "Open CASCADE Topology V2 (c)";
-Standard_CString BinTools_ShapeSet::Version_3 = "Open CASCADE Topology V3 (c)";
+
+const Standard_CString BinTools_ShapeSet::THE_ASCII_VERSIONS[BinTools_FormatVersion_UPPER + 1] =
+{
+  "",
+  "Open CASCADE Topology V1 (c)",
+  "Open CASCADE Topology V2 (c)",
+  "Open CASCADE Topology V3 (c)",
+  "Open CASCADE Topology V4, (c) Open Cascade"
+};
 
 //=======================================================================
 //function : operator << (gp_Pnt)
@@ -75,9 +81,10 @@ static Standard_OStream& operator <<(Standard_OStream& OS, const gp_Pnt P)
 //function : BinTools_ShapeSet
 //purpose  :
 //=======================================================================
-BinTools_ShapeSet::BinTools_ShapeSet (const Standard_Boolean theWithTriangles)
+BinTools_ShapeSet::BinTools_ShapeSet ()
 : myFormatNb (BinTools_FormatVersion_CURRENT),
-  myWithTriangles (theWithTriangles)
+  myWithTriangles (Standard_False),
+  myWithNormals(Standard_False)
 {}
 
 //=======================================================================
@@ -94,9 +101,8 @@ BinTools_ShapeSet::~BinTools_ShapeSet()
 //=======================================================================
 void BinTools_ShapeSet::SetFormatNb(const Standard_Integer theFormatNb)
 {
-  Standard_ASSERT_RETURN(theFormatNb == BinTools_FormatVersion_VERSION_1 ||
-                         theFormatNb == BinTools_FormatVersion_VERSION_2 ||
-                         theFormatNb == BinTools_FormatVersion_VERSION_3,
+  Standard_ASSERT_RETURN(theFormatNb >= BinTools_FormatVersion_LOWER &&
+                         theFormatNb <= BinTools_FormatVersion_UPPER,
     "Error: unsupported BinTools version.", );
 
   myFormatNb = theFormatNb;
@@ -261,7 +267,11 @@ void BinTools_ShapeSet::AddGeometry(const TopoDS_Shape& S)
           }
         }
         else if (CR->IsPolygonOnTriangulation()) {
-          myTriangulations.Add(CR->Triangulation());
+          // NCollection_IndexedDataMap::Add() function use is correct because
+          // Bin(Brep)Tools_ShapeSet::AddGeometry() is called from Bin(Brep)Tools_ShapeSet::Add()
+          // that processes shapes recursively from complex to elementary ones.
+          // As a result, the TopAbs_FACE's will be processed earlier than the TopAbs_EDGE's.
+          myTriangulations.Add(CR->Triangulation(), Standard_False); // edge triangulation does not need normals
           myNodes.Add(CR->PolygonOnTriangulation());
           ChangeLocations().Add(CR->Location());
           if (CR->IsPolygonOnClosedTriangulation())
@@ -282,14 +292,21 @@ void BinTools_ShapeSet::AddGeometry(const TopoDS_Shape& S)
   else if (S.ShapeType() == TopAbs_FACE) {
 
     // Add the surface geometry
+    Standard_Boolean needNormals(myWithNormals);
     Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(S.TShape());
-    if (!TF->Surface().IsNull())  mySurfaces.Add(TF->Surface());
-
+    if (!TF->Surface().IsNull())
+    {
+      mySurfaces.Add(TF->Surface());
+    }
+    else
+    {
+      needNormals = Standard_True;
+    }
     if (myWithTriangles
      || TF->Surface().IsNull())
     {
       Handle(Poly_Triangulation) Tr = TF->Triangulation();
-      if (!Tr.IsNull()) myTriangulations.Add(Tr);
+      if (!Tr.IsNull()) myTriangulations.Add(Tr, needNormals);
     }
 
     ChangeLocations().Add(TF->Location());
@@ -332,18 +349,7 @@ void  BinTools_ShapeSet::Write (Standard_OStream& OS,
                                 const Message_ProgressRange& theRange)const
 {
   // write the copyright
-  if (myFormatNb == BinTools_FormatVersion_VERSION_3)
-  {
-    OS << "\n" << Version_3 << "\n";
-  }
-  else if (myFormatNb == BinTools_FormatVersion_VERSION_2)
-  {
-    OS << "\n" << Version_2 << "\n";
-  }
-  else
-  {
-    OS << "\n" << Version_1 << "\n";
-  }
+  OS << "\n" << THE_ASCII_VERSIONS[myFormatNb] << "\n";
 
   //-----------------------------------------
   // write the locations
@@ -413,6 +419,7 @@ void  BinTools_ShapeSet::Read (Standard_IStream& IS,
 
   // Check the version
   char vers[101];
+  Standard_Boolean anIsSetFormat = Standard_False;
   do {
     IS.getline(vers,100,'\n');
     // BUC60769 PTV 18.10.2000: remove possible '\r' at the end of the line
@@ -422,27 +429,28 @@ void  BinTools_ShapeSet::Read (Standard_IStream& IS,
       for (lv--; lv > 0 && (vers[lv] == '\r' || vers[lv] == '\n'); lv--)
         vers[lv] = '\0';
     }
-    
-  } while ( ! IS.fail() && strcmp(vers,Version_1) && strcmp(vers,Version_2) &&
-          strcmp(vers,Version_3));
+
+    for (Standard_Integer i = BinTools_FormatVersion_LOWER;
+         i <= BinTools_FormatVersion_UPPER; ++i)
+    {
+      if (!strcmp(vers, THE_ASCII_VERSIONS[i]))
+      {
+        SetFormatNb(i);
+        anIsSetFormat = Standard_True;
+        break;
+      }
+    }
+    if (anIsSetFormat)
+    {
+      break;
+    }
+  } 
+  while ( ! IS.fail());
   if (IS.fail()) {
     std::cout << "BinTools_ShapeSet::Read: File was not written with this version of the topology" << std::endl;
     return;
   }
 
-  if (strcmp (vers, Version_3) == 0)
-  {
-    SetFormatNb (BinTools_FormatVersion_VERSION_3);
-  }
-  else if (strcmp (vers, Version_2) == 0)
-  {
-    SetFormatNb (BinTools_FormatVersion_VERSION_2);
-  }
-  else
-  {
-    SetFormatNb (BinTools_FormatVersion_VERSION_1);
-  }
-
   //-----------------------------------------
   // read the locations
   //-----------------------------------------
@@ -1111,11 +1119,11 @@ void  BinTools_ShapeSet::ReadGeometry(const TopAbs_ShapeEnum T,
            BinTools::GetInteger(IS, l);
             if (closed)
             {
-              myBuilder.UpdateEdge (E, myNodes(pt), myNodes(pt2), myTriangulations(t), Locations().Location(l));
+              myBuilder.UpdateEdge (E, myNodes(pt), myNodes(pt2), myTriangulations.FindKey(t), Locations().Location(l));
             }
             else
             {
-              myBuilder.UpdateEdge (E, myNodes(pt), myTriangulations(t), Locations().Location(l));
+              myBuilder.UpdateEdge (E, myNodes(pt), myTriangulations.FindKey(t), Locations().Location(l));
             }
             // range            
             break;
@@ -1164,7 +1172,7 @@ void  BinTools_ShapeSet::ReadGeometry(const TopAbs_ShapeEnum T,
       // cas triangulation
        if(aByte == 2) {
          BinTools::GetInteger(IS, s);
-         myBuilder.UpdateFace(TopoDS::Face(S), myTriangulations(s));
+         myBuilder.UpdateFace(TopoDS::Face(S), myTriangulations.FindKey(s));
        }
       }
       break;
@@ -1477,11 +1485,16 @@ void BinTools_ShapeSet::WriteTriangulation (Standard_OStream& OS,
     for (Standard_Integer aTriangulationIter = 1; aTriangulationIter <= aNbTriangulations && aPS.More(); ++aTriangulationIter, aPS.Next())
     {
       const Handle(Poly_Triangulation)& aTriangulation = myTriangulations.FindKey (aTriangulationIter);
+      Standard_Boolean NeedToWriteNormals = myTriangulations.FindFromIndex(aTriangulationIter);
       const Standard_Integer aNbNodes     = aTriangulation->NbNodes();
       const Standard_Integer aNbTriangles = aTriangulation->NbTriangles();
       BinTools::PutInteger(OS, aNbNodes);
       BinTools::PutInteger(OS, aNbTriangles);
       BinTools::PutBool(OS, aTriangulation->HasUVNodes() ? 1 : 0);
+      if (myFormatNb >= BinTools_FormatVersion_VERSION_4)
+      {
+        BinTools::PutBool(OS, (aTriangulation->HasNormals() && NeedToWriteNormals) ? 1 : 0);
+      }
       BinTools::PutReal(OS, aTriangulation->Deflection());
 
       // write the 3d nodes
@@ -1513,6 +1526,20 @@ void BinTools_ShapeSet::WriteTriangulation (Standard_OStream& OS,
         BinTools::PutInteger(OS, aTri.Value (2));
         BinTools::PutInteger(OS, aTri.Value (3));
       }
+
+      // write the normals
+      if (myFormatNb >= BinTools_FormatVersion_VERSION_4)
+      {
+        if (aTriangulation->HasNormals() && NeedToWriteNormals)
+        {
+          const TShort_Array1OfShortReal& aNormals = aTriangulation->Normals();
+          for (Standard_Integer aNormalIter = 1; aNormalIter <= 3 * aNbNodes; ++aNormalIter)
+          {
+            const Standard_ShortReal& aNormal = aNormals.Value(aNormalIter);
+            BinTools::PutShortReal(OS, aNormal);
+          }
+        }
+      }
     }
   }
   catch (Standard_Failure const& anException)
@@ -1549,12 +1576,17 @@ void BinTools_ShapeSet::ReadTriangulation (Standard_IStream& IS,
     {
       Standard_Integer aNbNodes = 0, aNbTriangles = 0;
       Standard_Boolean hasUV = Standard_False;
+      Standard_Boolean hasNormals = Standard_False;
       Standard_Real aDefl = 0.0;
       BinTools::GetInteger(IS, aNbNodes);
       BinTools::GetInteger(IS, aNbTriangles);
       BinTools::GetBool(IS, hasUV);
+      if (myFormatNb >= BinTools_FormatVersion_VERSION_4)
+      {
+        BinTools::GetBool(IS, hasNormals);
+      }
       BinTools::GetReal(IS, aDefl); //deflection
-      Handle(Poly_Triangulation) aTriangulation = new Poly_Triangulation (aNbNodes, aNbTriangles, hasUV);
+      Handle(Poly_Triangulation) aTriangulation = new Poly_Triangulation (aNbNodes, aNbTriangles, hasUV, hasNormals);
       aTriangulation->Deflection (aDefl);
 
       TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
@@ -1587,7 +1619,19 @@ void BinTools_ShapeSet::ReadTriangulation (Standard_IStream& IS,
         BinTools::GetInteger(IS, aTri.ChangeValue (3));
       }
 
-      myTriangulations.Add (aTriangulation);
+      if (hasNormals)
+      {
+        TShort_Array1OfShortReal& aNormals = aTriangulation->ChangeNormals();
+        for (Standard_Integer aNormalIter = 1; aNormalIter <= aNbNodes*3; ++aNormalIter)
+        {
+          Standard_ShortReal aNormalFromFile;
+          BinTools::GetShortReal(IS, aNormalFromFile);
+          Standard_ShortReal& aNormalCoordinate = aNormals.ChangeValue(aNormalIter);
+          aNormalCoordinate = aNormalFromFile;
+        }
+      }
+
+      myTriangulations.Add (aTriangulation, hasNormals);
     }
   }
   catch (Standard_Failure const& anException)
index 365d614..87cae7c 100644 (file)
@@ -47,16 +47,22 @@ public:
 
   //! Builds an empty ShapeSet.
   //! @param theWithTriangles [in] flag to write triangulation data
-  Standard_EXPORT BinTools_ShapeSet (const Standard_Boolean theWithTriangles = Standard_False);
+  Standard_EXPORT BinTools_ShapeSet ();
 
   Standard_EXPORT virtual ~BinTools_ShapeSet();
 
   //! Return true if shape should be stored with triangles.
   Standard_Boolean IsWithTriangles() const { return myWithTriangles; }
+  //! Return true if shape should be stored triangulation with normals.
+  Standard_Boolean IsWithNormals() const { return myWithNormals; }
+
 
   //! Define if shape will be stored with triangles.
   //! Ignored (always written) if face defines only triangulation (no surface).
   void SetWithTriangles (const Standard_Boolean theWithTriangles) { myWithTriangles = theWithTriangles; }
+  //! Define if shape will be stored triangulation with normals.
+  //! Ignored (always written) if face defines only triangulation (no surface).
+  void SetWithNormals(const Standard_Boolean theWithNormals) { myWithNormals = theWithNormals; }
 
   //! Sets the BinTools_FormatVersion.
   Standard_EXPORT void SetFormatNb (const Standard_Integer theFormatNb);
@@ -193,9 +199,7 @@ public:
 
 public:
 
-  static Standard_CString Version_1;
-  static Standard_CString Version_2;
-  static Standard_CString Version_3;
+  static const Standard_CString THE_ASCII_VERSIONS[BinTools_FormatVersion_UPPER + 1];
 
 private:
 
@@ -208,9 +212,12 @@ private:
   BinTools_Curve2dSet myCurves2d;
   NCollection_IndexedMap<Handle(Poly_Polygon2D), TColStd_MapTransientHasher> myPolygons2D;
   NCollection_IndexedMap<Handle(Poly_Polygon3D), TColStd_MapTransientHasher> myPolygons3D;
-  NCollection_IndexedMap<Handle(Poly_Triangulation), TColStd_MapTransientHasher> myTriangulations;
+  NCollection_IndexedDataMap<Handle(Poly_Triangulation),
+                             Standard_Boolean> myTriangulations; //!< Contains a boolean flag with information
+                                                                 //!  to save normals for triangulation
   NCollection_IndexedMap<Handle(Poly_PolygonOnTriangulation), TColStd_MapTransientHasher> myNodes;
   Standard_Boolean myWithTriangles;
+  Standard_Boolean myWithNormals;
 
 };
 
index bb3ed45..43727a7 100644 (file)
@@ -1386,10 +1386,12 @@ static Standard_Integer writebrep (Draw_Interpretor& theDI,
   Standard_Integer aVersion = -1;
   TCollection_AsciiString aShapeName, aFileName;
   TopoDS_Shape aShape;
-  bool isBinaryFormat = false, isWithTriangles = true;
+  Standard_Boolean isBinaryFormat(Standard_False);
+  Standard_Boolean isWithTriangles(Standard_True);
+  Standard_Boolean isWithNormals(Standard_False);
   if (!strcasecmp (theArgVec[0], "binsave"))
   {
-    isBinaryFormat = true;
+    isBinaryFormat = Standard_True;
   }
 
   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
@@ -1398,7 +1400,7 @@ static Standard_Integer writebrep (Draw_Interpretor& theDI,
     aParam.LowerCase();
     if (aParam == "-binary")
     {
-      isBinaryFormat = true;
+      isBinaryFormat = Standard_True;
       if (anArgIter + 1 < theNbArgs
        && Draw::ParseOnOff (theArgVec[anArgIter + 1], isBinaryFormat))
       {
@@ -1418,7 +1420,7 @@ static Standard_Integer writebrep (Draw_Interpretor& theDI,
     else if (aParam == "-notriangles"
           || aParam == "-triangles")
     {
-      isWithTriangles = true;
+      isWithTriangles = Standard_True;
       if (anArgIter + 1 < theNbArgs
        && Draw::ParseOnOff (theArgVec[anArgIter + 1], isWithTriangles))
       {
@@ -1429,6 +1431,20 @@ static Standard_Integer writebrep (Draw_Interpretor& theDI,
         isWithTriangles = !isWithTriangles;
       }
     }
+    else if (aParam == "-nonormals"
+          || aParam == "-normals")
+    {
+      isWithNormals = Standard_True;
+      if (anArgIter + 1 < theNbArgs
+       && Draw::ParseOnOff (theArgVec[anArgIter + 1], isWithNormals))
+      {
+        ++anArgIter;
+      }
+      if (aParam == "-nonormals")
+      {
+        isWithNormals = !isWithNormals;
+      }
+    }
     else if (aShapeName.IsEmpty())
     {
       aShapeName = theArgVec[anArgIter];
@@ -1467,7 +1483,7 @@ static Standard_Integer writebrep (Draw_Interpretor& theDI,
     BinTools_FormatVersion aBinToolsVersion = aVersion > 0
                                             ? static_cast<BinTools_FormatVersion> (aVersion)
                                             : BinTools_FormatVersion_CURRENT;
-    if (!BinTools::Write (aShape, aFileName.ToCString(), isWithTriangles, aBinToolsVersion, aProgress->Start()))
+    if (!BinTools::Write (aShape, aFileName.ToCString(), isWithTriangles, isWithNormals, aBinToolsVersion, aProgress->Start()))
     {
       theDI << "Cannot write to the file " << aFileName;
       return 1;
@@ -1484,7 +1500,7 @@ static Standard_Integer writebrep (Draw_Interpretor& theDI,
     TopTools_FormatVersion aTopToolsVersion = aVersion > 0
                                             ? static_cast<TopTools_FormatVersion> (aVersion)
                                             : TopTools_FormatVersion_CURRENT;
-    if (!BRepTools::Write (aShape, aFileName.ToCString(), isWithTriangles, aTopToolsVersion, aProgress->Start()))
+    if (!BRepTools::Write (aShape, aFileName.ToCString(), isWithTriangles, isWithNormals, aTopToolsVersion, aProgress->Start()))
     {
       theDI << "Cannot write to the file " << aFileName;
       return 1;
@@ -1652,13 +1668,14 @@ void  DBRep::BasicCommands(Draw_Interpretor& theCommands)
                     "\n\t\t   +|-g :  switch on/off graphical mode of Progress Indicator",
                     XProgress,"DE: General");
   theCommands.Add("writebrep",
-                  "writebrep shape filename [-binary] [-version Version] [-noTriangles]"
+                  "writebrep shape filename [-binary=off] [-version Version=4] [-noTriangles=off]"
                   "\n\t\t: Save the shape in the ASCII (default) or binary format file."
                   "\n\t\t:  -binary  write into the binary format (ASCII when unspecified)"
                   "\n\t\t:  -version a number of format version to save;"
-                  "\n\t\t:           ASCII  versions: 1, 2       (1 for ASCII  when unspecified);"
-                  "\n\t\t:           Binary versions: 1, 2 and 3 (1 for Binary when unspecified)."
-                  "\n\t\t:  -noTriangles skip triangulation data (OFF when unspecified).",
+                  "\n\t\t:           ASCII  versions: 1, 2 and 3    (3 for ASCII  when unspecified);"
+                  "\n\t\t:           Binary versions: 1, 2, 3 and 4 (4 for Binary when unspecified)."
+                  "\n\t\t:  -noTriangles skip triangulation data (OFF when unspecified)."
+                  "\n\t\t:           Ignored (always written) if face defines only triangulation (no surface).",
                   __FILE__, writebrep, g);
   theCommands.Add("readbrep",
                   "readbrep filename shape"
index 078df02..462ae50 100644 (file)
@@ -436,15 +436,44 @@ static Standard_Integer DDocStd_StoreTriangulation (Draw_Interpretor& theDi,
     theDi << (aDriverXCaf->IsWithTriangles() ? "1" : "0");
     return 0;
   }
-  else if (theNbArgs != 2)
+
+  for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
   {
-    std::cout << "Syntax error: wrong number of arguments\n";
-    return 1;
-  }
+    TCollection_AsciiString aParam(theArgVec[anArgIter]);
+    aParam.LowerCase();
+
+    // toStore optional positional parameter
+    Standard_Integer aParsedIntegerValue(0);
+    if (anArgIter == 1 && Draw::ParseInteger(aParam.ToCString(), aParsedIntegerValue))
+    {
+      const Standard_Boolean toEnable = (aParsedIntegerValue != 0);
+      aDriverXCaf->SetWithTriangles(anApp->MessageDriver(), toEnable);
+      aDriverOcaf->SetWithTriangles(anApp->MessageDriver(), toEnable);
+      continue;
+    }
 
-  const Standard_Boolean toEnable = (Draw::Atoi (theArgVec[1]) != 0);
-  aDriverXCaf->SetWithTriangles (anApp->MessageDriver(), toEnable);
-  aDriverOcaf->SetWithTriangles (anApp->MessageDriver(), toEnable);
+    if (aParam == "-nonormals"
+      || aParam == "-normals")
+    {
+      Standard_Boolean isWithNormals(Standard_True);
+      if (anArgIter + 1 < theNbArgs
+        && Draw::ParseOnOff(theArgVec[anArgIter + 1], isWithNormals))
+      {
+        ++anArgIter;
+      }
+      if (aParam == "-nonormals")
+      {
+        isWithNormals = !isWithNormals;
+      }
+      aDriverXCaf->SetWithNormals(anApp->MessageDriver(), isWithNormals);
+      aDriverOcaf->SetWithNormals(anApp->MessageDriver(), isWithNormals);
+    }
+    if (aParam == "-getnormals")
+    {
+      theDi << (aDriverXCaf->IsWithNormals() ? "1" : "0");
+      continue;
+    }
+  }
   return 0;
 }
 
@@ -480,7 +509,9 @@ void DDocStd::DocumentCommands(Draw_Interpretor& theCommands)
                   __FILE__, DDocStd_DumpDocument, g);   
 
   theCommands.Add ("StoreTriangulation",
-                   "StoreTriangulation [toStore={0|1}]"
+                   "StoreTriangulation [toStore={0|1}] [-normals=off] [-noNormals=on]"
+                   "\n\t\t:  -normals -noNormals write triangulation normals."
+                   "\n\t\t:  Ignored (always off) if toStore=0 or skipped"
                    "\nSetup BinXCAF/BinOcaf storage drivers to write triangulation",
                    __FILE__, DDocStd_StoreTriangulation, g);
 
index b367b5a..a1d67cc 100644 (file)
@@ -41,9 +41,30 @@ Poly_Triangulation::Poly_Triangulation(const Standard_Integer theNbNodes,
 
 //=======================================================================
 //function : Poly_Triangulation
-//purpose  : 
+//purpose  :
 //=======================================================================
+Poly_Triangulation::Poly_Triangulation(const Standard_Integer theNbNodes,
+                                       const Standard_Integer theNbTriangles,
+                                       const Standard_Boolean theHasUVNodes,
+                                       const Standard_Boolean theHasNormals)
+: myDeflection(0),
+  myNodes     (1, theNbNodes),
+  myTriangles (1, theNbTriangles)
+{
+  if (theHasUVNodes)
+  {
+    myUVNodes = new TColgp_HArray1OfPnt2d(1, theNbNodes);
+  }
+  if (theHasNormals)
+  {
+    myNormals = new TShort_HArray1OfShortReal(1, theNbNodes * 3);
+  }
+}
 
+//=======================================================================
+//function : Poly_Triangulation
+//purpose  :
+//=======================================================================
 Poly_Triangulation::Poly_Triangulation(const TColgp_Array1OfPnt&    theNodes,
                                        const Poly_Array1OfTriangle& theTriangles)
 : myDeflection(0),
index 0465962..ad7bc94 100644 (file)
@@ -76,6 +76,17 @@ public:
   //! enable a 2D representation).
   Standard_EXPORT Poly_Triangulation(const Standard_Integer nbNodes, const Standard_Integer nbTriangles, const Standard_Boolean UVNodes);
 
+  //! Constructs a triangulation from a set of triangles.
+  //! The triangulation is initialized without a triangle or a node,
+  //! but capable of containing nbNodes nodes, and nbTriangles triangles.
+  //! Here the UVNodes flag indicates whether 2D nodes will be associated with 3D ones,
+  //! (i.e. to enable a 2D representation).
+  //! Here the hasNormals flag indicates whether normals will be given and associated with nodes.
+  Standard_EXPORT Poly_Triangulation(const Standard_Integer nbNodes,
+                                     const Standard_Integer nbTriangles,
+                                     const Standard_Boolean UVNodes,
+                                     const Standard_Boolean hasNormals);
+
   //! Constructs a triangulation from a set of triangles. The
   //! triangulation is initialized with 3D points from Nodes and triangles
   //! from Triangles.
index 3634ee6..99511d1 100644 (file)
@@ -63,7 +63,18 @@ enum TDocStd_FormatVersion
   TDocStd_FormatVersion_VERSION_10,    //!< OCCT 7.2.0
                                        //!< * BIN: ReadTOC changed to handle 64-bit file length [#0028736]
 
-  TDocStd_FormatVersion_CURRENT = TDocStd_FormatVersion_VERSION_10 //!< The latest version
+  TDocStd_FormatVersion_VERSION_11,    //!< OCCT 7.6.0
+                                       //!< * BIN, XML: TopTools_FormatVersion_CURRENT changed to 3 and 
+                                       //!< BinTools_FormatVersion_CURRENT changed to 4 to preserve per-vertex normal 
+                                       //!< information in case of triangulation-only Faces [#0031136]
+  TDocStd_FormatVersion_CURRENT = TDocStd_FormatVersion_VERSION_11 //!< Current version
 };
 
+enum
+{
+  TDocStd_FormatVersion_LOWER   = TDocStd_FormatVersion_VERSION_2,
+  TDocStd_FormatVersion_UPPER   = TDocStd_FormatVersion_VERSION_11
+};
+
+
 #endif // _TDocStdFormatVersion_HeaderFile
index 2cc523e..598830c 100644 (file)
@@ -22,8 +22,16 @@ enum TopTools_FormatVersion
                                         //!  This is default version.
   TopTools_FormatVersion_VERSION_2 = 2, //!< Stores CurveOnSurface UV Points.
                                         //!  On reading format is recognized from Version string.
+  TopTools_FormatVersion_VERSION_3 = 3,  //!< Stores per-vertex normal information in case of triangulation-only Faces,
+                                        //!  because no analytical geometry to restore normals
+  TopTools_FormatVersion_CURRENT = TopTools_FormatVersion_VERSION_3 //!< Current version
+};
 
-  TopTools_FormatVersion_CURRENT = TopTools_FormatVersion_VERSION_1 //!< The current version.
+enum
+{
+  TopTools_FormatVersion_LOWER   = TopTools_FormatVersion_VERSION_1,
+  TopTools_FormatVersion_UPPER   = TopTools_FormatVersion_VERSION_3
 };
 
+
 #endif
index 417fd66..7733994 100644 (file)
 
 #include <locale.h>
 #include <string.h>
-Standard_CString TopTools_ShapeSet::Version_1 = "CASCADE Topology V1, (c) Matra-Datavision";
-Standard_CString TopTools_ShapeSet::Version_2 = "CASCADE Topology V2, (c) Matra-Datavision";
+
+const Standard_CString TopTools_ShapeSet::THE_ASCII_VERSIONS[TopTools_FormatVersion_UPPER + 1] =
+{
+  "",
+  "CASCADE Topology V1, (c) Matra-Datavision",
+  "CASCADE Topology V2, (c) Matra-Datavision",
+  "CASCADE Topology V3, (c) Open Cascade"
+};
 
 //=======================================================================
 //function : TopTools_ShapeSet
@@ -55,8 +61,8 @@ TopTools_ShapeSet::~TopTools_ShapeSet()
 //=======================================================================
 void TopTools_ShapeSet::SetFormatNb(const Standard_Integer theFormatNb)
 {
-  Standard_ASSERT_RETURN(theFormatNb == TopTools_FormatVersion_VERSION_1 ||
-                         theFormatNb == TopTools_FormatVersion_VERSION_2,
+  Standard_ASSERT_RETURN(theFormatNb >= TopTools_FormatVersion_LOWER &&
+                         theFormatNb <= TopTools_FormatVersion_UPPER,
     "Error: unsupported TopTools version.", );
 
   myFormatNb = theFormatNb;
@@ -458,14 +464,7 @@ void  TopTools_ShapeSet::Write(Standard_OStream& OS, const Message_ProgressRange
   std::streamsize prec = OS.precision(15);
 
   // write the copyright
-  if (myFormatNb == TopTools_FormatVersion_VERSION_2)
-  {
-    OS << "\n" << Version_2 << "\n";
-  }
-  else
-  {
-    OS << "\n" << Version_1 << "\n";
-  }
+  OS << "\n" << THE_ASCII_VERSIONS[myFormatNb] << "\n";
 
   //-----------------------------------------
   // write the locations
@@ -603,6 +602,7 @@ void  TopTools_ShapeSet::Read(Standard_IStream& IS, const Message_ProgressRange&
 
   // Check the version
   char vers[101];
+  Standard_Boolean anIsSetFormat = Standard_False;
   do {
     IS.getline(vers,100,'\n');
     // BUC60769 PTV 18.10.2000: remove possible '\r' at the end of the line
@@ -616,23 +616,27 @@ void  TopTools_ShapeSet::Read(Standard_IStream& IS, const Message_ProgressRange&
       for (lv--; lv > 0 && (vers[lv] == '\r' || vers[lv] == '\n') ;lv--) 
         vers[lv] = '\0';
     }
+    for (Standard_Integer i = TopTools_FormatVersion_LOWER;
+         i <= TopTools_FormatVersion_UPPER; ++i)
+    {
+      if (!strcmp(vers, THE_ASCII_VERSIONS[i]))
+      {
+        SetFormatNb(i);
+        anIsSetFormat = Standard_True;
+        break;
+      }
+    }
+    if (anIsSetFormat)
+    {
+      break;
+    }
     
-  } while (!IS.fail()
-        && strcmp(vers, Version_1)
-        && strcmp(vers, Version_2));
+  } while (!IS.fail());
   if (IS.fail()) {
     std::cout << "File was not written with this version of the topology"<<std::endl;
     IS.imbue (anOldLocale);
     return;
   }
-  else if (strcmp(vers, Version_2) == 0)
-  {
-    SetFormatNb(TopTools_FormatVersion_VERSION_2);
-  }
-  else
-  {
-    SetFormatNb(TopTools_FormatVersion_VERSION_1);
-  }
 
   //-----------------------------------------
   // read the locations
index d62fe82..1668a9d 100644 (file)
@@ -181,8 +181,7 @@ public:
 
 public:
 
-  static Standard_CString Version_1;
-  static Standard_CString Version_2;
+  static const Standard_CString THE_ASCII_VERSIONS[TopTools_FormatVersion_VERSION_3 + 1];
 
 private:
 
index 08f7366..e81c049 100644 (file)
@@ -52,6 +52,7 @@ Handle(XmlMDF_ADriverTable) XmlDrivers_DocumentStorageDriver::AttributeDrivers
 //=======================================================================
 Standard_Boolean XmlDrivers_DocumentStorageDriver::WriteShapeSection
                                          (XmlObjMgt_Element&  theElement,
+                                          const TDocStd_FormatVersion theStorageFormatVersion,
                                           const Message_ProgressRange& theRange)
 {
   Standard_Boolean isShape(Standard_False);
@@ -60,7 +61,7 @@ Standard_Boolean XmlDrivers_DocumentStorageDriver::WriteShapeSection
   {
     Handle(XmlMNaming_NamedShapeDriver) aNamedShapeDriver = 
       Handle(XmlMNaming_NamedShapeDriver)::DownCast (aDriver);
-    aNamedShapeDriver->WriteShapeSection (theElement, theRange);
+    aNamedShapeDriver->WriteShapeSection (theElement, theStorageFormatVersion, theRange);
     isShape = Standard_True;
   }
   return isShape;
index 2f111e4..6e43ff9 100644 (file)
@@ -42,7 +42,8 @@ public:
                       (const Handle(Message_Messenger)& theMsgDriver) Standard_OVERRIDE;
   
   Standard_EXPORT virtual Standard_Boolean WriteShapeSection
-                      (XmlObjMgt_Element& thePDoc, 
+                      (XmlObjMgt_Element& thePDoc,
+                       const TDocStd_FormatVersion theStorageFormatVersion,
                        const Message_ProgressRange& theRange = Message_ProgressRange()) Standard_OVERRIDE;
 
   DEFINE_STANDARD_RTTIEXT(XmlDrivers_DocumentStorageDriver,XmlLDrivers_DocumentStorageDriver)
index 869747e..000faa5 100644 (file)
@@ -270,7 +270,7 @@ Standard_Boolean XmlLDrivers_DocumentStorageDriver::WriteToDomDocument
 
   // Document version
   Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast (theDocument);
-  Standard_Integer aFormatVersion = TDocStd_Document::CurrentStorageFormatVersion(); // the last version of the format
+  TDocStd_FormatVersion aFormatVersion = TDocStd_Document::CurrentStorageFormatVersion(); // the last version of the format
   if (TDocStd_Document::CurrentStorageFormatVersion() < aDoc->StorageFormatVersion())
   {
     TCollection_ExtendedString anErrorString("Unacceptable storage format version, the last verson is used");
@@ -365,7 +365,7 @@ Standard_Boolean XmlLDrivers_DocumentStorageDriver::WriteToDomDocument
   myRelocTable.Clear();
 
   // 4. Write Shapes section
-  if (WriteShapeSection(theElement, aPS.Next()))
+  if (WriteShapeSection(theElement, aFormatVersion, aPS.Next()))
     ::take_time (0, " +++ Fin DOM data for Shapes : ", aMessageDriver);
   if (!aPS.More())
   {
@@ -466,7 +466,8 @@ static void take_time (const Standard_Integer isReset, const char * aHeader,
 //=======================================================================
 Standard_Boolean XmlLDrivers_DocumentStorageDriver::WriteShapeSection
                                 (XmlObjMgt_Element&           /*theElement*/,
-                                const Message_ProgressRange&  /*theRange*/)
+                                 const TDocStd_FormatVersion /*theStorageFormatVersion*/,
+                                 const Message_ProgressRange&  /*theRange*/)
 {
   // empty; should be redefined in subclasses
   return Standard_False;
index 6f94bb0..944ac31 100644 (file)
@@ -26,6 +26,7 @@
 #include <Standard_Boolean.hxx>
 #include <XmlObjMgt_Element.hxx>
 #include <Standard_Integer.hxx>
+#include <TDocStd_FormatVersion.hxx>
 
 class XmlMDF_ADriverTable;
 class TCollection_ExtendedString;
@@ -79,6 +80,7 @@ protected:
   
   Standard_EXPORT virtual Standard_Boolean WriteShapeSection
                                 (XmlObjMgt_Element& thePDoc, 
+                                 const TDocStd_FormatVersion theStorageFormatVersion,
                                  const Message_ProgressRange& theRange = Message_ProgressRange());
 
   Handle(XmlMDF_ADriverTable) myDrivers;
index 21408ff..7545449 100644 (file)
@@ -29,6 +29,7 @@
 #include <TNaming_NamedShape.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopTools_LocationSet.hxx>
+#include <XmlLDrivers.hxx>
 #include <XmlMNaming_NamedShapeDriver.hxx>
 #include <XmlMNaming_Shape1.hxx>
 #include <XmlObjMgt.hxx>
@@ -361,6 +362,7 @@ void XmlMNaming_NamedShapeDriver::ReadShapeSection (const XmlObjMgt_Element& the
 //=======================================================================
 
 void XmlMNaming_NamedShapeDriver::WriteShapeSection (XmlObjMgt_Element& theElement,
+                                                     TDocStd_FormatVersion theStorageFormatVersion,
                                                      const Message_ProgressRange& theRange)
 {
   //  Create "shapes" element and append it as child
@@ -369,8 +371,17 @@ void XmlMNaming_NamedShapeDriver::WriteShapeSection (XmlObjMgt_Element& theEleme
   theElement.appendChild (anElement);
 
   //  Add text to the "shapes" element
-  if (myShapeSet.NbShapes() > 0) {
-    myShapeSet.SetFormatNb(TopTools_FormatVersion_VERSION_1);
+  if (myShapeSet.NbShapes() > 0) 
+  {
+    if (theStorageFormatVersion >= TDocStd_FormatVersion_VERSION_11)
+    {
+      myShapeSet.SetFormatNb(TopTools_FormatVersion_VERSION_3);
+    }
+    else
+    {
+      myShapeSet.SetFormatNb(TopTools_FormatVersion_VERSION_1);
+    }
+
     LDOM_OSStream aStream (16 * 1024);
 //    ostrstream aStream;
 //    aStream.rdbuf() -> setbuf (0, 16380);
index 100772b..61d3111 100644 (file)
@@ -22,6 +22,7 @@
 #include <BRepTools_ShapeSet.hxx>
 #include <XmlMDF_ADriver.hxx>
 #include <Standard_Boolean.hxx>
+#include <TDocStd_FormatVersion.hxx>
 #include <XmlObjMgt_RRelocationTable.hxx>
 #include <XmlObjMgt_SRelocationTable.hxx>
 #include <XmlObjMgt_Element.hxx>
@@ -59,6 +60,7 @@ public:
   
   //! Output the shapes into DOM element
   Standard_EXPORT void WriteShapeSection (XmlObjMgt_Element& anElement,
+                                          TDocStd_FormatVersion theStorageFormatVersion,
                                           const Message_ProgressRange& theRange = Message_ProgressRange());
   
   //! Clear myShapeSet
diff --git a/tests/bugs/moddata_3/bug31136_1 b/tests/bugs/moddata_3/bug31136_1
new file mode 100644 (file)
index 0000000..332f556
--- /dev/null
@@ -0,0 +1,23 @@
+puts "=========="
+puts "0031136: BinXCAF persistence loses normals from triangulation-only Faces"
+puts "=========="
+puts ""
+
+pload MODELING XDE OCAF VISUALIZATION
+source $env(CSF_OCCTSamplesPath)/tcl/cad.tcl
+trinfo res
+wavefront res $imagedir/${test_image}
+readobj o $imagedir/${test_image}.obj
+
+# binary format
+set test_image_bbrep ${test_image}_bbrep
+binsave o $imagedir/${test_image_bbrep}.bbrep
+binrestore $imagedir/${test_image_bbrep}.bbrep b1
+vclear
+vclose ALL
+vinit v1/v1
+vbottom
+vdisplay -dispMode 1 b1
+vfit
+vrenderparams -shadingModel phong
+checkview -screenshot -3d -path ${imagedir}/${test_image_bbrep}.png
diff --git a/tests/bugs/moddata_3/bug31136_2 b/tests/bugs/moddata_3/bug31136_2
new file mode 100644 (file)
index 0000000..23c834a
--- /dev/null
@@ -0,0 +1,24 @@
+puts "=========="
+puts "0031136: BinXCAF persistence loses normals from triangulation-only Faces"
+puts "=========="
+puts ""
+
+pload MODELING XDE OCAF VISUALIZATION
+source $env(CSF_OCCTSamplesPath)/tcl/cad.tcl
+trinfo res
+wavefront res $imagedir/${test_image}
+readobj o $imagedir/${test_image}.obj
+
+# ASCII format
+set test_image_brep ${test_image}_brep
+save o $imagedir/${test_image_brep}.brep
+restore $imagedir/${test_image_brep}.brep b2
+vclear
+vclose ALL
+vinit v1/v1
+vbottom
+vdisplay -dispMode 1 b2
+vfit
+vrenderparams -shadingModel phong
+checkview -screenshot -3d -path ${imagedir}/${test_image_brep}.png
+
diff --git a/tests/bugs/moddata_3/bug31136_3 b/tests/bugs/moddata_3/bug31136_3
new file mode 100644 (file)
index 0000000..3d5538a
--- /dev/null
@@ -0,0 +1,27 @@
+puts "=========="
+puts "0031136: BinXCAF persistence loses normals from triangulation-only Faces"
+puts "=========="
+puts ""
+
+pload MODELING XDE OCAF VISUALIZATION
+source $env(CSF_OCCTSamplesPath)/tcl/cad.tcl
+trinfo res
+wavefront res $imagedir/${test_image}
+readobj o $imagedir/${test_image}.obj
+
+# XBF format
+set test_image_XBF ${test_image}_XBF
+XNewDoc D1
+XAddShape D1 o
+XSave D1 $imagedir/${test_image_XBF}.xbf
+Close D1
+XOpen $imagedir/${test_image_XBF}.xbf D2
+vclear
+vclose ALL
+vinit v1/v1
+vbottom
+XDisplay -dispMode 1 D2
+Close D2
+vfit
+vrenderparams -shadingModel phong
+checkview -screenshot -3d -path ${imagedir}/${test_image_XBF}.png
diff --git a/tests/bugs/moddata_3/bug31136_4 b/tests/bugs/moddata_3/bug31136_4
new file mode 100644 (file)
index 0000000..5a8dc30
--- /dev/null
@@ -0,0 +1,29 @@
+puts "=========="
+puts "0031136: BinXCAF persistence loses normals from triangulation-only Faces"
+puts "=========="
+puts ""
+
+pload MODELING XDE OCAF VISUALIZATION
+source $env(CSF_OCCTSamplesPath)/tcl/cad.tcl
+trinfo res
+wavefront res $imagedir/${test_image}
+readobj o $imagedir/${test_image}.obj
+
+
+# XML format
+set test_image_XML ${test_image}_XML
+NewDocument D1 XmlXCAF
+XAddShape D1 o
+# SetStorageFormatVersion D1 10
+SaveAs D1 $imagedir/${test_image_XML}.xml
+Close D1
+Open $imagedir/${test_image_XML}.xml D2
+vclear
+vclose ALL
+vinit v1/v1
+vbottom
+XDisplay -dispMode 1 D2
+Close D2
+vfit
+vrenderparams -shadingModel phong
+checkview -screenshot -3d -path ${imagedir}/${test_image_XML}.png
diff --git a/tests/bugs/moddata_3/bug31136_5 b/tests/bugs/moddata_3/bug31136_5
new file mode 100644 (file)
index 0000000..8df910c
--- /dev/null
@@ -0,0 +1,69 @@
+puts "=========="
+puts "0031136: BinXCAF persistence loses normals from triangulation-only Faces"
+puts "=========="
+puts ""
+
+pload XDE OCAF
+
+StoreTriangulation 1 -normals
+set res [StoreTriangulation -getnormals]
+if { $res != 1 } {
+   puts "Error : normals not on"
+}
+StoreTriangulation 1 -normals 0
+set res [StoreTriangulation -getnormals]
+if { $res != 0 } {
+   puts "Error : normals not off"
+}
+StoreTriangulation 1 -normals 1
+set res [StoreTriangulation -getnormals]
+if { $res != 1 } {
+   puts "Error : normals not on"
+}
+StoreTriangulation 1 -nonormals
+set res [StoreTriangulation -getnormals]
+if { $res != 0 } {
+   puts "Error : normals not off"
+}
+StoreTriangulation 1 -nonormals 0
+set res [StoreTriangulation -getnormals]
+if { $res != 1 } {
+   puts "Error : normals not on"
+}
+StoreTriangulation 1 -nonormals 1
+set res [StoreTriangulation -getnormals]
+if { $res != 0 } {
+   puts "Error : normals not off"
+}
+StoreTriangulation -normals
+set res [StoreTriangulation -getnormals]
+if { $res != 1 } {
+   puts "Error : normals not on"
+}
+StoreTriangulation -normals 0
+set res [StoreTriangulation -getnormals]
+if { $res != 0 } {
+   puts "Error : normals not off"
+}
+StoreTriangulation -normals 1
+set res [StoreTriangulation -getnormals]
+if { $res != 1 } {
+   puts "Error : normals not on"
+}
+StoreTriangulation -nonormals
+set res [StoreTriangulation -getnormals]
+if { $res != 0 } {
+   puts "Error : normals not off"
+}
+StoreTriangulation -nonormals 0
+set res [StoreTriangulation -getnormals]
+if { $res != 1 } {
+   puts "Error : normals not on"
+}
+StoreTriangulation -nonormals 1
+set res [StoreTriangulation -getnormals]
+if { $res != 0 } {
+   puts "Error : normals not off"
+}
+
+puts "OK"
\ No newline at end of file