quadricFittingI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | cfMesh: A library for mesh generation
4  \\ / O peration |
5  \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6  \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of cfMesh.
10 
11  cfMesh is free software; you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation; either version 3 of the License, or (at your
14  option) any later version.
15 
16  cfMesh 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 cfMesh. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "quadricFitting.H"
29 
30 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34 
35 // * * * * * * * * * Private Member Functions * * * * * * * * * * * * * * * * //
36 
38 {
40 
42  {
43  const vector d = (otherPoints_[i] - origin_);
44 
45  mat += symm(d * d);
46  }
47 
48  mat /= otherPoints_.size();
49 
50  //- find the eigenvalues of the tensor
51  const vector ev = eigenValues(mat);
52 
53  //- estimate the normal as the eigenvector associated
54  //- to the smallest eigenvalue
55  normal_ = eigenVector(mat, ev[0]);
56 }
57 
59 {
60  if( mag(normal_) < VSMALL )
61  {
65 
66  return;
67  }
68 
69  const plane pl(origin_, normal_);
70 
71  bool valid(false);
72 
73  label pI(0);
74  while( !valid )
75  {
76  const point vp = pl.nearestPoint(otherPoints_[pI]);
77  vecX_ = vp - origin_;
78 
79  if( magSqr(vecX_) < VSMALL )
80  {
81  ++pI;
82  continue;
83  }
84 
85  vecX_ /= mag(vecX_);
86  vecY_ = normal_ ^ vecX_;
87  valid = true;
88  }
89 
90  if( !valid )
91  {
93  (
94  "void quadricFitting::calculateCoordinateSystem()"
95  ) << "Cannot find a valid coordinate system!" << endl;
96 
98  }
99 
100  //- transform other points to this new coordinate system
101  transformedPoints_.setSize(otherPoints_.size());
102 
103  forAll(otherPoints_, i)
104  {
105  const vector delta = (otherPoints_[i] - origin_);
106  point& p = transformedPoints_[i];
107 
108  p.x() = delta & vecX_;
109  p.y() = delta & vecY_;
110  p.z() = delta & normal_;
111  }
112 }
113 
115 {
116  if( mag(normal_) < VSMALL )
117  {
118  coefficients_.setSize(5);
119  coefficients_ = 0.0;
120  return;
121  }
122 
123  simpleMatrix<scalar> mat(5, 0.0, 0.0);
124  DynList<scalar> helper;
125  helper.setSize(5);
126 
128  {
129  const point& p = transformedPoints_[i];
130 
131  helper[0] = sqr(p.x());
132  helper[1] = sqr(p.y());
133  helper[2] = p.x() * p.y();
134  helper[3] = p.x();
135  helper[4] = p.y();
136 
137  for(label rowI=0;rowI<5;++rowI)
138  {
139  for(label colI=rowI;colI<5;++colI)
140  mat[rowI][colI] += helper[rowI] * helper[colI];
141 
142  mat.source()[rowI] += helper[rowI] * p.z();
143  }
144  }
145 
146  for(label rowI=1;rowI<5;++rowI)
147  {
148  for(label colI=0;colI<rowI;++colI)
149  mat[rowI][colI] = mat[colI][rowI];
150 
151  if( mag(mat[rowI][rowI]) < SMALL )
152  mat[rowI][rowI] = SMALL;
153  }
154 
155  coefficients_ = mat.LUsolve();
156 }
157 
159 {
160  label iteration(0);
161 
162  while( iteration++ < 10 )
163  {
165 
167 
168  if( (mag(coefficients_[3]) > SMALL) || (mag(coefficients_[4]) > SMALL) )
169  {
170  //- correct the normal
171  const scalar d =
173 
174  const vector newNormal
175  (
176  normal_ / d -
177  coefficients_[3] * vecX_ / d -
178  coefficients_[4] * vecY_ / d
179  );
180 
181  normal_ = newNormal;
182  }
183  else
184  {
185  break;
186  }
187  }
188 
189  # ifdef DEBUGQuadric
190  Info << "Other points " << otherPoints_ << endl;
191  Info << "Transformed points " << transformedPoints_ << endl;
192  Info << "normal " << normal_ << endl;
193  Info << "Coefficients " << coefficients_ << endl;
194  # endif
195 }
196 
197 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
198 
199 template<class ListType>
201 (
202  const point& origin,
203  const vector normal,
204  const ListType& otherPoints
205 )
206 :
207  origin_(origin),
208  normal_(normal),
209  vecX_(vector::zero),
210  vecY_(vector::zero),
211  otherPoints_(),
212  transformedPoints_(),
213  coefficients_()
214 {
215  otherPoints_.setSize(otherPoints.size());
216  forAll(otherPoints, i)
217  otherPoints_[i] = otherPoints[i];
218 
219  if( magSqr(normal_) < VSMALL )
220  {
222  (
223  "template<class ListType>\n"
224  "inline quadricFitting::quadricFitting"
225  "(const point& origin, const vector normal,"
226  " const ListType& otherPoints)"
227  ) << "Cannot construct the quadric surface for point "
228  << origin_ << " because the normal does not exist!"
229  << "\nThis indicates that the input"
230  << " surface mesh is of poor quality" << exit(FatalError);
231 
232  normal_ = vector::zero;
233  }
234  else
235  {
236  normal_ /= mag(normal_);
237  }
238 
239  calculateBestFit();
240 }
241 
242 //- Construct from point and other points
243 template<class ListType>
245 (
246  const point& origin,
247  const ListType& otherPoints
248 )
249 :
250  origin_(origin),
251  normal_(),
252  vecX_(),
253  vecY_(),
254  otherPoints_(),
255  transformedPoints_(),
256  coefficients_()
257 {
258  otherPoints_.setSize(otherPoints.size());
259  forAll(otherPoints, i)
260  otherPoints_[i] = otherPoints[i];
261 
262  calculateNormalVector();
263 
264  calculateBestFit();
265 }
266 
268 {
269 }
270 
271 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
272 
273 inline const vector& quadricFitting::normal() const
274 {
275  return normal_;
276 }
277 
278 //- Return min curvature
279 inline scalar quadricFitting::minCurvature() const
280 {
281  return
282  (
283  coefficients_[0] + coefficients_[1] -
285  );
286 }
287 
288 //- Return max curvature
289 inline scalar quadricFitting::maxCurvature() const
290 {
291  return
292  (
293  coefficients_[0] + coefficients_[1] +
295  );
296 }
297 
298 //- Return mean curvature
299 inline scalar quadricFitting::meanCurvature() const
300 {
301  return 0.5 * (minCurvature() + maxCurvature());
302 }
303 
304 //- Return Gaussian curvature
306 {
307  return minCurvature() * maxCurvature();
308 }
309 
310 //- Return min curvature vector
312 {
313  const scalar theta =
314  0.5 * Foam::atan
315  (
316  coefficients_[2] /
317  stabilise(coefficients_[0] - coefficients_[1], VSMALL)
318  );
319 
320  return Foam::cos(theta) * vecX_ + Foam::sin(theta) * vecY_;
321 }
322 
323 //- Return max curvature vector
325 {
326  const scalar theta =
327  0.5 * Foam::atan
328  (
329  coefficients_[2] /
330  stabilise(coefficients_[0] - coefficients_[1], VSMALL)
331  );
332 
333  return Foam::sin(theta) * vecX_ + Foam::cos(theta) * vecY_;
334 }
335 
336 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
337 
338 } // End namespace Foam
339 
340 // ************************************************************************* //
Foam::quadricFitting::meanCurvature
scalar meanCurvature() const
Return mean curvature.
Definition: quadricFittingI.H:299
Foam::quadricFitting::transformedPoints_
DynList< point > transformedPoints_
transformed coordinates of other points
Definition: quadricFitting.H:70
Foam::symm
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
Definition: dimensionedSymmTensor.C:82
Foam::SymmTensor< scalar >
Foam::plane::nearestPoint
point nearestPoint(const point &p) const
Return nearest point in the plane for the given point.
Definition: plane.C:310
quadricFitting.H
Foam::simpleMatrix
A simple square matrix solver with scalar coefficients.
Definition: simpleMatrix.H:47
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
p
p
Definition: pEqn.H:62
Foam::quadricFitting::calculateCoordinateSystem
void calculateCoordinateSystem()
calculate transformed coordinate system
Definition: quadricFittingI.H:58
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::quadricFitting::minCurvatureVector
vector minCurvatureVector() const
Return min curvature vector.
Definition: quadricFittingI.H:311
Foam::quadricFitting::calculateQuadricCoeffs
void calculateQuadricCoeffs()
calculate coefficients of the quadric surface fit
Definition: quadricFittingI.H:114
Foam::quadricFitting::calculateNormalVector
void calculateNormalVector()
initial estimate of the normal vector
Definition: quadricFittingI.H:37
Foam::sin
dimensionedScalar sin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:255
Foam::quadricFitting::normal_
vector normal_
normal vector at the origin
Definition: quadricFitting.H:58
Foam::simpleMatrix::LUsolve
Field< Type > LUsolve() const
Solve the matrix using LU decomposition with pivoting.
Definition: simpleMatrix.C:86
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::quadricFitting::gaussianCurvature
scalar gaussianCurvature() const
Return Gaussian curvature.
Definition: quadricFittingI.H:305
Foam::quadricFitting::calculateBestFit
void calculateBestFit()
Definition: quadricFittingI.H:158
Foam::quadricFitting::~quadricFitting
~quadricFitting()
Definition: quadricFittingI.H:267
Foam::simpleMatrix::source
Field< Type > & source()
Return access to the source.
Definition: simpleMatrix.H:97
Foam::plane
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
Definition: plane.H:60
Foam::quadricFitting::vecY_
vector vecY_
y-coordinate vector for the transformed coordinate system
Definition: quadricFitting.H:64
Foam::label
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
Foam::quadricFitting::vecX_
vector vecX_
x-coordinate vector for the transformed coordinate system
Definition: quadricFitting.H:61
Foam::eigenVector
vector eigenVector(const tensor &, const scalar lambda)
Definition: tensor.C:207
Foam::eigenValues
dimensionedVector eigenValues(const dimensionedTensor &dt)
Definition: dimensionedTensor.C:146
Foam::stabilise
tmp< DimensionedField< scalar, GeoMesh > > stabilise(const DimensionedField< scalar, GeoMesh > &dsf, const dimensioned< scalar > &ds)
Definition: DimensionedScalarField.C:40
Foam::Info
messageStream Info
delta
scalar delta
Definition: LISASMDCalcMethod2.H:8
Foam::quadricFitting::coefficients_
scalarField coefficients_
coefficients of the quadric surface
Definition: quadricFitting.H:73
Foam::quadricFitting::origin_
point origin_
seed point for fitting the quadric surface
Definition: quadricFitting.H:55
Foam::quadricFitting::normal
const vector & normal() const
Return surface normal.
Definition: quadricFittingI.H:273
Foam::FatalError
error FatalError
Foam::SymmTensor< scalar >::zero
static const SymmTensor zero
Definition: SymmTensor.H:77
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::quadricFitting::quadricFitting
quadricFitting(const point &, const vector, const ListType &)
Construct from point, normal, and neighbouring points.
Definition: quadricFittingI.H:201
Foam::DynList
Definition: DynList.H:53
Foam::quadricFitting::minCurvature
scalar minCurvature() const
Return min curvature.
Definition: quadricFittingI.H:279
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::quadricFitting::otherPoints_
DynList< point > otherPoints_
other points
Definition: quadricFitting.H:67
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:49
Foam::Vector< scalar >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:142
Foam::DynList::setSize
void setSize(const label)
Reset size of List.
Definition: DynListI.H:263
Foam::atan
dimensionedScalar atan(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:260
FatalErrorIn
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:313
Foam::quadricFitting::maxCurvatureVector
vector maxCurvatureVector() const
Return max curvature vector.
Definition: quadricFittingI.H:324
Foam::quadricFitting::maxCurvature
scalar maxCurvature() const
Return max curvature.
Definition: quadricFittingI.H:289
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
normal
A normal distribution model.
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:256