FreeFOAM The Cross-Platform CFD Toolkit
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 | Copyright (C) 1991-2010 OpenCFD Ltd.
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 Usage
37 
38  - surfaceCoarsen [OPTIONS] <Foam surface file> <factor> <Foam output surface file>
39 
40  @param <Foam surface file> \n
41  @todo Detailed description of argument.
42 
43  @param <factor> \n
44  @todo Detailed description of argument.
45 
46  @param <Foam output surface file> \n
47  @todo Detailed description of argument.
48 
49  @param -case <dir>\n
50  Case directory.
51 
52  @param -help \n
53  Display help message.
54 
55  @param -doc \n
56  Display Doxygen API documentation page for this application.
57 
58  @param -srcDoc \n
59  Display Doxygen source documentation page for this application.
60 
61 \*---------------------------------------------------------------------------*/
62 
63 #include <OpenFOAM/argList.H>
64 #include <OpenFOAM/fileName.H>
65 #include <triSurface/triSurface.H>
66 #include <OpenFOAM/OFstream.H>
67 #include <OpenFOAM/triFace.H>
68 #include <OpenFOAM/triFaceList.H>
69 
70 // From bunnylod
71 #include "bunnylod/progmesh.h"
72 
73 using namespace Foam;
74 
75 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
76 
77 int mapVertex(::List<int>& collapse_map, int a, int mx)
78 {
79  if (mx <= 0)
80  {
81  return 0;
82  }
83  while (a >= mx)
84  {
85  a = collapse_map[a];
86  }
87  return a;
88 }
89 
90 
91 // Main program:
92 
93 int main(int argc, char *argv[])
94 {
97  argList::validArgs.append("Foam surface file");
98  argList::validArgs.append("reduction factor");
99  argList::validArgs.append("Foam output file");
100  argList args(argc, argv);
101 
102  fileName inFileName(args.additionalArgs()[0]);
103 
104  scalar reduction(readScalar(IStringStream(args.additionalArgs()[1])()));
105 
106  if (reduction <= 0 || reduction > 1)
107  {
109  << "Reduction factor " << reduction
110  << " should be within 0..1" << endl
111  << "(it is the reduction in number of vertices)"
112  << exit(FatalError);
113  }
114 
115  fileName outFileName(args.additionalArgs()[2]);
116 
117  Info<< "Input surface :" << inFileName << endl
118  << "Reduction factor:" << reduction << endl
119  << "Output surface :" << outFileName << endl << endl;
120 
121  const triSurface surf(inFileName);
122 
123  Info<< "Surface:" << endl;
124  surf.writeStats(Info);
125  Info<< endl;
126 
127 
128  ::List< ::Vector> vert; // global list of vertices
129  ::List< ::tridata> tri; // global list of triangles
130 
131 
132  // Convert triSurface to progmesh format. Note: can use global point
133  // numbering since surface read in from file.
134  const pointField& pts = surf.points();
135 
136  forAll(pts, ptI)
137  {
138  const point& pt = pts[ptI];
139 
140  vert.Add( ::Vector(pt.x(), pt.y(), pt.z()));
141  }
142 
143  forAll(surf, faceI)
144  {
145  const labelledTri& f = surf[faceI];
146 
147  tridata td;
148  td.v[0]=f[0];
149  td.v[1]=f[1];
150  td.v[2]=f[2];
151  tri.Add(td);
152  }
153 
154  ::List<int> collapse_map; // to which neighbor each vertex collapses
155  ::List<int> permutation;
156 
157  ::ProgressiveMesh(vert,tri,collapse_map,permutation);
158 
159  // rearrange the vertex list
160  ::List< ::Vector> temp_list;
161  for(int i=0;i<vert.num;i++)
162  {
163  temp_list.Add(vert[i]);
164  }
165  for(int i=0;i<vert.num;i++)
166  {
167  vert[permutation[i]]=temp_list[i];
168  }
169 
170  // update the changes in the entries in the triangle list
171  for(int i=0;i<tri.num;i++)
172  {
173  for(int j=0;j<3;j++)
174  {
175  tri[i].v[j] = permutation[tri[i].v[j]];
176  }
177  }
178 
179  // Only get triangles with non-collapsed edges.
180  int render_num = int(reduction * surf.nPoints());
181 
182  Info<< "Reducing to " << render_num << " vertices" << endl;
183 
184 
185  // Storage for new surface.
186  Foam::List<labelledTri> newTris(surf.size());
187 
188  label newI = 0;
189 
190  for (int i=0; i<tri.num; i++)
191  {
192  int p0 = mapVertex(collapse_map, tri[i].v[0], render_num);
193  int p1 = mapVertex(collapse_map, tri[i].v[1], render_num);
194  int p2 = mapVertex(collapse_map, tri[i].v[2], render_num);
195 
196  // note: serious optimization opportunity here,
197  // by sorting the triangles the following "continue"
198  // could have been made into a "break" statement.
199  if (p0 == p1 || p1 == p2 || p2 == p0)
200  {
201  continue;
202  }
203 
204  newTris[newI++] = labelledTri(p0, p1, p2, 0);
205  }
206  newTris.setSize(newI);
207 
208  // Convert vert into pointField.
209  pointField newPoints(vert.num);
210 
211  for(int i=0; i<vert.num; i++)
212  {
213  const ::Vector & v = vert[i];
214 
215  newPoints[i] = point(v.x, v.y, v.z);
216  }
217 
218  triSurface surf2(newTris, newPoints);
219 
220  triSurface outSurf
221  (
222  surf2.localFaces(),
223  surf2.patches(),
224  surf2.localPoints()
225  );
226 
227  Info<< "Coarsened surface:" << endl;
228  surf2.writeStats(Info);
229  Info<< endl;
230 
231  Info<< "Writing to file " << outFileName << endl << endl;
232 
233  surf2.write(outFileName);
234 
235  Info << "End\n" << endl;
236 
237  return 0;
238 }
239 
240 
241 // ************************ vim: set sw=4 sts=4 et: ************************ //