surfaceAdd.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Application
25  surfaceAdd
26 
27 Description
28  Add two surfaces. Does geometric merge on points. Does not check for
29  overlapping/intersecting triangles.
30 
31  Keeps patches separate by renumbering.
32 
33 \*---------------------------------------------------------------------------*/
34 
35 #include "argList.H"
36 #include "fileName.H"
37 #include "triSurface.H"
38 #include "OFstream.H"
39 #include "IFstream.H"
40 #include "triFace.H"
41 #include "triFaceList.H"
42 
43 using namespace Foam;
44 
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 
47 
48 int main(int argc, char *argv[])
49 {
50  #include "removeCaseOptions.H"
51 
53  (
54  "add two surfaces via a geometric merge on points."
55  );
56 
57  argList::validArgs.append("surface file");
58  argList::validArgs.append("surface file");
59  argList::validArgs.append("output surface file");
60 
62  (
63  "points",
64  "file",
65  "provide additional points"
66  );
68  (
69  "mergeRegions",
70  "combine regions from both surfaces"
71  );
72 
73  argList args(argc, argv);
74 
75  const fileName inFileName1 = args[1];
76  const fileName inFileName2 = args[2];
77  const fileName outFileName = args[3];
78 
79  const bool addPoint = args.optionFound("points");
80  const bool mergeRegions = args.optionFound("mergeRegions");
81 
82  if (addPoint)
83  {
84  Info<< "Reading a surface and adding points from a file"
85  << "; merging the points and writing the surface to another file"
86  << nl << endl;
87 
88  Info<< "Surface : " << inFileName1<< nl
89  << "Points : " << args["points"] << nl
90  << "Writing : " << outFileName << nl << endl;
91  }
92  else
93  {
94  Info<< "Reading two surfaces"
95  << "; merging points and writing the surface to another file"
96  << nl << endl;
97 
98  if (mergeRegions)
99  {
100  Info<< "Regions from the two files will get merged" << nl
101  << "Do not use this option if you want to keep the regions"
102  << " separate" << nl << endl;
103  }
104  else
105  {
106  Info<< "Regions from the two files will not get merged" << nl
107  << "Regions from " << inFileName2 << " will get offset so"
108  << " as not to overlap with the regions in " << inFileName1
109  << nl << endl;
110  }
111 
112 
113  Info<< "Surface1 : " << inFileName1<< nl
114  << "Surface2 : " << inFileName2<< nl
115  << "Writing : " << outFileName << nl << endl;
116  }
117 
118  const triSurface surface1(inFileName1);
119 
120  Info<< "Surface1:" << endl;
121  surface1.writeStats(Info);
122  Info<< endl;
123 
124  const pointField& points1 = surface1.points();
125 
126  // Final surface
127  triSurface combinedSurf;
128 
129  if (addPoint)
130  {
131  IFstream pointsFile(args["points"]);
132  pointField extraPoints(pointsFile);
133 
134  Info<< "Additional Points:" << extraPoints.size() << endl;
135 
136  vectorField pointsAll(points1);
137  label pointi = pointsAll.size();
138  pointsAll.setSize(pointsAll.size() + extraPoints.size());
139 
140  forAll(extraPoints, i)
141  {
142  pointsAll[pointi++] = extraPoints[i];
143  }
144 
145  combinedSurf = triSurface(surface1, surface1.patches(), pointsAll);
146  }
147  else
148  {
149  const triSurface surface2(inFileName2);
150 
151  Info<< "Surface2:" << endl;
152  surface2.writeStats(Info);
153  Info<< endl;
154 
155 
156  // Make new storage
157  List<labelledTri> facesAll(surface1.size() + surface2.size());
158 
159  const pointField& points2 = surface2.points();
160 
161  vectorField pointsAll(points1.size() + points2.size());
162 
163 
164  label pointi = 0;
165  // Copy points1 into pointsAll
166  forAll(points1, point1i)
167  {
168  pointsAll[pointi++] = points1[point1i];
169  }
170  // Add surface2 points
171  forAll(points2, point2i)
172  {
173  pointsAll[pointi++] = points2[point2i];
174  }
175 
176 
177  label trianglei = 0;
178 
179  // Copy triangles1 into trianglesAll
180  forAll(surface1, facei)
181  {
182  facesAll[trianglei++] = surface1[facei];
183  }
184  label nRegions1 = surface1.patches().size();
185 
186 
187  if (!mergeRegions)
188  {
189  Info<< "Surface " << inFileName1 << " has " << nRegions1
190  << " regions"
191  << nl
192  << "All region numbers in " << inFileName2 << " will be offset"
193  << " by this amount" << nl << endl;
194  }
195 
196  // Add (renumbered) surface2 triangles
197  forAll(surface2, facei)
198  {
199  const labelledTri& tri = surface2[facei];
200 
201  labelledTri& destTri = facesAll[trianglei++];
202  destTri[0] = tri[0] + points1.size();
203  destTri[1] = tri[1] + points1.size();
204  destTri[2] = tri[2] + points1.size();
205  if (mergeRegions)
206  {
207  destTri.region() = tri.region();
208  }
209  else
210  {
211  destTri.region() = tri.region() + nRegions1;
212  }
213  }
214 
215  label nRegions2 = surface2.patches().size();
216 
217  geometricSurfacePatchList newPatches;
218 
219  if (mergeRegions)
220  {
221  // Overwrite
222  newPatches.setSize(max(nRegions1, nRegions2));
223 
224  forAll(surface1.patches(), patchi)
225  {
226  newPatches[patchi] = surface1.patches()[patchi];
227  }
228  forAll(surface2.patches(), patchi)
229  {
230  newPatches[patchi] = surface2.patches()[patchi];
231  }
232  }
233  else
234  {
235  Info<< "Regions from " << inFileName2 << " have been renumbered:"
236  << nl
237  << " old\tnew" << nl;
238 
239  for (label regionI = 0; regionI < nRegions2; regionI++)
240  {
241  Info<< " " << regionI << '\t' << regionI+nRegions1
242  << nl;
243  }
244  Info<< nl;
245 
246  newPatches.setSize(nRegions1 + nRegions2);
247 
248  label newPatchi = 0;
249 
250  forAll(surface1.patches(), patchi)
251  {
252  newPatches[newPatchi++] = surface1.patches()[patchi];
253  }
254 
255  forAll(surface2.patches(), patchi)
256  {
257  newPatches[newPatchi++] = surface2.patches()[patchi];
258  }
259  }
260 
261 
262  Info<< "New patches:" << nl;
263  forAll(newPatches, patchi)
264  {
265  Info<< " " << patchi << '\t' << newPatches[patchi].name() << nl;
266  }
267  Info<< endl;
268 
269 
270  // Construct new surface mesh
271  combinedSurf = triSurface(facesAll, newPatches, pointsAll);
272  }
273 
274  // Merge all common points and do some checks
275  combinedSurf.cleanup(true);
276 
277  Info<< "Merged surface:" << endl;
278 
279  combinedSurf.writeStats(Info);
280 
281  Info<< endl;
282 
283  Info<< "Writing : " << outFileName << endl;
284 
285  // No need to 'group' while writing since all in correct order anyway.
286  combinedSurf.write(outFileName);
287 
288  Info<< "End\n" << endl;
289 
290  return 0;
291 }
292 
293 
294 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Input from file stream.
Definition: IFstream.H:85
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:103
static void addOption(const word &opt, const string &param="", const string &usage="")
Add to an option to validOptions with usage information.
Definition: argList.C:128
static void addNote(const string &)
Add extra notes for the usage information.
Definition: argList.C:159
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:118
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:114
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:153
A class for handling file names.
Definition: fileName.H:82
Triangle with additional region number.
Definition: labelledTri.H:60
label region() const
Return region label.
Definition: labelledTriI.H:68
Triangulated surface description with patch information.
Definition: triSurface.H:69
void cleanup(const bool verbose)
Remove non-valid triangles.
Definition: triSurface.C:920
void writeStats(Ostream &) const
Write some statistics.
Definition: triSurface.C:1352
int main(int argc, char *argv[])
Definition: financialFoam.C:44
label patchi
Namespace for OpenFOAM.
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:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
messageStream Info
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
static const char nl
Definition: Ostream.H:260
Foam::argList args(argc, argv)