surfaceCoarsen.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-2021 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  surfaceCoarsen
26 
27 Description
28  Surface coarsening using 'bunnylod':
29 
30  Polygon Reduction Demo
31  By Stan Melax (c) 1998
32  mailto:melax@cs.ualberta.ca
33  http://www.cs.ualberta.ca/~melax
34 
35 \*---------------------------------------------------------------------------*/
36 
37 #include "argList.H"
38 #include "fileName.H"
39 #include "triSurface.H"
40 #include "OFstream.H"
41 #include "triFace.H"
42 #include "triFaceList.H"
43 
44 // From bunnylod
45 #include "progmesh.h"
46 
47 using namespace Foam;
48 
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 
51 int mapVertex(::List<int>& collapse_map, int a, int mx)
52 {
53  if (mx <= 0)
54  {
55  return 0;
56  }
57  while (a >= mx)
58  {
59  a = collapse_map[a];
60  }
61  return a;
62 }
63 
64 
65 
66 int main(int argc, char *argv[])
67 {
68  #include "removeCaseOptions.H"
69 
70  argList::validArgs.append("surface file");
71  argList::validArgs.append("output surface file");
72  argList::validArgs.append("reductionFactor");
73  argList args(argc, argv);
74 
75  const fileName inFileName = args[1];
76  const fileName outFileName = args[2];
77  const scalar reduction = args.argRead<scalar>(3);
78 
79  if (reduction <= 0 || reduction > 1)
80  {
82  << "Reduction factor " << reduction
83  << " should be within 0..1" << endl
84  << "(it is the reduction in number of vertices)"
85  << exit(FatalError);
86  }
87 
88  Info<< "Input surface :" << inFileName << endl
89  << "Reduction factor:" << reduction << endl
90  << "Output surface :" << outFileName << endl << endl;
91 
92  const triSurface surf(inFileName);
93 
94  Info<< "Surface:" << endl;
95  surf.writeStats(Info);
96  Info<< endl;
97 
98 
99  ::List< ::Vector> vert; // global list of vertices
100  ::List< ::tridata> tri; // global list of triangles
101 
102 
103  // Convert triSurface to progmesh format. Note: can use global point
104  // numbering since surface read in from file.
105  const pointField& pts = surf.points();
106 
107  forAll(pts, ptI)
108  {
109  const point& pt = pts[ptI];
110 
111  vert.Add( ::Vector(pt.x(), pt.y(), pt.z()));
112  }
113 
114  forAll(surf, facei)
115  {
116  const labelledTri& f = surf[facei];
117 
118  tridata td;
119  td.v[0]=f[0];
120  td.v[1]=f[1];
121  td.v[2]=f[2];
122  tri.Add(td);
123  }
124 
125  ::List<int> collapse_map; // to which neighbor each vertex collapses
126  ::List<int> permutation;
127 
128  ::ProgressiveMesh(vert,tri,collapse_map,permutation);
129 
130  // rearrange the vertex list
131  ::List< ::Vector> temp_list;
132  for (int i=0;i<vert.num;i++)
133  {
134  temp_list.Add(vert[i]);
135  }
136  for (int i=0;i<vert.num;i++)
137  {
138  vert[permutation[i]]=temp_list[i];
139  }
140 
141  // update the changes in the entries in the triangle list
142  for (int i=0;i<tri.num;i++)
143  {
144  for (int j=0;j<3;j++)
145  {
146  tri[i].v[j] = permutation[tri[i].v[j]];
147  }
148  }
149 
150  // Only get triangles with non-collapsed edges.
151  int render_num = int(reduction * surf.nPoints());
152 
153  Info<< "Reducing to " << render_num << " vertices" << endl;
154 
155 
156  // Storage for new surface.
157  Foam::List<labelledTri> newTris(surf.size());
158 
159  label newI = 0;
160 
161  for (int i=0; i<tri.num; i++)
162  {
163  int p0 = mapVertex(collapse_map, tri[i].v[0], render_num);
164  int p1 = mapVertex(collapse_map, tri[i].v[1], render_num);
165  int p2 = mapVertex(collapse_map, tri[i].v[2], render_num);
166 
167  // note: serious optimisation opportunity here,
168  // by sorting the triangles the following "continue"
169  // could have been made into a "break" statement.
170  if (p0 == p1 || p1 == p2 || p2 == p0)
171  {
172  continue;
173  }
174 
175  newTris[newI++] = labelledTri(p0, p1, p2, 0);
176  }
177  newTris.setSize(newI);
178 
179  // Convert vert into pointField.
180  pointField newPoints(vert.num);
181 
182  for (int i=0; i<vert.num; i++)
183  {
184  const ::Vector & v = vert[i];
185 
186  newPoints[i] = point(v.x, v.y, v.z);
187  }
188 
189  triSurface surf2(newTris, newPoints);
190 
191  triSurface outSurf
192  (
193  surf2.localFaces(),
194  surf2.patches(),
195  surf2.localPoints()
196  );
197 
198  Info<< "Coarsened surface:" << endl;
199  surf2.writeStats(Info);
200  Info<< endl;
201 
202  Info<< "Writing to file " << outFileName << endl << endl;
203 
204  surf2.write(outFileName);
205 
206  Info<< "End\n" << endl;
207 
208  return 0;
209 }
210 
211 
212 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
virtual Ostream & write(const char)=0
Write character.
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:103
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:153
T argRead(const label index) const
Read a value from the argument at index.
Definition: argListI.H:183
A class for handling file names.
Definition: fileName.H:82
Triangle with additional region number.
Definition: labelledTri.H:60
Triangulated surface description with patch information.
Definition: triSurface.H:69
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
int main(int argc, char *argv[])
Definition: financialFoam.C:44
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
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
vector point
Point is a vector.
Definition: point.H:41
error FatalError
labelList f(nPoints)
Foam::argList args(argc, argv)