OSDN Git Service

stlmesh asciiモードの出力を追加
[qtgeoviewer/QtGeoViewer.git] / Lib / LibGeo / Mesh / STL / STLMesh.cpp
1 #include "stdafx.h"
2 #include "StlMesh.h"
3
4 #include "../BaseMesh.h"
5
6 #include <C2/util/stream_util.h>
7
8 #include <set>
9 #include <fstream>
10
11
12 namespace lib_geo
13 {
14
15
16 StlMesh::StlMesh(void)
17 {
18         ClearMessage();
19 }
20
21 void StlMesh::Clear(void)
22 {
23         ClearMessage();
24         m_Faces.clear();
25 }
26
27 void StlMesh::ClearMessage(void)
28 {
29         for (int i = 0; i < MSG_LENGTH; ++i)
30         {
31                 m_Message[i] = 0;
32         }
33 }
34
35 bool StlMesh::LoadBinary(std::istream& in)
36 {
37         Clear();
38
39         size_t fileSize = util::GetStreamSize(in);
40
41         in.read(m_Message, MSG_LENGTH);
42
43         unsigned int NumFaces;
44         in.read((char*)&NumFaces, sizeof(unsigned int));
45
46         const size_t expectedBinaryFileSize = NumFaces * 50 + 84;
47
48         if (expectedBinaryFileSize != fileSize)
49                 return false;
50
51         m_Faces.resize(NumFaces);
52         for (size_t i = 0; i < NumFaces; ++i)
53         {
54                 char padding[2] = {0, 0};
55
56                 StlFace& f = m_Faces[i];
57                 in.read((char*)f.m_Normal.v(), sizeof(float) * 3);
58                 in.read((char*)f.m_Verts[0].v(), sizeof(float) * 3);
59                 in.read((char*)f.m_Verts[1].v(), sizeof(float) * 3);
60                 in.read((char*)f.m_Verts[2].v(), sizeof(float) * 3);
61                 in.read(padding, 2);
62         }
63
64         return true;
65 }
66
67 bool StlMesh::LoadAscii(std::istream& in)
68 {
69         if (!IsExistValidAsciiHeader(in))
70                 return false;
71
72         Clear();
73
74         in.seekg(0, std::ios::beg);
75
76         StlFace f;
77         int vcount = 0;
78
79         std::string ws;
80         std::getline(in, ws);
81         while (!in.eof())
82         {
83                 std::getline(in, ws);
84                 if (ws.empty())
85                         break;
86
87                 std::istringstream is(ws);
88                 std::string s;
89                 is >> s;
90
91                 if (s == "facet")
92                 {
93                         lm::vec3f o(0.0f, 0.0f, 0.0f);
94                         f.m_Normal = o;
95                         f.m_Verts[0] = o;
96                         f.m_Verts[1] = o;
97                         f.m_Verts[2] = o;
98                         vcount = 0;
99
100                         lm::vec3f& n = f.m_Normal;
101                         is >> n.x >> n.y >> n.z;
102                 }
103                 else if (s == "endloop")
104                 {
105                         m_Faces.push_back(f);
106                 }
107                 else if (s == "vertex")
108                 {
109                         lm::vec3f& v = f.m_Verts[vcount++];
110                         is >> v.x >> v.y >> v.z;
111                 }
112                 else if (s == "endfacet")
113                 {
114                 }
115                 else if (s == "outer")
116                 {
117                 }
118                 else if (s == "endsolid")
119                 {
120                 }
121                 else
122                 {
123                         return false;
124                 }
125         }
126
127         return true;
128 }
129
130 bool StlMesh::IsExistValidAsciiHeader(std::istream& in)
131 {
132         in.read(m_Message, MSG_LENGTH);
133
134         m_Message[5] = '\0';
135         std::string top = m_Message;
136         ClearMessage();
137
138         return top == "solid";
139 }
140
141 bool StlMesh::Load(std::istream& ist)
142 {
143         if (LoadBinary(ist))
144                 return true;
145
146         ist.seekg(0, std::ios::beg);
147
148         if (LoadAscii(ist))
149                 return true;
150
151         return false;
152 }
153
154 bool StlMesh::Load(const std::string& filename)
155 {
156         std::ifstream ifs(filename.c_str(), std::ios::binary);
157         if (!ifs.is_open())
158                 return false;
159
160         return Load(ifs);
161 }
162
163 bool StlMesh::SaveBinary(std::ostream& ost) const
164 {
165         unsigned int NumFaces = (unsigned int)m_Faces.size();
166         ost.write(m_Message, MSG_LENGTH);
167         ost.write((char*)&NumFaces, sizeof(unsigned int));
168
169         char padding[2] = {0, 0};
170
171         for (const StlFace& f : m_Faces)
172         {
173                 ost.write((char*)f.m_Normal.v(), sizeof(float) * 3);
174                 ost.write((char*)f.m_Verts[0].v(), sizeof(float) * 3);
175                 ost.write((char*)f.m_Verts[1].v(), sizeof(float) * 3);
176                 ost.write((char*)f.m_Verts[2].v(), sizeof(float) * 3);
177                 ost.write(padding, 2);
178         }
179
180         return true;
181 }
182
183 bool StlMesh::SaveBinary(const std::string& filename) const
184 {
185         std::ofstream ofs(filename.c_str(), std::ios::binary);
186         if (!ofs.is_open())
187                 return false;
188
189         return SaveBinary(ofs);
190 }
191
192 bool StlMesh::SaveAscii(std::ostream& ost) const
193 {
194         ost << "solid " << m_Message << std::endl;
195
196         for (const StlFace& f : m_Faces)
197         {
198                 WriteAscciiVert(ost, "facet normal", f.m_Normal);
199                 ost << "outer loop" << std::endl;
200                 WriteAscciiVert(ost, "vertex", f.m_Verts[0]);
201                 WriteAscciiVert(ost, "vertex", f.m_Verts[1]);
202                 WriteAscciiVert(ost, "vertex", f.m_Verts[2]);
203                 ost << "endloop" << std::endl;
204                 ost << "endfacet" << std::endl;
205         }
206
207         ost << "endsolid" << std::endl;
208
209         return true;
210 }
211
212 bool StlMesh::SaveAscii(const std::string& filename) const
213 {
214         std::ofstream ofs(filename.c_str());
215         if (!ofs.is_open())
216                 return false;
217
218         return SaveAscii(ofs);
219 }
220
221 void StlMesh::WriteAscciiVert(std::ostream& out, const char* head, const lm::vec3f& v) const
222 {
223         out << head
224                 << " " << v.x
225                 << " " << v.y
226                 << " " << v.z
227                 << std::endl;
228 }
229
230 bool StlMesh::ConvertToBaseMesh(BaseMesh& bm) const
231 {
232         bm.Clear();
233
234         bm.m_Verts.resize(m_Faces.size() * 3);
235         bm.m_Normals.resize(m_Faces.size());
236         bm.m_Faces.resize(m_Faces.size());
237
238         for (size_t i = 0; i < m_Faces.size(); ++i)
239         {
240                 const StlFace& f = m_Faces[i];
241
242                 bm.m_Verts[i * 3 + 0] = f.m_Verts[0];
243                 bm.m_Verts[i * 3 + 1] = f.m_Verts[1];
244                 bm.m_Verts[i * 3 + 2] = f.m_Verts[2];
245
246                 bm.m_Normals[i] = f.m_Normal;
247
248                 BaseFace& bf = bm.m_Faces[i];
249                 bf.m_VertIds.resize(3);
250                 bf.m_NormIds.resize(3);
251
252                 bf.m_VertIds[0] = (int)(i * 3 + 0);
253                 bf.m_VertIds[1] = (int)(i * 3 + 1);
254                 bf.m_VertIds[2] = (int)(i * 3 + 2);
255
256                 bf.m_NormIds[0] = (int)i;
257                 bf.m_NormIds[1] = (int)i;
258                 bf.m_NormIds[2] = (int)i;
259         }
260
261         return true;
262 }
263
264 //! \83T\83C\83Y0\82Ì\96@\90ü\82ð\8aÜ\82Þ\8fê\8d\87\82Étrue\82ð\95Ô\82·
265 bool StlMesh::ExistZeroLengthNormal(void) const
266 {
267         for (const StlFace& f : m_Faces)
268         {
269                 if (f.m_Normal.is_zero())
270                         return true;
271         }
272
273         return false;
274 }
275
276
277 }