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

OBJsurfaceFormat.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 "OBJsurfaceFormat.H"
00027 #include <OpenFOAM/clock.H>
00028 #include <OpenFOAM/IFstream.H>
00029 #include <OpenFOAM/IStringStream.H>
00030 #include <OpenFOAM/Ostream.H>
00031 #include <OpenFOAM/OFstream.H>
00032 #include <OpenFOAM/ListOps.H>
00033 
00034 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00035 
00036 template<class Face>
00037 Foam::fileFormats::OBJsurfaceFormat<Face>::OBJsurfaceFormat
00038 (
00039     const fileName& filename
00040 )
00041 {
00042     read(filename);
00043 }
00044 
00045 
00046 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00047 
00048 template<class Face>
00049 bool Foam::fileFormats::OBJsurfaceFormat<Face>::read
00050 (
00051     const fileName& filename
00052 )
00053 {
00054     const bool mustTriangulate = this->isTri();
00055     this->clear();
00056 
00057     IFstream is(filename);
00058     if (!is.good())
00059     {
00060         FatalErrorIn
00061         (
00062             "fileFormats::OBJsurfaceFormat::read(const fileName&)"
00063         )
00064             << "Cannot read file " << filename
00065             << exit(FatalError);
00066     }
00067 
00068     // assume that the groups are not intermixed
00069     bool sorted = true;
00070 
00071     DynamicList<point> dynPoints;
00072     DynamicList<Face>  dynFaces;
00073     DynamicList<label> dynZones;
00074     DynamicList<word>  dynNames;
00075     DynamicList<label> dynSizes;
00076     HashTable<label>   lookup;
00077 
00078     // place faces without a group in zone0
00079     label zoneI = 0;
00080     lookup.insert("zone0", zoneI);
00081     dynNames.append("zone0");
00082     dynSizes.append(0);
00083 
00084     while (is.good())
00085     {
00086         string line = this->getLineNoComment(is);
00087 
00088         // handle continuations
00089         if (line[line.size()-1] == '\\')
00090         {
00091             line.substr(0, line.size()-1);
00092             line += this->getLineNoComment(is);
00093         }
00094 
00095         // Read first word
00096         IStringStream lineStream(line);
00097         word cmd;
00098         lineStream >> cmd;
00099 
00100         if (cmd == "v")
00101         {
00102             scalar x, y, z;
00103             lineStream >> x >> y >> z;
00104             dynPoints.append(point(x, y, z));
00105         }
00106         else if (cmd == "g")
00107         {
00108             word name;
00109             lineStream >> name;
00110 
00111             HashTable<label>::const_iterator fnd = lookup.find(name);
00112             if (fnd != lookup.end())
00113             {
00114                 if (zoneI != fnd())
00115                 {
00116                     // group appeared out of order
00117                     sorted = false;
00118                 }
00119                 zoneI = fnd();
00120             }
00121             else
00122             {
00123                 zoneI = dynSizes.size();
00124                 lookup.insert(name, zoneI);
00125                 dynNames.append(name);
00126                 dynSizes.append(0);
00127             }
00128         }
00129         else if (cmd == "f")
00130         {
00131             DynamicList<label> dynVertices;
00132 
00133             // Assume 'f' is followed by space.
00134             string::size_type endNum = 1;
00135 
00136             while (true)
00137             {
00138                 string::size_type startNum =
00139                     line.find_first_not_of(' ', endNum);
00140 
00141                 if (startNum == string::npos)
00142                 {
00143                     break;
00144                 }
00145 
00146                 endNum = line.find(' ', startNum);
00147 
00148                 string vertexSpec;
00149                 if (endNum != string::npos)
00150                 {
00151                     vertexSpec = line.substr(startNum, endNum-startNum);
00152                 }
00153                 else
00154                 {
00155                     vertexSpec = line.substr(startNum, line.size() - startNum);
00156                 }
00157 
00158                 string::size_type slashPos = vertexSpec.find('/');
00159 
00160                 label vertI = 0;
00161                 if (slashPos != string::npos)
00162                 {
00163                     IStringStream intStream(vertexSpec.substr(0, slashPos));
00164 
00165                     intStream >> vertI;
00166                 }
00167                 else
00168                 {
00169                     IStringStream intStream(vertexSpec);
00170 
00171                     intStream >> vertI;
00172                 }
00173                 dynVertices.append(vertI - 1);
00174             }
00175             dynVertices.shrink();
00176 
00177             UList<label>& f = static_cast<UList<label>&>(dynVertices);
00178 
00179             if (mustTriangulate && f.size() > 3)
00180             {
00181                 // simple face triangulation about f[0]
00182                 // points may be incomplete
00183                 for (label fp1 = 1; fp1 < f.size() - 1; fp1++)
00184                 {
00185                     label fp2 = f.fcIndex(fp1);
00186 
00187                     dynFaces.append(triFace(f[0], f[fp1], f[fp2]));
00188                     dynZones.append(zoneI);
00189                     dynSizes[zoneI]++;
00190                 }
00191             }
00192             else
00193             {
00194                 dynFaces.append(Face(f));
00195                 dynZones.append(zoneI);
00196                 dynSizes[zoneI]++;
00197             }
00198         }
00199     }
00200 
00201 
00202     // transfer to normal lists
00203     this->storedPoints().transfer(dynPoints);
00204 
00205     this->sortFacesAndStore(dynFaces.xfer(), dynZones.xfer(), sorted);
00206 
00207     // add zones, culling empty ones
00208     this->addZones(dynSizes, dynNames, true);
00209     return true;
00210 }
00211 
00212 
00213 template<class Face>
00214 void Foam::fileFormats::OBJsurfaceFormat<Face>::write
00215 (
00216     const fileName& filename,
00217     const MeshedSurfaceProxy<Face>& surf
00218 )
00219 {
00220     const pointField& pointLst = surf.points();
00221     const List<Face>&  faceLst = surf.faces();
00222     const List<label>& faceMap = surf.faceMap();
00223 
00224     // for no zones, suppress the group name
00225     const List<surfZone>& zones =
00226     (
00227         surf.surfZones().size() > 1
00228       ? surf.surfZones()
00229       : OBJsurfaceFormat::oneZone(faceLst, "")
00230     );
00231 
00232     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
00233 
00234     OFstream os(filename);
00235     if (!os.good())
00236     {
00237         FatalErrorIn
00238         (
00239             "fileFormats::OBJsurfaceFormat::write"
00240             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
00241         )
00242             << "Cannot open file for writing " << filename
00243             << exit(FatalError);
00244     }
00245 
00246 
00247     os  << "# Wavefront OBJ file written " << clock::dateTime().c_str() << nl
00248         << "o " << os.name().lessExt().name() << nl
00249         << nl
00250         << "# points : " << pointLst.size() << nl
00251         << "# faces  : " << faceLst.size() << nl
00252         << "# zones  : " << zones.size() << nl;
00253 
00254     // Print zone names as comment
00255     forAll(zones, zoneI)
00256     {
00257         os  << "#   " << zoneI << "  " << zones[zoneI].name()
00258             << "  (nFaces: " << zones[zoneI].size() << ")" << nl;
00259     }
00260 
00261     os  << nl
00262         << "# <points count=\"" << pointLst.size() << "\">" << nl;
00263 
00264     // Write vertex coords
00265     forAll(pointLst, ptI)
00266     {
00267         const point& pt = pointLst[ptI];
00268 
00269         os  << "v " << pt.x() << ' '  << pt.y() << ' '  << pt.z() << nl;
00270     }
00271 
00272     os  << "# </points>" << nl
00273         << nl
00274         << "# <faces count=\"" << faceLst.size() << "\">" << endl;
00275 
00276 
00277     label faceIndex = 0;
00278     forAll(zones, zoneI)
00279     {
00280         const surfZone& zone = zones[zoneI];
00281 
00282         if (zone.name().size())
00283         {
00284             os << "g " << zone.name() << endl;
00285         }
00286 
00287         if (useFaceMap)
00288         {
00289             forAll(zone, localFaceI)
00290             {
00291                 const Face& f = faceLst[faceMap[faceIndex++]];
00292 
00293                 os << 'f';
00294                 forAll(f, fp)
00295                 {
00296                     os << ' ' << f[fp] + 1;
00297                 }
00298                 os << endl;
00299             }
00300         }
00301         else
00302         {
00303             forAll(zone, localFaceI)
00304             {
00305                 const Face& f = faceLst[faceIndex++];
00306 
00307                 os << 'f';
00308                 forAll(f, fp)
00309                 {
00310                     os << ' ' << f[fp] + 1;
00311                 }
00312                 os << endl;
00313             }
00314         }
00315     }
00316     os << "# </faces>" << endl;
00317 }
00318 
00319 
00320 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines