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-2020 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  // Clear everything
55  this->clear();
56 
57  IFstream is(filename);
58  if (!is.good())
59  {
61  << "Cannot read file " << filename << nl
62  << exit(FatalError);
63  }
64 
65  string line, cmd, args;
66 
67  is.getLine(line);
68 
69  // Verify version
70  {
71  const string version = line.substr(4);
72 
73  if (version != "b")
74  {
76  << "When reading AC3D file " << filename
77  << " read header " << line << " with version "
78  << version << endl
79  << "Only tested reading with version 'b'."
80  << " This might give problems" << endl;
81  }
82  }
83 
84 
85  if (!cueTo(is, "OBJECT", args) || args != "world")
86  {
88  << "Cannot find 'OBJECT world' in file " << filename << nl
89  << exit(FatalError);
90  }
91 
92  // Number of kids is the number of zones
93  args = cueToOrDie(is, "kids");
94  const label nZones = parse<int>(args);
95 
96  // Start of vertices for object/zones
97  label vertexOffset = 0;
98 
99  DynamicList<point> dynPoints;
100  DynamicList<Face> dynFaces;
102  List<label> sizes(nZones, Zero);
103 
104  for (label zoneI = 0; zoneI < nZones; ++zoneI)
105  {
106  names[zoneI] = surfZone::defaultName(zoneI);
107 
108  args = cueToOrDie(is, "OBJECT", "while reading " + names[zoneI]);
109 
110  // number of vertices for this zone
111  label nZonePoints = 0;
112  vector location(Zero);
113  // tensor rotation(I);
114 
115  // Read all info for current zone
116  while (is.good())
117  {
118  // Read line and get first word. If end of file break since
119  // zone should always end with 'kids' command ?not sure.
120  if (!readCmd(is, cmd, args))
121  {
123  << "Did not read up to 'kids 0' while reading zone "
124  << zoneI << " from file " << filename << nl
125  << exit(FatalError);
126  }
127 
128  if (cmd == "name")
129  {
130  // name %s
131  const string str = parse<string>(args);
132  names[zoneI] = word::validate(str);
133  }
134  else if (cmd == "rot")
135  {
136  // rot %f %f %f %f %f %f %f %f %f
137 
138  // IStringStream lineStream(args);
139  //
140  // lineStream
141  // >> rotation.xx() >> rotation.xy() >> rotation.xz()
142  // >> rotation.yx() >> rotation.yy() >> rotation.yz()
143  // >> rotation.zx() >> rotation.zy() >> rotation.zz();
144 
146  << "rot (rotation tensor) command not implemented"
147  << "Line:" << cmd << ' ' << args << endl
148  << "while reading zone " << zoneI << endl;
149  }
150  else if (cmd == "loc")
151  {
152  // loc %f %f %f
153  IStringStream lineStream(args);
154 
155  lineStream
156  >> location.x()
157  >> location.y()
158  >> location.z();
159  }
160  else if (cmd == "numvert")
161  {
162  // numvert %d
163  nZonePoints = parse<int>(args);
164 
165  for (label vertI = 0; vertI < nZonePoints; ++vertI)
166  {
167  is.getLine(line);
168  IStringStream lineStream(line);
169 
170  point pt;
171  lineStream
172  >> pt.x() >> pt.y() >> pt.z();
173 
174  // Offset with current translation vector
175  dynPoints.append(location + pt);
176  }
177  }
178  else if (cmd == "numsurf")
179  {
180  const label nFaces = parse<int>(args);
181 
182  for (label facei = 0; facei < nFaces; ++facei)
183  {
184  const string errorMsg =
185  string(" while reading face ")
186  + Foam::name(facei) + " on zone "
187  + Foam::name(zoneI)
188  + " from file " + filename;
189 
190  cueToOrDie(is, "SURF", errorMsg);
191  cueToOrDie(is, "mat", errorMsg);
192  args = cueToOrDie(is, "refs", errorMsg);
193 
194  const label nVert = parse<int>(args);
195 
196  List<label> verts(nVert);
197  forAll(verts, vertI)
198  {
199  is.getLine(line);
200  verts[vertI] = vertexOffset + parse<int>(line);
201  }
202 
203  const labelUList& f = static_cast<const labelUList&>(verts);
204 
205  if (faceTraits<Face>::isTri() && f.size() > 3)
206  {
207  // simple face triangulation about f[0]
208  // points may be incomplete
209  for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
210  {
211  label fp2 = f.fcIndex(fp1);
212 
213  dynFaces.append(Face{f[0], f[fp1], f[fp2]});
214  sizes[zoneI]++;
215  }
216  }
217  else
218  {
219  dynFaces.append(Face(f));
220  sizes[zoneI]++;
221  }
222  }
223 
224  // Done the current zone.
225  // Increment the offset vertices are stored at
226  vertexOffset += nZonePoints;
227  }
228  else if (cmd == "kids")
229  {
230  // 'kids' denotes the end of the current zone.
231  const label nKids = parse<int>(args);
232 
233  if (nKids != 0)
234  {
236  << "Can only read objects without kids."
237  << " Encountered " << nKids << " kids when"
238  << " reading zone " << zoneI
239  << exit(FatalError);
240  }
241 
242  // Done reading current zone
243  break;
244  }
245  }
246  }
247 
248  // transfer to normal lists
249  this->storedPoints().transfer(dynPoints);
250  this->storedFaces().transfer(dynFaces);
251 
252  // Add zones (retaining empty ones)
253  this->addZones(sizes, names);
254  this->addZonesToFaces(); // for labelledTri
255  this->stitchFaces(SMALL);
256 
257  return true;
258 }
259 
260 
261 namespace Foam
262 {
263 // file-scope writing of a patch of faces
264 template<class Patch>
265 static void writeZone
266 (
267  Ostream& os,
268  const Patch& patch,
269  const word& name,
270  const label zoneI
271 )
272 {
273  // An isolated surface region (patch).
274  os << "OBJECT poly" << nl
275  << "name \"" << name << "\"" << nl;
276 
277  os << "numvert " << patch.nPoints() << nl;
278 
279  for (const point& pt : patch.localPoints())
280  {
281  os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
282  }
283 
284  os << "numsurf " << patch.size() << nl;
285 
286  for (const auto& f : patch.localFaces())
287  {
288  os << "SURF 0x20" << nl // polygon
289  << "mat " << zoneI << nl
290  << "refs " << f.size() << nl;
291 
292  for (const label verti : f)
293  {
294  os << verti << " 0 0" << nl;
295  }
296  }
297 
298  os << "kids 0" << endl;
299 }
300 }
301 
302 template<class Face>
304 (
305  const fileName& filename,
306  const MeshedSurfaceProxy<Face>& surf,
307  IOstreamOption streamOpt,
308  const dictionary&
309 )
310 {
311  // ASCII only, allow output compression
312  streamOpt.format(IOstream::ASCII);
313 
314  const pointField& pointLst = surf.points();
315  const UList<Face>& faceLst = surf.surfFaces();
316 
317  const surfZoneList zones =
318  (
319  surf.surfZones().size()
320  ? surf.surfZones()
321  : surfaceFormatsCore::oneZone(faceLst)
322  );
323 
324  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
325 
326  OFstream os(filename, streamOpt);
327  if (!os.good())
328  {
330  << "Cannot write file " << filename << nl
331  << exit(FatalError);
332  }
333 
334  writeHeader(os, zones);
335 
336  if (zones.size() == 1)
337  {
339  (
340  faceLst, pointLst
341  );
342 
343  writeZone(os, patch, zones[0].name(), 0);
344  return;
345  }
346 
347  label zoneIndex = 0;
348  for (const surfZone& zone : zones)
349  {
350  if (useFaceMap)
351  {
352  typedef UIndirectList<Face> FaceListType;
353 
354  SubList<label> zoneMap(surf.faceMap(), zone.range());
355 
357  (
358  FaceListType(faceLst, zoneMap),
359  pointLst
360  );
361 
362  writeZone(os, patch, zone.name(), zoneIndex);
363  }
364  else
365  {
366  typedef SubList<Face> FaceListType;
367 
369  (
370  FaceListType(faceLst, zone.range()),
371  pointLst
372  );
373 
374  writeZone(os, patch, zone.name(), zoneIndex);
375  }
376 
377  ++zoneIndex;
378  }
379 }
380 
381 
382 template<class Face>
384 (
385  const fileName& filename,
386  const UnsortedMeshedSurface<Face>& surf,
387  IOstreamOption streamOpt,
388  const dictionary&
389 )
390 {
391  // ASCII only, allow output compression
392  streamOpt.format(IOstream::ASCII);
393 
394  OFstream os(filename, streamOpt);
395  if (!os.good())
396  {
398  << "Cannot write file " << filename << nl
399  << exit(FatalError);
400  }
401 
403  List<surfZone> zoneLst = surf.sortedZones(faceMap);
404 
405  if (zoneLst.size() <= 1)
406  {
407  const surfZoneList zones =
408  (
409  zoneLst.size()
410  ? zoneLst
411  : surfaceFormatsCore::oneZone(surf.surfFaces())
412  );
413 
414  writeHeader(os, zones);
415  writeZone(os, surf, zones[0].name(), 0);
416  return;
417  }
418 
419  writeHeader(os, zoneLst);
420 
421  label zoneIndex = 0;
422  for (const surfZone& zone : zoneLst)
423  {
424  typedef UIndirectList<Face> FaceListType;
425 
426  SubList<label> zoneMap(faceMap, zone.range());
427 
429  (
430  FaceListType(surf.surfFaces(), zoneMap),
431  surf.points()
432  );
433 
434  writeZone(os, patch, zone.name(), zoneIndex);
435 
436  ++zoneIndex;
437  }
438 }
439 
440 
441 // ************************************************************************* //
nZones
label nZones
Definition: interpolatedFaces.H:24
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::ISstream::getLine
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition: ISstreamI.H:76
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::fileFormats::AC3DsurfaceFormat::write
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &=dictionary::null)
Write surface mesh components by proxy.
Definition: AC3DsurfaceFormat.C:304
Foam::MeshedSurfaceProxy::useFaceMap
bool useFaceMap() const
Can/should use faceMap?
Definition: MeshedSurfaceProxy.H:203
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:53
Foam::DynamicList< point >
AC3DsurfaceFormat.H
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:54
Foam::fileFormats::AC3DsurfaceFormat::AC3DsurfaceFormat
AC3DsurfaceFormat(const fileName &filename)
Construct from file name.
Definition: AC3DsurfaceFormat.C:38
Foam::zone
Base class for mesh zones.
Definition: zone.H:63
Foam::IOstreamOption::format
streamFormat format() const noexcept
Get the current stream format.
Definition: IOstreamOption.H:286
Foam::MeshedSurfaceProxy::points
const pointField & points() const
Return const access to the points.
Definition: MeshedSurfaceProxy.H:171
StringStream.H
Input/output from string buffers.
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:76
Foam::writeHeader
static void writeHeader(Ostream &os, const word &fieldName)
Definition: rawSurfaceWriterImpl.C:66
Foam::MeshedSurfaceProxy
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
Definition: MeshedSurface.H:82
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
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:191
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::IOstream::good
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:233
Foam::writeZone
static void writeZone(Ostream &os, const Patch &patch, const word &name, const label zoneI)
Definition: AC3DsurfaceFormat.C:266
Foam::blockMeshTools::read
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:57
Foam::faceTraits
Traits class for faces.
Definition: faceTraits.H:50
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:83
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
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:123
os
OBJstream os(runTime.globalPath()/outputName)
Foam::IStringStream
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Definition: StringStream.H:108
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
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:53
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::zoneIdentifier::name
const word & name() const noexcept
The zone name.
Definition: zoneIdentifier.H:123
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:56
Foam::UList< label >
Foam::line
A line primitive.
Definition: line.H:53
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:60
Foam::MeshedSurfaceProxy::surfFaces
const UList< Face > & surfFaces() const
Return const access to the faces.
Definition: MeshedSurfaceProxy.H:177
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::stringOps::validate
StringType validate(const std::string &str, const UnaryPredicate &accept, const bool invert=false)
Return a copy of the input string with validated characters.
Definition: stringOpsTemplates.C:71
args
Foam::argList args(argc, argv)
faceTraits.H
Foam::PtrListOps::names
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::UnsortedMeshedSurface::sortedZones
surfZoneList sortedZones(labelList &faceMap) const
Sort faces according to zoneIds.
Definition: UnsortedMeshedSurface.C:510
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:79
Foam::MeshedSurfaceProxy::surfZones
const UList< surfZone > & surfZones() const
Const access to the surface zones.
Definition: MeshedSurfaceProxy.H:185