STLsurfaceFormat.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-2019 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 "STLsurfaceFormat.H"
30 #include "triPointRef.H"
31 #include "ListOps.H"
32 
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 
35 template<class Face>
37 (
38  Ostream& os,
39  const UList<point>& pts,
40  const Face& f
41 )
42 {
43  // Calculate the normal ourselves, for flexibility and speed
44  const vector norm =
45  triPointRef(pts[f[0]], pts[f[1]], pts[f[2]]).unitNormal();
46 
47  // simple triangulation about f[0].
48  // better triangulation should have been done before
49  const point& p0 = pts[f[0]];
50 
51  for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
52  {
53  const label fp2 = f.fcIndex(fp1);
54 
55  // Write ASCII
57  (
58  os,
59  norm,
60  p0,
61  pts[f[fp1]],
62  pts[f[fp2]]
63  );
64  }
65 }
66 
67 
68 template<class Face>
70 (
71  ostream& os,
72  const UList<point>& pts,
73  const Face& f,
74  const label zoneI
75 )
76 {
77  // Calculate the normal ourselves, for flexibility and speed
78  const vector norm =
79  triPointRef(pts[f[0]], pts[f[1]], pts[f[2]]).unitNormal();
80 
81  // simple triangulation about f[0].
82  // better triangulation should have been done before
83  const point& p0 = pts[f[0]];
84 
85  for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
86  {
87  const label fp2 = f.fcIndex(fp1);
88 
89  // Write BINARY
90  STLtriangle
91  (
92  norm,
93  p0,
94  pts[f[fp1]],
95  pts[f[fp2]],
96  zoneI
97  ).write(os);
98  }
99 }
100 
101 
102 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
103 
104 template<class Face>
106 (
107  const fileName& filename
108 )
109 {
110  read(filename);
111 }
112 
113 
114 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
115 
116 template<class Face>
118 (
119  const fileName& filename
120 )
121 {
122  this->clear();
123 
124  // Read in the values
125  STLReader reader(filename);
126 
127  // Get the map for stitched surface points, with merge tolerance depending
128  // on the input format
129  labelList pointMap;
130  const label nUniquePoints = reader.mergePointsMap(pointMap);
131 
132  const auto& readpts = reader.points();
133 
134  // Assign points
135  pointField& pointLst = this->storedPoints();
136  pointLst.setSize(nUniquePoints);
137  forAll(readpts, pointi)
138  {
139  pointLst[pointMap[pointi]] = readpts[pointi];
140  }
141 
142  // Retrieve the original zone information
143  List<word> names(std::move(reader.names()));
144  List<label> sizes(std::move(reader.sizes()));
145  List<label> zoneIds(std::move(reader.zoneIds()));
146 
147  // Generate the (sorted) faces
148  List<Face> faceLst(zoneIds.size());
149 
150  if (reader.sorted())
151  {
152  // Already sorted - generate directly
153  forAll(faceLst, facei)
154  {
155  const label startPt = 3*facei;
156  faceLst[facei] = Face
157  {
158  pointMap[startPt],
159  pointMap[startPt+1],
160  pointMap[startPt+2]
161  };
162  }
163  }
164  else
165  {
166  // Determine the sorted order:
167  // use sortedOrder directly (the intermediate list is discarded anyhow)
168  labelList faceMap(sortedOrder(zoneIds));
169 
170  // Generate sorted faces
171  forAll(faceMap, facei)
172  {
173  const label startPt = 3*faceMap[facei];
174  faceLst[facei] = Face
175  {
176  pointMap[startPt],
177  pointMap[startPt+1],
178  pointMap[startPt+2]
179  };
180  }
181  }
182  zoneIds.clear();
183 
184  // Transfer:
185  this->storedFaces().transfer(faceLst);
186 
187  if (names.size())
188  {
189  this->addZones(sizes, names);
190  }
191  else
192  {
193  this->addZones(sizes);
194  }
195  this->addZonesToFaces(); // for labelledTri
196 
197  return true;
198 }
199 
200 
201 template<class Face>
203 (
204  const fileName& filename,
205  const MeshedSurfaceProxy<Face>& surf
206 )
207 {
208  OFstream os(filename);
209  if (!os.good())
210  {
212  << "Cannot open file for writing " << filename
213  << exit(FatalError);
214  }
215 
216  const UList<point>& pointLst = surf.points();
217  const UList<Face>& faceLst = surf.surfFaces();
218  const UList<label>& faceMap = surf.faceMap();
219 
220  const surfZoneList zones =
221  (
222  surf.surfZones().empty()
223  ? surfaceFormatsCore::oneZone(faceLst)
224  : surf.surfZones()
225  );
226 
227  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
228 
229  label faceIndex = 0;
230  for (const surfZone& zone : zones)
231  {
232  const label nLocalFaces = zone.size();
233 
234  os << "solid " << zone.name() << nl;
235 
236  if (useFaceMap)
237  {
238  for (label i=0; i<nLocalFaces; ++i)
239  {
240  writeShell(os, pointLst, faceLst[faceMap[faceIndex++]]);
241  }
242  }
243  else
244  {
245  for (label i=0; i<nLocalFaces; ++i)
246  {
247  writeShell(os, pointLst, faceLst[faceIndex++]);
248  }
249  }
250  os << "endsolid " << zone.name() << endl;
251  }
252 }
253 
254 
255 template<class Face>
257 (
258  const fileName& filename,
259  const MeshedSurfaceProxy<Face>& surf
260 )
261 {
262  std::ofstream os(filename, std::ios::binary);
263  if (!os.good())
264  {
266  << "Cannot open file for writing " << filename
267  << exit(FatalError);
268  }
269 
270  const UList<point>& pointLst = surf.points();
271  const UList<Face>& faceLst = surf.surfFaces();
272  const UList<label>& faceMap = surf.faceMap();
273 
274  const surfZoneList zones =
275  (
276  surf.surfZones().size() > 1
277  ? surf.surfZones()
278  : surfaceFormatsCore::oneZone(faceLst)
279  );
280 
281  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
282 
283  // Write the STL header
284  unsigned int nTris = surf.nTriangles();
285  STLCore::writeBinaryHeader(os, nTris);
286 
287  label faceIndex = 0;
288  label zoneIndex = 0;
289  for (const surfZone& zone : zones)
290  {
291  const label nLocalFaces = zone.size();
292 
293  if (useFaceMap)
294  {
295  for (label i=0; i<nLocalFaces; ++i)
296  {
297  const Face& f = faceLst[faceMap[faceIndex++]];
298  writeShell(os, pointLst, f, zoneIndex);
299  }
300  }
301  else
302  {
303  for (label i=0; i<nLocalFaces; ++i)
304  {
305  const Face& f = faceLst[faceIndex++];
306  writeShell(os, pointLst, f, zoneIndex);
307  }
308  }
309 
310  ++zoneIndex;
311  }
312 }
313 
314 
315 template<class Face>
317 (
318  const fileName& filename,
319  const UnsortedMeshedSurface<Face>& surf
320 )
321 {
322  OFstream os(filename);
323  if (!os.good())
324  {
326  << "Cannot open file for writing " << filename
327  << exit(FatalError);
328  }
329 
330  const pointField& pointLst = surf.points();
331  const UList<Face>& faceLst = surf.surfFaces();
332 
333  // A single zone - we can skip sorting
334  if (surf.zoneToc().size() == 1)
335  {
336  os << "solid " << surf.zoneToc()[0].name() << nl;
337  for (const Face& f : faceLst)
338  {
339  writeShell(os, pointLst, f);
340  }
341  os << "endsolid " << surf.zoneToc()[0].name() << nl;
342  }
343  else
344  {
346  List<surfZone> zoneLst = surf.sortedZones(faceMap);
347 
348  writeAscii
349  (
350  filename,
352  (
353  pointLst,
354  faceLst,
355  zoneLst,
356  faceMap
357  )
358  );
359  }
360 }
361 
362 
363 template<class Face>
365 (
366  const fileName& filename,
367  const UnsortedMeshedSurface<Face>& surf
368 )
369 {
370  std::ofstream os(filename, std::ios::binary);
371  if (!os.good())
372  {
374  << "Cannot open file for writing " << filename
375  << exit(FatalError);
376  }
377 
378  const pointField& pointLst = surf.points();
379  const UList<Face>& faceLst = surf.surfFaces();
380  const UList<label>& zoneIds = surf.zoneIds();
381 
382  // Write the STL header
383  unsigned int nTris = surf.nTriangles();
384  STLCore::writeBinaryHeader(os, nTris);
385 
386  // Always write unsorted
387  forAll(faceLst, facei)
388  {
389  writeShell
390  (
391  os,
392  pointLst,
393  faceLst[facei],
394  zoneIds[facei]
395  );
396  }
397 }
398 
399 
400 template<class Face>
402 (
403  const fileName& filename,
404  const MeshedSurfaceProxy<Face>& surf,
405  const dictionary& options
406 )
407 {
408  // Detect "stlb" extension
409  bool useBinary = STLCore::isBinaryName(filename, STLCore::UNKNOWN);
410 
411  if (useBinary)
412  {
413  writeBinary(filename, surf);
414  }
415  else
416  {
417  writeAscii(filename, surf);
418  }
419 }
420 
421 
422 template<class Face>
424 (
425  const fileName& filename,
426  const MeshedSurfaceProxy<Face>& surf,
427  const STLFormat format
428 )
429 {
430  if (STLCore::isBinaryName(filename, format))
431  {
432  writeBinary(filename, surf);
433  }
434  else
435  {
436  writeAscii(filename, surf);
437  }
438 }
439 
440 
441 template<class Face>
443 (
444  const fileName& filename,
445  const UnsortedMeshedSurface<Face>& surf,
446  const dictionary& options
447 )
448 {
449  // Detect "stlb" extension
450  bool useBinary = STLCore::isBinaryName(filename, STLCore::UNKNOWN);
451 
452  if (useBinary)
453  {
454  writeBinary(filename, surf);
455  }
456  else
457  {
458  writeAscii(filename, surf);
459  }
460 }
461 
462 
463 template<class Face>
465 (
466  const fileName& filename,
467  const UnsortedMeshedSurface<Face>& surf,
468  const STLFormat format
469 )
470 {
471  if (STLCore::isBinaryName(filename, format))
472  {
473  writeBinary(filename, surf);
474  }
475  else
476  {
477  writeAscii(filename, surf);
478  }
479 }
480 
481 
482 // ************************************************************************* //
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeFast.C:94
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::MeshedSurfaceProxy::nTriangles
label nTriangles() const
Count number of triangles.
Definition: MeshedSurfaceProxy.C:248
Foam::fileFormats::STLsurfaceFormat::STLsurfaceFormat
STLsurfaceFormat(const fileName &filename)
Construct from file name.
Definition: STLsurfaceFormat.C:106
Foam::zone
Base class for mesh zones.
Definition: zone.H:63
Foam::fileFormats::STLsurfaceFormat::writeBinary
static void writeBinary(const fileName &filename, const MeshedSurfaceProxy< Face > &surf)
Write surface mesh components by proxy (as BINARY)
Definition: STLsurfaceFormat.C:257
Foam::MeshedSurfaceProxy::points
const pointField & points() const
Return const access to the points.
Definition: MeshedSurfaceProxy.H:160
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::fileFormats::STLsurfaceFormat
Provide a means of reading/writing STL files (ASCII and BINARY).
Definition: STLsurfaceFormat.H:62
triPointRef.H
Foam::fileFormats::STLReader::sizes
List< label > & sizes()
The list of solid sizes in the order of their first appearance.
Definition: STLReader.H:184
Foam::MeshedSurfaceProxy
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
Definition: MeshedSurface.H:78
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::UnsortedMeshedSurface::zoneIds
virtual const labelList & zoneIds() const
Return const access to the zone ids.
Definition: UnsortedMeshedSurface.H:300
format
word format(conversionProperties.get< word >("format"))
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 >
Foam::fileFormats::STLReader::zoneIds
List< label > & zoneIds()
Return full access to the zoneIds.
Definition: STLReader.H:172
Foam::UnsortedMeshedSurface
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
Definition: MeshedSurface.H:79
Foam::fileFormats::STLsurfaceFormat::write
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, const STLFormat format)
Write surface mesh components by proxy.
Definition: STLsurfaceFormat.C:424
Foam::fileFormats::STLReader::sorted
bool sorted() const
File read was already sorted?
Definition: STLReader.H:160
Foam::fileFormats::STLReader::names
List< word > & names()
The list of solid names in the order of their first appearance.
Definition: STLReader.H:178
Foam::fileFormats::STLReader::points
List< STLpoint > & points()
Return full access to the points.
Definition: STLReader.H:166
Foam::fileFormats::STLReader::mergePointsMap
label mergePointsMap(labelList &pointMap) const
Calculate merge points mapping, return old to new pointMap.
Definition: STLReader.C:255
Foam::UnsortedMeshedSurface::zoneToc
const List< surfZoneIdentifier > & zoneToc() const
Return const access to the zone table-of-contents.
Definition: UnsortedMeshedSurface.H:306
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::fileFormats::STLsurfaceFormat::read
virtual bool read(const fileName &filename)
Read from file.
Definition: STLsurfaceFormat.C:118
Foam::zone::name
const word & name() const
Return name.
Definition: zone.H:158
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:99
Foam::fileFormats::STLCore::STLFormat
STLFormat
Enumeration for the format of data in the stream.
Definition: STLCore.H:61
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)
STLsurfaceFormat.H
Foam::List< label >
Foam::surfZone
A surface zone on a MeshedSurface.
Definition: surfZone.H:65
Foam::UList
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:103
Foam::fileFormats::STLsurfaceFormat::writeAscii
static void writeAscii(const fileName &filename, const MeshedSurfaceProxy< Face > &surf)
Write surface mesh components by proxy (as ASCII)
Definition: STLsurfaceFormat.C:203
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:115
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:35
ListOps.H
Various functions to operate on Lists.
Foam::sortedOrder
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
Foam::fileFormats::STLReader
Internal class used by the STLsurfaceFormat and triSurface.
Definition: STLReader.H:67
Foam::MeshedSurfaceProxy::surfFaces
const UList< Face > & surfFaces() const
Return const access to the faces.
Definition: MeshedSurfaceProxy.H:166
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:216
Foam::UnsortedMeshedSurface::sortedZones
surfZoneList sortedZones(labelList &faceMap) const
Sort faces according to zoneIds.
Definition: UnsortedMeshedSurface.C:462
Foam::triPointRef
triangle< point, const point & > triPointRef
Definition: triangle.H:78
Foam::MeshedSurfaceProxy::surfZones
const UList< surfZone > & surfZones() const
Const access to the surface zones.
Definition: MeshedSurfaceProxy.H:174