0028962: Configuration, genproj.bat - add /LARGEADDRESSAWARE option to 32-bit target...
[occt.git] / src / StlAPI / StlAPI_Writer.cxx
CommitLineData
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
42cf5bc1 14
7fd59977 15#include <Bnd_Box.hxx>
7fd59977 16#include <BRepBndLib.hxx>
17#include <OSD_Path.hxx>
b508cbc5 18#include <OSD_OpenFile.hxx>
42cf5bc1 19#include <RWStl.hxx>
20#include <StlAPI_Writer.hxx>
21#include <StlMesh_Mesh.hxx>
22#include <StlTransfer.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
7fd59977 29StlAPI_Writer::StlAPI_Writer()
30{
31 theStlMesh = new StlMesh_Mesh;
32 theASCIIMode = Standard_True;
7fd59977 33}
34
35Standard_Boolean& StlAPI_Writer::ASCIIMode()
36{
37 return theASCIIMode;
38}
39
b508cbc5 40// Auxiliary tools
41namespace
7fd59977 42{
b508cbc5 43 // Tool to get triangles from triangulation taking into account face
44 // orientation and location
45 class TriangleAccessor
46 {
47 public:
48 TriangleAccessor (const TopoDS_Face& aFace)
49 {
50 TopLoc_Location aLoc;
51 myPoly = BRep_Tool::Triangulation (aFace, aLoc);
52 myTrsf = aLoc.Transformation();
53 myNbTriangles = (myPoly.IsNull() ? 0 : myPoly->Triangles().Length());
54 myInvert = (aFace.Orientation() == TopAbs_REVERSED);
55 if (myTrsf.IsNegative())
56 myInvert = ! myInvert;
7fd59977 57 }
b9c1e440 58
b508cbc5 59 int NbTriangles () const { return myNbTriangles; }
60
61 // get i-th triangle and outward normal
62 void GetTriangle (int iTri, gp_Vec &theNormal, gp_Pnt &thePnt1, gp_Pnt &thePnt2, gp_Pnt &thePnt3)
63 {
64 // get positions of nodes
65 int iNode1, iNode2, iNode3;
66 myPoly->Triangles()(iTri).Get (iNode1, iNode2, iNode3);
67 thePnt1 = myPoly->Nodes()(iNode1);
68 thePnt2 = myPoly->Nodes()(myInvert ? iNode3 : iNode2);
69 thePnt3 = myPoly->Nodes()(myInvert ? iNode2 : iNode3);
70
71 // apply transormation if not identity
72 if (myTrsf.Form() != gp_Identity)
73 {
74 thePnt1.Transform (myTrsf);
75 thePnt2.Transform (myTrsf);
76 thePnt3.Transform (myTrsf);
77 }
78
79 // calculate normal
80 theNormal = (thePnt2.XYZ() - thePnt1.XYZ()) ^ (thePnt3.XYZ() - thePnt1.XYZ());
81 Standard_Real aNorm = theNormal.Magnitude();
82 if (aNorm > gp::Resolution())
83 theNormal /= aNorm;
84 }
85
86 private:
87 Handle(Poly_Triangulation) myPoly;
88 gp_Trsf myTrsf;
89 int myNbTriangles;
90 bool myInvert;
91 };
92
93 // convert to float and, on big-endian platform, to little-endian representation
94 inline float convertFloat (Standard_Real aValue)
95 {
96#ifdef OCCT_BINARY_FILE_DO_INVERSE
97 return OSD_BinaryFile::InverseShortReal ((float)aValue);
98#else
99 return (float)aValue;
100#endif
101 }
102}
103
104StlAPI_ErrorStatus StlAPI_Writer::Write(const TopoDS_Shape& theShape, const Standard_CString theFileName)
105{
106 // open file
107 FILE* aFile = OSD_OpenFile (theFileName, "wb");
108 if (!aFile)
b9c1e440 109 return StlAPI_CannotOpenFile;
110
b508cbc5 111 // write
112 if (theASCIIMode)
113 {
114 // header
115 Fprintf (aFile, "solid shape, STL ascii file, created with Open CASCADE Technology\n");
116
117 // facets
118 for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
119 {
120 TriangleAccessor aTool (TopoDS::Face (exp.Current()));
121 for (int iTri = 1; iTri <= aTool.NbTriangles(); iTri++)
122 {
123 gp_Vec aNorm;
124 gp_Pnt aPnt1, aPnt2, aPnt3;
125 aTool.GetTriangle (iTri, aNorm, aPnt1, aPnt2, aPnt3);
126
127 Fprintf (aFile,
128 " facet normal %12e %12e %12e\n"
129 " outer loop\n"
130 " vertex %12e %12e %12e\n"
131 " vertex %12e %12e %12e\n"
132 " vertex %12e %12e %12e\n"
133 " endloop\n"
134 " endfacet\n",
135 aNorm.X(), aNorm.Y(), aNorm.Z(),
136 aPnt1.X(), aPnt1.Y(), aPnt1.Z(),
137 aPnt2.X(), aPnt2.Y(), aPnt2.Z(),
138 aPnt3.X(), aPnt3.Y(), aPnt3.Z());
139 }
140 }
141
142 // footer
143 Fprintf (aFile, "endsolid shape\n");
144 }
145 else
146 {
147 // header block (meaningless 80 bytes)
148 Fprintf (aFile, "%-80.80s", "STL binary file, created with Open CASCADE Technology");
149
150 // number of facets
151 int32_t aNbTri = 0;
152 for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
153 {
154 TopLoc_Location aLoc;
155 Handle(Poly_Triangulation) aPoly =
156 BRep_Tool::Triangulation (TopoDS::Face (exp.Current()), aLoc);
157 if (! aPoly.IsNull())
158 aNbTri += aPoly->NbTriangles();
159 }
160 // suppose that number of triangles must be little endian...
161#ifdef OCCT_BINARY_FILE_DO_INVERSE
162 aNbTri = OSD_BinaryFile::InverseInteger (aNbTri);
163#endif
164 fwrite (&aNbTri, sizeof(int32_t), 1, aFile);
165
166 // facets
167 struct Facet {
168 float nx, ny, nz;
169 float x1, y1, z1;
170 float x2, y2, z2;
171 float x3, y3, z3;
172 uint16_t dummy;
173 } f;
174 f.dummy = 0;
175 for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
176 {
177 TriangleAccessor aTool (TopoDS::Face (exp.Current()));
178 for (int iTri = 1; iTri <= aTool.NbTriangles(); iTri++)
179 {
180 gp_Vec aNorm;
181 gp_Pnt aPnt1, aPnt2, aPnt3;
182 aTool.GetTriangle (iTri, aNorm, aPnt1, aPnt2, aPnt3);
183
184 f.nx = convertFloat (aNorm.X());
185 f.ny = convertFloat (aNorm.Y());
186 f.nz = convertFloat (aNorm.Z());
187
188 f.x1 = convertFloat (aPnt1.X());
189 f.y1 = convertFloat (aPnt1.Y());
190 f.z1 = convertFloat (aPnt1.Z());
191
192 f.x2 = convertFloat (aPnt2.X());
193 f.y2 = convertFloat (aPnt2.Y());
194 f.z2 = convertFloat (aPnt2.Z());
195
196 f.x3 = convertFloat (aPnt3.X());
197 f.y3 = convertFloat (aPnt3.Y());
198 f.z3 = convertFloat (aPnt3.Z());
199
200 fwrite (&f, 50 /* 50 bytes per facet */, 1, aFile);
201 }
202 }
203 }
204
205 fclose (aFile);
206 return ferror(aFile) ? StlAPI_WriteError : StlAPI_StatusOK;
7fd59977 207}
208