AC3DsurfaceFormat.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2017 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "AC3DsurfaceFormat.H"
30 #include "StringStream.H"
31 #include "PrimitivePatch.H"
32 #include "faceTraits.H"
33 
34 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35 
36 template<class Face>
38 (
39  const fileName& filename
40 )
41 {
42  read(filename);
43 }
44 
45 
46 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
47 
48 template<class Face>
50 (
51  const fileName& filename
52 )
53 {
54  this->clear();
55 
56  IFstream is(filename);
57  if (!is.good())
58  {
60  << "Cannot read file " << filename
61  << exit(FatalError);
62  }
63 
64  string line, cmd, args;
65 
66  is.getLine(line);
67 
68  // Verify version
69  {
70  const string version = line.substr(4);
71 
72  if (version != "b")
73  {
75  << "When reading AC3D file " << filename
76  << " read header " << line << " with version "
77  << version << endl
78  << "Only tested reading with version 'b'."
79  << " This might give problems" << endl;
80  }
81  }
82 
83 
84  if (!cueTo(is, "OBJECT", args) || args != "world")
85  {
87  << "Cannot find \"OBJECT world\" in file " << filename
88  << exit(FatalError);
89  }
90 
91  // Number of kids is the number of zones
92  args = cueToOrDie(is, "kids");
93  const label nZones = parse<int>(args);
94 
95  // Start of vertices for object/zones
96  label vertexOffset = 0;
97 
98  DynamicList<point> dynPoints;
99  DynamicList<Face> dynFaces;
100  List<word> names(nZones);
101  List<label> sizes(nZones, Zero);
102 
103  for (label zoneI = 0; zoneI < nZones; ++zoneI)
104  {
105  names[zoneI] = word("zone") + Foam::name(zoneI);
106 
107  args = cueToOrDie(is, "OBJECT", "while reading " + names[zoneI]);
108 
109  // number of vertices for this zone
110  label nZonePoints = 0;
111  vector location(Zero);
112  // tensor rotation(I);
113 
114  // Read all info for current zone
115  while (is.good())
116  {
117  // Read line and get first word. If end of file break since
118  // zone should always end with 'kids' command ?not sure.
119  if (!readCmd(is, cmd, args))
120  {
122  << "Did not read up to \"kids 0\" while reading zone "
123  << zoneI << " from file " << filename
124  << exit(FatalError);
125  }
126 
127  if (cmd == "name")
128  {
129  // name %s
130  const string str = parse<string>(args);
131  names[zoneI] = word::validate(str);
132  }
133  else if (cmd == "rot")
134  {
135  // rot %f %f %f %f %f %f %f %f %f
136 
137  // IStringStream lineStream(args);
138  //
139  // lineStream
140  // >> rotation.xx() >> rotation.xy() >> rotation.xz()
141  // >> rotation.yx() >> rotation.yy() >> rotation.yz()
142  // >> rotation.zx() >> rotation.zy() >> rotation.zz();
143 
145  << "rot (rotation tensor) command not implemented"
146  << "Line:" << cmd << ' ' << args << endl
147  << "while reading zone " << zoneI << endl;
148  }
149  else if (cmd == "loc")
150  {
151  // loc %f %f %f
152  IStringStream lineStream(args);
153 
154  lineStream
155  >> location.x()
156  >> location.y()
157  >> location.z();
158  }
159  else if (cmd == "numvert")
160  {
161  // numvert %d
162  nZonePoints = parse<int>(args);
163 
164  for (label vertI = 0; vertI < nZonePoints; ++vertI)
165  {
166  is.getLine(line);
167  IStringStream lineStream(line);
168 
169  point pt;
170  lineStream
171  >> pt.x() >> pt.y() >> pt.z();
172 
173  // Offset with current translation vector
174  dynPoints.append(location + pt);
175  }
176  }
177  else if (cmd == "numsurf")
178  {
179  const label nFaces = parse<int>(args);
180 
181  for (label facei = 0; facei < nFaces; ++facei)
182  {
183  const string errorMsg =
184  string(" while reading face ")
185  + Foam::name(facei) + " on zone "
186  + Foam::name(zoneI)
187  + " from file " + filename;
188 
189  cueToOrDie(is, "SURF", errorMsg);
190  cueToOrDie(is, "mat", errorMsg);
191  args = cueToOrDie(is, "refs", errorMsg);
192 
193  const label nVert = parse<int>(args);
194 
195  List<label> verts(nVert);
196  forAll(verts, vertI)
197  {
198  is.getLine(line);
199  verts[vertI] = vertexOffset + parse<int>(line);
200  }
201 
202  const labelUList& f = static_cast<const labelUList&>(verts);
203 
204  if (faceTraits<Face>::isTri() && f.size() > 3)
205  {
206  // simple face triangulation about f[0]
207  // points may be incomplete
208  for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
209  {
210  label fp2 = f.fcIndex(fp1);
211 
212  dynFaces.append(Face{f[0], f[fp1], f[fp2]});
213  sizes[zoneI]++;
214  }
215  }
216  else
217  {
218  dynFaces.append(Face(f));
219  sizes[zoneI]++;
220  }
221  }
222 
223  // Done the current zone.
224  // Increment the offset vertices are stored at
225  vertexOffset += nZonePoints;
226  }
227  else if (cmd == "kids")
228  {
229  // 'kids' denotes the end of the current zone.
230  const label nKids = parse<int>(args);
231 
232  if (nKids != 0)
233  {
235  << "Can only read objects without kids."
236  << " Encountered " << nKids << " kids when"
237  << " reading zone " << zoneI
238  << exit(FatalError);
239  }
240 
241  // Done reading current zone
242  break;
243  }
244  }
245  }
246 
247  // transfer to normal lists
248  this->storedPoints().transfer(dynPoints);
249  this->storedFaces().transfer(dynFaces);
250 
251  // Add zones (retaining empty ones)
252  this->addZones(sizes, names);
253  this->addZonesToFaces(); // for labelledTri
254  this->stitchFaces(SMALL);
255 
256  return true;
257 }
258 
259 
260 namespace Foam
261 {
262 // file-scope writing of a patch of faces
263 template
264 <
265  class Face,
266  template<class> class FaceList,
267  class PointField,
268  class PointType
269 >
270 static void writeZone
271 (
272  Ostream& os,
274  const word& name,
275  const label zoneI
276 )
277 {
278  // An isolated surface region (patch).
279  os << "OBJECT poly" << nl
280  << "name \"" << name << "\"" << nl;
281 
282  os << "numvert " << patch.nPoints() << nl;
283 
284  for (const point& pt : patch.localPoints())
285  {
286  os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
287  }
288 
289  os << "numsurf " << patch.size() << nl;
290 
291  for (const Face& f : patch.localFaces())
292  {
293  os << "SURF 0x20" << nl // polygon
294  << "mat " << zoneI << nl
295  << "refs " << f.size() << nl;
296 
297  for (const label verti : f)
298  {
299  os << verti << " 0 0" << nl;
300  }
301  }
302 
303  os << "kids 0" << endl;
304 }
305 }
306 
307 template<class Face>
309 (
310  const fileName& filename,
311  const MeshedSurfaceProxy<Face>& surf,
312  const dictionary&
313 )
314 {
315  const pointField& pointLst = surf.points();
316  const UList<Face>& faceLst = surf.surfFaces();
317 
318  const surfZoneList zones =
319  (
320  surf.surfZones().size()
321  ? surf.surfZones()
322  : surfaceFormatsCore::oneZone(faceLst)
323  );
324 
325  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
326 
327  OFstream os(filename);
328  if (!os.good())
329  {
331  << "Cannot open file for writing " << filename
332  << exit(FatalError);
333  }
334 
335  writeHeader(os, zones);
336 
337  if (zones.size() == 1)
338  {
340  (
341  faceLst, pointLst
342  );
343 
344  writeZone(os, patch, zones[0].name(), 0);
345  return;
346  }
347 
348  label zoneIndex = 0;
349  for (const surfZone& zone : zones)
350  {
351  if (useFaceMap)
352  {
353  SubList<label> zoneMap(surf.faceMap(), zone.size(), zone.start());
355  (
356  UIndirectList<Face>(faceLst, zoneMap),
357  pointLst
358  );
359 
360  writeZone(os, patch, zone.name(), zoneIndex);
361  }
362  else
363  {
365  (
366  SubList<Face>(faceLst, zone.size(), zone.start()),
367  pointLst
368  );
369 
370  writeZone(os, patch, zone.name(), zoneIndex);
371  }
372 
373  ++zoneIndex;
374  }
375 }
376 
377 
378 template<class Face>
380 (
381  const fileName& filename,
382  const UnsortedMeshedSurface<Face>& surf,
383  const dictionary&
384 )
385 {
386  OFstream os(filename);
387  if (!os.good())
388  {
390  << "Cannot open file for writing " << filename
391  << exit(FatalError);
392  }
393 
395  List<surfZone> zoneLst = surf.sortedZones(faceMap);
396 
397  if (zoneLst.size() <= 1)
398  {
399  const surfZoneList zones =
400  (
401  zoneLst.size()
402  ? zoneLst
403  : surfaceFormatsCore::oneZone(surf.surfFaces())
404  );
405 
406  writeHeader(os, zones);
407  writeZone(os, surf, zones[0].name(), 0);
408  return;
409  }
410 
411  writeHeader(os, zoneLst);
412 
413  label zoneIndex = 0;
414  for (const surfZone& zone : zoneLst)
415  {
416  SubList<label> zoneMap(faceMap, zone.size(), zone.start());
418  (
419  UIndirectList<Face>(surf.surfFaces(), zoneMap),
420  surf.points()
421  );
422 
423  writeZone(os, patch, zone.name(), zoneIndex);
424 
425  ++zoneIndex;
426  }
427 }
428 
429 
430 // ************************************************************************* //
nZones
label nZones
Definition: interpolatedFaces.H:24
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:78
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeFast.C:94
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::ISstream::getLine
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline into a string function.
Definition: ISstreamI.H:78
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::MeshedSurfaceProxy::useFaceMap
bool useFaceMap() const
Use faceMap?
Definition: MeshedSurfaceProxy.H:186
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:97
Foam::DynamicList< point >
AC3DsurfaceFormat.H
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
Foam::fileFormats::AC3DsurfaceFormat::AC3DsurfaceFormat
AC3DsurfaceFormat(const fileName &filename)
Construct from file name.
Definition: AC3DsurfaceFormat.C:38
validate
thermo validate(args.executable(), "h")
Foam::zone
Base class for mesh zones.
Definition: zone.H:63
Foam::writeZone
static void writeZone(Ostream &os, const PrimitivePatch< Face, FaceList, PointField, PointType > &patch, const word &name, const label zoneI)
Definition: AC3DsurfaceFormat.C:271
Foam::MeshedSurfaceProxy::points
const pointField & points() const
Return const access to the points.
Definition: MeshedSurfaceProxy.H:160
StringStream.H
Input/output from string buffers.
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:73
Foam::writeHeader
static void writeHeader(Ostream &os, const word &fieldName)
Definition: rawSurfaceWriterImpl.C:49
Foam::MeshedSurfaceProxy
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
Definition: MeshedSurface.H:78
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:90
Foam::fileFormats::AC3DsurfaceFormat::read
virtual bool read(const fileName &filename)
Read from file.
Definition: AC3DsurfaceFormat.C:50
Foam::MeshedSurfaceProxy::faceMap
const labelUList & faceMap() const
Const access to the faceMap, zero-sized when unused.
Definition: MeshedSurfaceProxy.H:180
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::fileFormats::AC3DsurfaceFormat::write
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, const dictionary &options=dictionary::null)
Write surface mesh components by proxy.
Definition: AC3DsurfaceFormat.C:309
Foam::faceTraits
Traits class for faces.
Definition: faceTraits.H:50
Foam::label
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:62
Foam::Field< vector >
PrimitivePatch.H
Foam::UnsortedMeshedSurface
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
Definition: MeshedSurface.H:79
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::blockMeshTools::read
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:33
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::IStringStream
Input from string buffer, using a ISstream.
Definition: StringStream.H:112
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::zone::name
const word & name() const
Return name.
Definition: zone.H:158
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::foamVersion::version
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:99
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:84
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:372
f
labelList f(nPoints)
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::Vector< scalar >
Foam::List< word >
Foam::surfZone
A surface zone on a MeshedSurface.
Definition: surfZone.H:65
Foam::UList< label >
Foam::line
A line primitive.
Definition: line.H:59
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:109
Foam::MeshedSurfaceProxy::surfFaces
const UList< Face > & surfFaces() const
Return const access to the faces.
Definition: MeshedSurfaceProxy.H:166
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:216
args
Foam::argList args(argc, argv)
faceTraits.H
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:294
Foam::UnsortedMeshedSurface::sortedZones
surfZoneList sortedZones(labelList &faceMap) const
Sort faces according to zoneIds.
Definition: UnsortedMeshedSurface.C:462
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:90
Foam::MeshedSurfaceProxy::surfZones
const UList< surfZone > & surfZones() const
Const access to the surface zones.
Definition: MeshedSurfaceProxy.H:174