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

AC3DsurfaceFormat.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 "AC3DsurfaceFormat.H"
00027 #include <OpenFOAM/clock.H>
00028 #include <OpenFOAM/IStringStream.H>
00029 #include <OpenFOAM/tensor.H>
00030 #include <OpenFOAM/primitivePatch.H>
00031 
00032 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00033 
00034 template<class Face>
00035 Foam::fileFormats::AC3DsurfaceFormat<Face>::AC3DsurfaceFormat
00036 (
00037     const fileName& filename
00038 )
00039 {
00040     read(filename);
00041 }
00042 
00043 
00044 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00045 
00046 template<class Face>
00047 bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
00048 (
00049     const fileName& filename
00050 )
00051 {
00052     const bool mustTriangulate = this->isTri();
00053     this->clear();
00054 
00055     IFstream is(filename);
00056     if (!is.good())
00057     {
00058         FatalErrorIn
00059         (
00060             "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
00061         )
00062             << "Cannot read file " << filename
00063             << exit(FatalError);
00064     }
00065 
00066     string line, cmd, args;
00067 
00068     is.getLine(line);
00069 
00070     string version = line.substr(4);
00071 
00072     if (version != "b")
00073     {
00074         WarningIn
00075         (
00076             "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
00077         )
00078             << "When reading AC3D file " << filename
00079             << " read header " << line << " with version "
00080             << version << endl
00081             << "Only tested reading with version 'b'."
00082             << " This might give problems" << endl;
00083     }
00084 
00085 
00086     if (!cueTo(is, "OBJECT", args) || (args != "world"))
00087     {
00088         FatalErrorIn
00089         (
00090             "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
00091         )
00092             << "Cannot find \"OBJECT world\" in file " << filename
00093             << exit(FatalError);
00094     }
00095 
00096     // # of kids is the # of zones
00097     args = cueToOrDie(is, "kids");
00098     label nZones = parse<int>(args);
00099 
00100     // Start of vertices for object/zones
00101     label vertexOffset = 0;
00102 
00103     DynamicList<point> dynPoints;
00104     DynamicList<Face>  dynFaces;
00105     List<word>         names(nZones);
00106     List<label>        sizes(nZones, 0);
00107 
00108     for (label zoneI = 0; zoneI < nZones; ++zoneI)
00109     {
00110         names[zoneI] = word("zone") + Foam::name(zoneI);
00111 
00112         args = cueToOrDie(is, "OBJECT", "while reading " + names[zoneI]);
00113 
00114         // number of vertices for this zone
00115         label  nZonePoints = 0;
00116         vector location(pTraits<vector>::zero);
00117         // tensor rotation(I);
00118 
00119         // Read all info for current zone
00120         while (is.good())
00121         {
00122             // Read line and get first word. If end of file break since
00123             // zone should always end with 'kids' command ?not sure.
00124             if (!readCmd(is, cmd, args))
00125             {
00126                 FatalErrorIn
00127                 (
00128                     "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
00129                 )
00130                     << "Did not read up to \"kids 0\" while reading zone "
00131                     << zoneI << " from file " << filename
00132                     << exit(FatalError);
00133             }
00134 
00135             if (cmd == "name")
00136             {
00137                 // name %s
00138                 string str = parse<string>(args);
00139                 string::stripInvalid<word>(str);
00140 
00141                 names[zoneI] = str;
00142             }
00143             else if (cmd == "rot")
00144             {
00145                 // rot  %f %f %f  %f %f %f  %f %f %f
00146 
00147                 // IStringStream lineStream(args);
00148                 //
00149                 // lineStream
00150                 //     >> rotation.xx() >> rotation.xy() >> rotation.xz()
00151                 //     >> rotation.yx() >> rotation.yy() >> rotation.yz()
00152                 //     >> rotation.zx() >> rotation.zy() >> rotation.zz();
00153 
00154                 WarningIn
00155                 (
00156                     "fileFormats::AC3DsurfaceFormat::read"
00157                     "(const fileName&)"
00158                 )
00159                     << "rot (rotation tensor) command not implemented"
00160                     << "Line:" << cmd << ' ' << args << endl
00161                     << "while reading zone " << zoneI << endl;
00162             }
00163             else if (cmd == "loc")
00164             {
00165                 // loc  %f %f %f
00166                 IStringStream lineStream(args);
00167 
00168                 lineStream
00169                     >> location.x()
00170                     >> location.y()
00171                     >> location.z();
00172             }
00173             else if (cmd == "numvert")
00174             {
00175                 // numvert  %d
00176                 nZonePoints = parse<int>(args);
00177 
00178                 for (label vertI = 0; vertI < nZonePoints; ++vertI)
00179                 {
00180                     is.getLine(line);
00181                     IStringStream lineStream(line);
00182 
00183                     point pt;
00184                     lineStream
00185                         >> pt.x() >> pt.y() >> pt.z();
00186 
00187                     // Offset with current translation vector
00188                     dynPoints.append(location + pt);
00189                 }
00190             }
00191             else if (cmd == "numsurf")
00192             {
00193                 label nFaces = parse<int>(args);
00194 
00195                 for (label faceI = 0; faceI < nFaces; ++faceI)
00196                 {
00197                     static string errorMsg =
00198                         string(" while reading face ")
00199                             + Foam::name(faceI) + " on zone "
00200                             + Foam::name(zoneI)
00201                             + " from file " + filename;
00202 
00203                     cueToOrDie(is, "SURF", errorMsg);
00204                     cueToOrDie(is, "mat", errorMsg);
00205                     args = cueToOrDie(is, "refs", errorMsg);
00206 
00207                     label nVert = parse<int>(args);
00208 
00209                     List<label> verts(nVert);
00210                     forAll(verts, vertI)
00211                     {
00212                         is.getLine(line);
00213                         verts[vertI] = parse<int>(line) + vertexOffset;
00214                     }
00215 
00216                     UList<label>& f = static_cast<UList<label>&>(verts);
00217 
00218                     if (mustTriangulate && f.size() > 3)
00219                     {
00220                         // simple face triangulation about f[0]
00221                         // points may be incomplete
00222                         for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
00223                         {
00224                             label fp2 = f.fcIndex(fp1);
00225 
00226                             dynFaces.append(triFace(f[0], f[fp1], f[fp2]));
00227                             sizes[zoneI]++;
00228                         }
00229                     }
00230                     else
00231                     {
00232                         dynFaces.append(Face(f));
00233                         sizes[zoneI]++;
00234                     }
00235                 }
00236 
00237                 // Done the current zone.
00238                 // Increment the offset vertices are stored at
00239                 vertexOffset += nZonePoints;
00240             }
00241             else if (cmd == "kids")
00242             {
00243                 // 'kids' denotes the end of the current zone.
00244                 label nKids = parse<int>(args);
00245 
00246                 if (nKids != 0)
00247                 {
00248                     FatalErrorIn
00249                     (
00250                         "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
00251                     )
00252                         << "Can only read objects without kids."
00253                         << " Encountered " << nKids << " kids when"
00254                         << " reading zone " << zoneI
00255                         << exit(FatalError);
00256                 }
00257 
00258                 // Done reading current zone
00259                 break;
00260             }
00261         }
00262     }
00263 
00264     // transfer to normal lists
00265     this->storedPoints().transfer(dynPoints);
00266     this->storedFaces().transfer(dynFaces);
00267 
00268     // add zones, culling empty ones
00269     this->addZones(sizes, names, true);
00270     this->stitchFaces(SMALL);
00271     return true;
00272 }
00273 
00274 
00275 template<class Face>
00276 void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
00277 (
00278     const fileName& filename,
00279     const MeshedSurfaceProxy<Face>& surf
00280 )
00281 {
00282     const pointField& pointLst = surf.points();
00283     const List<Face>&  faceLst = surf.faces();
00284 
00285     const List<surfZone>& zones =
00286     (
00287         surf.surfZones().size()
00288       ? surf.surfZones()
00289       : AC3DsurfaceFormat::oneZone(faceLst)
00290     );
00291 
00292     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
00293 
00294     if (useFaceMap)
00295     {
00296         FatalErrorIn
00297         (
00298             "fileFormats::AC3DsurfaceFormat::write"
00299             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
00300         )
00301             << "output with faceMap is not supported " << filename
00302             << exit(FatalError);
00303     }
00304 
00305 
00306     OFstream os(filename);
00307     if (!os.good())
00308     {
00309         FatalErrorIn
00310         (
00311             "fileFormats::AC3DsurfaceFormat::write"
00312             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
00313         )
00314             << "Cannot open file for writing " << filename
00315             << exit(FatalError);
00316     }
00317 
00318     writeHeader(os, zones);
00319 
00320     forAll(zones, zoneI)
00321     {
00322         const surfZone& zone = zones[zoneI];
00323 
00324         os  << "OBJECT poly" << nl
00325             << "name \"" << zone.name() << "\"\n";
00326 
00327         // Temporary PrimitivePatch to calculate compact points & faces
00328         // use 'UList' to avoid allocations!
00329         PrimitivePatch<Face, UList, const pointField&> patch
00330         (
00331             SubList<Face>
00332             (
00333                 faceLst,
00334                 zone.size(),
00335                 zone.start()
00336             ),
00337             pointLst
00338         );
00339 
00340         os << "numvert " << patch.nPoints() << endl;
00341 
00342         forAll(patch.localPoints(), ptI)
00343         {
00344             const point& pt = patch.localPoints()[ptI];
00345 
00346             os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
00347         }
00348 
00349         os << "numsurf " << patch.localFaces().size() << endl;
00350 
00351         forAll(patch.localFaces(), localFaceI)
00352         {
00353             const Face& f = patch.localFaces()[localFaceI];
00354 
00355             os  << "SURF 0x20" << nl          // polygon
00356                 << "mat " << zoneI << nl
00357                 << "refs " << f.size() << nl;
00358 
00359             forAll(f, fp)
00360             {
00361                 os << f[fp] << " 0 0" << nl;
00362             }
00363         }
00364 
00365         os << "kids 0" << endl;
00366     }
00367 }
00368 
00369 
00370 template<class Face>
00371 void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
00372 (
00373     const fileName& filename,
00374     const UnsortedMeshedSurface<Face>& surf
00375 )
00376 {
00377     labelList faceMap;
00378     List<surfZone> zoneLst = surf.sortedZones(faceMap);
00379 
00380     if (zoneLst.size() <= 1)
00381     {
00382         write
00383         (
00384             filename,
00385             MeshedSurfaceProxy<Face>
00386             (
00387                 surf.points(),
00388                 surf.faces(),
00389                 zoneLst
00390             )
00391         );
00392     }
00393     else
00394     {
00395         OFstream os(filename);
00396         if (!os.good())
00397         {
00398             FatalErrorIn
00399             (
00400                 "fileFormats::AC3DsurfaceFormat::write"
00401                 "(const fileName&, const MeshedSurfaceProxy<Face>&)"
00402             )
00403                 << "Cannot open file for writing " << filename
00404                 << exit(FatalError);
00405         }
00406 
00407         writeHeader(os, zoneLst);
00408 
00409         label faceIndex = 0;
00410         forAll(zoneLst, zoneI)
00411         {
00412             const surfZone& zone = zoneLst[zoneI];
00413 
00414             os  << "OBJECT poly" << nl
00415                 << "name \"" << zone.name() << "\"\n";
00416 
00417             // Create zone with only zone faces included for ease of addressing
00418             labelHashSet include(surf.size());
00419 
00420             forAll(zone, localFaceI)
00421             {
00422                 const label faceI = faceMap[faceIndex++];
00423                 include.insert(faceI);
00424             }
00425 
00426             UnsortedMeshedSurface<Face> subm = surf.subsetMesh(include);
00427 
00428             // Now we have isolated surface for this patch alone. Write it.
00429             os << "numvert " << subm.nPoints() << endl;
00430 
00431             forAll(subm.localPoints(), ptI)
00432             {
00433                 const point& pt = subm.localPoints()[ptI];
00434 
00435                 os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
00436             }
00437 
00438             os << "numsurf " << subm.localFaces().size() << endl;
00439 
00440             forAll(subm.localFaces(), localFaceI)
00441             {
00442                 const Face& f = subm.localFaces()[localFaceI];
00443 
00444                 os  << "SURF 0x20" << nl          // polygon
00445                     << "mat " << zoneI << nl
00446                     << "refs " << f.size() << nl;
00447 
00448                 forAll(f, fp)
00449                 {
00450                     os << f[fp] << " 0 0" << nl;
00451                 }
00452             }
00453 
00454             os << "kids 0" << endl;
00455         }
00456     }
00457 }
00458 
00459 
00460 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines