FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

STLsurfaceFormat.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "STLsurfaceFormat.H"
00027 #include <OpenFOAM/ListOps.H>
00028 #include <OpenFOAM/triPointRef.H>
00029 
00030 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00031 
00032 template<class Face>
00033 inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
00034 (
00035     Ostream& os,
00036     const pointField& pointLst,
00037     const Face& f
00038 )
00039 {
00040     // calculate the normal ourselves, for flexibility and speed
00041     vector norm = triPointRef
00042     (
00043         pointLst[f[0]],
00044         pointLst[f[1]],
00045         pointLst[f[2]]
00046     ).normal();
00047     norm /= mag(norm) + VSMALL;
00048 
00049     // simple triangulation about f[0].
00050     // better triangulation should have been done before
00051     const point& p0 = pointLst[f[0]];
00052     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
00053     {
00054         label fp2 = f.fcIndex(fp1);
00055 
00056         const point& p1 = pointLst[f[fp1]];
00057         const point& p2 = pointLst[f[fp2]];
00058 
00059         // write STL triangle
00060         os  << " facet normal "
00061             << norm.x() << ' ' << norm.y() << ' ' << norm.z() << nl
00062             << "  outer loop\n"
00063             << "   vertex " << p0.x() << ' ' << p0.y() << ' ' << p0.z() << nl
00064             << "   vertex " << p1.x() << ' ' << p1.y() << ' ' << p1.z() << nl
00065             << "   vertex " << p2.x() << ' ' << p2.y() << ' ' << p2.z() << nl
00066             << "  endloop\n"
00067             << " endfacet" << endl;
00068     }
00069 }
00070 
00071 
00072 template<class Face>
00073 inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
00074 (
00075     ostream& os,
00076     const pointField& pointLst,
00077     const Face& f,
00078     const label zoneI
00079 )
00080 {
00081     // calculate the normal ourselves, for flexibility and speed
00082     vector norm = triPointRef
00083     (
00084         pointLst[f[0]],
00085         pointLst[f[1]],
00086         pointLst[f[2]]
00087     ).normal();
00088     norm /= mag(norm) + VSMALL;
00089 
00090     // simple triangulation about f[0].
00091     // better triangulation should have been done before
00092     const point& p0 = pointLst[f[0]];
00093     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
00094     {
00095         label fp2 = f.fcIndex(fp1);
00096 
00097         STLtriangle stlTri
00098         (
00099             norm,
00100             p0,
00101             pointLst[f[fp1]],
00102             pointLst[f[fp2]],
00103             zoneI
00104         );
00105 
00106         stlTri.write(os);
00107     }
00108 }
00109 
00110 
00111 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00112 
00113 template<class Face>
00114 Foam::fileFormats::STLsurfaceFormat<Face>::STLsurfaceFormat
00115 (
00116     const fileName& filename
00117 )
00118 {
00119     read(filename);
00120 }
00121 
00122 
00123 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00124 
00125 template<class Face>
00126 bool Foam::fileFormats::STLsurfaceFormat<Face>::read
00127 (
00128     const fileName& filename
00129 )
00130 {
00131     this->clear();
00132 
00133     // read in the values
00134     STLsurfaceFormatCore reader(filename);
00135 
00136     // transfer points
00137     this->storedPoints().transfer(reader.points());
00138 
00139     // retrieve the original zone information
00140     List<word>  names(reader.names().xfer());
00141     List<label> sizes(reader.sizes().xfer());
00142     List<label> zoneIds(reader.zoneIds().xfer());
00143 
00144     // generate the (sorted) faces
00145     List<Face> faceLst(zoneIds.size());
00146 
00147     if (reader.sorted())
00148     {
00149         // already sorted - generate directly
00150         forAll(faceLst, faceI)
00151         {
00152             const label startPt = 3*faceI;
00153             faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
00154         }
00155     }
00156     else
00157     {
00158         // unsorted - determine the sorted order:
00159         // avoid SortableList since we discard the main list anyhow
00160         List<label> faceMap;
00161         sortedOrder(zoneIds, faceMap);
00162 
00163         // generate sorted faces
00164         forAll(faceMap, faceI)
00165         {
00166             const label startPt = 3*faceMap[faceI];
00167             faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
00168         }
00169     }
00170     zoneIds.clear();
00171 
00172     // transfer:
00173     this->storedFaces().transfer(faceLst);
00174 
00175     if (names.size())
00176     {
00177         this->addZones(sizes, names);
00178     }
00179     else
00180     {
00181         this->addZones(sizes);
00182     }
00183 
00184     this->stitchFaces(SMALL);
00185     return true;
00186 }
00187 
00188 
00189 
00190 template<class Face>
00191 void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
00192 (
00193     const fileName& filename,
00194     const MeshedSurfaceProxy<Face>& surf
00195 )
00196 {
00197     OFstream os(filename);
00198     if (!os.good())
00199     {
00200         FatalErrorIn
00201         (
00202             "fileFormats::STLsurfaceFormat::writeAscii"
00203             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
00204         )
00205             << "Cannot open file for writing " << filename
00206             << exit(FatalError);
00207     }
00208 
00209     const pointField& pointLst = surf.points();
00210     const List<Face>&  faceLst = surf.faces();
00211     const List<label>& faceMap = surf.faceMap();
00212 
00213     const List<surfZone>& zones =
00214     (
00215         surf.surfZones().size() > 1
00216       ? surf.surfZones()
00217       : STLsurfaceFormat::oneZone(faceLst)
00218     );
00219 
00220     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
00221 
00222     label faceIndex = 0;
00223     forAll(zones, zoneI)
00224     {
00225         // Print all faces belonging to this zone
00226         const surfZone& zone = zones[zoneI];
00227 
00228         os << "solid " << zone.name() << nl;
00229 
00230         if (useFaceMap)
00231         {
00232             forAll(zone, localFaceI)
00233             {
00234                 const label faceI = faceMap[faceIndex++];
00235                 writeShell(os, pointLst, faceLst[faceI]);
00236             }
00237         }
00238         else
00239         {
00240             forAll(zone, localFaceI)
00241             {
00242                 writeShell(os, pointLst, faceLst[faceIndex++]);
00243             }
00244         }
00245         os << "endsolid " << zone.name() << endl;
00246     }
00247 }
00248 
00249 
00250 template<class Face>
00251 void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
00252 (
00253     const fileName& filename,
00254     const MeshedSurfaceProxy<Face>& surf
00255 )
00256 {
00257     std::ofstream os(filename.c_str(), std::ios::binary);
00258     if (!os.good())
00259     {
00260         FatalErrorIn
00261         (
00262             "fileFormats::STLsurfaceFormat::writeBinary"
00263             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
00264         )
00265             << "Cannot open file for writing " << filename
00266             << exit(FatalError);
00267     }
00268 
00269 
00270     const pointField& pointLst = surf.points();
00271     const List<Face>&  faceLst = surf.faces();
00272     const List<label>& faceMap = surf.faceMap();
00273 
00274     const List<surfZone>& zones =
00275     (
00276         surf.surfZones().size() > 1
00277       ? surf.surfZones()
00278       : STLsurfaceFormat::oneZone(faceLst)
00279     );
00280 
00281     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
00282 
00283 
00284     unsigned int nTris = 0;
00285     if (MeshedSurface<Face>::isTri())
00286     {
00287         nTris = faceLst.size();
00288     }
00289     else
00290     {
00291         // count triangles for on-the-fly triangulation
00292         forAll(faceLst, faceI)
00293         {
00294             nTris += faceLst[faceI].size() - 2;
00295         }
00296     }
00297 
00298     // Write the STL header
00299     STLsurfaceFormatCore::writeHeaderBINARY(os, nTris);
00300 
00301     label faceIndex = 0;
00302     forAll(zones, zoneI)
00303     {
00304         const surfZone& zone = zones[zoneI];
00305 
00306         if (useFaceMap)
00307         {
00308             forAll(zone, localFaceI)
00309             {
00310                 writeShell
00311                 (
00312                     os,
00313                     pointLst,
00314                     faceLst[faceMap[faceIndex++]],
00315                     zoneI
00316                 );
00317             }
00318         }
00319         else
00320         {
00321             forAll(zone, localFaceI)
00322             {
00323                 writeShell
00324                 (
00325                     os,
00326                     pointLst,
00327                     faceLst[faceIndex++],
00328                     zoneI
00329                 );
00330             }
00331         }
00332     }
00333 }
00334 
00335 
00336 template<class Face>
00337 void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
00338 (
00339     const fileName& filename,
00340     const UnsortedMeshedSurface<Face>& surf
00341 )
00342 {
00343     OFstream os(filename);
00344     if (!os.good())
00345     {
00346         FatalErrorIn
00347         (
00348             "fileFormats::STLsurfaceFormat::writeAscii"
00349             "(const fileName&, const UnsortedMeshedSurface<Face>&)"
00350         )
00351             << "Cannot open file for writing " << filename
00352             << exit(FatalError);
00353     }
00354 
00355     // a single zone - we can skip sorting
00356     if (surf.zoneToc().size() == 1)
00357     {
00358         const pointField& pointLst = surf.points();
00359         const List<Face>& faceLst  = surf.faces();
00360 
00361         os << "solid " << surf.zoneToc()[0].name() << endl;
00362         forAll(faceLst, faceI)
00363         {
00364             writeShell(os, pointLst, faceLst[faceI]);
00365         }
00366         os << "endsolid " << surf.zoneToc()[0].name() << endl;
00367     }
00368    else
00369    {
00370        labelList faceMap;
00371        List<surfZone> zoneLst = surf.sortedZones(faceMap);
00372 
00373        writeAscii
00374        (
00375            filename,
00376            MeshedSurfaceProxy<Face>
00377            (
00378                surf.points(),
00379                surf.faces(),
00380                zoneLst,
00381                faceMap
00382            )
00383        );
00384    }
00385 }
00386 
00387 
00388 template<class Face>
00389 void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
00390 (
00391     const fileName& filename,
00392     const UnsortedMeshedSurface<Face>& surf
00393 )
00394 {
00395     std::ofstream os(filename.c_str(), std::ios::binary);
00396     if (!os.good())
00397     {
00398         FatalErrorIn
00399         (
00400             "fileFormats::STLsurfaceFormat::writeBinary"
00401             "(const fileName&, const UnsortedMeshedSurface<Face>&)"
00402         )
00403             << "Cannot open file for writing " << filename
00404             << exit(FatalError);
00405     }
00406 
00407     const pointField&  pointLst = surf.points();
00408     const List<Face>&  faceLst  = surf.faces();
00409     const List<label>& zoneIds  = surf.zoneIds();
00410 
00411     unsigned int nTris = 0;
00412     if (MeshedSurface<Face>::isTri())
00413     {
00414         nTris = faceLst.size();
00415     }
00416     else
00417     {
00418         // count triangles for on-the-fly triangulation
00419         forAll(faceLst, faceI)
00420         {
00421             nTris += faceLst[faceI].size() - 2;
00422         }
00423     }
00424 
00425     // Write the STL header
00426     STLsurfaceFormatCore::writeHeaderBINARY(os, nTris);
00427 
00428     // always write unsorted
00429     forAll(faceLst, faceI)
00430     {
00431         writeShell
00432         (
00433             os,
00434             pointLst,
00435             faceLst[faceI],
00436             zoneIds[faceI]
00437         );
00438     }
00439 }
00440 
00441 
00442 template<class Face>
00443 void Foam::fileFormats::STLsurfaceFormat<Face>::write
00444 (
00445     const fileName& filename,
00446     const MeshedSurfaceProxy<Face>& surf
00447 )
00448 {
00449     const word ext = filename.ext();
00450 
00451     // handle 'stlb' as binary directly
00452     if (ext == "stlb")
00453     {
00454         writeBinary(filename, surf);
00455     }
00456     else
00457     {
00458         writeAscii(filename, surf);
00459     }
00460 }
00461 
00462 
00463 template<class Face>
00464 void Foam::fileFormats::STLsurfaceFormat<Face>::write
00465 (
00466     const fileName& filename,
00467     const UnsortedMeshedSurface<Face>& surf
00468 )
00469 {
00470     word ext = filename.ext();
00471 
00472     // handle 'stlb' as binary directly
00473     if (ext == "stlb")
00474     {
00475         writeBinary(filename, surf);
00476     }
00477     else
00478     {
00479         writeAscii(filename, surf);
00480     }
00481 }
00482 
00483 
00484 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines