BUG: UListIO: byteSize overflowing on really big faceLists
[OpenFOAM-2.0.x.git] / src / surfMesh / surfaceFormats / ac3d / AC3DsurfaceFormat.C
blob151f0fd788aeb3023c34789b20150b51730eb8a8
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by
13     the Free Software Foundation, either version 3 of the License, or
14     (at your option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "AC3DsurfaceFormat.H"
27 #include "clock.H"
28 #include "IStringStream.H"
29 #include "tensor.H"
30 #include "primitivePatch.H"
32 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
34 template<class Face>
35 Foam::fileFormats::AC3DsurfaceFormat<Face>::AC3DsurfaceFormat
37     const fileName& filename
40     read(filename);
44 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
46 template<class Face>
47 bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
49     const fileName& filename
52     const bool mustTriangulate = this->isTri();
53     this->clear();
55     IFstream is(filename);
56     if (!is.good())
57     {
58         FatalErrorIn
59         (
60             "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
61         )
62             << "Cannot read file " << filename
63             << exit(FatalError);
64     }
66     string line, cmd, args;
68     is.getLine(line);
70     string version = line.substr(4);
72     if (version != "b")
73     {
74         WarningIn
75         (
76             "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
77         )
78             << "When reading AC3D file " << filename
79             << " read header " << line << " with version "
80             << version << endl
81             << "Only tested reading with version 'b'."
82             << " This might give problems" << endl;
83     }
86     if (!cueTo(is, "OBJECT", args) || (args != "world"))
87     {
88         FatalErrorIn
89         (
90             "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
91         )
92             << "Cannot find \"OBJECT world\" in file " << filename
93             << exit(FatalError);
94     }
96     // # of kids is the # of zones
97     args = cueToOrDie(is, "kids");
98     label nZones = parse<int>(args);
100     // Start of vertices for object/zones
101     label vertexOffset = 0;
103     DynamicList<point> dynPoints;
104     DynamicList<Face>  dynFaces;
105     List<word>         names(nZones);
106     List<label>        sizes(nZones, 0);
108     for (label zoneI = 0; zoneI < nZones; ++zoneI)
109     {
110         names[zoneI] = word("zone") + Foam::name(zoneI);
112         args = cueToOrDie(is, "OBJECT", "while reading " + names[zoneI]);
114         // number of vertices for this zone
115         label  nZonePoints = 0;
116         vector location(pTraits<vector>::zero);
117         // tensor rotation(I);
119         // Read all info for current zone
120         while (is.good())
121         {
122             // Read line and get first word. If end of file break since
123             // zone should always end with 'kids' command ?not sure.
124             if (!readCmd(is, cmd, args))
125             {
126                 FatalErrorIn
127                 (
128                     "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
129                 )
130                     << "Did not read up to \"kids 0\" while reading zone "
131                     << zoneI << " from file " << filename
132                     << exit(FatalError);
133             }
135             if (cmd == "name")
136             {
137                 // name %s
138                 string str = parse<string>(args);
139                 string::stripInvalid<word>(str);
141                 names[zoneI] = str;
142             }
143             else if (cmd == "rot")
144             {
145                 // rot  %f %f %f  %f %f %f  %f %f %f
147                 // IStringStream lineStream(args);
148                 //
149                 // lineStream
150                 //     >> rotation.xx() >> rotation.xy() >> rotation.xz()
151                 //     >> rotation.yx() >> rotation.yy() >> rotation.yz()
152                 //     >> rotation.zx() >> rotation.zy() >> rotation.zz();
154                 WarningIn
155                 (
156                     "fileFormats::AC3DsurfaceFormat::read"
157                     "(const fileName&)"
158                 )
159                     << "rot (rotation tensor) command not implemented"
160                     << "Line:" << cmd << ' ' << args << endl
161                     << "while reading zone " << zoneI << endl;
162             }
163             else if (cmd == "loc")
164             {
165                 // loc  %f %f %f
166                 IStringStream lineStream(args);
168                 lineStream
169                     >> location.x()
170                     >> location.y()
171                     >> location.z();
172             }
173             else if (cmd == "numvert")
174             {
175                 // numvert  %d
176                 nZonePoints = parse<int>(args);
178                 for (label vertI = 0; vertI < nZonePoints; ++vertI)
179                 {
180                     is.getLine(line);
181                     IStringStream lineStream(line);
183                     point pt;
184                     lineStream
185                         >> pt.x() >> pt.y() >> pt.z();
187                     // Offset with current translation vector
188                     dynPoints.append(location + pt);
189                 }
190             }
191             else if (cmd == "numsurf")
192             {
193                 label nFaces = parse<int>(args);
195                 for (label faceI = 0; faceI < nFaces; ++faceI)
196                 {
197                     static string errorMsg =
198                         string(" while reading face ")
199                             + Foam::name(faceI) + " on zone "
200                             + Foam::name(zoneI)
201                             + " from file " + filename;
203                     cueToOrDie(is, "SURF", errorMsg);
204                     cueToOrDie(is, "mat", errorMsg);
205                     args = cueToOrDie(is, "refs", errorMsg);
207                     label nVert = parse<int>(args);
209                     List<label> verts(nVert);
210                     forAll(verts, vertI)
211                     {
212                         is.getLine(line);
213                         verts[vertI] = parse<int>(line) + vertexOffset;
214                     }
216                     labelUList& f = static_cast<labelUList&>(verts);
218                     if (mustTriangulate && f.size() > 3)
219                     {
220                         // simple face triangulation about f[0]
221                         // points may be incomplete
222                         for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
223                         {
224                             label fp2 = f.fcIndex(fp1);
226                             dynFaces.append(triFace(f[0], f[fp1], f[fp2]));
227                             sizes[zoneI]++;
228                         }
229                     }
230                     else
231                     {
232                         dynFaces.append(Face(f));
233                         sizes[zoneI]++;
234                     }
235                 }
237                 // Done the current zone.
238                 // Increment the offset vertices are stored at
239                 vertexOffset += nZonePoints;
240             }
241             else if (cmd == "kids")
242             {
243                 // 'kids' denotes the end of the current zone.
244                 label nKids = parse<int>(args);
246                 if (nKids != 0)
247                 {
248                     FatalErrorIn
249                     (
250                         "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
251                     )
252                         << "Can only read objects without kids."
253                         << " Encountered " << nKids << " kids when"
254                         << " reading zone " << zoneI
255                         << exit(FatalError);
256                 }
258                 // Done reading current zone
259                 break;
260             }
261         }
262     }
264     // transfer to normal lists
265     this->storedPoints().transfer(dynPoints);
266     this->storedFaces().transfer(dynFaces);
268     // add zones, culling empty ones
269     this->addZones(sizes, names, true);
270     this->stitchFaces(SMALL);
271     return true;
275 template<class Face>
276 void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
278     const fileName& filename,
279     const MeshedSurfaceProxy<Face>& surf
282     const pointField& pointLst = surf.points();
283     const List<Face>&  faceLst = surf.faces();
285     const List<surfZone>& zones =
286     (
287         surf.surfZones().size()
288       ? surf.surfZones()
289       : surfaceFormatsCore::oneZone(faceLst)
290     );
292     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
294     if (useFaceMap)
295     {
296         FatalErrorIn
297         (
298             "fileFormats::AC3DsurfaceFormat::write"
299             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
300         )
301             << "output with faceMap is not supported " << filename
302             << exit(FatalError);
303     }
306     OFstream os(filename);
307     if (!os.good())
308     {
309         FatalErrorIn
310         (
311             "fileFormats::AC3DsurfaceFormat::write"
312             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
313         )
314             << "Cannot open file for writing " << filename
315             << exit(FatalError);
316     }
318     writeHeader(os, zones);
320     forAll(zones, zoneI)
321     {
322         const surfZone& zone = zones[zoneI];
324         os  << "OBJECT poly" << nl
325             << "name \"" << zone.name() << "\"\n";
327         // Temporary PrimitivePatch to calculate compact points & faces
328         // use 'UList' to avoid allocations!
329         PrimitivePatch<Face, UList, const pointField&> patch
330         (
331             SubList<Face>
332             (
333                 faceLst,
334                 zone.size(),
335                 zone.start()
336             ),
337             pointLst
338         );
340         os << "numvert " << patch.nPoints() << endl;
342         forAll(patch.localPoints(), ptI)
343         {
344             const point& pt = patch.localPoints()[ptI];
346             os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
347         }
349         os << "numsurf " << patch.localFaces().size() << endl;
351         forAll(patch.localFaces(), localFaceI)
352         {
353             const Face& f = patch.localFaces()[localFaceI];
355             os  << "SURF 0x20" << nl          // polygon
356                 << "mat " << zoneI << nl
357                 << "refs " << f.size() << nl;
359             forAll(f, fp)
360             {
361                 os << f[fp] << " 0 0" << nl;
362             }
363         }
365         os << "kids 0" << endl;
366     }
370 template<class Face>
371 void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
373     const fileName& filename,
374     const UnsortedMeshedSurface<Face>& surf
377     labelList faceMap;
378     List<surfZone> zoneLst = surf.sortedZones(faceMap);
380     if (zoneLst.size() <= 1)
381     {
382         write
383         (
384             filename,
385             MeshedSurfaceProxy<Face>
386             (
387                 surf.points(),
388                 surf.faces(),
389                 zoneLst
390             )
391         );
392     }
393     else
394     {
395         OFstream os(filename);
396         if (!os.good())
397         {
398             FatalErrorIn
399             (
400                 "fileFormats::AC3DsurfaceFormat::write"
401                 "(const fileName&, const MeshedSurfaceProxy<Face>&)"
402             )
403                 << "Cannot open file for writing " << filename
404                 << exit(FatalError);
405         }
407         writeHeader(os, zoneLst);
409         label faceIndex = 0;
410         forAll(zoneLst, zoneI)
411         {
412             const surfZone& zone = zoneLst[zoneI];
414             os  << "OBJECT poly" << nl
415                 << "name \"" << zone.name() << "\"\n";
417             // Create zone with only zone faces included for ease of addressing
418             labelHashSet include(surf.size());
420             forAll(zone, localFaceI)
421             {
422                 const label faceI = faceMap[faceIndex++];
423                 include.insert(faceI);
424             }
426             UnsortedMeshedSurface<Face> subm = surf.subsetMesh(include);
428             // Now we have isolated surface for this patch alone. Write it.
429             os << "numvert " << subm.nPoints() << endl;
431             forAll(subm.localPoints(), ptI)
432             {
433                 const point& pt = subm.localPoints()[ptI];
435                 os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
436             }
438             os << "numsurf " << subm.localFaces().size() << endl;
440             forAll(subm.localFaces(), localFaceI)
441             {
442                 const Face& f = subm.localFaces()[localFaceI];
444                 os  << "SURF 0x20" << nl          // polygon
445                     << "mat " << zoneI << nl
446                     << "refs " << f.size() << nl;
448                 forAll(f, fp)
449                 {
450                     os << f[fp] << " 0 0" << nl;
451                 }
452             }
454             os << "kids 0" << endl;
455         }
456     }
460 // ************************************************************************* //