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-2021 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  // Clear everything
123  this->clear();
124 
125  // Read in the values
126  STLReader reader(filename);
127 
128  // Get the map for stitched surface points, with merge tolerance depending
129  // on the input format
130  labelList pointMap;
131  const label nUniquePoints = reader.mergePointsMap(pointMap);
132 
133  const auto& readpts = reader.points();
134 
135  // Assign points
136  pointField& pointLst = this->storedPoints();
137  pointLst.setSize(nUniquePoints);
138  forAll(readpts, pointi)
139  {
140  pointLst[pointMap[pointi]] = readpts[pointi];
141  }
142 
143  // Retrieve the original zone information
144  List<word> names(std::move(reader.names()));
145  List<label> sizes(std::move(reader.sizes()));
146  List<label> zoneIds(std::move(reader.zoneIds()));
147 
148  // Generate the (sorted) faces
149  List<Face> faceLst(zoneIds.size());
150 
151  if (reader.sorted())
152  {
153  // Already sorted - generate directly
154  forAll(faceLst, facei)
155  {
156  const label startPt = 3*facei;
157  faceLst[facei] = Face
158  {
159  pointMap[startPt],
160  pointMap[startPt+1],
161  pointMap[startPt+2]
162  };
163  }
164  }
165  else
166  {
167  // Determine the sorted order:
168  // use sortedOrder directly (the intermediate list is discarded anyhow)
169  labelList faceMap(sortedOrder(zoneIds));
170 
171  // Generate sorted faces
172  forAll(faceMap, facei)
173  {
174  const label startPt = 3*faceMap[facei];
175  faceLst[facei] = Face
176  {
177  pointMap[startPt],
178  pointMap[startPt+1],
179  pointMap[startPt+2]
180  };
181  }
182  }
183  zoneIds.clear();
184 
185  // Transfer
186  this->storedFaces().transfer(faceLst);
187 
188  if (names.size())
189  {
190  this->addZones(sizes, names);
191  }
192  else
193  {
194  this->addZones(sizes);
195  }
196  this->addZonesToFaces(); // for labelledTri
197 
198  return true;
199 }
200 
201 
202 template<class Face>
204 (
205  const fileName& filename,
206  const MeshedSurfaceProxy<Face>& surf,
208 )
209 {
210  OFstream os(filename, IOstreamOption(IOstream::ASCII, comp));
211  if (!os.good())
212  {
214  << "Cannot write file " << filename << nl
215  << exit(FatalError);
216  }
217 
218  const UList<point>& pointLst = surf.points();
219  const UList<Face>& faceLst = surf.surfFaces();
220  const UList<label>& faceMap = surf.faceMap();
221 
222  const surfZoneList zones =
223  (
224  surf.surfZones().empty()
225  ? surfaceFormatsCore::oneZone(faceLst)
226  : surf.surfZones()
227  );
228 
229  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
230 
231  label faceIndex = 0;
232  for (const surfZone& zone : zones)
233  {
234  os << "solid " << zone.name() << nl;
235 
236  for (label nLocal = zone.size(); nLocal--; ++faceIndex)
237  {
238  const label facei =
239  (useFaceMap ? faceMap[faceIndex] : faceIndex);
240 
241  const Face& f = faceLst[facei];
242 
243  writeShell(os, pointLst, f);
244  }
245  os << "endsolid " << zone.name() << endl;
246  }
247 }
248 
249 
250 template<class Face>
252 (
253  const fileName& filename,
254  const MeshedSurfaceProxy<Face>& surf
255 )
256 {
257  std::ofstream os(filename, std::ios::binary);
258  if (!os.good())
259  {
261  << "Cannot write file " << filename << nl
262  << exit(FatalError);
263  }
264 
265  const UList<point>& pointLst = surf.points();
266  const UList<Face>& faceLst = surf.surfFaces();
267  const UList<label>& faceMap = surf.faceMap();
268 
269  const surfZoneList zones =
270  (
271  surf.surfZones().size() > 1
272  ? surf.surfZones()
273  : surfaceFormatsCore::oneZone(faceLst)
274  );
275 
276  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
277 
278  // Write the STL header
279  unsigned int nTris = surf.nTriangles();
280  STLCore::writeBinaryHeader(os, nTris);
281 
282  label faceIndex = 0;
283  label zoneIndex = 0;
284  for (const surfZone& zone : zones)
285  {
286  for (label nLocal = zone.size(); nLocal--; ++faceIndex)
287  {
288  const label facei =
289  (useFaceMap ? faceMap[faceIndex] : faceIndex);
290 
291  const Face& f = faceLst[facei];
292 
293  writeShell(os, pointLst, f, zoneIndex);
294  }
295 
296  ++zoneIndex;
297  }
298 }
299 
300 
301 template<class Face>
303 (
304  const fileName& filename,
305  const UnsortedMeshedSurface<Face>& surf,
307 )
308 {
309  const pointField& pointLst = surf.points();
310  const UList<Face>& faceLst = surf.surfFaces();
311 
312  // A single zone - we can skip sorting
313  if (surf.zoneToc().size() == 1)
314  {
315  OFstream os(filename, IOstreamOption(IOstream::ASCII, comp));
316  if (!os.good())
317  {
319  << "Cannot write file " << filename << nl
320  << exit(FatalError);
321  }
322 
323  os << "solid " << surf.zoneToc()[0].name() << nl;
324  for (const Face& f : faceLst)
325  {
326  writeShell(os, pointLst, f);
327  }
328  os << "endsolid " << surf.zoneToc()[0].name() << nl;
329  }
330  else
331  {
333  List<surfZone> zoneLst = surf.sortedZones(faceMap);
334 
335  writeAscii
336  (
337  filename,
339  (
340  pointLst,
341  faceLst,
342  zoneLst,
343  faceMap
344  ),
345  comp
346  );
347  }
348 }
349 
350 
351 template<class Face>
353 (
354  const fileName& filename,
355  const UnsortedMeshedSurface<Face>& surf
356 )
357 {
358  std::ofstream os(filename, std::ios::binary);
359  if (!os.good())
360  {
362  << "Cannot write file " << filename << nl
363  << exit(FatalError);
364  }
365 
366  const pointField& pointLst = surf.points();
367  const UList<Face>& faceLst = surf.surfFaces();
368  const UList<label>& zoneIds = surf.zoneIds();
369 
370  // Write the STL header
371  unsigned int nTris = surf.nTriangles();
372  STLCore::writeBinaryHeader(os, nTris);
373 
374  // Always write unsorted
375  forAll(faceLst, facei)
376  {
377  writeShell
378  (
379  os,
380  pointLst,
381  faceLst[facei],
382  zoneIds[facei]
383  );
384  }
385 }
386 
387 
388 template<class Face>
390 (
391  const fileName& filename,
392  const MeshedSurfaceProxy<Face>& surf,
393  IOstreamOption streamOpt,
394  const dictionary& options
395 )
396 {
397  if
398  (
399  streamOpt.format() == IOstream::BINARY
400  // Detected "stlb" extension?
401  || STLCore::isBinaryName(filename, STLCore::UNKNOWN)
402  )
403  {
404  writeBinary(filename, surf);
405  }
406  else
407  {
408  writeAscii(filename, surf, streamOpt.compression());
409  }
410 }
411 
412 
413 template<class Face>
415 (
416  const fileName& filename,
417  const MeshedSurfaceProxy<Face>& surf,
418  const STLFormat format,
420 )
421 {
422  if (STLCore::isBinaryName(filename, format))
423  {
424  writeBinary(filename, surf);
425  }
426  else
427  {
428  writeAscii(filename, surf, comp);
429  }
430 }
431 
432 
433 template<class Face>
435 (
436  const fileName& filename,
437  const UnsortedMeshedSurface<Face>& surf,
438  IOstreamOption streamOpt,
439  const dictionary& options
440 )
441 {
442  if
443  (
444  streamOpt.format() == IOstream::BINARY
445  // Detected "stlb" extension?
446  || STLCore::isBinaryName(filename, STLCore::UNKNOWN)
447  )
448  {
449  writeBinary(filename, surf);
450  }
451  else
452  {
453  writeAscii(filename, surf, streamOpt.compression());
454  }
455 }
456 
457 
458 template<class Face>
460 (
461  const fileName& filename,
462  const UnsortedMeshedSurface<Face>& surf,
463  const STLFormat format,
465 )
466 {
467  if (STLCore::isBinaryName(filename, format))
468  {
469  writeBinary(filename, surf);
470  }
471  else
472  {
473  writeAscii(filename, surf, comp);
474  }
475 }
476 
477 
478 // ************************************************************************* //
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::MeshedSurfaceProxy::useFaceMap
bool useFaceMap() const
Can/should use faceMap?
Definition: MeshedSurfaceProxy.H:203
Foam::MeshedSurfaceProxy::nTriangles
label nTriangles() const
Count number of triangles.
Definition: MeshedSurfaceProxy.C:256
Foam::fileFormats::STLsurfaceFormat::writeAscii
static void writeAscii(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption::compressionType comp=IOstreamOption::UNCOMPRESSED)
Write surface mesh components by proxy (as ASCII)
Definition: STLsurfaceFormat.C:204
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::IOstreamOption::format
streamFormat format() const noexcept
Get the current stream format.
Definition: IOstreamOption.H:286
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:252
Foam::MeshedSurfaceProxy::points
const pointField & points() const
Return const access to the points.
Definition: MeshedSurfaceProxy.H:171
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::fileFormats::STLsurfaceFormat
Provide a means of reading/writing STL files (ASCII and BINARY).
Definition: STLsurfaceFormat.H:66
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:82
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::blockMeshTools::read
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:57
Foam::UnsortedMeshedSurface::zoneIds
virtual const labelList & zoneIds() const
Return const access to the zone ids.
Definition: UnsortedMeshedSurface.H:336
format
word format(conversionProperties.get< word >("format"))
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:83
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
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:256
Foam::UnsortedMeshedSurface::zoneToc
const List< surfZoneIdentifier > & zoneToc() const
Return const access to the zone table-of-contents.
Definition: UnsortedMeshedSurface.H:342
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::fileFormats::STLsurfaceFormat::read
virtual bool read(const fileName &filename)
Read from file.
Definition: STLsurfaceFormat.C:118
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:53
Foam::fileFormats::STLsurfaceFormat::write
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, const STLFormat format, IOstreamOption::compressionType comp=IOstreamOption::UNCOMPRESSED)
Write surface mesh components by proxy.
Definition: STLsurfaceFormat.C:415
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: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)
STLsurfaceFormat.H
Foam::List< label >
Foam::surfZone
A surface zone on a MeshedSurface.
Definition: surfZone.H:56
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::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:116
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:36
Foam::IOstreamOption::compressionType
compressionType
Compression treatment (UNCOMPRESSED | COMPRESSED)
Definition: IOstreamOption.H:77
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:177
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::IOstreamOption::compression
compressionType compression() const noexcept
Get the stream compression.
Definition: IOstreamOption.H:312
Foam::PtrListOps::names
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Foam::UnsortedMeshedSurface::sortedZones
surfZoneList sortedZones(labelList &faceMap) const
Sort faces according to zoneIds.
Definition: UnsortedMeshedSurface.C:510
Foam::triPointRef
triangle< point, const point & > triPointRef
A triangle using referred points.
Definition: triangle.H:71
Foam::MeshedSurfaceProxy::surfZones
const UList< surfZone > & surfZones() const
Const access to the surface zones.
Definition: MeshedSurfaceProxy.H:185