00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #include <math_Gauss.hxx>
00026 #include <math_Householder.hxx>
00027 #include <Geom_BSplineSurface.hxx>
00028
00029 #include <Mod/Mesh/App/Core/Approximation.h>
00030 #include <Base/Sequencer.h>
00031 #include <Base/Tools2D.h>
00032
00033 #include "ApproxSurface.h"
00034
00035 using namespace Reen;
00036
00037
00038
00039 SplineBasisfunction::SplineBasisfunction(int iSize)
00040 : _vKnotVector(0,iSize-1)
00041 {
00042 }
00043
00044 SplineBasisfunction::SplineBasisfunction
00045 (TColStd_Array1OfReal& vKnots,
00046 TColStd_Array1OfInteger& vMults,
00047 int iSize,
00048 int iOrder)
00049 : _vKnotVector(0,iSize-1)
00050 {
00051 int sum = 0;
00052 for (int h=vMults.Lower(); h<=vMults.Upper(); h++)
00053 sum += vMults(h);
00054
00055 if (vKnots.Length() != vMults.Length() || iSize != sum)
00056 {
00057
00058 Standard_ConstructionError::Raise("BSplineBasis");
00059 }
00060
00061 int k=0;
00062 for (int i=vMults.Lower(); i<=vMults.Upper(); i++)
00063 {
00064 for (int j=0; j<vMults(i); j++)
00065 {
00066 _vKnotVector(k) = vKnots(i);
00067 k++;
00068 }
00069 }
00070
00071 _iOrder = iOrder;
00072 }
00073
00074 SplineBasisfunction::SplineBasisfunction(TColStd_Array1OfReal& vKnots, int iOrder)
00075 : _vKnotVector(0,vKnots.Length()-1)
00076 {
00077 _vKnotVector = vKnots;
00078 _iOrder = iOrder;
00079 }
00080
00081 SplineBasisfunction::~SplineBasisfunction()
00082 {
00083 }
00084
00085 void SplineBasisfunction::SetKnots(TColStd_Array1OfReal& vKnots, int iOrder)
00086 {
00087 if (_vKnotVector.Length() != vKnots.Length())
00088 Standard_RangeError::Raise("BSplineBasis");
00089
00090 _vKnotVector = vKnots;
00091 _iOrder = iOrder;
00092 }
00093
00094 void SplineBasisfunction::SetKnots(TColStd_Array1OfReal& vKnots, TColStd_Array1OfInteger& vMults,
00095 int iOrder)
00096 {
00097 int sum = 0;
00098 for (int h=vMults.Lower(); h<=vMults.Upper(); h++)
00099 sum += vMults(h);
00100
00101 if (vKnots.Length() != vMults.Length() || _vKnotVector.Length() != sum)
00102 {
00103
00104 Standard_RangeError::Raise("BSplineBasis");
00105 }
00106 int k=0;
00107 for (int i=vMults.Lower(); i<=vMults.Upper(); i++)
00108 {
00109 for (int j=0; j<vMults(i); j++)
00110 {
00111 _vKnotVector(k) = vKnots(i);
00112 k++;
00113 }
00114 }
00115
00116 _iOrder = iOrder;
00117 }
00118
00120
00121 BSplineBasis::BSplineBasis(int iSize)
00122 : SplineBasisfunction(iSize)
00123 {
00124 }
00125
00126 BSplineBasis::BSplineBasis(TColStd_Array1OfReal& vKnots, TColStd_Array1OfInteger& vMults, int iSize,
00127 int iOrder)
00128 : SplineBasisfunction(vKnots, vMults, iSize, iOrder)
00129 {
00130 }
00131
00132 BSplineBasis::BSplineBasis(TColStd_Array1OfReal& vKnots, int iOrder)
00133 : SplineBasisfunction(vKnots, iOrder)
00134 {
00135 }
00136
00137 BSplineBasis::~BSplineBasis()
00138 {
00139 }
00140
00141 int BSplineBasis::FindSpan(double fParam)
00142 {
00143 int n = _vKnotVector.Length()-_iOrder-1;
00144 if (fParam == _vKnotVector(n+1))
00145 return n;
00146
00147 int low = _iOrder-1;
00148 int high = n+1;
00149 int mid = (low+high)/2;
00150
00151 while (fParam < _vKnotVector(mid) || fParam>= _vKnotVector(mid+1))
00152 {
00153 if (fParam < _vKnotVector(mid))
00154 high = mid;
00155 else
00156 low = mid;
00157 mid = (low+high)/2;
00158 }
00159
00160 return mid;
00161 }
00162
00163 void BSplineBasis::AllBasisFunctions(double fParam, TColStd_Array1OfReal& vFuncVals)
00164 {
00165 if (vFuncVals.Length() != _iOrder)
00166 Standard_RangeError::Raise("BSplineBasis");
00167
00168 int iIndex = FindSpan(fParam);
00169
00170 TColStd_Array1OfReal zaehler_left(1,_iOrder-1);
00171 TColStd_Array1OfReal zaehler_right(1,_iOrder-1);
00172 vFuncVals(0) = 1.0f;
00173
00174 for (int j=1; j<_iOrder; j++)
00175 {
00176 zaehler_left(j) = fParam - _vKnotVector(iIndex+1-j);
00177 zaehler_right(j) = _vKnotVector(iIndex+j) - fParam;
00178 double saved = 0.0f;
00179 for (int r=0; r<j; r++)
00180 {
00181 double tmp = vFuncVals(r)/(zaehler_right(r+1) + zaehler_left(j-r));
00182 vFuncVals(r) = saved + zaehler_right(r+1)*tmp;
00183 saved = zaehler_left(j-r)*tmp;
00184 }
00185
00186 vFuncVals(j) = saved;
00187 }
00188 }
00189
00190 double BSplineBasis::BasisFunction(int iIndex, double fParam)
00191 {
00192 int m = _vKnotVector.Length()-1;
00193 int p = _iOrder-1;
00194 double saved;
00195 TColStd_Array1OfReal N(0,p);
00196
00197 if ((iIndex == 0 && fParam == _vKnotVector(0)) ||
00198 (iIndex == m-p-1 && fParam == _vKnotVector(m)))
00199 {
00200 return 1.0f;
00201 }
00202
00203 if (fParam < _vKnotVector(iIndex) || fParam >= _vKnotVector(iIndex+p+1))
00204 {
00205 return 0.0f;
00206 }
00207
00208 for (int j=0; j<=p; j++)
00209 {
00210 if (fParam >= _vKnotVector(iIndex+j) && fParam < _vKnotVector(iIndex+j+1))
00211 N(j) = 1.0f;
00212 else
00213 N(j) = 0.0f;
00214 }
00215
00216 for (int k=1; k<=p; k++)
00217 {
00218 if (N(0) == 0.0f)
00219 saved = 0.0f;
00220 else
00221 saved = ((fParam - _vKnotVector(iIndex))*N(0)) / (_vKnotVector(iIndex+k) - _vKnotVector(iIndex));
00222
00223 for (int j=0; j<p-k+1; j++)
00224 {
00225 double Tleft = _vKnotVector(iIndex+j+1);
00226 double Tright = _vKnotVector(iIndex+j+k+1);
00227
00228 if (N(j+1) == 0.0)
00229 {
00230 N(j) = saved;
00231 saved = 0.0;
00232 }
00233 else
00234 {
00235 double tmp = N(j+1)/(Tright-Tleft);
00236 N(j) = saved + (Tright - fParam)*tmp;
00237 saved = (fParam-Tleft)*tmp;
00238 }
00239 }
00240 }
00241
00242 return N(0);
00243 }
00244
00245 void BSplineBasis::DerivativesOfBasisFunction(int iIndex, int iMaxDer, double fParam,
00246 TColStd_Array1OfReal& Derivat)
00247 {
00248 int iMax = iMaxDer;
00249 if (Derivat.Length() != iMax+1)
00250 Standard_RangeError::Raise("BSplineBasis");
00251
00252 if (iMax >= _iOrder)
00253 {
00254 for (int i=_iOrder; i<=iMaxDer; i++)
00255 Derivat(i) = 0.0f;
00256 iMax = _iOrder - 1;
00257 }
00258
00259 TColStd_Array1OfReal ND(0, iMax);
00260 int p = _iOrder-1;
00261 math_Matrix N(0,p,0,p);
00262 double saved;
00263
00264
00265 if (fParam < _vKnotVector(iIndex) || fParam >= _vKnotVector(iIndex+p+1))
00266 {
00267 for (int k=0; k<=iMax; k++)
00268 Derivat(k) = 0.0f;
00269 return;
00270 }
00271
00272
00273 for (int j=0; j<_iOrder; j++)
00274 {
00275 if (fParam >= _vKnotVector(iIndex+j) && fParam < _vKnotVector(iIndex+j+1))
00276 N(j,0) = 1.0f;
00277 else
00278 N(j,0) = 0.0f;
00279 }
00280
00281
00282 for (int k=1; k<_iOrder; k++)
00283 {
00284 if (N(0,k-1) == 0.0f)
00285 saved = 0.0f;
00286 else
00287 saved = ((fParam - _vKnotVector(iIndex))*N(0,k-1))/(_vKnotVector(iIndex+k)-_vKnotVector(iIndex));
00288 for (int j=0; j<p-k+1; j++)
00289 {
00290 double Tleft = _vKnotVector(iIndex+j+1);
00291 double Tright = _vKnotVector(iIndex+j+k+1);
00292
00293 if (N(j+1,k-1) == 0.0)
00294 {
00295 N(j,k) = saved;
00296 saved = 0.0f;
00297 }
00298 else
00299 {
00300 double tmp = N(j+1,k-1)/(Tright-Tleft);
00301 N(j,k) = saved + (Tright-fParam)*tmp;
00302 saved = (fParam-Tleft)*tmp;
00303 }
00304 }
00305 }
00306
00307
00308 Derivat(0) = N(0,p);
00309
00310 for (int k=1; k<=iMax; k++)
00311 {
00312 for (int j=0; j<=k; j++)
00313 {
00314
00315 ND(j) = N(j,p-k);
00316 }
00317
00318 for (int jj=1; jj<=k; jj++)
00319 {
00320 if (ND(0) == 0.0f)
00321 saved = 0.0f;
00322 else
00323 saved = ND(0)/(_vKnotVector(iIndex+p-k+jj) - _vKnotVector(iIndex));
00324
00325 for (int j=0; j<k-jj+1; j++)
00326 {
00327 double Tleft = _vKnotVector(iIndex+j+1);
00328 double Tright = _vKnotVector(iIndex+j+p-k+jj+1);
00329 if (ND(j+1) == 0.0f)
00330 {
00331 ND(j) = (p-k+jj)*saved;
00332 saved = 0.0f;
00333 }
00334 else
00335 {
00336 double tmp = ND(j+1)/(Tright-Tleft);
00337 ND(j) = (p-k+jj)*(saved-tmp);
00338 saved = tmp;
00339 }
00340 }
00341 }
00342
00343 Derivat(k) = ND(0);
00344 }
00345
00346 return;
00347 }
00348
00349 double BSplineBasis::DerivativeOfBasisFunction(int iIndex, int iMaxDer, double fParam)
00350 {
00351 int iMax = iMaxDer;
00352
00353
00354 if (iMax == 0)
00355 return BasisFunction(iIndex, fParam);
00356
00357
00358 if (iMax >= _iOrder)
00359 {
00360 return 0.0f;
00361 }
00362
00363 TColStd_Array1OfReal ND(0, iMax);
00364 int p = _iOrder-1;
00365 math_Matrix N(0,p,0,p);
00366 double saved;
00367
00368
00369 if (fParam < _vKnotVector(iIndex) || fParam >= _vKnotVector(iIndex+p+1))
00370 {
00371 return 0.0f;
00372 }
00373
00374
00375 for (int j=0; j<_iOrder; j++)
00376 {
00377 if (fParam >= _vKnotVector(iIndex+j) && fParam < _vKnotVector(iIndex+j+1))
00378 N(j,0) = 1.0f;
00379 else
00380 N(j,0) = 0.0f;
00381 }
00382
00383
00384 for (int k=1; k<_iOrder; k++)
00385 {
00386 if (N(0,k-1) == 0.0f)
00387 saved = 0.0f;
00388 else
00389 saved = ((fParam - _vKnotVector(iIndex))*N(0,k-1))/(_vKnotVector(iIndex+k)-_vKnotVector(iIndex));
00390 for (int j=0; j<p-k+1; j++)
00391 {
00392 double Tleft = _vKnotVector(iIndex+j+1);
00393 double Tright = _vKnotVector(iIndex+j+k+1);
00394
00395 if (N(j+1,k-1) == 0.0)
00396 {
00397 N(j,k) = saved;
00398 saved = 0.0f;
00399 }
00400 else
00401 {
00402 double tmp = N(j+1,k-1)/(Tright-Tleft);
00403 N(j,k) = saved + (Tright-fParam)*tmp;
00404 saved = (fParam-Tleft)*tmp;
00405 }
00406 }
00407 }
00408
00409
00410 for (int j=0; j<=iMax; j++)
00411 {
00412
00413 ND(j) = N(j,p-iMax);
00414 }
00415
00416 for (int jj=1; jj<=iMax; jj++)
00417 {
00418 if (ND(0) == 0.0f)
00419 saved = 0.0f;
00420 else
00421 saved = ND(0)/(_vKnotVector(iIndex+p-iMax+jj) - _vKnotVector(iIndex));
00422
00423 for (int j=0; j<iMax-jj+1; j++)
00424 {
00425 double Tleft = _vKnotVector(iIndex+j+1);
00426 double Tright = _vKnotVector(iIndex+j+p-iMax+jj+1);
00427 if (ND(j+1) == 0.0f)
00428 {
00429 ND(j) = (p-iMax+jj)*saved;
00430 saved = 0.0f;
00431 }
00432 else
00433 {
00434 double tmp = ND(j+1)/(Tright-Tleft);
00435 ND(j) = (p-iMax+jj)*(saved-tmp);
00436 saved = tmp;
00437 }
00438 }
00439 }
00440
00441 return ND(0);
00442 }
00443
00444 double BSplineBasis::GetIntegralOfProductOfBSplines(int iIdx1, int iIdx2, int iOrd1, int iOrd2)
00445 {
00446 int iMax = CalcSize(iOrd1, iOrd2);
00447 double dIntegral=0.0f;
00448 double fMin, fMax;
00449
00450 TColStd_Array1OfReal vRoots(0,iMax), vWeights(0,iMax);
00451 GenerateRootsAndWeights(vRoots, vWeights);
00452
00453
00454
00455 int iBegin=0; int iEnd=0;
00456 FindIntegrationArea(iIdx1, iIdx2, iBegin, iEnd);
00457
00458 for (int j=iBegin; j<iEnd; j++)
00459 {
00460 fMax = _vKnotVector(j+1);
00461 fMin = _vKnotVector(j);
00462
00463 if (fMax > fMin)
00464 {
00465 for (int i=0; i<=iMax; i++)
00466 {
00467 double fParam = 0.5*(vRoots(i)+1)*(fMax-fMin)+fMin;
00468 dIntegral += 0.5*(fMax-fMin)*vWeights(i) *
00469 DerivativeOfBasisFunction(iIdx1, iOrd1, fParam) *
00470 DerivativeOfBasisFunction(iIdx2, iOrd2, fParam);
00471 }
00472 }
00473 }
00474
00475 return dIntegral;
00476 }
00477
00478 void BSplineBasis::GenerateRootsAndWeights(TColStd_Array1OfReal& vRoots, TColStd_Array1OfReal& vWeights)
00479 {
00480 int iSize = vRoots.Length();
00481
00482
00483 if (iSize == 1)
00484 {
00485 vRoots(0) = 0.0f; vWeights(0) = 2.0f;
00486 }
00487 else if (iSize == 2)
00488 {
00489 vRoots(0) = 0.57735f; vWeights(0) = 1.0f;
00490 vRoots(1) = -vRoots(0); vWeights(1) = vWeights(0);
00491 }
00492 else if (iSize == 4)
00493 {
00494 vRoots(0) = 0.33998f; vWeights(0) = 0.65214f;
00495 vRoots(1) = 0.86113f; vWeights(1) = 0.34785f;
00496 vRoots(2) = -vRoots(0); vWeights(2) = vWeights(0);
00497 vRoots(3) = -vRoots(1); vWeights(3) = vWeights(1);
00498 }
00499 else if (iSize == 6)
00500 {
00501 vRoots(0) = 0.23861f; vWeights(0) = 0.46791f;
00502 vRoots(1) = 0.66120f; vWeights(1) = 0.36076f;
00503 vRoots(2) = 0.93246f; vWeights(2) = 0.17132f;
00504 vRoots(3) = -vRoots(0); vWeights(3) = vWeights(0);
00505 vRoots(4) = -vRoots(1); vWeights(4) = vWeights(1);
00506 vRoots(5) = -vRoots(2); vWeights(5) = vWeights(2);
00507 }
00508 else if (iSize == 8)
00509 {
00510 vRoots(0) = 0.18343f; vWeights(0) = 0.36268f;
00511 vRoots(1) = 0.52553f; vWeights(1) = 0.31370f;
00512 vRoots(2) = 0.79666f; vWeights(2) = 0.22238f;
00513 vRoots(3) = 0.96028f; vWeights(3) = 0.10122f;
00514 vRoots(4) = -vRoots(0); vWeights(4) = vWeights(0);
00515 vRoots(5) = -vRoots(1); vWeights(5) = vWeights(1);
00516 vRoots(6) = -vRoots(2); vWeights(6) = vWeights(2);
00517 vRoots(7) = -vRoots(3); vWeights(7) = vWeights(3);
00518 }
00519 else if (iSize == 10)
00520 {
00521 vRoots(0) = 0.14887f; vWeights(0) = 0.29552f;
00522 vRoots(1) = 0.43339f; vWeights(1) = 0.26926f;
00523 vRoots(2) = 0.67940f; vWeights(2) = 0.21908f;
00524 vRoots(3) = 0.86506f; vWeights(3) = 0.14945f;
00525 vRoots(4) = 0.97390f; vWeights(4) = 0.06667f;
00526 vRoots(5) = -vRoots(0); vWeights(5) = vWeights(0);
00527 vRoots(6) = -vRoots(1); vWeights(6) = vWeights(1);
00528 vRoots(7) = -vRoots(2); vWeights(7) = vWeights(2);
00529 vRoots(8) = -vRoots(3); vWeights(8) = vWeights(3);
00530 vRoots(9) = -vRoots(4); vWeights(9) = vWeights(4);
00531 }
00532 else
00533 {
00534 vRoots(0) = 0.12523f; vWeights(0) = 0.24914f;
00535 vRoots(1) = 0.36783f; vWeights(1) = 0.23349f;
00536 vRoots(2) = 0.58731f; vWeights(2) = 0.20316f;
00537 vRoots(3) = 0.76990f; vWeights(3) = 0.16007f;
00538 vRoots(4) = 0.90411f; vWeights(4) = 0.10693f;
00539 vRoots(5) = 0.98156f; vWeights(5) = 0.04717f;
00540 vRoots(6) = -vRoots(0); vWeights(6) = vWeights(0);
00541 vRoots(7) = -vRoots(1); vWeights(7) = vWeights(1);
00542 vRoots(8) = -vRoots(2); vWeights(8) = vWeights(2);
00543 vRoots(9) = -vRoots(3); vWeights(9) = vWeights(3);
00544 vRoots(10)= -vRoots(4); vWeights(10)= vWeights(4);
00545 vRoots(11)= -vRoots(5); vWeights(11)= vWeights(5);
00546 }
00547 }
00548
00549 void BSplineBasis::FindIntegrationArea(int iIdx1, int iIdx2, int& iBegin, int& iEnd)
00550 {
00551
00552 if (iIdx2 < iIdx1)
00553 {
00554 int tmp=iIdx1;
00555 iIdx1 = iIdx2;
00556 iIdx2 = tmp;
00557 }
00558
00559 iBegin = iIdx2;
00560 iEnd = iIdx1+_iOrder;
00561 if (iEnd == _vKnotVector.Upper())
00562 iEnd -= 1;
00563 }
00564
00565 int BSplineBasis::CalcSize(int r, int s)
00566 {
00567 int iMaxDegree = 2*(_iOrder-1)-r-s;
00568
00569 if (iMaxDegree < 0)
00570 return 0;
00571 else if (iMaxDegree < 4)
00572 return 1;
00573 else if (iMaxDegree < 8)
00574 return 3;
00575 else if (iMaxDegree < 12)
00576 return 5;
00577 else if (iMaxDegree < 16)
00578 return 7;
00579 else if (iMaxDegree < 20)
00580 return 9;
00581 else
00582 return 11;
00583 }
00584
00586
00587 ParameterCorrection::ParameterCorrection(unsigned short usUOrder, unsigned short usVOrder,
00588 unsigned short usUCtrlpoints, unsigned short usVCtrlpoints)
00589 : _usUOrder(usUOrder),
00590 _usVOrder(usVOrder),
00591 _usUCtrlpoints(usUCtrlpoints),
00592 _usVCtrlpoints(usVCtrlpoints),
00593 _vCtrlPntsOfSurf(0,usUCtrlpoints-1,0,usVCtrlpoints-1),
00594 _vUKnots(0,usUCtrlpoints-usUOrder+1),
00595 _vVKnots(0,usVCtrlpoints-usVOrder+1),
00596 _vUMults(0,usUCtrlpoints-usUOrder+1),
00597 _vVMults(0,usVCtrlpoints-usVOrder+1)
00598 {
00599 _bGetUVDir = false;
00600 _bSmoothing = false;
00601 _fSmoothInfluence = 0.0f;
00602 }
00603
00604 void ParameterCorrection::CalcEigenvectors()
00605 {
00606 MeshCore::PlaneFit planeFit;
00607
00608
00609 for (int i=_pvcPoints->Lower(); i<=_pvcPoints->Upper(); i++) {
00610 planeFit.AddPoint(Base::Vector3f(
00611 (float)(*_pvcPoints)(i).X(),
00612 (float)(*_pvcPoints)(i).Y(),
00613 (float)(*_pvcPoints)(i).Z()));
00614 }
00615
00616
00617 planeFit.Fit();
00618 _clU = planeFit.GetDirU();
00619 _clV = planeFit.GetDirV();
00620 _clW = planeFit.GetNormal();
00621 }
00622
00623 bool ParameterCorrection::DoInitialParameterCorrection(float fSizeFactor)
00624 {
00625
00626 if (_bGetUVDir == false)
00627 CalcEigenvectors();
00628 if (!GetUVParameters(fSizeFactor))
00629 return false;
00630 if (_bSmoothing)
00631 {
00632 if (!SolveWithSmoothing(_fSmoothInfluence))
00633 return false;
00634 }
00635 else
00636 {
00637 if (!SolveWithoutSmoothing())
00638 return false;
00639 }
00640
00641 return true;
00642 }
00643
00644 bool ParameterCorrection::GetUVParameters(float fSizeFactor)
00645 {
00646
00647 Base::Vector3f e[3];
00648 e[0] = _clU;
00649 e[1] = _clV;
00650 e[2] = _clW;
00651
00652
00653 Base::Vector3f b[3];
00654 b[0]=Base::Vector3f(1.0f,0.0f,0.0f); b[1]=Base::Vector3f(0.0f,1.0f,0.0f);b[2]=Base::Vector3f(0.0f,0.0f,1.0f);
00655
00656 if ((e[0]%e[1])*e[2] < 0)
00657 {
00658 Base::Vector3f tmp = e[0];
00659 e[0] = e[1];
00660 e[1] = tmp;
00661 }
00662
00663
00664 Wm4::Matrix3f clRotMatTrans;
00665 for (int i=0; i<3; i++)
00666 {
00667 for (int j=0; j<3; j++)
00668 {
00669 clRotMatTrans[i][j] = b[j]*e[i];
00670 }
00671 }
00672
00673 std::vector<Base::Vector2D> vcProjPts;
00674 Base::BoundBox2D clBBox;
00675
00676
00677
00678 for (int ii=_pvcPoints->Lower(); ii<=_pvcPoints->Upper(); ii++)
00679 {
00680 Wm4::Vector3f clProjPnt = clRotMatTrans * ( Wm4::Vector3f(
00681 (float)(*_pvcPoints)(ii).X(),
00682 (float)(*_pvcPoints)(ii).Y(),
00683 (float)(*_pvcPoints)(ii).Z()));
00684 vcProjPts.push_back(Base::Vector2D(clProjPnt.X(), clProjPnt.Y()));
00685 clBBox &= (Base::Vector2D(clProjPnt.X(), clProjPnt.Y()));
00686 }
00687
00688 if ((clBBox.fMaxX == clBBox.fMinX) || (clBBox.fMaxY == clBBox.fMinY))
00689 return false;
00690 float tx = fSizeFactor*clBBox.fMinX-(fSizeFactor-1.0f)*clBBox.fMaxX;
00691 float ty = fSizeFactor*clBBox.fMinY-(fSizeFactor-1.0f)*clBBox.fMaxY;
00692 float fDeltaX = (2*fSizeFactor-1.0f)*(clBBox.fMaxX - clBBox.fMinX);
00693 float fDeltaY = (2*fSizeFactor-1.0f)*(clBBox.fMaxY - clBBox.fMinY);
00694
00695
00696 _pvcUVParam->Init(gp_Pnt2d(0.0f, 0.0f));
00697 int ii=0;
00698 if (clBBox.fMaxX - clBBox.fMinX >= clBBox.fMaxY - clBBox.fMinY)
00699 for (std::vector<Base::Vector2D>::iterator It2=vcProjPts.begin(); It2!=vcProjPts.end(); It2++)
00700 {
00701 (*_pvcUVParam)(ii) = gp_Pnt2d((It2->fX-tx)/fDeltaX, (It2->fY-ty)/fDeltaY);
00702 ii++;
00703 }
00704 else
00705 for (std::vector<Base::Vector2D>::iterator It2=vcProjPts.begin(); It2!=vcProjPts.end(); It2++)
00706 {
00707 (*_pvcUVParam)(ii) = gp_Pnt2d((It2->fY-ty)/fDeltaY, (It2->fX-tx)/fDeltaX);
00708 ii++;
00709 }
00710
00711 return true;
00712 }
00713
00714 void ParameterCorrection::SetUVW(const Base::Vector3f& clU, const Base::Vector3f& clV, const Base::Vector3f& clW, bool bUseDir)
00715 {
00716 _clU = clU;
00717 _clV = clV;
00718 _clW = clW;
00719 _bGetUVDir = bUseDir;
00720 }
00721
00722 void ParameterCorrection::GetUVW(Base::Vector3f& clU, Base::Vector3f& clV, Base::Vector3f& clW) const
00723 {
00724 clU = _clU;
00725 clV = _clV;
00726 clW = _clW;
00727 }
00728
00729 Base::Vector3f ParameterCorrection::GetGravityPoint() const
00730 {
00731 unsigned long ulSize = _pvcPoints->Length();
00732 float x=0.0f, y=0.0f, z=0.0f;
00733 for (int i=_pvcPoints->Lower(); i<=_pvcPoints->Upper(); i++)
00734 {
00735 x += (float)(*_pvcPoints)(i).X();
00736 y += (float)(*_pvcPoints)(i).Y();
00737 z += (float)(*_pvcPoints)(i).Z();
00738 }
00739
00740 return Base::Vector3f(float(x/ulSize), float(y/ulSize), float(z/ulSize));
00741 }
00742
00743 Handle(Geom_BSplineSurface) ParameterCorrection::CreateSurface(const TColgp_Array1OfPnt& points,
00744 unsigned short usIter,
00745 bool bParaCor,
00746 float fSizeFactor)
00747 {
00748 if (_pvcPoints != NULL)
00749 {
00750 delete _pvcPoints;
00751 _pvcPoints = NULL;
00752 delete _pvcUVParam;
00753 _pvcUVParam = NULL;
00754 }
00755 _pvcPoints = new TColgp_Array1OfPnt(points.Lower(), points.Upper());
00756 *_pvcPoints = points;
00757 _pvcUVParam = new TColgp_Array1OfPnt2d(points.Lower(), points.Upper());
00758
00759 if (_usUCtrlpoints*_usVCtrlpoints > _pvcPoints->Length())
00760 return NULL;
00761 if(!DoInitialParameterCorrection(fSizeFactor))
00762 return NULL;
00763
00764 if (bParaCor)
00765 DoParameterCorrection(usIter);
00766
00767 return new Geom_BSplineSurface
00768 (_vCtrlPntsOfSurf,
00769 _vUKnots,
00770 _vVKnots,
00771 _vUMults,
00772 _vVMults,
00773 _usUOrder-1,
00774 _usVOrder-1);
00775 }
00776
00777 void ParameterCorrection::EnableSmoothing(bool bSmooth, float fSmoothInfl)
00778 {
00779 _bSmoothing = bSmooth;
00780 _fSmoothInfluence = fSmoothInfl;
00781 }
00782
00784
00785
00786 BSplineParameterCorrection::BSplineParameterCorrection(unsigned short usUOrder, unsigned short usVOrder,
00787 unsigned short usUCtrlpoints, unsigned short usVCtrlpoints)
00788 : ParameterCorrection
00789 (usUOrder, usVOrder, usUCtrlpoints, usVCtrlpoints),
00790 _clUSpline(usUCtrlpoints+usUOrder),
00791 _clVSpline(usVCtrlpoints+usVOrder),
00792 _clSmoothMatrix
00793 (0,usUCtrlpoints*usVCtrlpoints-1,
00794 0,usUCtrlpoints*usVCtrlpoints-1),
00795 _clFirstMatrix
00796 (0,usUCtrlpoints*usVCtrlpoints-1,
00797 0,usUCtrlpoints*usVCtrlpoints-1),
00798 _clSecondMatrix
00799 (0,usUCtrlpoints*usVCtrlpoints-1,
00800 0,usUCtrlpoints*usVCtrlpoints-1),
00801 _clThirdMatrix
00802 (0,usUCtrlpoints*usVCtrlpoints-1,
00803 0,usUCtrlpoints*usVCtrlpoints-1)
00804 {
00805 Init();
00806 }
00807
00808 void BSplineParameterCorrection::Init()
00809 {
00810
00811 _pvcUVParam = NULL;
00812 _pvcPoints = NULL;
00813 _clFirstMatrix.Init(0.0f);
00814 _clSecondMatrix.Init(0.0f);
00815 _clThirdMatrix.Init(0.0f);
00816 _clSmoothMatrix.Init(0.0f);
00817
00818
00819 unsigned short usUMax = _usUCtrlpoints-_usUOrder+1;
00820 unsigned short usVMax = _usVCtrlpoints-_usVOrder+1;
00821
00822
00823
00824 for (int i=0;i<=usUMax; i++)
00825 {
00826 _vUKnots(i) = ((float)i) / ((float)usUMax);
00827 _vUMults(i) = 1;
00828 }
00829 _vUMults(0) = _usUOrder;
00830 _vUMults(usUMax) = _usUOrder;
00831
00832 for (int i=0; i<=usVMax; i++)
00833 {
00834 _vVKnots(i) = ((float)i) / ((float)usVMax);
00835 _vVMults(i) = 1;
00836 }
00837 _vVMults(0) = _usVOrder;
00838 _vVMults(usVMax) = _usVOrder;
00839
00840
00841 _clUSpline.SetKnots(_vUKnots, _vUMults, _usUOrder);
00842 _clVSpline.SetKnots(_vVKnots, _vVMults, _usVOrder);
00843 }
00844
00845 void BSplineParameterCorrection::SetUKnots(const std::vector<float>& afKnots)
00846 {
00847 if (afKnots.size() != (unsigned long)(_usUCtrlpoints+_usUOrder))
00848 return;
00849
00850 unsigned short usUMax = _usUCtrlpoints-_usUOrder+1;
00851
00852
00853
00854 for (int i=1;i<usUMax; i++)
00855 {
00856 _vUKnots(i) = afKnots[_usUOrder+i-1];
00857 _vUMults(i) = 1;
00858 }
00859
00860
00861 _clUSpline.SetKnots(_vUKnots, _vUMults, _usUOrder);
00862 }
00863
00864 void BSplineParameterCorrection::SetVKnots(const std::vector<float>& afKnots)
00865 {
00866 if (afKnots.size() != (unsigned long)(_usVCtrlpoints+_usVOrder))
00867 return;
00868
00869 unsigned short usVMax = _usVCtrlpoints-_usVOrder+1;
00870
00871
00872
00873 for (int i=1; i<usVMax; i++)
00874 {
00875 _vVKnots(i) = afKnots[_usVOrder+i-1];
00876 _vVMults(i) = 1;
00877 }
00878
00879
00880 _clVSpline.SetKnots(_vVKnots, _vVMults, _usVOrder);
00881 }
00882
00883 void BSplineParameterCorrection::DoParameterCorrection(unsigned short usIter)
00884 {
00885 int i=0;
00886 float fMaxDiff=0.0f, fMaxScalar=1.0f;
00887 float fWeight = _fSmoothInfluence;
00888
00889 Base::SequencerLauncher seq("Calc surface...", usIter*_pvcPoints->Length());
00890
00891 do
00892 {
00893 fMaxScalar = 1.0f;
00894 fMaxDiff = 0.0f;
00895
00896 Geom_BSplineSurface* pclBSplineSurf = new Geom_BSplineSurface
00897 (_vCtrlPntsOfSurf,
00898 _vUKnots,
00899 _vVKnots,
00900 _vUMults,
00901 _vVMults,
00902 _usUOrder-1,
00903 _usVOrder-1);
00904
00905 for (int ii=_pvcPoints->Lower();ii <=_pvcPoints->Upper();ii++)
00906 {
00907
00908 double fDeltaU, fDeltaV, fU, fV;
00909 gp_Vec P((*_pvcPoints)(ii).X(), (*_pvcPoints)(ii).Y(), (*_pvcPoints)(ii).Z());
00910 gp_Pnt PntX;
00911 gp_Vec Xu, Xv, Xuv, Xuu, Xvv;
00912
00913 pclBSplineSurf->D2((*_pvcUVParam)(ii).X(), (*_pvcUVParam)(ii).Y(), PntX, Xu, Xv, Xuu, Xvv, Xuv);
00914 gp_Vec X(PntX.X(), PntX.Y(), PntX.Z());
00915 gp_Vec ErrorVec = X - P;
00916
00917
00918 gp_Dir clNormal = Xu ^ Xv;
00919
00920
00921 if (!(X.IsEqual(P,0.001,0.001)))
00922 {
00923 ErrorVec.Normalize();
00924 if(fabs(clNormal*ErrorVec) < fMaxScalar)
00925 fMaxScalar = (float)fabs(clNormal*ErrorVec);
00926 }
00927
00928 fDeltaU = ( (P-X) * Xu ) / ( (P-X)*Xuu - Xu*Xu );
00929 if (fabs(fDeltaU) < FLOAT_EPS)
00930 fDeltaU = 0.0f;
00931 fDeltaV = ( (P-X) * Xv ) / ( (P-X)*Xvv - Xv*Xv );
00932 if (fabs(fDeltaV) < FLOAT_EPS)
00933 fDeltaV = 0.0f;
00934
00935
00936 fU = (*_pvcUVParam)(ii).X() - fDeltaU;
00937 fV = (*_pvcUVParam)(ii).Y() - fDeltaV;
00938 if (fU <= 1.0f && fU >= 0.0f &&
00939 fV <= 1.0f && fV >= 0.0f)
00940 {
00941 (*_pvcUVParam)(ii).SetX(fU);
00942 (*_pvcUVParam)(ii).SetY(fV);
00943 fMaxDiff = std::max<float>(float(fabs(fDeltaU)), fMaxDiff);
00944 fMaxDiff = std::max<float>(float(fabs(fDeltaV)), fMaxDiff);
00945 }
00946
00947 seq.next();
00948 }
00949
00950 if (_bSmoothing)
00951 {
00952 fWeight *= 0.5f;
00953 SolveWithSmoothing(fWeight);
00954 }
00955 else
00956 SolveWithoutSmoothing();
00957
00958 i++;
00959 }
00960 while(i<usIter && fMaxDiff > FLOAT_EPS && fMaxScalar < 0.99);
00961 }
00962
00963 bool BSplineParameterCorrection::SolveWithoutSmoothing()
00964 {
00965 unsigned long ulSize = _pvcPoints->Length();
00966 math_Matrix M (0, ulSize-1, 0,_usUCtrlpoints*_usVCtrlpoints-1);
00967 math_Matrix Xx (0, _usUCtrlpoints*_usVCtrlpoints-1,0,0);
00968 math_Matrix Xy (0, _usUCtrlpoints*_usVCtrlpoints-1,0,0);
00969 math_Matrix Xz (0, _usUCtrlpoints*_usVCtrlpoints-1,0,0);
00970 math_Vector bx (0, ulSize-1);
00971 math_Vector by (0, ulSize-1);
00972 math_Vector bz (0, ulSize-1);
00973
00974
00975 for (unsigned long i=0; i<ulSize; i++)
00976 {
00977 float fU = (float)(*_pvcUVParam)(i).X();
00978 float fV = (float)(*_pvcUVParam)(i).Y();
00979 unsigned long ulIdx=0;
00980
00981 for (unsigned short j=0; j<_usUCtrlpoints; j++)
00982 {
00983 for (unsigned short k=0; k<_usVCtrlpoints; k++)
00984 {
00985 M(i,ulIdx) = _clUSpline.BasisFunction(j,fU)*_clVSpline.BasisFunction(k,fV);
00986 ulIdx++;
00987 }
00988 }
00989 }
00990
00991
00992 for (int ii=_pvcPoints->Lower(); ii<=_pvcPoints->Upper(); ii++)
00993 {
00994 bx(ii) = (*_pvcPoints)(ii).X(); by(ii) = (*_pvcPoints)(ii).Y(); bz(ii) = (*_pvcPoints)(ii).Z();
00995 }
00996
00997
00998 math_Householder hhX(M,bx);
00999 math_Householder hhY(M,by);
01000 math_Householder hhZ(M,bz);
01001
01002 if (!(hhX.IsDone() && hhY.IsDone() && hhZ.IsDone()))
01003
01004 return false;
01005 Xx = hhX.AllValues();
01006 Xy = hhY.AllValues();
01007 Xz = hhZ.AllValues();
01008
01009 unsigned long ulIdx=0;
01010 for (unsigned short j=0;j<_usUCtrlpoints;j++)
01011 {
01012 for (unsigned short k=0;k<_usVCtrlpoints;k++)
01013 {
01014 _vCtrlPntsOfSurf(j,k) = gp_Pnt(Xx(ulIdx,0),Xy(ulIdx,0),Xz(ulIdx,0));
01015 ulIdx++;
01016 }
01017 }
01018
01019 return true;
01020 }
01021
01022 bool BSplineParameterCorrection::SolveWithSmoothing(float fWeight)
01023 {
01024 unsigned long ulSize = _pvcPoints->Length();
01025 unsigned long ulDim = _usUCtrlpoints*_usVCtrlpoints;
01026 math_Matrix M (0, ulSize-1, 0,_usUCtrlpoints*_usVCtrlpoints-1);
01027 math_Matrix MTM(0, _usUCtrlpoints*_usVCtrlpoints-1,
01028 0, _usUCtrlpoints*_usVCtrlpoints-1);
01029 math_Vector Xx (0, _usUCtrlpoints*_usVCtrlpoints-1);
01030 math_Vector Xy (0, _usUCtrlpoints*_usVCtrlpoints-1);
01031 math_Vector Xz (0, _usUCtrlpoints*_usVCtrlpoints-1);
01032 math_Vector bx (0, ulSize-1);
01033 math_Vector by (0, ulSize-1);
01034 math_Vector bz (0, ulSize-1);
01035 math_Vector Mbx(0, _usUCtrlpoints*_usVCtrlpoints-1);
01036 math_Vector Mby(0, _usUCtrlpoints*_usVCtrlpoints-1);
01037 math_Vector Mbz(0, _usUCtrlpoints*_usVCtrlpoints-1);
01038
01039
01040 for (unsigned long i=0; i<ulSize; i++)
01041 {
01042 float fU = (float)(*_pvcUVParam)(i).X();
01043 float fV = (float)(*_pvcUVParam)(i).Y();
01044 unsigned long ulIdx=0;
01045
01046 for (unsigned short j=0; j<_usUCtrlpoints; j++)
01047 {
01048 for (unsigned short k=0; k<_usVCtrlpoints; k++)
01049 {
01050 M(i,ulIdx) = _clUSpline.BasisFunction(j,fU)*_clVSpline.BasisFunction(k,fV);
01051 ulIdx++;
01052 }
01053 }
01054 }
01055
01056 for (unsigned long m=0; m<ulDim; m++)
01057 {
01058 for (unsigned long n=m; n<ulDim; n++)
01059 {
01060 MTM(m,n)=MTM(n,m)=M.Col(m)*M.Col(n);
01061 }
01062 }
01063
01064
01065 for (int ii=_pvcPoints->Lower(); ii<=_pvcPoints->Upper(); ii++)
01066 {
01067 bx(ii) = (*_pvcPoints)(ii).X(); by(ii) = (*_pvcPoints)(ii).Y(); bz(ii) = (*_pvcPoints)(ii).Z();
01068 }
01069 for (unsigned long i=0; i<ulDim; i++)
01070 {
01071 Mbx(i) = M.Col(i) * bx;
01072 Mby(i) = M.Col(i) * by;
01073 Mbz(i) = M.Col(i) * bz;
01074 }
01075
01076
01077 math_Gauss mgGaussX(MTM+fWeight*_clSmoothMatrix);
01078 math_Gauss mgGaussY(MTM+fWeight*_clSmoothMatrix);
01079 math_Gauss mgGaussZ(MTM+fWeight*_clSmoothMatrix);
01080
01081 mgGaussX.Solve(Mbx,Xx);
01082 if (!mgGaussX.IsDone())
01083 return false;
01084
01085 mgGaussY.Solve(Mby,Xy);
01086 if (!mgGaussY.IsDone())
01087 return false;
01088
01089 mgGaussZ.Solve(Mbz,Xz);
01090 if (!mgGaussZ.IsDone())
01091 return false;
01092
01093 unsigned long ulIdx=0;
01094 for (unsigned short j=0;j<_usUCtrlpoints;j++)
01095 {
01096 for (unsigned short k=0;k<_usVCtrlpoints;k++)
01097 {
01098 _vCtrlPntsOfSurf(j,k) = gp_Pnt(Xx(ulIdx),Xy(ulIdx),Xz(ulIdx));
01099 ulIdx++;
01100 }
01101 }
01102
01103 return true;
01104 }
01105
01106 void BSplineParameterCorrection::CalcSmoothingTerms(bool bRecalc, float fFirst, float fSecond, float fThird)
01107 {
01108 if (bRecalc)
01109 {
01110 Base::SequencerLauncher seq("Initializing...", 3 * _usUCtrlpoints * _usUCtrlpoints * _usVCtrlpoints * _usVCtrlpoints);
01111 CalcFirstSmoothMatrix(seq);
01112 CalcSecondSmoothMatrix(seq);
01113 CalcThirdSmoothMatrix(seq);
01114 }
01115
01116 _clSmoothMatrix = fFirst * _clFirstMatrix +
01117 fSecond * _clSecondMatrix +
01118 fThird * _clThirdMatrix ;
01119 }
01120
01121 void BSplineParameterCorrection::CalcFirstSmoothMatrix(Base::SequencerLauncher& seq)
01122 {
01123 unsigned long m=0;
01124 for (unsigned long k=0; k<_usUCtrlpoints; k++)
01125 {
01126 for (unsigned long l=0; l<_usVCtrlpoints; l++)
01127 {
01128 unsigned long n=0;
01129
01130 for (unsigned short i=0; i<_usUCtrlpoints; i++)
01131 {
01132 for (unsigned short j=0; j<_usVCtrlpoints; j++)
01133 {
01134 _clFirstMatrix(m,n) = _clUSpline.GetIntegralOfProductOfBSplines(i,k,1,1) *
01135 _clVSpline.GetIntegralOfProductOfBSplines(j,l,0,0) +
01136 _clUSpline.GetIntegralOfProductOfBSplines(i,k,0,0) *
01137 _clVSpline.GetIntegralOfProductOfBSplines(j,l,1,1);
01138 seq.next();
01139 n++;
01140 }
01141 }
01142 m++;
01143 }
01144 }
01145 }
01146
01147 void BSplineParameterCorrection::CalcSecondSmoothMatrix(Base::SequencerLauncher& seq)
01148 {
01149 unsigned long m=0;
01150 for (unsigned long k=0; k<_usUCtrlpoints; k++)
01151 {
01152 for (unsigned long l=0; l<_usVCtrlpoints; l++)
01153 {
01154 unsigned long n=0;
01155
01156 for (unsigned short i=0; i<_usUCtrlpoints; i++)
01157 {
01158 for (unsigned short j=0; j<_usVCtrlpoints; j++)
01159 {
01160 _clSecondMatrix(m,n) = _clUSpline.GetIntegralOfProductOfBSplines(i,k,2,2) *
01161 _clVSpline.GetIntegralOfProductOfBSplines(j,l,0,0) +
01162 2*_clUSpline.GetIntegralOfProductOfBSplines(i,k,1,1) *
01163 _clVSpline.GetIntegralOfProductOfBSplines(j,l,1,1) +
01164 _clUSpline.GetIntegralOfProductOfBSplines(i,k,0,0) *
01165 _clVSpline.GetIntegralOfProductOfBSplines(j,l,2,2);
01166 seq.next();
01167 n++;
01168 }
01169 }
01170 m++;
01171 }
01172 }
01173 }
01174
01175 void BSplineParameterCorrection::CalcThirdSmoothMatrix(Base::SequencerLauncher& seq)
01176 {
01177 unsigned long m=0;
01178 for (unsigned long k=0; k<_usUCtrlpoints; k++)
01179 {
01180 for (unsigned long l=0; l<_usVCtrlpoints; l++)
01181 {
01182 unsigned long n=0;
01183
01184 for (unsigned short i=0; i<_usUCtrlpoints; i++)
01185 {
01186 for (unsigned short j=0; j<_usVCtrlpoints; j++)
01187 {
01188 _clThirdMatrix(m,n) = _clUSpline.GetIntegralOfProductOfBSplines(i,k,3,3) *
01189 _clVSpline.GetIntegralOfProductOfBSplines(j,l,0,0) +
01190 _clUSpline.GetIntegralOfProductOfBSplines(i,k,3,1) *
01191 _clVSpline.GetIntegralOfProductOfBSplines(j,l,0,2) +
01192 _clUSpline.GetIntegralOfProductOfBSplines(i,k,1,3) *
01193 _clVSpline.GetIntegralOfProductOfBSplines(j,l,2,0) +
01194 _clUSpline.GetIntegralOfProductOfBSplines(i,k,1,1) *
01195 _clVSpline.GetIntegralOfProductOfBSplines(j,l,2,2) +
01196 _clUSpline.GetIntegralOfProductOfBSplines(i,k,2,2) *
01197 _clVSpline.GetIntegralOfProductOfBSplines(j,l,1,1) +
01198 _clUSpline.GetIntegralOfProductOfBSplines(i,k,0,2) *
01199 _clVSpline.GetIntegralOfProductOfBSplines(j,l,3,1) +
01200 _clUSpline.GetIntegralOfProductOfBSplines(i,k,2,0) *
01201 _clVSpline.GetIntegralOfProductOfBSplines(j,l,1,3) +
01202 _clUSpline.GetIntegralOfProductOfBSplines(i,k,0,0) *
01203 _clVSpline.GetIntegralOfProductOfBSplines(j,l,3,3) ;
01204 seq.next();
01205 n++;
01206 }
01207 }
01208 m++;
01209 }
01210 }
01211 }
01212
01213 void BSplineParameterCorrection::EnableSmoothing(bool bSmooth, float fSmoothInfl)
01214 {
01215 EnableSmoothing(bSmooth, fSmoothInfl, 1.0f, 0.0f, 0.0f);
01216 }
01217
01218 void BSplineParameterCorrection::EnableSmoothing(bool bSmooth, float fSmoothInfl,
01219 float fFirst, float fSec, float fThird)
01220 {
01221 if (_bSmoothing && bSmooth)
01222 CalcSmoothingTerms(false, fFirst, fSec, fThird);
01223 else if (bSmooth)
01224 CalcSmoothingTerms(true, fFirst, fSec, fThird);
01225
01226 ParameterCorrection::EnableSmoothing(bSmooth, fSmoothInfl);
01227 }
01228
01229 const math_Matrix& BSplineParameterCorrection::GetFirstSmoothMatrix() const
01230 {
01231 return _clFirstMatrix;
01232 }
01233
01234 const math_Matrix& BSplineParameterCorrection::GetSecondSmoothMatrix() const
01235 {
01236 return _clSecondMatrix;
01237 }
01238
01239 const math_Matrix& BSplineParameterCorrection::GetThirdSmoothMatrix() const
01240 {
01241 return _clThirdMatrix;
01242 }
01243
01244 void BSplineParameterCorrection::SetFirstSmoothMatrix(const math_Matrix& rclMat)
01245 {
01246 _clFirstMatrix = rclMat;
01247 }
01248
01249 void BSplineParameterCorrection::SetSecondSmoothMatrix(const math_Matrix& rclMat)
01250 {
01251 _clSecondMatrix = rclMat;
01252 }
01253
01254 void BSplineParameterCorrection::SetThirdSmoothMatrix(const math_Matrix& rclMat)
01255 {
01256 _clThirdMatrix = rclMat;
01257 }