Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
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
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
00089 if (line[line.size()-1] == '\\')
00090 {
00091 line.substr(0, line.size()-1);
00092 line += this->getLineNoComment(is);
00093 }
00094
00095
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
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
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
00182
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
00203 this->storedPoints().transfer(dynPoints);
00204
00205 this->sortFacesAndStore(dynFaces.xfer(), dynZones.xfer(), sorted);
00206
00207
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
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
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
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