973c2be1 |
1 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
2 | // |
973c2be1 |
3 | // This file is part of Open CASCADE Technology software library. |
b311480e |
4 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
10 | // |
973c2be1 |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
b311480e |
13 | |
4178b353 |
14 | #include <StlAPI_Writer.hxx> |
42cf5bc1 |
15 | |
7fd59977 |
16 | #include <Bnd_Box.hxx> |
7fd59977 |
17 | #include <BRepBndLib.hxx> |
44d5a096 |
18 | #include <Message.hxx> |
19 | #include <Message_Messenger.hxx> |
7fd59977 |
20 | #include <OSD_Path.hxx> |
b508cbc5 |
21 | #include <OSD_OpenFile.hxx> |
42cf5bc1 |
22 | #include <RWStl.hxx> |
b508cbc5 |
23 | #include <BRep_Tool.hxx> |
24 | #include <TopoDS.hxx> |
25 | #include <TopoDS_Face.hxx> |
26 | #include <TopExp_Explorer.hxx> |
27 | #include <Poly_Triangulation.hxx> |
7fd59977 |
28 | |
4178b353 |
29 | //============================================================================= |
30 | //function : StlAPI_Writer |
31 | //purpose : |
32 | //============================================================================= |
7fd59977 |
33 | StlAPI_Writer::StlAPI_Writer() |
4178b353 |
34 | : myASCIIMode (Standard_True) |
7fd59977 |
35 | { |
4178b353 |
36 | // |
7fd59977 |
37 | } |
38 | |
4178b353 |
39 | //============================================================================= |
40 | //function : Write |
41 | //purpose : |
42 | //============================================================================= |
43 | Standard_Boolean StlAPI_Writer::Write (const TopoDS_Shape& theShape, |
1fc1a207 |
44 | const Standard_CString theFileName, |
45 | const Handle(Message_ProgressIndicator)& theProgress) |
7fd59977 |
46 | { |
4178b353 |
47 | Standard_Integer aNbNodes = 0; |
48 | Standard_Integer aNbTriangles = 0; |
b508cbc5 |
49 | |
4178b353 |
50 | // calculate total number of the nodes and triangles |
51 | for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) |
b508cbc5 |
52 | { |
4178b353 |
53 | TopLoc_Location aLoc; |
54 | Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc); |
22e70738 |
55 | if (! aTriangulation.IsNull()) |
56 | { |
57 | aNbNodes += aTriangulation->NbNodes (); |
58 | aNbTriangles += aTriangulation->NbTriangles (); |
59 | } |
b508cbc5 |
60 | } |
b508cbc5 |
61 | |
44d5a096 |
62 | if (aNbTriangles == 0) |
63 | { |
64 | // No triangulation on the shape |
65 | return Standard_False; |
66 | } |
67 | |
4178b353 |
68 | // create temporary triangulation |
69 | Handle(Poly_Triangulation) aMesh = new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False); |
44d5a096 |
70 | // count faces missing triangulation |
71 | Standard_Integer aNbFacesNoTri = 0; |
4178b353 |
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()) |
b508cbc5 |
76 | { |
44d5a096 |
77 | const TopoDS_Shape& aFace = anExpSF.Current(); |
4178b353 |
78 | TopLoc_Location aLoc; |
44d5a096 |
79 | Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (aFace), aLoc); |
80 | if (aTriangulation.IsNull()) |
81 | { |
82 | ++aNbFacesNoTri; |
83 | continue; |
84 | } |
b508cbc5 |
85 | |
4178b353 |
86 | const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes(); |
87 | const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles(); |
b508cbc5 |
88 | |
4178b353 |
89 | // copy nodes |
90 | gp_Trsf aTrsf = aLoc.Transformation(); |
91 | for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) |
b508cbc5 |
92 | { |
4178b353 |
93 | gp_Pnt aPnt = aNodes (aNodeIter); |
94 | aPnt.Transform (aTrsf); |
95 | aMesh->ChangeNode (aNodeIter + aNodeOffset) = aPnt; |
b508cbc5 |
96 | } |
b508cbc5 |
97 | |
4178b353 |
98 | // copy triangles |
99 | const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation(); |
100 | for (Standard_Integer aTriIter = aTriangles.Lower(); aTriIter <= aTriangles.Upper(); ++aTriIter) |
b508cbc5 |
101 | { |
4178b353 |
102 | Poly_Triangle aTri = aTriangles (aTriIter); |
b508cbc5 |
103 | |
4178b353 |
104 | Standard_Integer anId[3]; |
105 | aTri.Get (anId[0], anId[1], anId[2]); |
106 | if (anOrientation == TopAbs_REVERSED) |
107 | { |
108 | // Swap 1, 2. |
109 | Standard_Integer aTmpIdx = anId[1]; |
110 | anId[1] = anId[2]; |
111 | anId[2] = aTmpIdx; |
112 | } |
b508cbc5 |
113 | |
4178b353 |
114 | // Update nodes according to the offset. |
115 | anId[0] += aNodeOffset; |
116 | anId[1] += aNodeOffset; |
117 | anId[2] += aNodeOffset; |
b508cbc5 |
118 | |
4178b353 |
119 | aTri.Set (anId[0], anId[1], anId[2]); |
120 | aMesh->ChangeTriangle (aTriIter + aTriangleOffet) = aTri; |
b508cbc5 |
121 | } |
4178b353 |
122 | |
123 | aNodeOffset += aNodes.Size(); |
124 | aTriangleOffet += aTriangles.Size(); |
b508cbc5 |
125 | } |
126 | |
4178b353 |
127 | OSD_Path aPath (theFileName); |
44d5a096 |
128 | Standard_Boolean isDone = (myASCIIMode |
1fc1a207 |
129 | ? RWStl::WriteAscii(aMesh, aPath, theProgress) |
130 | : RWStl::WriteBinary(aMesh, aPath, theProgress)); |
44d5a096 |
131 | |
132 | if (isDone && (aNbFacesNoTri > 0)) |
133 | { |
134 | // Print warning with number of faces missing triangulation |
135 | TCollection_AsciiString aWarningMsg = |
136 | TCollection_AsciiString ("Warning: ") + |
137 | TCollection_AsciiString (aNbFacesNoTri) + |
138 | TCollection_AsciiString ((aNbFacesNoTri == 1) ? " face has" : " faces have") + |
139 | TCollection_AsciiString (" been skipped due to null triangulation"); |
a87b1b37 |
140 | Message::SendWarning (aWarningMsg); |
44d5a096 |
141 | } |
142 | |
143 | return isDone; |
7fd59977 |
144 | } |