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-2026 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<< nl << "Input surface : " << inFileName
89  << nl << "Reduction factor : " << reduction
90  << nl << "Output surface : " << outFileName << nl << endl;
91 
92  const triSurface surf(inFileName);
93 
94  Info<< "Surface:" << incrIndent << endl;
95  surf.writeStats(Info);
96  Info<< decrIndent << endl;
97 
98  ::List<::Vector> vertices; // global list of vertices
99  ::List<::tridata> triangles; // global list of triangles
100 
101  // Convert triSurface to progmesh format. Note: can use global point
102  // numbering since surface read in from file.
103  const pointField& pts = surf.points();
104  forAll(pts, ptI)
105  {
106  const point& pt = pts[ptI];
107  vertices.Add(::Vector(pt.x(), pt.y(), pt.z()));
108  }
109  forAll(surf, facei)
110  {
111  const labelledTri& f = surf[facei];
112  tridata td;
113  td.v[0] = f[0];
114  td.v[1] = f[1];
115  td.v[2] = f[2];
116  triangles.Add(td);
117  }
118 
119  ::List<int> collapse_map; // to which neighbor each vertex collapses
120  ::List<int> permutation;
121  ::ProgressiveMesh(vertices, triangles, collapse_map, permutation);
122 
123  // rearrange the vertex list
124  ::List<::Vector> temp_list;
125  for (int i = 0; i < vertices.num; i ++)
126  {
127  temp_list.Add(vertices[i]);
128  }
129  for (int i = 0; i < vertices.num; i ++)
130  {
131  vertices[permutation[i]] = temp_list[i];
132  }
133 
134  // update the changes in the entries in the triangle list
135  for (int i=0; i < triangles.num; i++)
136  {
137  for (int j=0;j<3;j++)
138  {
139  triangles[i].v[j] = permutation[triangles[i].v[j]];
140  }
141  }
142 
143  // Only get triangles with non-collapsed edges.
144  int render_num = int(reduction * surf.nPoints());
145 
146  Info<< "Reducing to " << render_num << " vertices" << endl << endl;
147 
148  // Convert triangles into labelledTris
149  Foam::List<labelledTri> newTriangles(surf.size());
150  label newTrianglei = 0;
151  for (int i = 0; i < triangles.num; i ++)
152  {
153  int p0 = mapVertex(collapse_map, triangles[i].v[0], render_num);
154  int p1 = mapVertex(collapse_map, triangles[i].v[1], render_num);
155  int p2 = mapVertex(collapse_map, triangles[i].v[2], render_num);
156 
157  if (p0 == p1 || p1 == p2 || p2 == p0) continue;
158 
159  newTriangles[newTrianglei++] = labelledTri(p0, p1, p2, 0);
160  }
161  newTriangles.setSize(newTrianglei);
162 
163  // Convert vertices into points
164  pointField newPoints(vertices.num);
165  for (int i = 0; i < vertices.num; i ++)
166  {
167  newPoints[i] = point(vertices[i].x, vertices[i].y, vertices[i].z);
168  }
169 
170  // Construct the new surface
171  triSurface newSurf(newTriangles, newPoints);
172 
173  // Remove any unused points
174  newSurf = triSurface(newSurf.localFaces(), newSurf.localPoints());
175 
176  Info<< "Coarsened surface:" << incrIndent << endl;
177  newSurf.writeStats(Info);
178  Info<< decrIndent << endl;
179 
180  Info<< "Writing to file " << outFileName << endl << endl;
181 
182  newSurf.write(outFileName);
183 
184  Info<< "End\n" << endl;
185 
186  return 0;
187 }
188 
189 
190 // ************************************************************************* //
scalar y
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
virtual Ostream & write(const token &)
Write token.
Definition: Ostream.C:51
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:234
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:68
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
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
pointField vertices(const blockVertexList &bvl)
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:272
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:288
messageStream Info
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:265
vector point
Point is a vector.
Definition: point.H:41
error FatalError
static const char nl
Definition: Ostream.H:297
labelList f(nPoints)
Foam::argList args(argc, argv)