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 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 fileName surfFileName = args[1];
160  const scalar lambda = args.get<scalar>(2);
161  const scalar mu = args.get<scalar>(3);
162  const label iters = args.get<label>(4);
163  const fileName outFileName = args[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 fileName featureFileName(args["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:44
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
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:64
Foam::constant::physicoChemical::mu
const dimensionedScalar mu
Atomic mass unit.
Definition: createFieldRefs.H:4
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero (0)
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:63
Foam::argList::addNote
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:413
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:563
Foam::argList
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:123
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::bitSet::test
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:512
Foam::argList::get
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:257
Foam::bitSet::count
unsigned int count(const bool on=true) const
Count number of bits set.
Definition: bitSetI.H:491
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:302
matchPoints.H
Determine correspondence between points. See below.
Foam::Field< vector >
edgeMesh.H
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
argList.H
Foam::edgeMesh::points
const pointField & points() const
Return points.
Definition: edgeMeshI.H:99
Foam::argList::validOptions
static HashTable< string > validOptions
A list of valid options.
Definition: argList.H:210
Foam::FatalError
error FatalError
lambda
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
iters
loopControl iters(runTime, aMesh.solutionDict(), "solution")
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
boundBox.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::Vector< scalar >
Foam::List< labelList >
MeshedSurfaces.H
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:109
Foam::argList::noParallel
static void noParallel()
Remove the parallel options.
Definition: argList.C:491
Foam::MeshedSurface< face >
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition: argList.C:336
args
Foam::argList args(argc, argv)
Foam::edgeMesh
Mesh data needed to do the Finite Area discretisation.
Definition: edgeFaMesh.H:52
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)
Determine correspondence between pointFields. Gets passed.
Definition: matchPoints.C:36
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:298
Foam::argList::found
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:157