Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / src / surfMesh / surfaceFormats / stl / STLsurfaceFormat.C
blob881d44b057dc783db3a56e7ff88e7a2fcd60ed59
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "STLsurfaceFormat.H"
27 #include "ListOps.H"
28 #include "triPointRef.H"
30 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
32 template<class Face>
33 inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
35     Ostream& os,
36     const pointField& pointLst,
37     const Face& f
40     // calculate the normal ourselves, for flexibility and speed
41     vector norm = triPointRef
42     (
43         pointLst[f[0]],
44         pointLst[f[1]],
45         pointLst[f[2]]
46     ).normal();
47     norm /= mag(norm) + VSMALL;
49     // simple triangulation about f[0].
50     // better triangulation should have been done before
51     const point& p0 = pointLst[f[0]];
52     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
53     {
54         label fp2 = f.fcIndex(fp1);
56         const point& p1 = pointLst[f[fp1]];
57         const point& p2 = pointLst[f[fp2]];
59         // write STL triangle
60         os  << " facet normal "
61             << norm.x() << ' ' << norm.y() << ' ' << norm.z() << nl
62             << "  outer loop\n"
63             << "   vertex " << p0.x() << ' ' << p0.y() << ' ' << p0.z() << nl
64             << "   vertex " << p1.x() << ' ' << p1.y() << ' ' << p1.z() << nl
65             << "   vertex " << p2.x() << ' ' << p2.y() << ' ' << p2.z() << nl
66             << "  endloop\n"
67             << " endfacet" << endl;
68     }
72 template<class Face>
73 inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
75     ostream& os,
76     const pointField& pointLst,
77     const Face& f,
78     const label zoneI
81     // calculate the normal ourselves, for flexibility and speed
82     vector norm = triPointRef
83     (
84         pointLst[f[0]],
85         pointLst[f[1]],
86         pointLst[f[2]]
87     ).normal();
88     norm /= mag(norm) + VSMALL;
90     // simple triangulation about f[0].
91     // better triangulation should have been done before
92     const point& p0 = pointLst[f[0]];
93     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
94     {
95         label fp2 = f.fcIndex(fp1);
97         STLtriangle stlTri
98         (
99             norm,
100             p0,
101             pointLst[f[fp1]],
102             pointLst[f[fp2]],
103             zoneI
104         );
106         stlTri.write(os);
107     }
111 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
113 template<class Face>
114 Foam::fileFormats::STLsurfaceFormat<Face>::STLsurfaceFormat
116     const fileName& filename
119     read(filename);
123 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
125 template<class Face>
126 bool Foam::fileFormats::STLsurfaceFormat<Face>::read
128     const fileName& filename
131     this->clear();
133     // read in the values
134     STLsurfaceFormatCore reader(filename);
136     // transfer points
137     this->storedPoints().transfer(reader.points());
139     // retrieve the original zone information
140     List<word>  names(reader.names().xfer());
141     List<label> sizes(reader.sizes().xfer());
142     List<label> zoneIds(reader.zoneIds().xfer());
144     // generate the (sorted) faces
145     List<Face> faceLst(zoneIds.size());
147     if (reader.sorted())
148     {
149         // already sorted - generate directly
150         forAll(faceLst, faceI)
151         {
152             const label startPt = 3*faceI;
153             faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
154         }
155     }
156     else
157     {
158         // unsorted - determine the sorted order:
159         // avoid SortableList since we discard the main list anyhow
160         List<label> faceMap;
161         sortedOrder(zoneIds, faceMap);
163         // generate sorted faces
164         forAll(faceMap, faceI)
165         {
166             const label startPt = 3*faceMap[faceI];
167             faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
168         }
169     }
170     zoneIds.clear();
172     // transfer:
173     this->storedFaces().transfer(faceLst);
175     if (names.size())
176     {
177         this->addZones(sizes, names);
178     }
179     else
180     {
181         this->addZones(sizes);
182     }
184     this->stitchFaces(SMALL);
185     return true;
190 template<class Face>
191 void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
193     const fileName& filename,
194     const MeshedSurfaceProxy<Face>& surf
197     OFstream os(filename);
198     if (!os.good())
199     {
200         FatalErrorIn
201         (
202             "fileFormats::STLsurfaceFormat::writeAscii"
203             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
204         )
205             << "Cannot open file for writing " << filename
206             << exit(FatalError);
207     }
209     const pointField& pointLst = surf.points();
210     const List<Face>&  faceLst = surf.faces();
211     const List<label>& faceMap = surf.faceMap();
213     const List<surfZone>& zones =
214     (
215         surf.surfZones().size() > 1
216       ? surf.surfZones()
217       : STLsurfaceFormat::oneZone(faceLst)
218     );
220     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
222     label faceIndex = 0;
223     forAll(zones, zoneI)
224     {
225         // Print all faces belonging to this zone
226         const surfZone& zone = zones[zoneI];
228         os << "solid " << zone.name() << nl;
230         if (useFaceMap)
231         {
232             forAll(zone, localFaceI)
233             {
234                 const label faceI = faceMap[faceIndex++];
235                 writeShell(os, pointLst, faceLst[faceI]);
236             }
237         }
238         else
239         {
240             forAll(zone, localFaceI)
241             {
242                 writeShell(os, pointLst, faceLst[faceIndex++]);
243             }
244         }
245         os << "endsolid " << zone.name() << endl;
246     }
250 template<class Face>
251 void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
253     const fileName& filename,
254     const MeshedSurfaceProxy<Face>& surf
257     std::ofstream os(filename.c_str(), std::ios::binary);
258     if (!os.good())
259     {
260         FatalErrorIn
261         (
262             "fileFormats::STLsurfaceFormat::writeBinary"
263             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
264         )
265             << "Cannot open file for writing " << filename
266             << exit(FatalError);
267     }
270     const pointField& pointLst = surf.points();
271     const List<Face>&  faceLst = surf.faces();
272     const List<label>& faceMap = surf.faceMap();
274     const List<surfZone>& zones =
275     (
276         surf.surfZones().size() > 1
277       ? surf.surfZones()
278       : STLsurfaceFormat::oneZone(faceLst)
279     );
281     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
284     unsigned int nTris = 0;
285     if (MeshedSurface<Face>::isTri())
286     {
287         nTris = faceLst.size();
288     }
289     else
290     {
291         // count triangles for on-the-fly triangulation
292         forAll(faceLst, faceI)
293         {
294             nTris += faceLst[faceI].size() - 2;
295         }
296     }
298     // Write the STL header
299     STLsurfaceFormatCore::writeHeaderBINARY(os, nTris);
301     label faceIndex = 0;
302     forAll(zones, zoneI)
303     {
304         const surfZone& zone = zones[zoneI];
306         if (useFaceMap)
307         {
308             forAll(zone, localFaceI)
309             {
310                 writeShell
311                 (
312                     os,
313                     pointLst,
314                     faceLst[faceMap[faceIndex++]],
315                     zoneI
316                 );
317             }
318         }
319         else
320         {
321             forAll(zone, localFaceI)
322             {
323                 writeShell
324                 (
325                     os,
326                     pointLst,
327                     faceLst[faceIndex++],
328                     zoneI
329                 );
330             }
331         }
332     }
336 template<class Face>
337 void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
339     const fileName& filename,
340     const UnsortedMeshedSurface<Face>& surf
343     OFstream os(filename);
344     if (!os.good())
345     {
346         FatalErrorIn
347         (
348             "fileFormats::STLsurfaceFormat::writeAscii"
349             "(const fileName&, const UnsortedMeshedSurface<Face>&)"
350         )
351             << "Cannot open file for writing " << filename
352             << exit(FatalError);
353     }
355     // a single zone - we can skip sorting
356     if (surf.zoneToc().size() == 1)
357     {
358         const pointField& pointLst = surf.points();
359         const List<Face>& faceLst  = surf.faces();
361         os << "solid " << surf.zoneToc()[0].name() << endl;
362         forAll(faceLst, faceI)
363         {
364             writeShell(os, pointLst, faceLst[faceI]);
365         }
366         os << "endsolid " << surf.zoneToc()[0].name() << endl;
367     }
368    else
369    {
370        labelList faceMap;
371        List<surfZone> zoneLst = surf.sortedZones(faceMap);
373        writeAscii
374        (
375            filename,
376            MeshedSurfaceProxy<Face>
377            (
378                surf.points(),
379                surf.faces(),
380                zoneLst,
381                faceMap
382            )
383        );
384    }
388 template<class Face>
389 void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
391     const fileName& filename,
392     const UnsortedMeshedSurface<Face>& surf
395     std::ofstream os(filename.c_str(), std::ios::binary);
396     if (!os.good())
397     {
398         FatalErrorIn
399         (
400             "fileFormats::STLsurfaceFormat::writeBinary"
401             "(const fileName&, const UnsortedMeshedSurface<Face>&)"
402         )
403             << "Cannot open file for writing " << filename
404             << exit(FatalError);
405     }
407     const pointField&  pointLst = surf.points();
408     const List<Face>&  faceLst  = surf.faces();
409     const List<label>& zoneIds  = surf.zoneIds();
411     unsigned int nTris = 0;
412     if (MeshedSurface<Face>::isTri())
413     {
414         nTris = faceLst.size();
415     }
416     else
417     {
418         // count triangles for on-the-fly triangulation
419         forAll(faceLst, faceI)
420         {
421             nTris += faceLst[faceI].size() - 2;
422         }
423     }
425     // Write the STL header
426     STLsurfaceFormatCore::writeHeaderBINARY(os, nTris);
428     // always write unsorted
429     forAll(faceLst, faceI)
430     {
431         writeShell
432         (
433             os,
434             pointLst,
435             faceLst[faceI],
436             zoneIds[faceI]
437         );
438     }
442 template<class Face>
443 void Foam::fileFormats::STLsurfaceFormat<Face>::write
445     const fileName& filename,
446     const MeshedSurfaceProxy<Face>& surf
449     const word ext = filename.ext();
451     // handle 'stlb' as binary directly
452     if (ext == "stlb")
453     {
454         writeBinary(filename, surf);
455     }
456     else
457     {
458         writeAscii(filename, surf);
459     }
463 template<class Face>
464 void Foam::fileFormats::STLsurfaceFormat<Face>::write
466     const fileName& filename,
467     const UnsortedMeshedSurface<Face>& surf
470     word ext = filename.ext();
472     // handle 'stlb' as binary directly
473     if (ext == "stlb")
474     {
475         writeBinary(filename, surf);
476     }
477     else
478     {
479         writeAscii(filename, surf);
480     }
484 // ************************************************************************* //