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-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 Application
28  surfaceAdd
29 
30 Group
31  grpSurfaceUtilities
32 
33 Description
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 
48 using namespace Foam;
49 
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 
52 
53 int 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  );
83 
84  argList args(argc, argv);
85 
86  const auto inFileName1 = args.get<fileName>(1);
87  const auto inFileName2 = args.get<fileName>(2);
88  const auto outFileName = args.get<fileName>(3);
89 
90  const bool addPoint = args.found("points");
91  const bool mergeRegions = args.found("mergeRegions");
92 
93  const scalar scaleFactor = args.getOrDefault<scalar>("scale", -1);
94 
95  if (addPoint)
96  {
97  Info<< "Reading a surface and adding points from a file"
98  << "; merging the points and writing the surface to another file"
99  << nl << endl;
100 
101  Info<< "Surface : " << inFileName1<< nl
102  << "Points : " << args.get<fileName>("points") << nl
103  << "Writing : " << outFileName << nl << endl;
104  }
105  else
106  {
107  Info<< "Reading two surfaces"
108  << "; merging points and writing the surface to another file"
109  << nl << endl;
110 
111  if (mergeRegions)
112  {
113  Info<< "Regions from the two files will get merged" << nl
114  << "Do not use this option if you want to keep the regions"
115  << " separate" << nl << endl;
116  }
117  else
118  {
119  Info<< "Regions from the two files will not get merged" << nl
120  << "Regions from " << inFileName2 << " will get offset so"
121  << " as not to overlap with the regions in " << inFileName1
122  << nl << endl;
123  }
124 
125 
126  Info<< "Surface1 : " << inFileName1<< nl
127  << "Surface2 : " << inFileName2<< nl
128  << "Writing : " << outFileName << nl << endl;
129  }
130 
131  if (scaleFactor > 0)
132  {
133  Info<< "Scaling : " << scaleFactor << nl;
134  }
135 
136  const triSurface surface1(inFileName1, scaleFactor);
137  Info<< "Surface1:" << endl;
138  surface1.writeStats(Info);
139  Info<< endl;
140 
141  const pointField& points1 = surface1.points();
142 
143  // Final surface
144  triSurface combinedSurf;
145 
146  if (addPoint)
147  {
148  IFstream pointsFile(args.get<fileName>("points"));
149  const pointField extraPoints(pointsFile);
150 
151  Info<< "Additional Points:" << extraPoints.size() << endl;
152 
153  vectorField pointsAll(points1);
154  label pointi = pointsAll.size();
155  pointsAll.setSize(pointsAll.size() + extraPoints.size());
156 
157  for (const auto& pt : extraPoints)
158  {
159  pointsAll[pointi++] = pt;
160  }
161 
162  combinedSurf = triSurface(surface1, surface1.patches(), pointsAll);
163  }
164  else
165  {
166  const triSurface surface2(inFileName2, scaleFactor);
167  Info<< "Surface2:" << endl;
168  surface2.writeStats(Info);
169  Info<< endl;
170 
171 
172  // Make new storage
173  List<labelledTri> facesAll(surface1.size() + surface2.size());
174 
175  const pointField& points2 = surface2.points();
176 
177  vectorField pointsAll(points1.size() + points2.size());
178 
179 
180  label pointi = 0;
181  // Copy points1 into pointsAll
182  for (const auto& pt : points1)
183  {
184  pointsAll[pointi++] = pt;
185  }
186  // Add surface2 points
187  for (const auto& pt : points2)
188  {
189  pointsAll[pointi++] = pt;
190  }
191 
192 
193  label trianglei = 0;
194 
195  // Determine map for both regions
196  label nNewPatches = 0;
197  labelList patch1Map(surface1.patches().size());
198  labelList patch2Map(surface2.patches().size());
199 
200  if (mergeRegions)
201  {
202  HashTable<label> nameToPatch;
203 
204  forAll(surface1.patches(), i)
205  {
206  const word& name = surface1.patches()[i].name();
207 
208  // Lookup or insert
209  const label combinedi = nameToPatch(name, nameToPatch.size());
210 
211  patch1Map[i] = combinedi;
212  }
213 
214  // Determine map for surface2 regions
215 
216  forAll(surface2.patches(), i)
217  {
218  const word& name = surface2.patches()[i].name();
219 
220  // Lookup or insert
221  const label combinedi = nameToPatch(name, nameToPatch.size());
222 
223  patch2Map[i] = combinedi;
224  }
225 
226  nNewPatches = nameToPatch.size();
227  }
228  else
229  {
230  Info<< "Surface " << inFileName1
231  << " has " << surface1.patches().size()
232  << " regions"
233  << nl
234  << "All region numbers in " << inFileName2 << " will be offset"
235  << " by this amount" << nl << endl;
236 
237  patch1Map = identity(surface1.patches().size());
238  patch2Map = identity(surface2.patches().size(), patch1Map.size());
239 
240  nNewPatches = surface1.patches().size()+surface2.patches().size();
241  }
242 
243 
244  // Copy triangles1 into trianglesAll
245  for (const labelledTri& tri : surface1)
246  {
247  labelledTri& destTri = facesAll[trianglei++];
248 
249  destTri.triFace::operator=(tri);
250  destTri.region() = patch1Map[tri.region()];
251  }
252 
253  // Add (renumbered) surface2 triangles
254  for (const labelledTri& tri : surface2)
255  {
256  labelledTri& destTri = facesAll[trianglei++];
257  destTri[0] = tri[0] + points1.size();
258  destTri[1] = tri[1] + points1.size();
259  destTri[2] = tri[2] + points1.size();
260  destTri.region() = patch2Map[tri.region()];
261  }
262 
263 
264  geometricSurfacePatchList newPatches(nNewPatches);
265  forAll(surface1.patches(), patchi)
266  {
267  newPatches[patch1Map[patchi]] = surface1.patches()[patchi];
268  }
269  forAll(surface2.patches(), patchi)
270  {
271  newPatches[patch2Map[patchi]] = surface2.patches()[patchi];
272  }
273 
274  Info<< "New patches:" << nl;
275  forAll(newPatches, patchi)
276  {
277  Info<< " " << patchi << '\t' << newPatches[patchi].name() << nl;
278  }
279  Info<< endl;
280 
281 
282  // Construct new surface mesh
283  combinedSurf = triSurface(facesAll, newPatches, pointsAll);
284  }
285 
286  // Merge all common points and do some checks
287  combinedSurf.cleanup(true);
288 
289  Info<< "Merged surface:" << endl;
290 
291  combinedSurf.writeStats(Info);
292 
293  Info<< endl;
294 
295  Info<< "Writing : " << outFileName << endl;
296 
297  // If merging regions also sort
298  combinedSurf.write(outFileName, mergeRegions);
299 
300  Info<< "End\n" << endl;
301 
302  return 0;
303 }
304 
305 
306 // ************************************************************************* //
Foam::triSurface::writeStats
void writeStats(Ostream &os) const
Definition: triSurfaceIO.C:346
Foam::HashTable::size
label size() const noexcept
Definition: HashTableI.H:45
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:63
Foam::fileName
A class for handling file names.
Definition: fileName.H:71
Foam::argList::getOrDefault
T getOrDefault(const word &optName, const T &deflt) const
Definition: argListI.H:300
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:49
Foam::argList::addNote
static void addNote(const string &note)
Definition: argList.C:405
Foam::FixedList::size
static constexpr label size() noexcept
Definition: FixedList.H:412
Foam::argList
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:119
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
triFace.H
triSurface.H
Foam::argList::get
T get(const label index) const
Definition: argListI.H:271
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Definition: argList.C:294
Foam::Field
Generic templated field type.
Definition: Field.H:59
Foam::triSurface::write
void write(Ostream &os) const
Definition: triSurfaceIO.C:329
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:72
Foam::Info
messageStream Info
argList.H
fileName.H
Foam
Definition: atmBoundaryLayer.C:26
Foam::triSurface::cleanup
void cleanup(const bool verbose)
Definition: triSurface.C:648
Foam::HashTable< label >
Foam::argList::addBoolOption
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Definition: argList.C:317
Foam::nl
constexpr char nl
Definition: Ostream.H:424
Fstream.H
Foam::List< labelledTri >
Foam::identity
labelList identity(const label len, label start=0)
Definition: labelList.C:31
Foam::labelledTri
A triFace with additional (region) index.
Definition: labelledTri.H:53
Foam::name
word name(const expressions::valueTypeCode typeCode)
Definition: exprTraits.C:52
triFaceList.H
Foam::argList::noParallel
static void noParallel()
Definition: argList.C:503
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Definition: argList.C:328
args
Foam::argList args(argc, argv)
Foam::argList::found
bool found(const word &optName) const
Definition: argListI.H:171
Foam::labelledTri::region
label region() const noexcept
Definition: labelledTri.H:126