GTSsurfaceFormat.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 -------------------------------------------------------------------------------
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 "GTSsurfaceFormat.H"
30 #include "surfaceFormatsCore.H"
31 #include "clock.H"
32 #include "Fstream.H"
33 #include "StringStream.H"
34 #include "faceTraits.H"
35 
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 
38 template<class Face>
40 (
41  const UList<Face>& faceLst
42 )
43 {
44  if constexpr (faceTraits<Face>::isTri())
45  {
46  return true;
47  }
48  else
49  {
50  label nNonTris = 0;
51 
52  for (const auto& f : faceLst)
53  {
54  if (f.size() != 3)
55  {
56  ++nNonTris;
57  }
58  }
59 
60  if (nNonTris)
61  {
63  << "Surface has " << nNonTris << '/' << faceLst.size()
64  << " non-triangulated faces - not writing!" << endl;
65  }
66 
67  return nNonTris == 0;
68  }
69 }
70 
71 
72 
73 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
74 
75 template<class Face>
77 (
78  const fileName& filename
79 )
80 {
81  read(filename);
82 }
83 
84 
85 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
86 
87 template<class Face>
89 (
90  const fileName& filename
91 )
92 {
93  // Clear everything
94  this->clear();
95 
96  IFstream is(filename);
97  if (!is.good())
98  {
100  << "Cannot read file " << filename << nl
101  << exit(FatalError);
102  }
103 
104  // Read header
105  string line = this->getLineNoComment(is);
106 
107  label nPoints, nEdges, nElems;
108  {
109  IStringStream lineStream(line);
110  lineStream
111  >> nPoints
112  >> nEdges
113  >> nElems;
114  }
115 
116 
117  // Write directly into the lists
118  auto& pointLst = this->storedPoints();
119  auto& faceLst = this->storedFaces();
120  auto& zoneIds = this->storedZoneIds();
121 
122  pointLst.resize(nPoints);
123  faceLst.resize(nElems);
124  zoneIds.resize(nElems);
125 
126  // Read points
127  forAll(pointLst, pointi)
128  {
129  scalar x, y, z;
130  line = this->getLineNoComment(is);
131  {
132  IStringStream lineStream(line);
133  lineStream
134  >> x >> y >> z;
135  }
136 
137  pointLst[pointi] = point(x, y, z);
138  }
139 
140  // Read edges (OpenFOAM indexing)
141  edgeList edges(nEdges);
142  forAll(edges, edgei)
143  {
144  label beg, end;
145  line = this->getLineNoComment(is);
146  {
147  IStringStream lineStream(line);
148  lineStream
149  >> beg >> end;
150  }
151  edges[edgei] = edge(beg - 1, end - 1);
152  }
153 
154 
155  // Read triangles. Convert references to edges into pointlabels
156  label maxZone = 0;
157  forAll(faceLst, facei)
158  {
159  label e0Label, e1Label, e2Label;
160  label zoneI = 0;
161 
162  line = this->getLineNoComment(is);
163  {
164  IStringStream lineStream(line);
165  lineStream
166  >> e0Label >> e1Label >> e2Label;
167 
168  // Optional zone number: read first, then check stream state
169  if (lineStream)
170  {
171  label num;
172  lineStream >> num;
173  if (!lineStream.bad())
174  {
175  zoneI = num;
176  if (maxZone < zoneI)
177  {
178  maxZone = zoneI;
179  }
180  }
181  }
182  }
183 
184  // Determine ordering of edges e0, e1
185  // common: common vertex, shared by e0 and e1
186  // e0Far: vertex on e0 which is not common
187  // e1Far: vertex on e1 which is not common
188  const edge& e0 = edges[e0Label - 1];
189  const edge& e1 = edges[e1Label - 1];
190  const edge& e2 = edges[e2Label - 1];
191 
192  label common01 = e0.commonVertex(e1);
193  if (common01 == -1)
194  {
196  << "Edges 0 and 1 of triangle " << facei
197  << " do not share a point.\n"
198  << " edge0:" << e0 << nl
199  << " edge1:" << e1
200  << exit(FatalError);
201  }
202 
203  const label e0Far = e0.otherVertex(common01);
204  const label e1Far = e1.otherVertex(common01);
205 
206  const label common12 = e1.commonVertex(e2);
207  if (common12 == -1)
208  {
210  << "Edges 1 and 2 of triangle " << facei
211  << " do not share a point.\n"
212  << " edge1:" << e1 << nl
213  << " edge2:" << e2
214  << exit(FatalError);
215  }
216  const label e2Far = e2.otherVertex(common12);
217 
218  // Does edge2 sit between edge1 and 0?
219  if (common12 != e1Far || e2Far != e0Far)
220  {
222  << "Edges of triangle " << facei
223  << " reference more than three points.\n"
224  << " edge0:" << e0 << nl
225  << " edge1:" << e1 << nl
226  << " edge2:" << e2 << nl
227  << exit(FatalError);
228  }
229 
230  faceLst[facei] = Face{e0Far, common01, e1Far};
231  zoneIds[facei] = zoneI;
232  }
233 
234 
235  List<surfZoneIdentifier> newZones(maxZone+1);
236  forAll(newZones, zonei)
237  {
238  newZones[zonei] = surfZoneIdentifier
239  (
240  surfZoneIdentifier::defaultName(zonei),
241  zonei
242  );
243  }
244 
245  this->storedZoneToc().transfer(newZones);
246  this->addZonesToFaces(); // for labelledTri
248  return true;
249 }
250 
251 
252 template<class Face>
254 (
255  const fileName& filename,
256  const MeshedSurface<Face>& surf,
257  IOstreamOption streamOpt,
258  const dictionary&
259 )
260 {
261  // ASCII only, allow output compression
262  streamOpt.format(IOstreamOption::ASCII);
263 
264  const UList<point>& pointLst = surf.points();
265  const UList<Face>& faceLst = surf.surfFaces();
266 
267  const surfZoneList zones
268  (
269  surf.surfZones().size()
270  ? surf.surfZones()
271  : surfaceFormatsCore::oneZone(faceLst)
272  );
273 
274  checkIfTriangulated(faceLst);
275 
276  OFstream os(filename, streamOpt);
277  if (!os.good())
278  {
280  << "Cannot write file " << filename << nl
281  << exit(FatalError);
282  }
283 
284 
285  // Write header, print zone names as comment
286  os << "# GTS file" << nl
287  << "# Zones:" << nl;
288 
289  forAll(zones, zonei)
290  {
291  os << "# " << zonei << " "
292  << zones[zonei].name() << nl;
293  }
294  os << "#" << nl;
295 
296  os << "# nPoints nEdges nTriangles" << nl
297  << pointLst.size() << ' ' << surf.nEdges() << ' '
298  << surf.size() << nl;
299 
300 
301  // Write vertex coords
302  for (const point& pt : pointLst)
303  {
304  os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
305  }
306 
307 
308  // Write edges.
309  // Note: edges are in local point labels so convert
310  const edgeList& es = surf.edges();
311  const labelList& meshPts = surf.meshPoints();
312 
313  for (const edge& e : es)
314  {
315  os << meshPts[e.start()] + 1 << ' '
316  << meshPts[e.end()] + 1 << nl;
317  }
318 
319  // Write faces in terms of edges
320  const labelListList& faceEs = surf.faceEdges();
321 
322  label faceIndex = 0;
323  label zoneIndex = 0;
324 
325  for (const surfZone& zone : zones)
326  {
327  for (label nLocal = zone.size(); nLocal--; ++faceIndex)
328  {
329  const label facei = faceIndex;
330 
331  const labelList& fEdges = faceEs[facei];
332 
333  os << fEdges[0] + 1 << ' '
334  << fEdges[1] + 1 << ' '
335  << fEdges[2] + 1 << ' '
336  << zoneIndex << nl;
337  }
338 
339  ++zoneIndex;
340  }
341 }
342 
343 
344 template<class Face>
346 (
347  const fileName& filename,
348  const UnsortedMeshedSurface<Face>& surf,
349  IOstreamOption streamOpt,
350  const dictionary&
351 )
352 {
353  // ASCII only, allow output compression
354  streamOpt.format(IOstreamOption::ASCII);
355 
356  const UList<point>& pointLst = surf.points();
357  const UList<Face>& faceLst = surf.surfFaces();
358  const UList<label>& zoneIds = surf.zoneIds();
359  const UList<surfZoneIdentifier>& zoneToc = surf.zoneToc();
360 
361  checkIfTriangulated(faceLst);
362 
363  OFstream os(filename, streamOpt);
364  if (!os.good())
365  {
367  << "Cannot write file " << filename << nl
368  << exit(FatalError);
369  }
370 
371 
372  // Write header, print zone names as comment
373  os << "# GTS file" << nl
374  << "# Zones:" << nl;
375 
376  forAll(zoneToc, zonei)
377  {
378  os << "# " << zonei << " "
379  << zoneToc[zonei].name() << nl;
380  }
381  os << "#" << nl;
382 
383  os << "# nPoints nEdges nTriangles" << nl
384  << pointLst.size() << ' ' << surf.nEdges() << ' '
385  << surf.size() << nl;
386 
387 
388  // Write vertex coords
389  for (const point& pt : pointLst)
390  {
391  os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
392  }
393 
394 
395  // Write edges.
396  // Note: edges are in local point labels so convert
397  const edgeList& es = surf.edges();
398  const labelList& meshPts = surf.meshPoints();
399 
400  for (const edge& e : es)
401  {
402  os << meshPts[e.start()] + 1 << ' '
403  << meshPts[e.end()] + 1 << nl;
404  }
405 
406  // Write faces in terms of edges.
407  const labelListList& faceEs = surf.faceEdges();
408 
409  forAll(faceLst, facei)
410  {
411  const labelList& fEdges = faceEs[facei];
412 
413  os << fEdges[0] + 1 << ' '
414  << fEdges[1] + 1 << ' '
415  << fEdges[2] + 1 << ' '
416  << zoneIds[facei] << nl;
417  }
418 }
419 
420 
421 // ************************************************************************* //
A surface geometry mesh, in which the surface zone information is conveyed by the &#39;zoneId&#39; associated...
Definition: MeshedSurface.H:76
GTSsurfaceFormat(const fileName &filename)
Construct from file name.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
virtual bool read(const fileName &filename) override
Read from file.
A line primitive.
Definition: line.H:52
A class for handling file names.
Definition: fileName.H:72
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:130
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:652
Input/output from string buffers.
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition: OSstream.H:134
A surface geometry mesh with zone information, not to be confused with the similarly named surfaceMes...
Output to file stream as an OSstream, normally using std::ofstream for the actual output...
Definition: OFstream.H:71
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:518
A simple container for options an IOstream can normally have.
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
const labelList & meshPoints() const
Return labelList of mesh points in patch.
label size() const
The surface size is the number of faces.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:400
scalar y
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
label nPoints
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const Field< point_type > & points() const noexcept
Return reference to global points.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
label nEdges() const
Number of edges in patch.
const List< Face > & surfFaces() const
Return const access to the faces.
virtual const labelList & zoneIds() const
Return const access to the zone ids.
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
const wordList edge
Standard (finite-area) edge field types (scalar, vector, tensor, etc)
Input from file stream as an ISstream, normally using std::ifstream for the actual input...
Definition: IFstream.H:51
labelList f(nPoints)
const List< surfZoneIdentifier > & zoneToc() const
Return const access to the zone table-of-contents.
label size() const
The surface size is the number of faces.
vector point
Point is a vector.
Definition: point.H:37
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Definition: StringStream.H:47
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
surface1 clear()
const char * end
Definition: SVGTools.H:223
const labelListList & faceEdges() const
Return face-edge addressing.
List< label > labelList
A List of labels.
Definition: List.H:61
const surfZoneList & surfZones() const
Const access to the surface zones.
static void write(const fileName &filename, const MeshedSurface< Face > &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &=dictionary::null)
Write MeshedSurface.
streamFormat format() const noexcept
Get the current stream format.