Loading...
Searching...
No Matches
surfaceAdd.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
27Application
28 surfaceAdd
29
30Group
31 grpSurfaceUtilities
32
33Description
34 Add two surfaces. Does geometric merge on points.
35 Does not check for overlapping/intersecting triangles.
36
37 Keeps patches separate by renumbering.
38
39\*---------------------------------------------------------------------------*/
40
41#include "argList.H"
42#include "fileName.H"
43#include "triSurface.H"
44#include "Fstream.H"
45#include "triFace.H"
46#include "triFaceList.H"
47
48using namespace Foam;
49
50// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51
52
53int main(int argc, char *argv[])
54{
56 (
57 "Add two surfaces via a geometric merge on points."
58 " Does not check for overlapping/intersecting triangles."
59 );
60
62 argList::addArgument("surface1", "The input surface file 1");
63 argList::addArgument("surface2", "The input surface file 2");
64 argList::addArgument("output", "The output surface file");
65
67 (
68 "points",
69 "file",
70 "Provide additional points"
71 );
73 (
74 "mergeRegions",
75 "Combine regions from both surfaces"
76 );
78 (
79 "scale",
80 "factor",
81 "Geometry scaling factor on input surfaces"
82 );
84
85 argList args(argc, argv);
86
87 const auto inFileName1 = args.get<fileName>(1);
88 const auto inFileName2 = args.get<fileName>(2);
89 const auto outFileName = args.get<fileName>(3);
90
91 const int optVerbose = args.verbose();
92 const bool addPoint = args.found("points");
93 const bool mergeRegions = args.found("mergeRegions");
94
95 const scalar scaleFactor = args.getOrDefault<scalar>("scale", -1);
96
97 if (addPoint)
98 {
99 Info<< "Reading a surface and adding points from a file"
100 << "; merging the points and writing the surface to another file"
101 << nl << endl;
102
103 Info<< "Surface : " << inFileName1<< nl
104 << "Points : " << args.get<fileName>("points") << nl
105 << "Writing : " << outFileName << nl << endl;
106 }
107 else
108 {
109 Info<< "Reading two surfaces"
110 << "; merging points and writing the surface to another file"
111 << nl << endl;
112
113 if (mergeRegions)
114 {
115 Info<< "Regions from the two files will get merged" << nl
116 << "Do not use this option if you want to keep the regions"
117 << " separate" << nl << endl;
118 }
119 else
120 {
121 Info<< "Regions from the two files will not get merged" << nl
122 << "Regions from " << inFileName2 << " will get offset so"
123 << " as not to overlap with the regions in " << inFileName1
124 << nl << endl;
125 }
126
127
128 Info<< "Surface1 : " << inFileName1<< nl
129 << "Surface2 : " << inFileName2<< nl
130 << "Writing : " << outFileName << nl << endl;
131 }
132
133 if (scaleFactor > 0)
134 {
135 Info<< "Scaling : " << scaleFactor << nl;
136 }
137
138 const triSurface surface1(inFileName1, scaleFactor);
139 Info<< "Surface1:" << endl;
140 surface1.writeStats(Info);
141 Info<< endl;
142
143 const pointField& points1 = surface1.points();
144
145 // Final surface
146 triSurface combinedSurf;
147
148 if (addPoint)
149 {
150 IFstream pointsFile(args.get<fileName>("points"));
151 const pointField extraPoints(pointsFile);
152
153 Info<< "Additional Points:" << extraPoints.size() << endl;
154
155 vectorField pointsAll(points1);
156 label pointi = pointsAll.size();
157 pointsAll.setSize(pointsAll.size() + extraPoints.size());
158
159 for (const auto& pt : extraPoints)
160 {
161 pointsAll[pointi++] = pt;
162 }
163
164 combinedSurf = triSurface(surface1, surface1.patches(), pointsAll);
165 }
166 else
167 {
168 const triSurface surface2(inFileName2, scaleFactor);
169 Info<< "Surface2:" << endl;
170 surface2.writeStats(Info);
171 Info<< endl;
172
173
174 // Make new storage
175 List<labelledTri> facesAll(surface1.size() + surface2.size());
176
177 const pointField& points2 = surface2.points();
178
179 vectorField pointsAll(points1.size() + points2.size());
180
181
182 label pointi = 0;
183 // Copy points1 into pointsAll
184 for (const auto& pt : points1)
185 {
186 pointsAll[pointi++] = pt;
187 }
188 // Add surface2 points
189 for (const auto& pt : points2)
190 {
191 pointsAll[pointi++] = pt;
192 }
193
194
195 label trianglei = 0;
196
197 // Determine map for both regions
198 label nNewPatches = 0;
199 labelList patch1Map(surface1.patches().size());
200 labelList patch2Map(surface2.patches().size());
201
202 if (mergeRegions)
203 {
204 HashTable<label> nameToPatch;
205
206 forAll(surface1.patches(), i)
207 {
208 const word& name = surface1.patches()[i].name();
209
210 // Lookup or insert
211 const label combinedi = nameToPatch(name, nameToPatch.size());
212
213 patch1Map[i] = combinedi;
214 }
215
216 // Determine map for surface2 regions
217
218 forAll(surface2.patches(), i)
219 {
220 const word& name = surface2.patches()[i].name();
221
222 // Lookup or insert
223 const label combinedi = nameToPatch(name, nameToPatch.size());
224
225 patch2Map[i] = combinedi;
226 }
227
228 nNewPatches = nameToPatch.size();
229 }
230 else
231 {
232 Info<< "Surface " << inFileName1
233 << " has " << surface1.patches().size()
234 << " regions"
235 << nl
236 << "All region numbers in " << inFileName2 << " will be offset"
237 << " by this amount" << nl << endl;
238
239 patch1Map = identity(surface1.patches().size());
240 patch2Map = identity(surface2.patches().size(), patch1Map.size());
241
242 nNewPatches = surface1.patches().size()+surface2.patches().size();
243 }
244
245
246 // Copy triangles1 into trianglesAll
247 for (const labelledTri& tri : surface1)
248 {
249 labelledTri& destTri = facesAll[trianglei++];
250
251 destTri.triFace::operator=(tri);
252 destTri.region() = patch1Map[tri.region()];
253 }
254
255 // Add (renumbered) surface2 triangles
256 for (const labelledTri& tri : surface2)
257 {
258 labelledTri& destTri = facesAll[trianglei++];
259 destTri[0] = tri[0] + points1.size();
260 destTri[1] = tri[1] + points1.size();
261 destTri[2] = tri[2] + points1.size();
262 destTri.region() = patch2Map[tri.region()];
263 }
264
265
266 geometricSurfacePatchList newPatches(nNewPatches);
267 forAll(surface1.patches(), patchi)
268 {
269 newPatches[patch1Map[patchi]] = surface1.patches()[patchi];
270 }
271 forAll(surface2.patches(), patchi)
272 {
273 newPatches[patch2Map[patchi]] = surface2.patches()[patchi];
274 }
275
276 Info<< "New patches:" << nl;
277 forAll(newPatches, patchi)
278 {
279 Info<< " " << patchi << '\t' << newPatches[patchi].name() << nl;
280 }
281 Info<< endl;
282
283
284 // Construct new surface mesh
285 combinedSurf = triSurface(facesAll, newPatches, pointsAll);
286 }
287
288 // Merge all common points and do some checks
289 combinedSurf.cleanup(optVerbose);
290
291 Info<< "Merged surface:" << endl;
292
293 combinedSurf.writeStats(Info);
294
295 Info<< endl;
296
297 Info<< "Writing : " << outFileName << endl;
298
299 // If merging regions also sort
300 combinedSurf.write(outFileName, mergeRegions);
301
302 Info<< "End\n" << endl;
303
304 return 0;
305}
306
307
308// ************************************************************************* //
static constexpr label size() noexcept
Return the number of elements in the FixedList.
Definition FixedList.H:619
A HashTable similar to std::unordered_map.
Definition HashTable.H:124
label size() const noexcept
The number of elements in table.
Definition HashTable.H:358
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
Extract command arguments and options from the supplied argc and argv parameters.
Definition argList.H:119
static void addVerboseOption(const string &usage="", bool advanced=false)
Enable a 'verbose' bool option, with usage information.
Definition argList.C:535
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition argList.C:366
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition argList.C:389
static void noParallel()
Remove the parallel options.
Definition argList.C:599
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition argList.C:400
static void addNote(const string &note)
Add extra notes for the usage information.
Definition argList.C:477
A class for handling file names.
Definition fileName.H:75
A triFace with additional (region) index.
Definition labelledTri.H:56
label region() const noexcept
Return the region index.
Triangulated surface description with patch information.
Definition triSurface.H:74
void cleanup(const bool verbose)
Remove non-valid triangles.
Definition triSurface.C:649
void write(Ostream &os) const
Write to Ostream in simple OpenFOAM format.
void writeStats(Ostream &os) const
Write some statistics.
A class for handling words, derived from Foam::string.
Definition word.H:66
auto & name
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Field< vector > vectorField
Specialisation of Field<T> for vector.
List< geometricSurfacePatch > geometricSurfacePatchList
List of geometricSurfacePatch.
vectorField pointField
pointField is a vectorField.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299