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-------------------------------------------------------------------------------
11License
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
27Application
28 surfaceCoarsen
29
30Group
31 grpSurfaceUtilities
32
33Description
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
56using namespace Foam;
57
58// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
59
60int 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
75int main(int argc, char *argv[])
76{
77 argList::addNote
78 (
79 "Surface coarsening using 'bunnylod'"
80 );
81
82 argList::noParallel();
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");
86 argList::addOption
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// ************************************************************************* //
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:124
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:278
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:307
A class for handling file names.
Definition: fileName.H:76
A triFace with additional (region) index.
Definition: labelledTri.H:60
Triangulated surface description with patch information.
Definition: triSurface.H:79
const volScalarField & p0
Definition: EEqn.H:36
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Namespace for OpenFOAM.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
labelList f(nPoints)
Foam::argList args(argc, argv)