Loading...
Searching...
No Matches
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-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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"
31#include "primitivePatch.H"
32#include "faceTraits.H"
33
34// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35
36template<class Face>
38(
39 const fileName& filename
40)
41{
42 read(filename);
43}
44
45
46// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
47
48template<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;
101 List<word> names(nZones);
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;
259
260
261namespace Foam
262{
263// file-scope writing of a patch of faces
264template<class Patch>
265static 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 }
297
298 os << "kids 0" << endl;
299}
300}
301
302template<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(IOstreamOption::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 {
338 PrimitivePatch<UList<Face>, const pointField&> patch
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
356 PrimitivePatch<FaceListType, const pointField&> patch
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
368 PrimitivePatch<FaceListType, const pointField&> patch
369 (
370 FaceListType(faceLst, zone.range()),
371 pointLst
372 );
373
374 writeZone(os, patch, zone.name(), zoneIndex);
375 }
377 ++zoneIndex;
378 }
379}
380
381
382template<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(IOstreamOption::ASCII);
393
394 OFstream os(filename, streamOpt);
395 if (!os.good())
396 {
398 << "Cannot write file " << filename << nl
399 << exit(FatalError);
400 }
401
402 labelList faceMap;
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
428 PrimitivePatch<FaceListType, const pointField&> patch
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// ************************************************************************* //
Input/output from string buffers.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void append(const T &val)
Copy append an element to the end of this list.
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
A simple container for options an IOstream can normally have.
streamFormat format() const noexcept
Get the current stream format.
@ ASCII
"ascii" (normal default)
bool good() const noexcept
True if next operation might succeed.
Definition IOstream.H:281
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition ISstreamI.H:69
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
const UList< surfZone > & surfZones() const noexcept
Const access to the surface zones.
const UList< Face > & surfFaces() const noexcept
Return const access to the faces.
const labelUList & faceMap() const noexcept
Const access to the faceMap, zero-sized when unused.
const pointField & points() const noexcept
Return const access to the points.
bool useFaceMap() const noexcept
Can/should use faceMap?
pointField & storedPoints()
Non-const access to global points.
virtual void addZones(const UList< surfZone > &, const bool cullEmpty=false)
Add surface zones.
const List< Face > & surfFaces() const
Return const access to the faces.
List< Face > & storedFaces()
Non-const access to the faces.
virtual bool stitchFaces(const scalar tol=SMALL, const bool verbose=false)
friend class UnsortedMeshedSurface
bool addZonesToFaces()
Propagate zone information on face regions.
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Definition OFstream.H:75
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
PrimitivePatch(const ::Foam::List< Face > &faces, const pointField &points)
const Field< point_type > & points() const noexcept
Return reference to global points.
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
A List with indirect addressing. Like IndirectList but does not store addressing.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
surfZoneList sortedZones(labelList &faceMap) const
Sort faces according to zoneIds.
const Cmpt & x() const noexcept
Access to the vector x component.
Definition Vector.H:135
const Cmpt & z() const noexcept
Access to the vector z component.
Definition Vector.H:145
const Cmpt & y() const noexcept
Access to the vector y component.
Definition Vector.H:140
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
static bool isTri()
Face-type only handles triangles. Not true in general.
Definition faceTraits.H:51
static Type parse(const string &str)
Read a type from string.
static string cueToOrDie(IFstream &, const string &cmd, const string &errorMsg=string::null)
Like cueTo(), but FatalError if not found.
static void writeHeader(Ostream &os, const UList< surfZone > &zones)
Write header with materials for each zone.
static bool cueTo(IFstream &, const string &cmd, string &args)
Read up to a line starting with cmd. Sets args to rest of line.
static bool readCmd(IFstream &is, string &cmd, string &args)
Read cmd, args from IFstream.
AC3DsurfaceFormat(const fileName &filename)
Construct from file name.
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &=dictionary::null)
Write surface mesh components by proxy.
virtual bool read(const fileName &filename) override
Read from file.
static List< surfZone > oneZone(const Container &container, const word &name="zone0")
Return a surfZone list with a single entry, the size of which corresponds to that of the container.
A class for handling file names.
Definition fileName.H:75
A line primitive.
Definition line.H:180
A class for handling character strings derived from std::string.
Definition string.H:76
static word defaultName(const label n=-1)
Default zone name: "zone" or "zoneN".
A surface zone on a MeshedSurface.
Definition surfZone.H:55
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
A class for handling words, derived from Foam::string.
Definition word.H:66
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition word.C:39
const word & name() const noexcept
The zone name.
Base class for mesh zones.
Definition zone.H:63
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
auto & name
auto & names
surface1 clear()
#define WarningInFunction
Report a warning using Foam::Warning.
const std::string patch
OpenFOAM patch number as a std::string.
Namespace for OpenFOAM.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
List< label > labelList
A List of labels.
Definition List.H:62
List< surfZone > surfZoneList
List of surfZone.
static void writeZone(Ostream &os, const Patch &patch, const word &name, const label zoneI)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
vector point
Point is a vector.
Definition point.H:37
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
vectorField pointField
pointField is a vectorField.
Vector< scalar > vector
Definition vector.H:57
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
labelList f(nPoints)
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299