initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / surfMesh / surfaceFormats / stl / STLsurfaceFormat.C
blobaf3f3fff81bd40f2bc99b9dd746c7ae405de6fc2
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM 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 2 of the License, or (at your
14     option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "STLsurfaceFormat.H"
28 #include "ListOps.H"
29 #include "triPointRef.H"
31 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
33 template<class Face>
34 inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
36     Ostream& os,
37     const pointField& pointLst,
38     const Face& f
41     // calculate the normal ourselves, for flexibility and speed
42     vector norm = triPointRef
43     (
44         pointLst[f[0]],
45         pointLst[f[1]],
46         pointLst[f[2]]
47     ).normal();
48     norm /= mag(norm) + VSMALL;
50     // simple triangulation about f[0].
51     // better triangulation should have been done before
52     const point& p0 = pointLst[f[0]];
53     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
54     {
55         label fp2 = f.fcIndex(fp1);
57         const point& p1 = pointLst[f[fp1]];
58         const point& p2 = pointLst[f[fp2]];
60         // write STL triangle
61         os  << " facet normal "
62             << norm.x() << ' ' << norm.y() << ' ' << norm.z() << nl
63             << "  outer loop\n"
64             << "   vertex " << p0.x() << ' ' << p0.y() << ' ' << p0.z() << nl
65             << "   vertex " << p1.x() << ' ' << p1.y() << ' ' << p1.z() << nl
66             << "   vertex " << p2.x() << ' ' << p2.y() << ' ' << p2.z() << nl
67             << "  endloop\n"
68             << " endfacet" << endl;
69     }
73 template<class Face>
74 inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
76     ostream& os,
77     const pointField& pointLst,
78     const Face& f,
79     const label zoneI
82     // calculate the normal ourselves, for flexibility and speed
83     vector norm = triPointRef
84     (
85         pointLst[f[0]],
86         pointLst[f[1]],
87         pointLst[f[2]]
88     ).normal();
89     norm /= mag(norm) + VSMALL;
91     // simple triangulation about f[0].
92     // better triangulation should have been done before
93     const point& p0 = pointLst[f[0]];
94     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
95     {
96         label fp2 = f.fcIndex(fp1);
98         STLtriangle stlTri
99         (
100             norm,
101             p0,
102             pointLst[f[fp1]],
103             pointLst[f[fp2]],
104             zoneI
105         );
107         stlTri.write(os);
108     }
112 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
114 template<class Face>
115 Foam::fileFormats::STLsurfaceFormat<Face>::STLsurfaceFormat
117     const fileName& filename
120     read(filename);
124 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
126 template<class Face>
127 bool Foam::fileFormats::STLsurfaceFormat<Face>::read
129     const fileName& filename
132     this->clear();
134     // read in the values
135     STLsurfaceFormatCore reader(filename);
137     // transfer points
138     this->storedPoints().transfer(reader.points());
140     // retrieve the original zone information
141     List<word>  names(reader.names().xfer());
142     List<label> sizes(reader.sizes().xfer());
143     List<label> zoneIds(reader.zoneIds().xfer());
145     // generate the (sorted) faces
146     List<Face> faceLst(zoneIds.size());
148     if (reader.sorted())
149     {
150         // already sorted - generate directly
151         forAll(faceLst, faceI)
152         {
153             const label startPt = 3*faceI;
154             faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
155         }
156     }
157     else
158     {
159         // unsorted - determine the sorted order:
160         // avoid SortableList since we discard the main list anyhow
161         List<label> faceMap;
162         sortedOrder(zoneIds, faceMap);
164         // generate sorted faces
165         forAll(faceMap, faceI)
166         {
167             const label startPt = 3*faceMap[faceI];
168             faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
169         }
170     }
171     zoneIds.clear();
173     // transfer:
174     this->storedFaces().transfer(faceLst);
176     if (names.size())
177     {
178         this->addZones(sizes, names);
179     }
180     else
181     {
182         this->addZones(sizes);
183     }
185     this->stitchFaces(SMALL);
186     return true;
191 template<class Face>
192 void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
194     const fileName& filename,
195     const MeshedSurfaceProxy<Face>& surf
198     OFstream os(filename);
199     if (!os.good())
200     {
201         FatalErrorIn
202         (
203             "fileFormats::STLsurfaceFormat::writeAscii"
204             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
205         )
206             << "Cannot open file for writing " << filename
207             << exit(FatalError);
208     }
210     const pointField& pointLst = surf.points();
211     const List<Face>&  faceLst = surf.faces();
212     const List<label>& faceMap = surf.faceMap();
214     const List<surfZone>& zones =
215     (
216         surf.surfZones().size() > 1
217       ? surf.surfZones()
218       : oneZone(faceLst)
219     );
221     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
223     label faceIndex = 0;
224     forAll(zones, zoneI)
225     {
226         // Print all faces belonging to this zone
227         const surfZone& zone = zones[zoneI];
229         os << "solid " << zone.name() << nl;
231         if (useFaceMap)
232         {
233             forAll(zone, localFaceI)
234             {
235                 const label faceI = faceMap[faceIndex++];
236                 writeShell(os, pointLst, faceLst[faceI]);
237             }
238         }
239         else
240         {
241             forAll(zone, localFaceI)
242             {
243                 writeShell(os, pointLst, faceLst[faceIndex++]);
244             }
245         }
246         os << "endsolid " << zone.name() << endl;
247     }
251 template<class Face>
252 void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
254     const fileName& filename,
255     const MeshedSurfaceProxy<Face>& surf
258     std::ofstream os(filename.c_str(), std::ios::binary);
259     if (!os.good())
260     {
261         FatalErrorIn
262         (
263             "fileFormats::STLsurfaceFormat::writeBinary"
264             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
265         )
266             << "Cannot open file for writing " << filename
267             << exit(FatalError);
268     }
271     const pointField& pointLst = surf.points();
272     const List<Face>&  faceLst = surf.faces();
273     const List<label>& faceMap = surf.faceMap();
275     const List<surfZone>& zones =
276     (
277         surf.surfZones().size() > 1
278       ? surf.surfZones()
279       : oneZone(faceLst)
280     );
282     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
285     unsigned int nTris = 0;
286     if (MeshedSurface<Face>::isTri())
287     {
288         nTris = faceLst.size();
289     }
290     else
291     {
292         // count triangles for on-the-fly triangulation
293         forAll(faceLst, faceI)
294         {
295             nTris += faceLst[faceI].size() - 2;
296         }
297     }
299     // Write the STL header
300     STLsurfaceFormatCore::writeHeaderBINARY(os, nTris);
302     label faceIndex = 0;
303     forAll(zones, zoneI)
304     {
305         const surfZone& zone = zones[zoneI];
307         if (useFaceMap)
308         {
309             forAll(zone, localFaceI)
310             {
311                 writeShell
312                 (
313                     os,
314                     pointLst,
315                     faceLst[faceMap[faceIndex++]],
316                     zoneI
317                 );
318             }
319         }
320         else
321         {
322             forAll(zone, localFaceI)
323             {
324                 writeShell
325                 (
326                     os,
327                     pointLst,
328                     faceLst[faceIndex++],
329                     zoneI
330                 );
331             }
332         }
333     }
337 template<class Face>
338 void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
340     const fileName& filename,
341     const UnsortedMeshedSurface<Face>& surf
344     OFstream os(filename);
345     if (!os.good())
346     {
347         FatalErrorIn
348         (
349             "fileFormats::STLsurfaceFormat::writeAscii"
350             "(const fileName&, const UnsortedMeshedSurface<Face>&)"
351         )
352             << "Cannot open file for writing " << filename
353             << exit(FatalError);
354     }
356     // a single zone - we can skip sorting
357     if (surf.zoneToc().size() == 1)
358     {
359         const pointField& pointLst = surf.points();
360         const List<Face>& faceLst  = surf.faces();
362         os << "solid " << surf.zoneToc()[0].name() << endl;
363         forAll(faceLst, faceI)
364         {
365             writeShell(os, pointLst, faceLst[faceI]);
366         }
367         os << "endsolid " << surf.zoneToc()[0].name() << endl;
368     }
369    else
370    {
371        labelList faceMap;
372        List<surfZone> zoneLst = surf.sortedZones(faceMap);
374        writeAscii
375        (
376            filename,
377            MeshedSurfaceProxy<Face>
378            (
379                surf.points(),
380                surf.faces(),
381                zoneLst,
382                faceMap
383            )
384        );
385    }
389 template<class Face>
390 void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
392     const fileName& filename,
393     const UnsortedMeshedSurface<Face>& surf
396     std::ofstream os(filename.c_str(), std::ios::binary);
397     if (!os.good())
398     {
399         FatalErrorIn
400         (
401             "fileFormats::STLsurfaceFormat::writeBinary"
402             "(const fileName&, const UnsortedMeshedSurface<Face>&)"
403         )
404             << "Cannot open file for writing " << filename
405             << exit(FatalError);
406     }
408     const pointField&  pointLst = surf.points();
409     const List<Face>&  faceLst  = surf.faces();
410     const List<label>& zoneIds  = surf.zoneIds();
412     unsigned int nTris = 0;
413     if (MeshedSurface<Face>::isTri())
414     {
415         nTris = faceLst.size();
416     }
417     else
418     {
419         // count triangles for on-the-fly triangulation
420         forAll(faceLst, faceI)
421         {
422             nTris += faceLst[faceI].size() - 2;
423         }
424     }
426     // Write the STL header
427     STLsurfaceFormatCore::writeHeaderBINARY(os, nTris);
429     // always write unsorted
430     forAll(faceLst, faceI)
431     {
432         writeShell
433         (
434             os,
435             pointLst,
436             faceLst[faceI],
437             zoneIds[faceI]
438         );
439     }
443 template<class Face>
444 void Foam::fileFormats::STLsurfaceFormat<Face>::write
446     const fileName& filename,
447     const MeshedSurfaceProxy<Face>& surf
450     const word ext = filename.ext();
452     // handle 'stlb' as binary directly
453     if (ext == "stlb")
454     {
455         writeBinary(filename, surf);
456     }
457     else
458     {
459         writeAscii(filename, surf);
460     }
464 template<class Face>
465 void Foam::fileFormats::STLsurfaceFormat<Face>::write
467     const fileName& filename,
468     const UnsortedMeshedSurface<Face>& surf
471     word ext = filename.ext();
473     // handle 'stlb' as binary directly
474     if (ext == "stlb")
475     {
476         writeBinary(filename, surf);
477     }
478     else
479     {
480         writeAscii(filename, surf);
481     }
485 // ************************************************************************* //