1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <StlAPI_Writer.hxx>
16 #include <Bnd_Box.hxx>
17 #include <BRepBndLib.hxx>
18 #include <Message.hxx>
19 #include <Message_Messenger.hxx>
20 #include <OSD_Path.hxx>
21 #include <OSD_OpenFile.hxx>
23 #include <BRep_Tool.hxx>
25 #include <TopoDS_Face.hxx>
26 #include <TopExp_Explorer.hxx>
27 #include <Poly_Triangulation.hxx>
29 //=============================================================================
30 //function : StlAPI_Writer
32 //=============================================================================
33 StlAPI_Writer::StlAPI_Writer()
34 : myASCIIMode (Standard_True)
39 //=============================================================================
42 //=============================================================================
43 Standard_Boolean StlAPI_Writer::Write (const TopoDS_Shape& theShape,
44 const Standard_CString theFileName,
45 const Message_ProgressRange& theProgress)
47 Standard_Integer aNbNodes = 0;
48 Standard_Integer aNbTriangles = 0;
50 // calculate total number of the nodes and triangles
51 for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
54 Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
55 if (! aTriangulation.IsNull())
57 aNbNodes += aTriangulation->NbNodes ();
58 aNbTriangles += aTriangulation->NbTriangles ();
62 if (aNbTriangles == 0)
64 // No triangulation on the shape
65 return Standard_False;
68 // create temporary triangulation
69 Handle(Poly_Triangulation) aMesh = new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
70 // count faces missing triangulation
71 Standard_Integer aNbFacesNoTri = 0;
72 // fill temporary triangulation
73 Standard_Integer aNodeOffset = 0;
74 Standard_Integer aTriangleOffet = 0;
75 for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
77 const TopoDS_Shape& aFace = anExpSF.Current();
79 Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (aFace), aLoc);
80 if (aTriangulation.IsNull())
87 gp_Trsf aTrsf = aLoc.Transformation();
88 for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter)
90 gp_Pnt aPnt = aTriangulation->Node (aNodeIter);
91 aPnt.Transform (aTrsf);
92 aMesh->SetNode (aNodeIter + aNodeOffset, aPnt);
96 const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
97 for (Standard_Integer aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter)
99 Poly_Triangle aTri = aTriangulation->Triangle (aTriIter);
101 Standard_Integer anId[3];
102 aTri.Get (anId[0], anId[1], anId[2]);
103 if (anOrientation == TopAbs_REVERSED)
106 Standard_Integer aTmpIdx = anId[1];
111 // Update nodes according to the offset.
112 anId[0] += aNodeOffset;
113 anId[1] += aNodeOffset;
114 anId[2] += aNodeOffset;
116 aTri.Set (anId[0], anId[1], anId[2]);
117 aMesh->SetTriangle (aTriIter + aTriangleOffet, aTri);
120 aNodeOffset += aTriangulation->NbNodes();
121 aTriangleOffet += aTriangulation->NbTriangles();
124 OSD_Path aPath (theFileName);
125 Standard_Boolean isDone = (myASCIIMode
126 ? RWStl::WriteAscii(aMesh, aPath, theProgress)
127 : RWStl::WriteBinary(aMesh, aPath, theProgress));
129 if (isDone && (aNbFacesNoTri > 0))
131 // Print warning with number of faces missing triangulation
132 TCollection_AsciiString aWarningMsg =
133 TCollection_AsciiString ("Warning: ") +
134 TCollection_AsciiString (aNbFacesNoTri) +
135 TCollection_AsciiString ((aNbFacesNoTri == 1) ? " face has" : " faces have") +
136 TCollection_AsciiString (" been skipped due to null triangulation");
137 Message::SendWarning (aWarningMsg);