surfaceLambdaMuSmooth.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) 2015-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  surfaceLambdaMuSmooth
29 
30 Group
31  grpSurfaceUtilities
32 
33 Description
34  Smooth a surface using lambda/mu smoothing.
35 
36  To get laplacian smoothing, set lambda to the relaxation factor and mu to
37  zero.
38 
39  Provide an edgeMesh file containing points that are not to be moved during
40  smoothing in order to preserve features.
41 
42  lambda/mu smoothing: G. Taubin, IBM Research report Rc-19923 (02/01/95)
43  "A signal processing approach to fair surface design"
44 
45 \*---------------------------------------------------------------------------*/
46 
47 #include "argList.H"
48 #include "boundBox.H"
49 #include "edgeMesh.H"
50 #include "matchPoints.H"
51 #include "MeshedSurfaces.H"
52 
53 using namespace Foam;
54 
55 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
56 
58 (
59  const meshedSurface& s,
60  const bitSet& fixedPoints
61 )
62 {
63  const labelListList& pointEdges = s.pointEdges();
64 
65  tmp<pointField> tavg(new pointField(s.nPoints(), Zero));
66  pointField& avg = tavg.ref();
67 
68  forAll(pointEdges, vertI)
69  {
70  vector& avgPos = avg[vertI];
71 
72  if (fixedPoints.test(vertI))
73  {
74  avgPos = s.localPoints()[vertI];
75  }
76  else
77  {
78  const labelList& pEdges = pointEdges[vertI];
79 
80  forAll(pEdges, myEdgeI)
81  {
82  const edge& e = s.edges()[pEdges[myEdgeI]];
83 
84  label otherVertI = e.otherVertex(vertI);
85 
86  avgPos += s.localPoints()[otherVertI];
87  }
88 
89  avgPos /= pEdges.size();
90  }
91  }
92 
93  return tavg;
94 }
95 
96 
97 void getFixedPoints
98 (
99  const edgeMesh& feMesh,
100  const pointField& points,
101  bitSet& fixedPoints
102 )
103 {
104  scalarList matchDistance(feMesh.points().size(), 1e-1);
105  labelList from0To1;
106 
107  bool matchedAll = matchPoints
108  (
109  feMesh.points(),
110  points,
111  matchDistance,
112  false,
113  from0To1
114  );
115 
116  if (!matchedAll)
117  {
119  << "Did not match all feature points to points on the surface"
120  << endl;
121  }
122 
123  forAll(from0To1, fpI)
124  {
125  if (from0To1[fpI] != -1)
126  {
127  fixedPoints.set(from0To1[fpI]);
128  }
129  }
130 }
131 
132 
133 // Main program:
134 
135 int main(int argc, char *argv[])
136 {
138  (
139  "Smooth a surface using lambda/mu smoothing.\n"
140  "For laplacian smoothing, set lambda to the relaxation factor"
141  " and mu to zero."
142  );
143 
145  argList::validOptions.clear();
146  argList::addArgument("input", "The input surface file");
147  argList::addArgument("lambda", "On the interval [0,1]");
148  argList::addArgument("mu", "On the interval [0,1]");
149  argList::addArgument("iterations", "The number of iterations to perform");
150  argList::addArgument("output", "The output surface file");
151 
153  (
154  "featureFile",
155  "Fix points from a file containing feature points and edges"
156  );
157  argList args(argc, argv);
158 
159  const auto surfFileName = args.get<fileName>(1);
160  const auto lambda = args.get<scalar>(2);
161  const auto mu = args.get<scalar>(3);
162  const auto iters = args.get<label>(4);
163  const auto outFileName = args.get<fileName>(5);
164 
165  if (lambda < 0 || lambda > 1)
166  {
168  << lambda << endl
169  << "0: no change 1: move vertices to average of neighbours"
170  << exit(FatalError);
171  }
172  if (mu < 0 || mu > 1)
173  {
175  << mu << endl
176  << "0: no change 1: move vertices to average of neighbours"
177  << exit(FatalError);
178  }
179 
180  Info<< "lambda : " << lambda << nl
181  << "mu : " << mu << nl
182  << "Iters : " << iters << nl
183  << "Reading surface from " << surfFileName << " ..." << endl;
184 
185  meshedSurface surf1(surfFileName);
186 
187  Info<< "Faces : " << surf1.size() << nl
188  << "Vertices : " << surf1.nPoints() << nl
189  << "Bounding Box: " << boundBox(surf1.localPoints()) << endl;
190 
191  bitSet fixedPoints(surf1.localPoints().size(), false);
192 
193  if (args.found("featureFile"))
194  {
195  const auto featureFileName = args.get<fileName>("featureFile");
196  Info<< "Reading features from " << featureFileName << " ..." << endl;
197 
198  edgeMesh feMesh(featureFileName);
199 
200  getFixedPoints(feMesh, surf1.localPoints(), fixedPoints);
201 
202  Info<< "Number of fixed points on surface = " << fixedPoints.count()
203  << endl;
204  }
205 
206  for (label iter = 0; iter < iters; iter++)
207  {
208  // Lambda
209  {
210  pointField newLocalPoints
211  (
212  (1 - lambda)*surf1.localPoints()
213  + lambda*avg(surf1, fixedPoints)
214  );
215 
216  pointField newPoints(surf1.points());
217  UIndirectList<point>(newPoints, surf1.meshPoints()) =
218  newLocalPoints;
219 
220  surf1.movePoints(newPoints);
221  }
222 
223  // Mu
224  if (mu != 0)
225  {
226  pointField newLocalPoints
227  (
228  (1 + mu)*surf1.localPoints()
229  - mu*avg(surf1, fixedPoints)
230  );
231 
232  pointField newPoints(surf1.points());
233  UIndirectList<point>(newPoints, surf1.meshPoints()) =
234  newLocalPoints;
235 
236  surf1.movePoints(newPoints);
237  }
238  }
239 
240  Info<< "Writing surface to " << outFileName << " ..." << endl;
241  surf1.write(outFileName);
242 
243  Info<< "End\n" << endl;
244 
245  return 0;
246 }
247 
248 
249 // ************************************************************************* //
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
Foam::edgeMesh::points
const pointField & points() const noexcept
Definition: edgeMeshI.H:92
Foam::fileName
A class for handling file names.
Definition: fileName.H:71
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
Foam::constant::physicoChemical::mu
const dimensionedScalar mu
Definition: createFieldRefs.H:4
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:57
Foam::Zero
static constexpr const zero Zero
Definition: zero.H:131
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:59
Foam::argList::addNote
static void addNote(const string &note)
Definition: argList.C:405
Foam::bitSet::set
void set(const bitSet &bitset)
Definition: bitSetI.H:567
Foam::argList
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:119
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
Foam::bitSet::test
bool test(const label pos) const
Definition: bitSetI.H:513
Foam::argList::get
T get(const label index) const
Definition: argListI.H:271
Foam::bitSet::count
unsigned int count(const bool on=true) const
Definition: bitSetI.H:492
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Definition: argList.C:294
matchPoints.H
Determine correspondence between points. See below.
Foam::Field
Generic templated field type.
Definition: Field.H:59
edgeMesh.H
Foam::Info
messageStream Info
argList.H
Foam::argList::validOptions
static HashTable< string > validOptions
Definition: argList.H:208
Foam::FatalError
error FatalError
lambda
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
Foam::Ostream::write
virtual bool write(const token &tok)=0
iters
loopControl iters(runTime, aMesh.solutionDict(), "solution")
Foam
Definition: atmBoundaryLayer.C:26
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
boundBox.H
FatalErrorInFunction
#define FatalErrorInFunction
Definition: error.H:465
Foam::nl
constexpr char nl
Definition: Ostream.H:424
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:58
MeshedSurfaces.H
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Definition: createFields.H:11
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:57
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:56
Foam::argList::noParallel
static void noParallel()
Definition: argList.C:503
Foam::MeshedSurface
A surface geometry mesh with zone information, not to be confused with the similarly named surfaceMes...
Definition: triSurfaceTools.H:76
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Definition: argList.C:328
args
Foam::argList args(argc, argv)
Foam::edgeMesh
Mesh data needed to do the Finite Area discretisation.
Definition: edgeFaMesh.H:47
Foam::matchPoints
bool matchPoints(const UList< point > &pts0, const UList< point > &pts1, const UList< scalar > &matchDistance, const bool verbose, labelList &from0To1, const point &origin=point::zero)
Definition: matchPoints.C:29
WarningInFunction
#define WarningInFunction
Definition: messageStream.H:353
Foam::argList::found
bool found(const word &optName) const
Definition: argListI.H:171