0028840: Data Exchange - rewrite the STL Reader/Writer
[occt.git] / src / StlAPI / StlAPI_Writer.cxx
index 9037efa..5defbc4 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <StlAPI_Writer.ixx>
-#include <StlTransfer.hxx>
-#include <TopoDS_Shape.hxx>
+#include <StlAPI_Writer.hxx>
+
 #include <Bnd_Box.hxx>
-#include <RWStl.hxx>
 #include <BRepBndLib.hxx>
 #include <OSD_Path.hxx>
+#include <OSD_OpenFile.hxx>
+#include <RWStl.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopExp_Explorer.hxx>
+#include <Poly_Triangulation.hxx>
 
-#define MAX2(X, Y)      (  Abs(X) > Abs(Y)? Abs(X) : Abs(Y) )
-#define MAX3(X, Y, Z)   ( MAX2 ( MAX2(X,Y) , Z) )
-
+//=============================================================================
+//function : StlAPI_Writer
+//purpose  :
+//=============================================================================
 StlAPI_Writer::StlAPI_Writer()
+: myASCIIMode (Standard_True)
 {
-  theStlMesh = new StlMesh_Mesh;
-  theASCIIMode = Standard_True;
-  theDeflection = 0.01;
-  theRelativeMode = Standard_True;
-  theCoefficient = 0.001;
+  //
 }
 
-void StlAPI_Writer::SetDeflection(const Standard_Real aDeflection) 
+//=============================================================================
+//function : Write
+//purpose  :
+//=============================================================================
+Standard_Boolean StlAPI_Writer::Write (const TopoDS_Shape&    theShape,
+                                       const Standard_CString theFileName)
 {
-  theDeflection = aDeflection;
-}
-void StlAPI_Writer::SetCoefficient(const Standard_Real aCoefficient) 
-{
-  theCoefficient = aCoefficient;
-}
+  Standard_Integer aNbNodes = 0;
+  Standard_Integer aNbTriangles = 0;
 
-Standard_Boolean& StlAPI_Writer::RelativeMode() 
-{
-  return theRelativeMode;
-}
+  // calculate total number of the nodes and triangles
+  for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
+  {
+    TopLoc_Location aLoc;
+    Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
+    aNbNodes     += aTriangulation->NbNodes();
+    aNbTriangles += aTriangulation->NbTriangles();
+  }
 
-Standard_Boolean& StlAPI_Writer::ASCIIMode() 
-{
-  return theASCIIMode;
-}
+  // create temporary triangulation
+  Handle(Poly_Triangulation) aMesh = new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
 
-void StlAPI_Writer::Write(const TopoDS_Shape& theShape, const Standard_CString theFileName, const Standard_Boolean theInParallel) 
-{
-  OSD_Path aFile(theFileName);
-  if (theRelativeMode) {
-    Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
-    Bnd_Box Total;
-    BRepBndLib::Add(theShape, Total);
-    Total.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
-    theDeflection = MAX3(aXmax-aXmin , aYmax-aYmin , aZmax-aZmin)*theCoefficient;
-  }
-  StlTransfer::BuildIncrementalMesh(theShape, theDeflection, theInParallel, theStlMesh);
-  // Write the built mesh
-  if (theASCIIMode) {
-    RWStl::WriteAscii(theStlMesh, aFile);
-    }  
-  else {
-    RWStl::WriteBinary(theStlMesh, aFile);
+  // fill temporary triangulation
+  Standard_Integer aNodeOffset = 0;
+  Standard_Integer aTriangleOffet = 0;
+  for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
+  {
+    TopLoc_Location aLoc;
+    Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
+
+    const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
+    const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
+
+    // copy nodes
+    gp_Trsf aTrsf = aLoc.Transformation();
+    for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
+    {
+      gp_Pnt aPnt = aNodes (aNodeIter);
+      aPnt.Transform (aTrsf);
+      aMesh->ChangeNode (aNodeIter + aNodeOffset) = aPnt;
     }
-}
 
+    // copy triangles
+    const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
+    for (Standard_Integer aTriIter = aTriangles.Lower(); aTriIter <= aTriangles.Upper(); ++aTriIter)
+    {
+      Poly_Triangle aTri = aTriangles (aTriIter);
+
+      Standard_Integer anId[3];
+      aTri.Get (anId[0], anId[1], anId[2]);
+      if (anOrientation == TopAbs_REVERSED)
+      {
+        // Swap 1, 2.
+        Standard_Integer aTmpIdx = anId[1];
+        anId[1] = anId[2];
+        anId[2] = aTmpIdx;
+      }
+
+      // Update nodes according to the offset.
+      anId[0] += aNodeOffset;
+      anId[1] += aNodeOffset;
+      anId[2] += aNodeOffset;
+
+      aTri.Set (anId[0], anId[1], anId[2]);
+      aMesh->ChangeTriangle (aTriIter + aTriangleOffet) =  aTri;
+    }
+
+    aNodeOffset += aNodes.Size();
+    aTriangleOffet += aTriangles.Size();
+  }
+
+  OSD_Path aPath (theFileName);
+  return myASCIIMode
+       ? RWStl::WriteAscii  (aMesh, aPath)
+       : RWStl::WriteBinary (aMesh, aPath);
+}