Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 1994-10-13 |
2 | // Created by: Marc LEGAY | |
3 | // Copyright (c) 1994-1999 Matra Datavision | |
973c2be1 | 4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e | 5 | // |
973c2be1 | 6 | // This file is part of Open CASCADE Technology software library. |
b311480e | 7 | // |
d5f74e42 | 8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
12 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 13 | // |
973c2be1 | 14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. | |
7fd59977 | 16 | |
42cf5bc1 | 17 | |
18 | #include <BRepBuilderAPI_CellFilter.hxx> | |
19 | #include <BRepBuilderAPI_VertexInspector.hxx> | |
20 | #include <gp.hxx> | |
21 | #include <gp_Vec.hxx> | |
22 | #include <gp_XYZ.hxx> | |
a47d34ef | 23 | #include <Message.hxx> |
24 | #include <Message_Messenger.hxx> | |
42cf5bc1 | 25 | #include <Message_ProgressIndicator.hxx> |
9c6afe19 | 26 | #include <Message_ProgressSentry.hxx> |
7fd59977 | 27 | #include <OSD.hxx> |
42cf5bc1 | 28 | #include <OSD_File.hxx> |
7fd59977 | 29 | #include <OSD_Host.hxx> |
94708556 | 30 | #include <OSD_OpenFile.hxx> |
42cf5bc1 | 31 | #include <OSD_Path.hxx> |
32 | #include <OSD_Protection.hxx> | |
33 | #include <Precision.hxx> | |
34 | #include <RWStl.hxx> | |
35 | #include <Standard_NoMoreObject.hxx> | |
36 | #include <Standard_TypeMismatch.hxx> | |
37 | #include <StlMesh_Mesh.hxx> | |
38 | #include <StlMesh_MeshExplorer.hxx> | |
39 | #include <TCollection_AsciiString.hxx> | |
7fd59977 | 40 | |
42cf5bc1 | 41 | #include <stdio.h> |
fcc61cc4 | 42 | // A static method adding nodes to a mesh and keeping coincident (sharing) nodes. |
43 | static Standard_Integer AddVertex(Handle(StlMesh_Mesh)& mesh, | |
44 | BRepBuilderAPI_CellFilter& filter, | |
45 | BRepBuilderAPI_VertexInspector& inspector, | |
46 | const gp_XYZ& p) | |
47 | { | |
48 | Standard_Integer index; | |
49 | inspector.SetCurrent(p); | |
50 | gp_XYZ minp = inspector.Shift(p, -Precision::Confusion()); | |
51 | gp_XYZ maxp = inspector.Shift(p, +Precision::Confusion()); | |
52 | filter.Inspect(minp, maxp, inspector); | |
53 | const TColStd_ListOfInteger& indices = inspector.ResInd(); | |
54 | if (indices.IsEmpty() == Standard_False) | |
55 | { | |
56 | index = indices.First(); // it should be only one | |
57 | inspector.ClearResList(); | |
58 | } | |
59 | else | |
60 | { | |
61 | index = mesh->AddVertex(p.X(), p.Y(), p.Z()); | |
62 | filter.Add(index, p); | |
63 | inspector.Add(p); | |
64 | } | |
65 | return index; | |
66 | } | |
67 | ||
7fd59977 | 68 | // constants |
8cb69787 | 69 | static const size_t HEADER_SIZE = 84; |
70 | static const size_t SIZEOF_STL_FACET = 50; | |
8cb69787 | 71 | static const size_t ASCII_LINES_PER_FACET = 7; |
72 | ||
73 | static const int IND_THRESHOLD = 1000; // increment the indicator every 1k triangles | |
7fd59977 | 74 | |
ed482379 | 75 | //======================================================================= |
7fd59977 | 76 | //function : WriteInteger |
77 | //purpose : writing a Little Endian 32 bits integer | |
78 | //======================================================================= | |
79 | ||
80 | inline static void WriteInteger(OSD_File& ofile,const Standard_Integer value) | |
81 | { | |
82 | union { | |
83 | Standard_Integer i;// don't be afraid, this is just an unsigned int | |
84 | char c[4]; | |
85 | } bidargum; | |
86 | ||
87 | bidargum.i = value; | |
88 | ||
89 | Standard_Integer entier; | |
ed482379 | 90 | |
7fd59977 | 91 | entier = bidargum.c[0] & 0xFF; |
92 | entier |= (bidargum.c[1] & 0xFF) << 0x08; | |
93 | entier |= (bidargum.c[2] & 0xFF) << 0x10; | |
94 | entier |= (bidargum.c[3] & 0xFF) << 0x18; | |
95 | ||
96 | ofile.Write((char *)&entier,sizeof(bidargum.c)); | |
97 | } | |
98 | ||
99 | //======================================================================= | |
100 | //function : WriteDouble2Float | |
101 | //purpose : writing a Little Endian 32 bits float | |
102 | //======================================================================= | |
103 | ||
104 | inline static void WriteDouble2Float(OSD_File& ofile,Standard_Real value) | |
105 | { | |
106 | union { | |
107 | Standard_ShortReal f; | |
108 | char c[4]; | |
109 | } bidargum; | |
110 | ||
111 | bidargum.f = (Standard_ShortReal)value; | |
112 | ||
113 | Standard_Integer entier; | |
ed482379 | 114 | |
7fd59977 | 115 | entier = bidargum.c[0] & 0xFF; |
116 | entier |= (bidargum.c[1] & 0xFF) << 0x08; | |
117 | entier |= (bidargum.c[2] & 0xFF) << 0x10; | |
118 | entier |= (bidargum.c[3] & 0xFF) << 0x18; | |
119 | ||
120 | ofile.Write((char *)&entier,sizeof(bidargum.c)); | |
121 | } | |
122 | ||
123 | ||
124 | //======================================================================= | |
125 | //function : readFloat2Double | |
126 | //purpose : reading a Little Endian 32 bits float | |
127 | //======================================================================= | |
128 | ||
129 | inline static Standard_Real ReadFloat2Double(OSD_File &aFile) | |
130 | { | |
131 | union { | |
dde68833 | 132 | uint32_t i; |
133 | float f; | |
7fd59977 | 134 | }bidargum; |
135 | ||
136 | char c[4]; | |
137 | Standard_Address adr; | |
138 | adr = (Standard_Address)c; | |
139 | Standard_Integer lread; | |
140 | aFile.Read(adr,4,lread); | |
141 | bidargum.i = c[0] & 0xFF; | |
142 | bidargum.i |= (c[1] & 0xFF) << 0x08; | |
143 | bidargum.i |= (c[2] & 0xFF) << 0x10; | |
144 | bidargum.i |= (c[3] & 0xFF) << 0x18; | |
145 | ||
146 | return (Standard_Real)(bidargum.f); | |
147 | } | |
148 | ||
149 | ||
150 | ||
151 | //======================================================================= | |
152 | //function : WriteBinary | |
153 | //purpose : write a binary STL file in Little Endian format | |
154 | //======================================================================= | |
155 | ||
9c6afe19 RK |
156 | Standard_Boolean RWStl::WriteBinary (const Handle(StlMesh_Mesh)& theMesh, |
157 | const OSD_Path& thePath, | |
158 | const Handle(Message_ProgressIndicator)& theProgInd) | |
7fd59977 | 159 | { |
9c6afe19 RK |
160 | OSD_File aFile (thePath); |
161 | aFile.Build (OSD_WriteOnly, OSD_Protection()); | |
7fd59977 | 162 | |
163 | Standard_Real x1, y1, z1; | |
164 | Standard_Real x2, y2, z2; | |
165 | Standard_Real x3, y3, z3; | |
ed482379 | 166 | |
9c6afe19 | 167 | // writing 80 bytes of the trash? |
7fd59977 | 168 | char sval[80]; |
9c6afe19 RK |
169 | aFile.Write ((Standard_Address)sval,80); |
170 | WriteInteger (aFile, theMesh->NbTriangles()); | |
171 | ||
7fd59977 | 172 | int dum=0; |
9c6afe19 RK |
173 | StlMesh_MeshExplorer aMexp (theMesh); |
174 | ||
175 | // create progress sentry for domains | |
176 | Standard_Integer aNbDomains = theMesh->NbDomains(); | |
177 | Message_ProgressSentry aDPS (theProgInd, "Mesh domains", 0, aNbDomains, 1); | |
178 | for (Standard_Integer nbd = 1; nbd <= aNbDomains && aDPS.More(); nbd++, aDPS.Next()) | |
179 | { | |
180 | // create progress sentry for triangles in domain | |
181 | Message_ProgressSentry aTPS (theProgInd, "Triangles", 0, | |
182 | theMesh->NbTriangles (nbd), IND_THRESHOLD); | |
183 | Standard_Integer aTriangleInd = 0; | |
184 | for (aMexp.InitTriangle (nbd); aMexp.MoreTriangle(); aMexp.NextTriangle()) | |
185 | { | |
186 | aMexp.TriangleVertices (x1,y1,z1,x2,y2,z2,x3,y3,z3); | |
187 | //pgo aMexp.TriangleOrientation (x,y,z); | |
188 | gp_XYZ Vect12 ((x2-x1), (y2-y1), (z2-z1)); | |
189 | gp_XYZ Vect13 ((x3-x1), (y3-y1), (z3-z1)); | |
190 | gp_XYZ Vnorm = Vect12 ^ Vect13; | |
191 | Standard_Real Vmodul = Vnorm.Modulus (); | |
192 | if (Vmodul > gp::Resolution()) | |
193 | { | |
194 | Vnorm.Divide(Vmodul); | |
195 | } | |
196 | else | |
197 | { | |
198 | // si Vnorm est quasi-nul, on le charge a 0 explicitement | |
199 | Vnorm.SetCoord (0., 0., 0.); | |
200 | } | |
201 | ||
202 | WriteDouble2Float (aFile, Vnorm.X()); | |
203 | WriteDouble2Float (aFile, Vnorm.Y()); | |
204 | WriteDouble2Float (aFile, Vnorm.Z()); | |
205 | ||
206 | WriteDouble2Float (aFile, x1); | |
207 | WriteDouble2Float (aFile, y1); | |
208 | WriteDouble2Float (aFile, z1); | |
209 | ||
210 | WriteDouble2Float (aFile, x2); | |
211 | WriteDouble2Float (aFile, y2); | |
212 | WriteDouble2Float (aFile, z2); | |
213 | ||
214 | WriteDouble2Float (aFile, x3); | |
215 | WriteDouble2Float (aFile, y3); | |
216 | WriteDouble2Float (aFile, z3); | |
ed482379 | 217 | |
9c6afe19 RK |
218 | aFile.Write (&dum, 2); |
219 | ||
220 | // update progress only per 1k triangles | |
221 | if (++aTriangleInd % IND_THRESHOLD == 0) | |
222 | { | |
223 | if (!aTPS.More()) | |
224 | break; | |
225 | aTPS.Next(); | |
7fd59977 | 226 | } |
9c6afe19 | 227 | } |
7fd59977 | 228 | } |
9c6afe19 RK |
229 | aFile.Close(); |
230 | Standard_Boolean isInterrupted = !aDPS.More(); | |
231 | return !isInterrupted; | |
7fd59977 | 232 | } |
233 | //======================================================================= | |
234 | //function : WriteAscii | |
235 | //purpose : write an ASCII STL file | |
236 | //======================================================================= | |
237 | ||
9c6afe19 RK |
238 | Standard_Boolean RWStl::WriteAscii (const Handle(StlMesh_Mesh)& theMesh, |
239 | const OSD_Path& thePath, | |
240 | const Handle(Message_ProgressIndicator)& theProgInd) | |
7fd59977 | 241 | { |
9c6afe19 | 242 | OSD_File theFile (thePath); |
7fd59977 | 243 | theFile.Build(OSD_WriteOnly,OSD_Protection()); |
9c6afe19 | 244 | TCollection_AsciiString buf ("solid\n"); |
7fd59977 | 245 | theFile.Write (buf,buf.Length());buf.Clear(); |
ed482379 | 246 | |
7fd59977 | 247 | Standard_Real x1, y1, z1; |
248 | Standard_Real x2, y2, z2; | |
249 | Standard_Real x3, y3, z3; | |
9c6afe19 RK |
250 | char sval[512]; |
251 | ||
252 | // create progress sentry for domains | |
253 | Standard_Integer aNbDomains = theMesh->NbDomains(); | |
254 | Message_ProgressSentry aDPS (theProgInd, "Mesh domains", 0, aNbDomains, 1); | |
255 | StlMesh_MeshExplorer aMexp (theMesh); | |
256 | for (Standard_Integer nbd = 1; nbd <= aNbDomains && aDPS.More(); nbd++, aDPS.Next()) | |
257 | { | |
258 | // create progress sentry for triangles in domain | |
259 | Message_ProgressSentry aTPS (theProgInd, "Triangles", 0, | |
260 | theMesh->NbTriangles (nbd), IND_THRESHOLD); | |
261 | Standard_Integer aTriangleInd = 0; | |
262 | for (aMexp.InitTriangle (nbd); aMexp.MoreTriangle(); aMexp.NextTriangle()) | |
263 | { | |
7fd59977 | 264 | aMexp.TriangleVertices (x1,y1,z1,x2,y2,z2,x3,y3,z3); |
ed482379 | 265 | |
7fd59977 | 266 | // Standard_Real x, y, z; |
267 | // aMexp.TriangleOrientation (x,y,z); | |
ed482379 | 268 | |
7fd59977 | 269 | gp_XYZ Vect12 ((x2-x1), (y2-y1), (z2-z1)); |
270 | gp_XYZ Vect23 ((x3-x2), (y3-y2), (z3-z2)); | |
9c6afe19 | 271 | gp_XYZ Vnorm = Vect12 ^ Vect23; |
7fd59977 | 272 | Standard_Real Vmodul = Vnorm.Modulus (); |
9c6afe19 RK |
273 | if (Vmodul > gp::Resolution()) |
274 | { | |
275 | Vnorm.Divide (Vmodul); | |
276 | } | |
277 | else | |
278 | { | |
279 | // si Vnorm est quasi-nul, on le charge a 0 explicitement | |
280 | Vnorm.SetCoord (0., 0., 0.); | |
7fd59977 | 281 | } |
91322f44 | 282 | Sprintf (sval, |
9c6afe19 RK |
283 | " facet normal % 12e % 12e % 12e\n" |
284 | " outer loop\n" | |
285 | " vertex % 12e % 12e % 12e\n" | |
286 | " vertex % 12e % 12e % 12e\n" | |
287 | " vertex % 12e % 12e % 12e\n" | |
288 | " endloop\n" | |
289 | " endfacet\n", | |
290 | Vnorm.X(), Vnorm.Y(), Vnorm.Z(), | |
291 | x1, y1, z1, | |
292 | x2, y2, z2, | |
293 | x3, y3, z3); | |
68bc5ed7 | 294 | buf += sval; |
9c6afe19 RK |
295 | theFile.Write (buf, buf.Length()); buf.Clear(); |
296 | ||
297 | // update progress only per 1k triangles | |
298 | if (++aTriangleInd % IND_THRESHOLD == 0) | |
299 | { | |
300 | if (!aTPS.More()) | |
301 | break; | |
302 | aTPS.Next(); | |
7fd59977 | 303 | } |
7fd59977 | 304 | } |
305 | } | |
ed482379 | 306 | |
7fd59977 | 307 | buf += "endsolid\n"; |
9c6afe19 RK |
308 | theFile.Write (buf, buf.Length()); buf.Clear(); |
309 | theFile.Close(); | |
310 | Standard_Boolean isInterrupted = !aDPS.More(); | |
311 | return !isInterrupted; | |
7fd59977 | 312 | } |
313 | //======================================================================= | |
314 | //function : ReadFile | |
ed482379 K |
315 | //Design : |
316 | //Warning : | |
7fd59977 | 317 | //======================================================================= |
318 | ||
857ffd5e | 319 | Handle(StlMesh_Mesh) RWStl::ReadFile (const OSD_Path& thePath, |
9c6afe19 | 320 | const Handle(Message_ProgressIndicator)& theProgInd) |
7fd59977 | 321 | { |
9c6afe19 | 322 | OSD_File file (thePath); |
7fd59977 | 323 | file.Open(OSD_ReadOnly,OSD_Protection(OSD_RWD,OSD_RWD,OSD_RWD,OSD_RWD)); |
324 | Standard_Boolean IsAscii; | |
325 | unsigned char str[128]; | |
326 | Standard_Integer lread,i; | |
327 | Standard_Address ach; | |
328 | ach = (Standard_Address)str; | |
ed482379 | 329 | |
7fd59977 | 330 | // we skip the header which is in Ascii for both modes |
331 | file.Read(ach,HEADER_SIZE,lread); | |
332 | ||
333 | // we read 128 characters to detect if we have a non-ascii char | |
334 | file.Read(ach,sizeof(str),lread); | |
335 | ||
336 | IsAscii = Standard_True; | |
337 | for (i = 0; i< lread && IsAscii; ++i) { | |
338 | if (str[i] > '~') { | |
339 | IsAscii = Standard_False; | |
340 | } | |
341 | } | |
0797d9d3 | 342 | #ifdef OCCT_DEBUG |
ed482379 K |
343 | cout << (IsAscii ? "ascii\n" : "binary\n"); |
344 | #endif | |
7fd59977 | 345 | file.Close(); |
ed482379 | 346 | |
9c6afe19 RK |
347 | return IsAscii ? RWStl::ReadAscii (thePath, theProgInd) |
348 | : RWStl::ReadBinary (thePath, theProgInd); | |
7fd59977 | 349 | } |
350 | ||
351 | //======================================================================= | |
352 | //function : ReadBinary | |
ed482379 K |
353 | //Design : |
354 | //Warning : | |
7fd59977 | 355 | //======================================================================= |
356 | ||
857ffd5e | 357 | Handle(StlMesh_Mesh) RWStl::ReadBinary (const OSD_Path& thePath, |
9c6afe19 | 358 | const Handle(Message_ProgressIndicator)& /*theProgInd*/) |
7fd59977 | 359 | { |
7fd59977 | 360 | Standard_Integer ifacet; |
361 | Standard_Real fx,fy,fz,fx1,fy1,fz1,fx2,fy2,fz2,fx3,fy3,fz3; | |
362 | Standard_Integer i1,i2,i3,lread; | |
363 | char buftest[5]; | |
364 | Standard_Address adr; | |
365 | adr = (Standard_Address)buftest; | |
366 | ||
ed482379 | 367 | // Open the file |
9c6afe19 | 368 | OSD_File theFile (thePath); |
7fd59977 | 369 | theFile.Open(OSD_ReadOnly,OSD_Protection(OSD_RWD,OSD_RWD,OSD_RWD,OSD_RWD)); |
370 | ||
371 | // the size of the file (minus the header size) | |
372 | // must be a multiple of SIZEOF_STL_FACET | |
373 | ||
374 | // compute file size | |
6ff736d8 | 375 | Standard_Size filesize = theFile.Size(); |
7fd59977 | 376 | |
a47d34ef | 377 | // don't trust the number of triangles which is coded in the file sometimes it is wrong |
378 | Standard_Integer NBFACET = (Standard_Integer)((filesize - HEADER_SIZE) / SIZEOF_STL_FACET); | |
379 | if (NBFACET < 1) | |
380 | { | |
9775fa61 | 381 | throw Standard_NoMoreObject("RWStl::ReadBinary (wrong file size)"); |
7fd59977 | 382 | } |
383 | ||
a47d34ef | 384 | theFile.Seek (80, OSD_FromBeginning); |
385 | theFile.Read (adr, 4, lread); | |
386 | Standard_Integer aNbTrisInHeader = (((char* )buftest)[3] << 24) | (((Standard_Byte* )buftest)[2] << 16) | |
387 | | (((Standard_Byte* )buftest)[1] << 8 ) | (((Standard_Byte* )buftest)[0] << 0 ); | |
388 | if (NBFACET < aNbTrisInHeader) | |
389 | { | |
390 | Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file defines more triangles (") + aNbTrisInHeader | |
391 | + ") that can be read (" + NBFACET + ") - probably corrupted file", | |
392 | Message_Warning); | |
393 | } | |
394 | else if (NBFACET > aNbTrisInHeader) | |
395 | { | |
396 | Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file defines less triangles (") + aNbTrisInHeader | |
397 | + ") that can be read (" + NBFACET + ") - probably corrupted file", | |
398 | Message_Warning); | |
399 | } | |
400 | else if ((filesize - HEADER_SIZE) % SIZEOF_STL_FACET != 0) | |
401 | { | |
402 | Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file has unidentified tail"), | |
403 | Message_Warning); | |
404 | } | |
7fd59977 | 405 | |
406 | // skip the header | |
407 | theFile.Seek(HEADER_SIZE,OSD_FromBeginning); | |
408 | ||
409 | // create the StlMesh_Mesh object | |
410 | Handle(StlMesh_Mesh) ReadMesh = new StlMesh_Mesh (); | |
411 | ReadMesh->AddDomain (); | |
412 | ||
fcc61cc4 | 413 | // Filter unique vertices to share the nodes of the mesh. |
a7653f4f | 414 | BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion()); |
fcc61cc4 | 415 | BRepBuilderAPI_VertexInspector inspector(Precision::Confusion()); |
416 | ||
7fd59977 | 417 | for (ifacet=1; ifacet<=NBFACET; ++ifacet) { |
418 | // read normal coordinates | |
419 | fx = ReadFloat2Double(theFile); | |
420 | fy = ReadFloat2Double(theFile); | |
421 | fz = ReadFloat2Double(theFile); | |
422 | ||
423 | // read vertex 1 | |
424 | fx1 = ReadFloat2Double(theFile); | |
425 | fy1 = ReadFloat2Double(theFile); | |
426 | fz1 = ReadFloat2Double(theFile); | |
427 | ||
428 | // read vertex 2 | |
429 | fx2 = ReadFloat2Double(theFile); | |
430 | fy2 = ReadFloat2Double(theFile); | |
431 | fz2 = ReadFloat2Double(theFile); | |
432 | ||
433 | // read vertex 3 | |
434 | fx3 = ReadFloat2Double(theFile); | |
435 | fy3 = ReadFloat2Double(theFile); | |
436 | fz3 = ReadFloat2Double(theFile); | |
437 | ||
fcc61cc4 | 438 | // Add vertices. |
439 | i1 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx1, fy1, fz1)); | |
440 | i2 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx2, fy2, fz2)); | |
441 | i3 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx3, fy3, fz3)); | |
442 | ||
443 | // Add triangle. | |
7fd59977 | 444 | ReadMesh->AddTriangle (i1,i2,i3,fx,fy,fz); |
445 | ||
446 | // skip extra bytes | |
447 | theFile.Read(adr,2,lread); | |
448 | } | |
449 | ||
450 | theFile.Close (); | |
451 | return ReadMesh; | |
7fd59977 | 452 | } |
fcc61cc4 | 453 | |
7fd59977 | 454 | //======================================================================= |
455 | //function : ReadAscii | |
ed482379 K |
456 | //Design : |
457 | //Warning : | |
7fd59977 | 458 | //======================================================================= |
459 | ||
857ffd5e | 460 | Handle(StlMesh_Mesh) RWStl::ReadAscii (const OSD_Path& thePath, |
9c6afe19 | 461 | const Handle(Message_ProgressIndicator)& theProgInd) |
7fd59977 | 462 | { |
463 | TCollection_AsciiString filename; | |
464 | long ipos; | |
465 | Standard_Integer nbLines = 0; | |
466 | Standard_Integer nbTris = 0; | |
467 | Standard_Integer iTri; | |
7fd59977 | 468 | Standard_Integer i1,i2,i3; |
469 | Handle(StlMesh_Mesh) ReadMesh; | |
470 | ||
9c6afe19 | 471 | thePath.SystemName (filename); |
7fd59977 | 472 | |
ed482379 | 473 | // Open the file |
94708556 | 474 | FILE* file = OSD_OpenFile(filename.ToCString(),"r"); |
7fd59977 | 475 | |
476 | fseek(file,0L,SEEK_END); | |
477 | ||
478 | long filesize = ftell(file); | |
479 | ||
94708556 | 480 | rewind(file); |
7fd59977 | 481 | |
7fd59977 | 482 | // count the number of lines |
483 | for (ipos = 0; ipos < filesize; ++ipos) { | |
484 | if (getc(file) == '\n') | |
485 | nbLines++; | |
486 | } | |
487 | ||
488 | // compute number of triangles | |
489 | nbTris = (nbLines / ASCII_LINES_PER_FACET); | |
490 | ||
491 | // go back to the beginning of the file | |
7fd59977 | 492 | rewind(file); |
493 | ||
494 | // skip header | |
495 | while (getc(file) != '\n'); | |
0797d9d3 | 496 | #ifdef OCCT_DEBUG |
ed482379 K |
497 | cout << "start mesh\n"; |
498 | #endif | |
499 | ReadMesh = new StlMesh_Mesh(); | |
7fd59977 | 500 | ReadMesh->AddDomain(); |
501 | ||
fcc61cc4 | 502 | // Filter unique vertices to share the nodes of the mesh. |
a7653f4f | 503 | BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion()); |
fcc61cc4 | 504 | BRepBuilderAPI_VertexInspector inspector(Precision::Confusion()); |
505 | ||
7fd59977 | 506 | // main reading |
9c6afe19 RK |
507 | Message_ProgressSentry aPS (theProgInd, "Triangles", 0, (nbTris - 1) * 1.0 / IND_THRESHOLD, 1); |
508 | for (iTri = 0; iTri < nbTris && aPS.More();) | |
509 | { | |
91322f44 | 510 | char x[256]="", y[256]="", z[256]=""; |
511 | ||
7fd59977 | 512 | // reading the facet normal |
91322f44 | 513 | if (3 != fscanf(file,"%*s %*s %80s %80s %80s\n", x, y, z)) |
514 | break; // error should be properly reported | |
515 | gp_XYZ aN (Atof(x), Atof(y), Atof(z)); | |
7fd59977 | 516 | |
517 | // skip the keywords "outer loop" | |
98160038 | 518 | if (fscanf(file,"%*s %*s") < 0) |
519 | break; | |
7fd59977 | 520 | |
521 | // reading vertex | |
91322f44 | 522 | if (3 != fscanf(file,"%*s %80s %80s %80s\n", x, y, z)) |
523 | break; // error should be properly reported | |
524 | gp_XYZ aV1 (Atof(x), Atof(y), Atof(z)); | |
525 | if (3 != fscanf(file,"%*s %80s %80s %80s\n", x, y, z)) | |
526 | break; // error should be properly reported | |
527 | gp_XYZ aV2 (Atof(x), Atof(y), Atof(z)); | |
528 | if (3 != fscanf(file,"%*s %80s %80s %80s\n", x, y, z)) | |
529 | break; // error should be properly reported | |
530 | gp_XYZ aV3 (Atof(x), Atof(y), Atof(z)); | |
7fd59977 | 531 | |
ed482379 | 532 | // here the facet must be built and put in the mesh datastructure |
7fd59977 | 533 | |
fcc61cc4 | 534 | i1 = AddVertex(ReadMesh, uniqueVertices, inspector, aV1); |
535 | i2 = AddVertex(ReadMesh, uniqueVertices, inspector, aV2); | |
536 | i3 = AddVertex(ReadMesh, uniqueVertices, inspector, aV3); | |
91322f44 | 537 | ReadMesh->AddTriangle (i1, i2, i3, aN.X(), aN.Y(), aN.Z()); |
7fd59977 | 538 | |
539 | // skip the keywords "endloop" | |
98160038 | 540 | if (fscanf(file,"%*s") < 0) |
541 | break; | |
7fd59977 | 542 | |
543 | // skip the keywords "endfacet" | |
98160038 | 544 | if (fscanf(file,"%*s") < 0) |
545 | break; | |
7fd59977 | 546 | |
9c6afe19 RK |
547 | // update progress only per 1k triangles |
548 | if (++iTri % IND_THRESHOLD == 0) | |
549 | aPS.Next(); | |
7fd59977 | 550 | } |
0797d9d3 | 551 | #ifdef OCCT_DEBUG |
ed482379 K |
552 | cout << "end mesh\n"; |
553 | #endif | |
7fd59977 | 554 | fclose(file); |
555 | return ReadMesh; | |
7fd59977 | 556 | } |