readAC.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation
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  Reader for .ac files generated by AC3D.
26 
27  See http://www.ac3d.org/ac3d/man/ac3dfileformat.html
28 
29 \*---------------------------------------------------------------------------*/
30 
31 #include "triSurface.H"
32 #include "IFstream.H"
33 #include "IStringStream.H"
34 #include "transform.H"
35 #include "tensor.H"
36 
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
44 static label parseInt(const string& str)
45 {
46  IStringStream intStream(str);
47 
48  label a;
49 
50  intStream >> a;
51 
52  return a;
53 }
54 
55 
56 static bool readCmd(IFstream& ACfile, string& cmd, string& args)
57 {
58  if (ACfile.good())
59  {
60  string line;
61  ACfile.getLine(line);
62 
63  string::size_type space = line.find(' ');
64 
65  if (space != string::npos)
66  {
67  cmd = line.substr(0, space);
68  args = line.substr(space+1);
69 
70  return true;
71  }
72  }
73  return false;
74 }
75 
76 
77 // Read up to line starting with cmd. Sets args to rest of line.
78 // Returns true if found, false if stream is not good anymore.
79 static bool readUpto
80 (
81  const string& cmd,
82  IFstream& ACfile,
83  string& args
84 )
85 {
86  while (ACfile.good())
87  {
88  string line;
89  ACfile.getLine(line);
90 
91  string::size_type space = line.find(' ');
92 
93  if (space != string::npos && line.substr(0, space) == cmd)
94  {
95  args = line.substr(space+1);
96  return true;
97  }
98  }
99  return false;
100 }
101 
102 
103 // Likewise but throws error if cmd not found
104 static void readUpto
105 (
106  const string& cmd,
107  IFstream& ACfile,
108  string& args,
109  const string errorMsg
110 )
111 {
112  if (!readUpto(cmd, ACfile, args))
113  {
115  << "Cannot find command " << cmd
116  << errorMsg << exit(FatalError);
117  }
118 }
119 
120 
121 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
122 
123 bool triSurface::readAC(const fileName& ACfileName)
124 {
125  IFstream ACfile(ACfileName);
126 
127  if (!ACfile.good())
128  {
130  << "Cannot read file " << ACfileName
131  << exit(FatalError);
132  }
133 
134  string line;
135  ACfile.getLine(line);
136 
137  string version = line.substr(4);
138 
139  if (version != "b")
140  {
142  << "When reading AC3D file " << ACfileName
143  << " read header " << line << " with version " << version
144  << endl << "Only tested reading with version 'b'."
145  << " This might give problems" << endl;
146  }
147 
148  string cmd;
149 
150  string args;
151 
152  if (!readUpto("OBJECT", ACfile, args) || (args != "world"))
153  {
155  << "Cannot find \"OBJECT world\" in file " << ACfileName
156  << exit(FatalError);
157  }
158 
159  // Number of kids = patches
160 
161  readUpto("kids", ACfile, args, "");
162 
163  label nPatches = parseInt(args);
164 
165  // Storage for patches and unmerged points and faces
166 
170 
171 
172  // Start of vertices for object/patch
173  label patchStartVert = 0;
174 
175  for (label patchi = 0; patchi < nPatches; patchi++)
176  {
177  readUpto
178  (
179  "OBJECT",
180  ACfile,
181  args,
182  " while reading patch " + Foam::name(patchi)
183  );
184 
185  // Object global values
186  string patchName = string("patch") + name(patchi);
187  label nVerts = 0;
188  tensor rot(I);
189  vector loc(0, 0, 0);
190 
191  // Read all info for current patch
192  while (ACfile.good())
193  {
194  // Read line and get first word. If end of file break since
195  // patch should always end with 'kids' command ?not sure.
196  if (!readCmd(ACfile, cmd, args))
197  {
199  << "Did not read up to \"kids 0\" while reading patch "
200  << patchi << " from file " << ACfileName
201  << exit(FatalError);
202  }
203 
204  if (cmd == "name")
205  {
206  IStringStream nameStream(args);
207 
208  nameStream >> patchName;
209  }
210  else if (cmd == "rot")
211  {
212  // rot %f %f %f %f %f %f %f %f %f
213  IStringStream lineStream(args);
214 
215  lineStream
216  >> rot.xx() >> rot.xy() >> rot.xz()
217  >> rot.yx() >> rot.yy() >> rot.yz()
218  >> rot.zx() >> rot.zy() >> rot.zz();
219 
221  << "rot (rotation tensor) command not implemented"
222  << "Line:" << cmd << ' ' << args << endl
223  << "while reading patch " << patchi << endl;
224  }
225  else if (cmd == "loc")
226  {
227  IStringStream lineStream(args);
228 
229  lineStream >> loc.x() >> loc.y() >> loc.z();
230  }
231  else if (cmd == "numvert")
232  {
233  nVerts = parseInt(args);
234 
235  for (label vertI = 0; vertI < nVerts; vertI++)
236  {
237  ACfile.getLine(line);
238 
239  IStringStream lineStream(line);
240 
241  point pt;
242 
243  lineStream >> pt.x() >> pt.y() >> pt.z();
244 
245  // Offset with current translation vector
246  points.append(pt+loc);
247  }
248  }
249  else if (cmd == "numsurf")
250  {
251  label nTris = parseInt(args);
252 
253  for (label triI = 0; triI < nTris; triI++)
254  {
255  static string errorMsg =
256  string(" while reading face ")
257  + name(triI) + " on patch " + name(patchi)
258  + " from file " + ACfileName;
259 
260  readUpto("SURF", ACfile, args, errorMsg);
261  readUpto("mat", ACfile, args, errorMsg);
262  readUpto("refs", ACfile, args, errorMsg);
263 
264  label size = parseInt(args);
265 
266  if (size != 3)
267  {
269  << "Can only read surfaces with 3 vertices."
270  << endl
271  << "Detected " << size << " when reading triangle "
272  << triI << " of patch " << patchi
273  << exit(FatalError);
274  }
275 
276  ACfile.getLine(line);
277 
278  label v0 = parseInt(line);
279 
280  ACfile.getLine(line);
281 
282  label v1 = parseInt(line);
283 
284  ACfile.getLine(line);
285 
286  label v2 = parseInt(line);
287 
288  faces.append
289  (
291  (
292  v0 + patchStartVert,
293  v1 + patchStartVert,
294  v2 + patchStartVert,
295  patchi
296  )
297  );
298  }
299 
300  // Done the current patch. Increment the offset vertices are
301  // stored at
302  patchStartVert += nVerts;
303  }
304  else if (cmd == "kids")
305  {
306  // 'kids' denotes the end of the current patch.
307 
308  label nKids = parseInt(args);
309 
310  if (nKids != 0)
311  {
313  << "Can only read objects without kids."
314  << " Encountered " << nKids << " kids when"
315  << " reading patch " << patchi
316  << exit(FatalError);
317  }
318 
319  patches[patchi] =
321  (
322  "empty",
323  word(patchName),
324  patchi
325  );
326 
327  // Stop reading current patch
328  break;
329  }
330  }
331  }
332 
333  faces.shrink();
334 
335  // Transfer DynamicLists to straight ones.
336  pointField allPoints(move(points));
337 
338  *this = triSurface(faces, patches, allPoints, true);
339 
340  stitchTriangles();
341 
342  return true;
343 }
344 
345 
346 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
347 
348 } // End namespace Foam
349 
350 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:402
const Cmpt & yx() const
Definition: TensorI.H:184
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A line primitive.
Definition: line.H:56
const Cmpt & zy() const
Definition: TensorI.H:212
A class for handling file names.
Definition: fileName.H:79
const Cmpt & xz() const
Definition: TensorI.H:177
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:323
static label parseInt(const string &str)
Definition: readAC.C:44
const Cmpt & yy() const
Definition: TensorI.H:191
const Cmpt & xx() const
Definition: TensorI.H:163
const Cmpt & yz() const
Definition: TensorI.H:198
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
const Cmpt & z() const
Definition: VectorI.H:87
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:330
const Cmpt & y() const
Definition: VectorI.H:81
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
static const Identity< scalar > I
Definition: Identity.H:93
A class for handling words, derived from string.
Definition: word.H:59
static bool readCmd(IFstream &ACfile, string &cmd, string &args)
Definition: readAC.C:56
3D tensor transformation operations.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
const Field< PointType > & points() const
Return reference to global points.
Triangle with additional region number.
Definition: labelledTri.H:57
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
const Cmpt & x() const
Definition: VectorI.H:75
static bool readUpto(const string &cmd, IFstream &ACfile, string &args)
Definition: readAC.C:80
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:252
Input from file stream.
Definition: IFstream.H:81
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
const Cmpt & zx() const
Definition: TensorI.H:205
const geometricSurfacePatchList & patches() const
Definition: triSurface.H:322
ISstream & getLine(string &, const bool continuation=true)
Read line into a string.
Definition: ISstream.C:692
triSurface()
Construct null.
Definition: triSurface.C:534
label patchi
#define WarningInFunction
Report a warning using Foam::Warning.
Input from memory buffer stream.
Definition: IStringStream.H:49
The geometricSurfacePatch is like patchIdentifier but for surfaces. Holds type, name and index...
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
faceList faces() const
Return the list of triangles as a faceList.
Definition: triSurface.C:1131
Foam::argList args(argc, argv)
A class for handling character strings derived from std::string.
Definition: string.H:76
label size() const
Return the number of elements in the UList.
Definition: ListI.H:171
const Cmpt & xy() const
Definition: TensorI.H:170
const Cmpt & zz() const
Definition: TensorI.H:219
Namespace for OpenFOAM.