surfaceCoarsen.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) 2020-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  surfaceCoarsen
29 
30 Group
31  grpSurfaceUtilities
32 
33 Description
34  Surface coarsening using 'bunnylod'
35 
36  Reference:
37  \verbatim
38  Polygon Reduction Demo
39  By Stan Melax (c) 1998
40  mailto:melax@cs.ualberta.ca
41  http://www.cs.ualberta.ca/~melax
42  \endverbatim
43 
44 \*---------------------------------------------------------------------------*/
45 
46 #include "argList.H"
47 #include "fileName.H"
48 #include "triSurface.H"
49 #include "OFstream.H"
50 #include "triFace.H"
51 #include "triFaceList.H"
52 
53 // From bunnylod
54 #include "progmesh.hxx"
55 
56 using namespace Foam;
57 
58 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
59 
60 int mapVertex(::List<int>& collapse_map, int a, int mx)
61 {
62  if (mx <= 0)
63  {
64  return 0;
65  }
66  while (a >= mx)
67  {
68  a = collapse_map[a];
69  }
70  return a;
71 }
72 
73 
74 
75 int main(int argc, char *argv[])
76 {
78  (
79  "Surface coarsening using 'bunnylod'"
80  );
81 
83  argList::addArgument("input", "The input surface file");
84  argList::addArgument("factor", "The reduction factor [0,1)");
85  argList::addArgument("output", "The output surface file");
87  (
88  "scale",
89  "factor",
90  "Input geometry scaling factor"
91  );
92 
93  argList args(argc, argv);
94 
95  const auto inFileName = args.get<fileName>(1);
96  const auto reduction = args.get<scalar>(2);
97  const auto outFileName = args.get<fileName>(3);
98 
99  if (reduction <= 0 || reduction > 1)
100  {
102  << "Reduction factor " << reduction
103  << " should be within 0..1" << endl
104  << "(it is the reduction in number of vertices)"
105  << exit(FatalError);
106  }
107 
108  const scalar scaleFactor = args.getOrDefault<scalar>("scale", -1);
109 
110  Info<< "Input surface :" << inFileName << nl
111  << "Scaling factor :" << scaleFactor << nl
112  << "Reduction factor:" << reduction << nl
113  << "Output surface :" << outFileName << nl
114  << endl;
115 
116  const triSurface surf(inFileName, scaleFactor);
117 
118  Info<< "Surface:" << endl;
119  surf.writeStats(Info);
120  Info<< endl;
121 
122  ::List<::Vector> vert; // global list of vertices
123  ::List<::tridata> tri; // global list of triangles
124 
125 
126  // Convert triSurface to progmesh format. Note: can use global point
127  // numbering since surface read in from file.
128  const pointField& pts = surf.points();
129 
130  for (const point& pt : pts)
131  {
132  vert.Add(::Vector(pt.x(), pt.y(), pt.z()));
133  }
134 
135  for (const labelledTri& f : surf)
136  {
137  tridata td;
138  td.v[0] = f[0];
139  td.v[1] = f[1];
140  td.v[2] = f[2];
141  tri.Add(td);
142  }
143 
144  ::List<int> collapse_map; // to which neighbor each vertex collapses
145  ::List<int> permutation;
146 
147  ::ProgressiveMesh(vert,tri,collapse_map,permutation);
148 
149  // rearrange the vertex list
150  ::List<::Vector> temp_list;
151  for (int i=0; i<vert.num; i++)
152  {
153  temp_list.Add(vert[i]);
154  }
155  for (int i=0; i<vert.num; i++)
156  {
157  vert[permutation[i]] = temp_list[i];
158  }
159 
160  // update the changes in the entries in the triangle list
161  for (int i=0; i<tri.num; i++)
162  {
163  for (int j=0; j<3; j++)
164  {
165  tri[i].v[j] = permutation[tri[i].v[j]];
166  }
167  }
168 
169  // Only get triangles with non-collapsed edges.
170  int render_num = int(reduction * surf.nPoints());
171 
172  Info<< "Reducing to " << render_num << " vertices" << endl;
173 
174 
175  // Storage for new surface.
176  Foam::List<labelledTri> newTris(surf.size());
177 
178  label newI = 0;
179 
180  for (int i=0; i<tri.num; i++)
181  {
182  int p0 = mapVertex(collapse_map, tri[i].v[0], render_num);
183  int p1 = mapVertex(collapse_map, tri[i].v[1], render_num);
184  int p2 = mapVertex(collapse_map, tri[i].v[2], render_num);
185 
186  // note: serious optimization opportunity here,
187  // by sorting the triangles the following "continue"
188  // could have been made into a "break" statement.
189  if (p0 == p1 || p1 == p2 || p2 == p0)
190  {
191  continue;
192  }
193 
194  newTris[newI++] = labelledTri(p0, p1, p2, 0);
195  }
196  newTris.setSize(newI);
197 
198  // Convert vert into pointField.
199  pointField newPoints(vert.num);
200 
201  for (int i=0; i<vert.num; i++)
202  {
203  const ::Vector & v = vert[i];
204 
205  newPoints[i] = point(v.x, v.y, v.z);
206  }
207 
208  triSurface surf2(newTris, newPoints);
209 
210  triSurface outSurf
211  (
212  surf2.localFaces(),
213  surf2.patches(),
214  surf2.localPoints()
215  );
216 
217  Info<< "Coarsened surface:" << endl;
218  surf2.writeStats(Info);
219  Info<< endl;
220 
221  Info<< "Writing to file " << outFileName << endl << endl;
222 
223  surf2.write(outFileName);
224 
225  Info<< "End\n" << endl;
226 
227  return 0;
228 }
229 
230 
231 // ************************************************************************* //
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:462
A class for handling file names.
Definition: fileName.H:72
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static void noParallel()
Remove the parallel options.
Definition: argList.C:584
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:300
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:118
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:385
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
A triFace with additional (region) index.
Definition: labelledTri.H:53
Templated 3D Vector derived from VectorSpace adding construction from 3 components, element access using x(), y() and z() member functions and the inner-product (dot-product) and cross-product operators.
Definition: Vector.H:58
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
labelList f(nPoints)
vector point
Point is a vector.
Definition: point.H:37
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:271
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:351
messageStream Info
Information stream (stdout output on master, null elsewhere)
Triangulated surface description with patch information.
Definition: triSurface.H:71
Foam::argList args(argc, argv)
const volScalarField & p0
Definition: EEqn.H:36
Namespace for OpenFOAM.
const pointField & pts