Loading...
Searching...
No Matches
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-2023 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 "STLsurfaceFormat.H"
30#include "triangle.H"
31#include "ListOps.H"
32
33// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34
35template<class Face>
36inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
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::unitNormal(pts[f[0]], pts[f[1]], pts[f[2]]);
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
56 STLtriangle::write
57 (
58 os,
59 norm,
60 p0,
61 pts[f[fp1]],
62 pts[f[fp2]]
63 );
64 }
65}
66
67
68template<class Face>
69inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
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::unitNormal(pts[f[0]], pts[f[1]], pts[f[2]]);
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
104template<class Face>
106(
107 const fileName& filename
108)
109{
110 read(filename);
111}
112
113
114// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
115
116template<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.is_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
202template<class Face>
204(
205 const fileName& filename,
206 const MeshedSurfaceProxy<Face>& surf,
208)
209{
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);
245 os << "endsolid " << zone.name() << endl;
246 }
247}
248
249
250template<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 }
296 ++zoneIndex;
297 }
298}
299
300
301template<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 {
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,
338 MeshedSurfaceProxy<Face>
339 (
340 pointLst,
341 faceLst,
342 zoneLst,
343 faceMap
344 ),
345 comp
346 );
347 }
348}
349
350
351template<class Face>
353(
354 const fileName& filename,
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
388template<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() == IOstreamOption::BINARY
400 // Detected "stlb" extension?
401 || STLCore::isBinaryName(filename, STLCore::UNKNOWN)
402 )
403 {
404 writeBinary(filename, surf);
405 }
406 else
408 writeAscii(filename, surf, streamOpt.compression());
409 }
410}
411
412
413template<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
428 writeAscii(filename, surf, comp);
429 }
430}
431
432
433template<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() == IOstreamOption::BINARY
445 // Detected "stlb" extension?
446 || STLCore::isBinaryName(filename, STLCore::UNKNOWN)
447 )
448 {
449 writeBinary(filename, surf);
450 }
451 else
453 writeAscii(filename, surf, streamOpt.compression());
454 }
455}
456
457
458template<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// ************************************************************************* //
Various functions to operate on Lists.
A simple container for options an IOstream can normally have.
compressionType compression() const noexcept
Get the stream compression.
streamFormat format() const noexcept
Get the current stream format.
@ ASCII
"ascii" (normal default)
compressionType
Compression treatment (UNCOMPRESSED | COMPRESSED).
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void setSize(label n)
Alias for resize().
Definition List.H:536
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
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.
label nTriangles() const
Count number of triangles.
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.
virtual label nTriangles() const
Count number of triangles.
List< Face > & storedFaces()
Non-const access to the faces.
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
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 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.
virtual const labelList & zoneIds() const
Return const access to the zone ids.
const List< surfZoneIdentifier > & zoneToc() const
Return const access to the zone table-of-contents.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
static bool isBinaryName(const fileName &filename, const STLFormat format)
Detect 'stlb' extension as binary when format = UNKNOWN.
Definition STLCore.C:90
static void writeBinaryHeader(ostream &os, uint32_t nTris)
Write STL binary file and number of triangles to stream.
Definition STLCore.C:249
STLFormat
Enumeration for the format of data in the stream.
Definition STLCore.H:60
@ UNKNOWN
Detect based on (input) content or (output) extension.
Definition STLCore.H:63
Internal class used by the STLsurfaceFormat and triSurface.
Definition STLReader.H:66
List< word > & names() noexcept
The list of solid names in the order of their first appearance.
Definition STLReader.H:219
label mergePointsMap(labelList &pointMap) const
Calculate merge points mapping, return old to new pointMap.
Definition STLReader.C:249
List< STLpoint > & points() noexcept
Return full access to the points.
Definition STLReader.H:209
bool is_sorted() const noexcept
File read was already sorted?
Definition STLReader.H:204
List< label > & sizes() noexcept
The list of solid sizes in the order of their first appearance.
Definition STLReader.H:224
List< label > & zoneIds() noexcept
Return full access to the zoneIds.
Definition STLReader.H:214
static void writeBinary(const fileName &filename, const MeshedSurfaceProxy< Face > &surf)
Write surface mesh components by proxy (as BINARY).
STLsurfaceFormat(const fileName &filename)
Construct from file name.
static void writeAscii(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption::compressionType comp=IOstreamOption::UNCOMPRESSED)
Write surface mesh components by proxy (as ASCII).
virtual bool read(const fileName &filename) override
Read from file.
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, const STLFormat format, IOstreamOption::compressionType comp=IOstreamOption::UNCOMPRESSED)
Write surface mesh components (by proxy) in STL format as ASCII or BINARY or dependent on the extensi...
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 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...
const word & name() const noexcept
The zone name.
Base class for mesh zones.
Definition zone.H:63
const volScalarField & p0
Definition EEqn.H:36
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
auto & names
surface1 clear()
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.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
vector point
Point is a vector.
Definition point.H:37
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
word format(conversionProperties.get< word >("format"))
labelList f(nPoints)
const pointField & pts
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299