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 | Copyright (C) 2011-2016 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 {
51  (
52  "add two surfaces via a geometric merge on points."
53  );
54 
56  argList::validArgs.append("surfaceFile");
57  argList::validArgs.append("surfaceFile");
58  argList::validArgs.append("output surfaceFile");
59 
61  (
62  "points",
63  "file",
64  "provide additional points"
65  );
67  (
68  "mergeRegions",
69  "combine regions from both surfaces"
70  );
71 
72  argList args(argc, argv);
73 
74  const fileName inFileName1 = args[1];
75  const fileName inFileName2 = args[2];
76  const fileName outFileName = args[3];
77 
78  const bool addPoint = args.optionFound("points");
79  const bool mergeRegions = args.optionFound("mergeRegions");
80 
81  if (addPoint)
82  {
83  Info<< "Reading a surface and adding points from a file"
84  << "; merging the points and writing the surface to another file"
85  << nl << endl;
86 
87  Info<< "Surface : " << inFileName1<< nl
88  << "Points : " << args["points"] << nl
89  << "Writing : " << outFileName << nl << endl;
90  }
91  else
92  {
93  Info<< "Reading two surfaces"
94  << "; merging points and writing the surface to another file"
95  << nl << endl;
96 
97  if (mergeRegions)
98  {
99  Info<< "Regions from the two files will get merged" << nl
100  << "Do not use this option if you want to keep the regions"
101  << " separate" << nl << endl;
102  }
103  else
104  {
105  Info<< "Regions from the two files will not get merged" << nl
106  << "Regions from " << inFileName2 << " will get offset so"
107  << " as not to overlap with the regions in " << inFileName1
108  << nl << endl;
109  }
110 
111 
112  Info<< "Surface1 : " << inFileName1<< nl
113  << "Surface2 : " << inFileName2<< nl
114  << "Writing : " << outFileName << nl << endl;
115  }
116 
117  const triSurface surface1(inFileName1);
118 
119  Info<< "Surface1:" << endl;
120  surface1.writeStats(Info);
121  Info<< endl;
122 
123  const pointField& points1 = surface1.points();
124 
125  // Final surface
126  triSurface combinedSurf;
127 
128  if (addPoint)
129  {
130  IFstream pointsFile(args["points"]);
131  pointField extraPoints(pointsFile);
132 
133  Info<< "Additional Points:" << extraPoints.size() << endl;
134 
135  vectorField pointsAll(points1);
136  label pointi = pointsAll.size();
137  pointsAll.setSize(pointsAll.size() + extraPoints.size());
138 
139  forAll(extraPoints, i)
140  {
141  pointsAll[pointi++] = extraPoints[i];
142  }
143 
144  combinedSurf = triSurface(surface1, surface1.patches(), pointsAll);
145  }
146  else
147  {
148  const triSurface surface2(inFileName2);
149 
150  Info<< "Surface2:" << endl;
151  surface2.writeStats(Info);
152  Info<< endl;
153 
154 
155  // Make new storage
156  List<labelledTri> facesAll(surface1.size() + surface2.size());
157 
158  const pointField& points2 = surface2.points();
159 
160  vectorField pointsAll(points1.size() + points2.size());
161 
162 
163  label pointi = 0;
164  // Copy points1 into pointsAll
165  forAll(points1, point1i)
166  {
167  pointsAll[pointi++] = points1[point1i];
168  }
169  // Add surface2 points
170  forAll(points2, point2i)
171  {
172  pointsAll[pointi++] = points2[point2i];
173  }
174 
175 
176  label trianglei = 0;
177 
178  // Copy triangles1 into trianglesAll
179  forAll(surface1, facei)
180  {
181  facesAll[trianglei++] = surface1[facei];
182  }
183  label nRegions1 = surface1.patches().size();
184 
185 
186  if (!mergeRegions)
187  {
188  Info<< "Surface " << inFileName1 << " has " << nRegions1
189  << " regions"
190  << nl
191  << "All region numbers in " << inFileName2 << " will be offset"
192  << " by this amount" << nl << endl;
193  }
194 
195  // Add (renumbered) surface2 triangles
196  forAll(surface2, facei)
197  {
198  const labelledTri& tri = surface2[facei];
199 
200  labelledTri& destTri = facesAll[trianglei++];
201  destTri[0] = tri[0] + points1.size();
202  destTri[1] = tri[1] + points1.size();
203  destTri[2] = tri[2] + points1.size();
204  if (mergeRegions)
205  {
206  destTri.region() = tri.region();
207  }
208  else
209  {
210  destTri.region() = tri.region() + nRegions1;
211  }
212  }
213 
214  label nRegions2 = surface2.patches().size();
215 
216  geometricSurfacePatchList newPatches;
217 
218  if (mergeRegions)
219  {
220  // Overwrite
221  newPatches.setSize(max(nRegions1, nRegions2));
222 
223  forAll(surface1.patches(), patchi)
224  {
225  newPatches[patchi] = surface1.patches()[patchi];
226  }
227  forAll(surface2.patches(), patchi)
228  {
229  newPatches[patchi] = surface2.patches()[patchi];
230  }
231  }
232  else
233  {
234  Info<< "Regions from " << inFileName2 << " have been renumbered:"
235  << nl
236  << " old\tnew" << nl;
237 
238  for (label regionI = 0; regionI < nRegions2; regionI++)
239  {
240  Info<< " " << regionI << '\t' << regionI+nRegions1
241  << nl;
242  }
243  Info<< nl;
244 
245  newPatches.setSize(nRegions1 + nRegions2);
246 
247  label newPatchi = 0;
248 
249  forAll(surface1.patches(), patchi)
250  {
251  newPatches[newPatchi++] = surface1.patches()[patchi];
252  }
253 
254  forAll(surface2.patches(), patchi)
255  {
256  newPatches[newPatchi++] = surface2.patches()[patchi];
257  }
258  }
259 
260 
261  Info<< "New patches:" << nl;
262  forAll(newPatches, patchi)
263  {
264  Info<< " " << patchi << '\t' << newPatches[patchi].name() << nl;
265  }
266  Info<< endl;
267 
268 
269  // Construct new surface mesh
270  combinedSurf = triSurface(facesAll, newPatches, pointsAll);
271  }
272 
273  // Merge all common points and do some checks
274  combinedSurf.cleanup(true);
275 
276  Info<< "Merged surface:" << endl;
277 
278  combinedSurf.writeStats(Info);
279 
280  Info<< endl;
281 
282  Info<< "Writing : " << outFileName << endl;
283 
284  // No need to 'group' while writing since all in correct order anyway.
285  combinedSurf.write(outFileName);
286 
287  Info<< "End\n" << endl;
288 
289  return 0;
290 }
291 
292 
293 // ************************************************************************* //
void cleanup(const bool verbose)
Remove non-valid triangles.
Definition: triSurface.C:818
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
A class for handling file names.
Definition: fileName.H:69
label region() const
Return region label.
Definition: labelledTriI.H:68
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
void writeStats(Ostream &) const
Write some statistics.
Definition: triSurface.C:1067
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
static void noParallel()
Remove the parallel options.
Definition: argList.C:146
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:154
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:102
static void addOption(const word &opt, const string &param="", const string &usage="")
Add to an option to validOptions with usage information.
Definition: argList.C:93
Triangle with additional region number.
Definition: labelledTri.H:57
static const char nl
Definition: Ostream.H:262
Input from file stream.
Definition: IFstream.H:81
void setSize(const label)
Reset size of List.
Definition: List.C:295
label patchi
messageStream Info
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:83
static void addNote(const string &)
Add extra notes for the usage information.
Definition: argList.C:124
Triangulated surface description with patch information.
Definition: triSurface.H:65
Foam::argList args(argc, argv)
Namespace for OpenFOAM.