1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "OBJsurfaceFormat.H"
29 #include "IStringStream.H"
34 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
37 Foam::fileFormats::OBJsurfaceFormat<Face>::OBJsurfaceFormat
39 const fileName& filename
46 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
49 bool Foam::fileFormats::OBJsurfaceFormat<Face>::read
51 const fileName& filename
54 const bool mustTriangulate = this->isTri();
57 IFstream is(filename);
62 "fileFormats::OBJsurfaceFormat::read(const fileName&)"
64 << "Cannot read file " << filename
68 // assume that the groups are not intermixed
71 DynamicList<point> dynPoints;
72 DynamicList<Face> dynFaces;
73 dynamicLabelList dynZones;
74 DynamicList<word> dynNames;
75 dynamicLabelList dynSizes;
76 HashTable<label> lookup;
78 // place faces without a group in zone0
80 lookup.insert("zone0", zoneI);
81 dynNames.append("zone0");
86 string line = this->getLineNoComment(is);
88 // handle continuations
89 if (line[line.size()-1] == '\\')
91 line.substr(0, line.size()-1);
92 line += this->getLineNoComment(is);
96 IStringStream lineStream(line);
103 lineStream >> x >> y >> z;
104 dynPoints.append(point(x, y, z));
111 HashTable<label>::const_iterator fnd = lookup.find(name);
112 if (fnd != lookup.end())
116 // group appeared out of order
123 zoneI = dynSizes.size();
124 lookup.insert(name, zoneI);
125 dynNames.append(name);
131 dynamicLabelList dynVertices;
133 // Assume 'f' is followed by space.
134 string::size_type endNum = 1;
138 string::size_type startNum =
139 line.find_first_not_of(' ', endNum);
141 if (startNum == string::npos)
146 endNum = line.find(' ', startNum);
149 if (endNum != string::npos)
151 vertexSpec = line.substr(startNum, endNum-startNum);
155 vertexSpec = line.substr(startNum, line.size() - startNum);
158 string::size_type slashPos = vertexSpec.find('/');
161 if (slashPos != string::npos)
163 IStringStream intStream(vertexSpec.substr(0, slashPos));
169 IStringStream intStream(vertexSpec);
173 dynVertices.append(vertI - 1);
175 dynVertices.shrink();
177 UList<label>& f = static_cast<UList<label>&>(dynVertices);
179 if (mustTriangulate && f.size() > 3)
181 // simple face triangulation about f[0]
182 // points may be incomplete
183 for (label fp1 = 1; fp1 < f.size() - 1; fp1++)
185 label fp2 = f.fcIndex(fp1);
187 dynFaces.append(triFace(f[0], f[fp1], f[fp2]));
188 dynZones.append(zoneI);
194 dynFaces.append(Face(f));
195 dynZones.append(zoneI);
202 // transfer to normal lists
203 this->storedPoints().transfer(dynPoints);
205 this->sortFacesAndStore(dynFaces.xfer(), dynZones.xfer(), sorted);
207 // add zones, culling empty ones
208 this->addZones(dynSizes, dynNames, true);
214 void Foam::fileFormats::OBJsurfaceFormat<Face>::write
216 const fileName& filename,
217 const MeshedSurfaceProxy<Face>& surf
220 const pointField& pointLst = surf.points();
221 const List<Face>& faceLst = surf.faces();
222 const List<label>& faceMap = surf.faceMap();
224 // for no zones, suppress the group name
225 const List<surfZone>& zones =
227 surf.surfZones().size() > 1
229 : OBJsurfaceFormat::oneZone(faceLst, "")
232 const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
234 OFstream os(filename);
239 "fileFormats::OBJsurfaceFormat::write"
240 "(const fileName&, const MeshedSurfaceProxy<Face>&)"
242 << "Cannot open file for writing " << filename
247 os << "# Wavefront OBJ file written " << clock::dateTime().c_str() << nl
248 << "o " << os.name().lessExt().name() << nl
250 << "# points : " << pointLst.size() << nl
251 << "# faces : " << faceLst.size() << nl
252 << "# zones : " << zones.size() << nl;
254 // Print zone names as comment
257 os << "# " << zoneI << " " << zones[zoneI].name()
258 << " (nFaces: " << zones[zoneI].size() << ")" << nl;
262 << "# <points count=\"" << pointLst.size() << "\">" << nl;
264 // Write vertex coords
265 forAll(pointLst, ptI)
267 const point& pt = pointLst[ptI];
269 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
272 os << "# </points>" << nl
274 << "# <faces count=\"" << faceLst.size() << "\">" << endl;
280 const surfZone& zone = zones[zoneI];
282 if (zone.name().size())
284 os << "g " << zone.name() << endl;
289 forAll(zone, localFaceI)
291 const Face& f = faceLst[faceMap[faceIndex++]];
296 os << ' ' << f[fp] + 1;
303 forAll(zone, localFaceI)
305 const Face& f = faceLst[faceIndex++];
310 os << ' ' << f[fp] + 1;
316 os << "# </faces>" << endl;
320 // ************************************************************************* //