FreeFOAM The Cross-Platform CFD Toolkit
readAC.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 Description
25 
26  Reader for .ac files generated by AC3D.
27 
28  See http://www.ac3d.org/ac3d/man/ac3dfileformat.html
29 
30 \*---------------------------------------------------------------------------*/
31 
32 #include <triSurface/triSurface.H>
33 #include <OpenFOAM/IFstream.H>
34 #include <OpenFOAM/IStringStream.H>
35 #include <OpenFOAM/transform.H>
36 #include <OpenFOAM/tensor.H>
37 
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
45 static label parseInt(const string& str)
46 {
47  IStringStream intStream(str);
48 
49  label a;
50 
51  intStream >> a;
52 
53  return a;
54 }
55 
56 
57 static bool readCmd(IFstream& ACfile, string& cmd, string& args)
58 {
59  if (ACfile.good())
60  {
61  string line;
62  ACfile.getLine(line);
63 
64  string::size_type space = line.find(' ');
65 
66  if (space != string::npos)
67  {
68  cmd = line.substr(0, space);
69  args = line.substr(space+1);
70 
71  return true;
72  }
73  }
74  return false;
75 }
76 
77 
78 // Read up to line starting with cmd. Sets args to rest of line.
79 // Returns true if found, false if stream is not good anymore.
80 static bool readUpto
81 (
82  const string& cmd,
83  IFstream& ACfile,
84  string& args
85 )
86 {
87  while (ACfile.good())
88  {
89  string line;
90  ACfile.getLine(line);
91 
92  string::size_type space = line.find(' ');
93 
94  if (space != string::npos && line.substr(0, space) == cmd)
95  {
96  args = line.substr(space+1);
97  return true;
98  }
99  }
100  return false;
101 }
102 
103 
104 // Likewise but throws error if cmd not found
105 static void readUpto
106 (
107  const string& cmd,
108  IFstream& ACfile,
109  string& args,
110  const string errorMsg
111 )
112 {
113  if (!readUpto(cmd, ACfile, args))
114  {
115  FatalErrorIn("triSurface::readAC(const fileName&)")
116  << "Cannot find command " << cmd
117  << errorMsg << exit(FatalError);
118  }
119 }
120 
121 
122 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
123 
124 bool triSurface::readAC(const fileName& ACfileName)
125 {
126  IFstream ACfile(ACfileName);
127 
128  if (!ACfile.good())
129  {
130  FatalErrorIn("triSurface::readAC(const fileName&)")
131  << "Cannot read file " << ACfileName
132  << exit(FatalError);
133  }
134 
135  string line;
136  ACfile.getLine(line);
137 
138  string version = line.substr(4);
139 
140  if (version != "b")
141  {
142  WarningIn("bool triSurface::readAC(const fileName& ACfileName)")
143  << "When reading AC3D file " << ACfileName
144  << " read header " << line << " with version " << version
145  << endl << "Only tested reading with version 'b'."
146  << " This might give problems" << endl;
147  }
148 
149  string cmd;
150 
151  string args;
152 
153  if (!readUpto("OBJECT", ACfile, args) || (args != "world"))
154  {
155  FatalErrorIn("bool triSurface::readAC(const fileName& ACfileName)")
156  << "Cannot find \"OBJECT world\" in file " << ACfileName
157  << exit(FatalError);
158  }
159 
160  // Number of kids = patches
161 
162  readUpto("kids", ACfile, args, "");
163 
164  label nPatches = parseInt(args);
165 
166  // Storage for patches and unmerged points and faces
167 
168  DynamicList<point> points;
169  DynamicList<labelledTri> faces;
171 
172 
173  // Start of vertices for object/patch
174  label patchStartVert = 0;
175 
176  for (label patchI = 0; patchI < nPatches; patchI++)
177  {
178  readUpto("OBJECT", ACfile, args, " while reading patch " + patchI);
179 
180  // Object global values
181  string patchName = string("patch") + name(patchI);
182  label nVerts = 0;
183  tensor rot(I);
184  vector loc(0, 0, 0);
185 
186  // Read all info for current patch
187  while (ACfile.good())
188  {
189  // Read line and get first word. If end of file break since
190  // patch should always end with 'kids' command ?not sure.
191  if (!readCmd(ACfile, cmd, args))
192  {
193  FatalErrorIn("triSurface::readAC(const fileName&)")
194  << "Did not read up to \"kids 0\" while reading patch "
195  << patchI << " from file " << ACfileName
196  << exit(FatalError);
197  }
198 
199  if (cmd == "name")
200  {
201  IStringStream nameStream(args);
202 
203  nameStream >> patchName;
204  }
205  else if (cmd == "rot")
206  {
207  // rot %f %f %f %f %f %f %f %f %f
208  IStringStream lineStream(args);
209 
210  lineStream
211  >> rot.xx() >> rot.xy() >> rot.xz()
212  >> rot.yx() >> rot.yy() >> rot.yz()
213  >> rot.zx() >> rot.zy() >> rot.zz();
214 
215  WarningIn("triSurface::readAC(const fileName&)")
216  << "rot (rotation tensor) command not implemented"
217  << "Line:" << cmd << ' ' << args << endl
218  << "while reading patch " << patchI << endl;
219  }
220  else if (cmd == "loc")
221  {
222  IStringStream lineStream(args);
223 
224  lineStream >> loc.x() >> loc.y() >> loc.z();
225  }
226  else if (cmd == "numvert")
227  {
228  nVerts = parseInt(args);
229 
230  for (label vertI = 0; vertI < nVerts; vertI++)
231  {
232  ACfile.getLine(line);
233 
234  IStringStream lineStream(line);
235 
236  point pt;
237 
238  lineStream >> pt.x() >> pt.y() >> pt.z();
239 
240  // Offset with current translation vector
241  points.append(pt+loc);
242  }
243  }
244  else if (cmd == "numsurf")
245  {
246  label nTris = parseInt(args);
247 
248  for (label triI = 0; triI < nTris; triI++)
249  {
250  static string errorMsg =
251  string(" while reading face ")
252  + name(triI) + " on patch " + name(patchI)
253  + " from file " + ACfileName;
254 
255  readUpto("SURF", ACfile, args, errorMsg);
256  readUpto("mat", ACfile, args, errorMsg);
257  readUpto("refs", ACfile, args, errorMsg);
258 
259  label size = parseInt(args);
260 
261  if (size != 3)
262  {
263  FatalErrorIn("triSurface::readAC(const fileName&)")
264  << "Can only read surfaces with 3 vertices."
265  << endl
266  << "Detected " << size << " when reading triangle "
267  << triI << " of patch " << patchI
268  << exit(FatalError);
269  }
270 
271  ACfile.getLine(line);
272 
273  label v0 = parseInt(line);
274 
275  ACfile.getLine(line);
276 
277  label v1 = parseInt(line);
278 
279  ACfile.getLine(line);
280 
281  label v2 = parseInt(line);
282 
283  faces.append
284  (
285  labelledTri
286  (
287  v0 + patchStartVert,
288  v1 + patchStartVert,
289  v2 + patchStartVert,
290  patchI
291  )
292  );
293  }
294 
295  // Done the current patch. Increment the offset vertices are
296  // stored at
297  patchStartVert += nVerts;
298  }
299  else if (cmd == "kids")
300  {
301  // 'kids' denotes the end of the current patch.
302 
303  label nKids = parseInt(args);
304 
305  if (nKids != 0)
306  {
307  FatalErrorIn("triSurface::readAC(const fileName&)")
308  << "Can only read objects without kids."
309  << " Encountered " << nKids << " kids when"
310  << " reading patch " << patchI
311  << exit(FatalError);
312  }
313 
314  patches[patchI] =
315  geometricSurfacePatch
316  (
317  "empty",
318  word(patchName),
319  patchI
320  );
321 
322  // Stop reading current patch
323  break;
324  }
325  }
326  }
327 
328  faces.shrink();
329 
330  // Transfer DynamicLists to straight ones.
331  pointField allPoints(points.xfer());
332 
333  *this = triSurface(faces, patches, allPoints, true);
334 
335  stitchTriangles(allPoints);
336 
337  return true;
338 }
339 
340 
341 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
342 
343 } // End namespace Foam
344 
345 // ************************ vim: set sw=4 sts=4 et: ************************ //