1258 lines
36 KiB
C++
1258 lines
36 KiB
C++
/***************************************************************************
|
||
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||
* *
|
||
* This file is part of the FreeCAD CAx development system. *
|
||
* *
|
||
* This library is free software; you can redistribute it and/or *
|
||
* modify it under the terms of the GNU Library General Public *
|
||
* License as published by the Free Software Foundation; either *
|
||
* version 2 of the License, or (at your option) any later version. *
|
||
* *
|
||
* This library is distributed in the hope that it will be useful, *
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||
* GNU Library General Public License for more details. *
|
||
* *
|
||
* You should have received a copy of the GNU Library General Public *
|
||
* License along with this library; see the file COPYING.LIB. If not, *
|
||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||
* Suite 330, Boston, MA 02111-1307, USA *
|
||
* *
|
||
***************************************************************************/
|
||
|
||
|
||
#include "PreCompiled.h"
|
||
#include <math_Gauss.hxx>
|
||
#include <math_Householder.hxx>
|
||
#include <Geom_BSplineSurface.hxx>
|
||
|
||
#include <Mod/Mesh/App/Core/Approximation.h>
|
||
#include <Base/Sequencer.h>
|
||
#include <Base/Tools2D.h>
|
||
|
||
#include "ApproxSurface.h"
|
||
|
||
using namespace Reen;
|
||
|
||
// SplineBasisfunction
|
||
|
||
SplineBasisfunction::SplineBasisfunction(int iSize)
|
||
: _vKnotVector(0,iSize-1)
|
||
{
|
||
}
|
||
|
||
SplineBasisfunction::SplineBasisfunction
|
||
(TColStd_Array1OfReal& vKnots,
|
||
TColStd_Array1OfInteger& vMults,
|
||
int iSize,
|
||
int iOrder)
|
||
: _vKnotVector(0,iSize-1)
|
||
{
|
||
int sum = 0;
|
||
for (int h=vMults.Lower(); h<=vMults.Upper(); h++)
|
||
sum += vMults(h);
|
||
|
||
if (vKnots.Length() != vMults.Length() || iSize != sum)
|
||
{
|
||
// Werfe Exception
|
||
Standard_ConstructionError::Raise("BSplineBasis");
|
||
}
|
||
|
||
int k=0;
|
||
for (int i=vMults.Lower(); i<=vMults.Upper(); i++)
|
||
{
|
||
for (int j=0; j<vMults(i); j++)
|
||
{
|
||
_vKnotVector(k) = vKnots(i);
|
||
k++;
|
||
}
|
||
}
|
||
|
||
_iOrder = iOrder;
|
||
}
|
||
|
||
SplineBasisfunction::SplineBasisfunction(TColStd_Array1OfReal& vKnots, int iOrder)
|
||
: _vKnotVector(0,vKnots.Length()-1)
|
||
{
|
||
_vKnotVector = vKnots;
|
||
_iOrder = iOrder;
|
||
}
|
||
|
||
SplineBasisfunction::~SplineBasisfunction()
|
||
{
|
||
}
|
||
|
||
void SplineBasisfunction::SetKnots(TColStd_Array1OfReal& vKnots, int iOrder)
|
||
{
|
||
if (_vKnotVector.Length() != vKnots.Length())
|
||
Standard_RangeError::Raise("BSplineBasis");
|
||
|
||
_vKnotVector = vKnots;
|
||
_iOrder = iOrder;
|
||
}
|
||
|
||
void SplineBasisfunction::SetKnots(TColStd_Array1OfReal& vKnots, TColStd_Array1OfInteger& vMults,
|
||
int iOrder)
|
||
{
|
||
int sum = 0;
|
||
for (int h=vMults.Lower(); h<=vMults.Upper(); h++)
|
||
sum += vMults(h);
|
||
|
||
if (vKnots.Length() != vMults.Length() || _vKnotVector.Length() != sum)
|
||
{
|
||
// Werfe Exception
|
||
Standard_RangeError::Raise("BSplineBasis");
|
||
}
|
||
int k=0;
|
||
for (int i=vMults.Lower(); i<=vMults.Upper(); i++)
|
||
{
|
||
for (int j=0; j<vMults(i); j++)
|
||
{
|
||
_vKnotVector(k) = vKnots(i);
|
||
k++;
|
||
}
|
||
}
|
||
|
||
_iOrder = iOrder;
|
||
}
|
||
|
||
////////////////////////////////////////// BSplineBasis
|
||
|
||
BSplineBasis::BSplineBasis(int iSize)
|
||
: SplineBasisfunction(iSize)
|
||
{
|
||
}
|
||
|
||
BSplineBasis::BSplineBasis(TColStd_Array1OfReal& vKnots, TColStd_Array1OfInteger& vMults, int iSize,
|
||
int iOrder)
|
||
: SplineBasisfunction(vKnots, vMults, iSize, iOrder)
|
||
{
|
||
}
|
||
|
||
BSplineBasis::BSplineBasis(TColStd_Array1OfReal& vKnots, int iOrder)
|
||
: SplineBasisfunction(vKnots, iOrder)
|
||
{
|
||
}
|
||
|
||
BSplineBasis::~BSplineBasis()
|
||
{
|
||
}
|
||
|
||
int BSplineBasis::FindSpan(double fParam)
|
||
{
|
||
int n = _vKnotVector.Length()-_iOrder-1;
|
||
if (fParam == _vKnotVector(n+1))
|
||
return n;
|
||
|
||
int low = _iOrder-1;
|
||
int high = n+1;
|
||
int mid = (low+high)/2; //Bin<69>rsuche
|
||
|
||
while (fParam < _vKnotVector(mid) || fParam>= _vKnotVector(mid+1))
|
||
{
|
||
if (fParam < _vKnotVector(mid))
|
||
high = mid;
|
||
else
|
||
low = mid;
|
||
mid = (low+high)/2;
|
||
}
|
||
|
||
return mid;
|
||
}
|
||
|
||
void BSplineBasis::AllBasisFunctions(double fParam, TColStd_Array1OfReal& vFuncVals)
|
||
{
|
||
if (vFuncVals.Length() != _iOrder)
|
||
Standard_RangeError::Raise("BSplineBasis");
|
||
|
||
int iIndex = FindSpan(fParam);
|
||
|
||
TColStd_Array1OfReal zaehler_left(1,_iOrder-1);
|
||
TColStd_Array1OfReal zaehler_right(1,_iOrder-1);
|
||
vFuncVals(0) = 1.0f;
|
||
|
||
for (int j=1; j<_iOrder; j++)
|
||
{
|
||
zaehler_left(j) = fParam - _vKnotVector(iIndex+1-j);
|
||
zaehler_right(j) = _vKnotVector(iIndex+j) - fParam;
|
||
double saved = 0.0f;
|
||
for (int r=0; r<j; r++)
|
||
{
|
||
double tmp = vFuncVals(r)/(zaehler_right(r+1) + zaehler_left(j-r));
|
||
vFuncVals(r) = saved + zaehler_right(r+1)*tmp;
|
||
saved = zaehler_left(j-r)*tmp;
|
||
}
|
||
|
||
vFuncVals(j) = saved;
|
||
}
|
||
}
|
||
|
||
double BSplineBasis::BasisFunction(int iIndex, double fParam)
|
||
{
|
||
int m = _vKnotVector.Length()-1;
|
||
int p = _iOrder-1;
|
||
double saved;
|
||
TColStd_Array1OfReal N(0,p);
|
||
|
||
if ((iIndex == 0 && fParam == _vKnotVector(0)) ||
|
||
(iIndex == m-p-1 && fParam == _vKnotVector(m)))
|
||
{
|
||
return 1.0f;
|
||
}
|
||
|
||
if (fParam < _vKnotVector(iIndex) || fParam >= _vKnotVector(iIndex+p+1))
|
||
{
|
||
return 0.0f;
|
||
}
|
||
|
||
for (int j=0; j<=p; j++)
|
||
{
|
||
if (fParam >= _vKnotVector(iIndex+j) && fParam < _vKnotVector(iIndex+j+1))
|
||
N(j) = 1.0f;
|
||
else
|
||
N(j) = 0.0f;
|
||
}
|
||
|
||
for (int k=1; k<=p; k++)
|
||
{
|
||
if (N(0) == 0.0f)
|
||
saved = 0.0f;
|
||
else
|
||
saved = ((fParam - _vKnotVector(iIndex))*N(0)) / (_vKnotVector(iIndex+k) - _vKnotVector(iIndex));
|
||
|
||
for (int j=0; j<p-k+1; j++)
|
||
{
|
||
double Tleft = _vKnotVector(iIndex+j+1);
|
||
double Tright = _vKnotVector(iIndex+j+k+1);
|
||
|
||
if (N(j+1) == 0.0)
|
||
{
|
||
N(j) = saved;
|
||
saved = 0.0;
|
||
}
|
||
else
|
||
{
|
||
double tmp = N(j+1)/(Tright-Tleft);
|
||
N(j) = saved + (Tright - fParam)*tmp;
|
||
saved = (fParam-Tleft)*tmp;
|
||
}
|
||
}
|
||
}
|
||
|
||
return N(0);
|
||
}
|
||
|
||
void BSplineBasis::DerivativesOfBasisFunction(int iIndex, int iMaxDer, double fParam,
|
||
TColStd_Array1OfReal& Derivat)
|
||
{
|
||
int iMax = iMaxDer;
|
||
if (Derivat.Length() != iMax+1)
|
||
Standard_RangeError::Raise("BSplineBasis");
|
||
//k-te Ableitungen (k>Grad) sind Null
|
||
if (iMax >= _iOrder)
|
||
{
|
||
for (int i=_iOrder; i<=iMaxDer; i++)
|
||
Derivat(i) = 0.0f;
|
||
iMax = _iOrder - 1;
|
||
}
|
||
|
||
TColStd_Array1OfReal ND(0, iMax);
|
||
int p = _iOrder-1;
|
||
math_Matrix N(0,p,0,p);
|
||
double saved;
|
||
|
||
// falls Wert au<61>erhalb Intervall, dann Funktionswert und alle Ableitungen gleich Null
|
||
if (fParam < _vKnotVector(iIndex) || fParam >= _vKnotVector(iIndex+p+1))
|
||
{
|
||
for (int k=0; k<=iMax; k++)
|
||
Derivat(k) = 0.0f;
|
||
return;
|
||
}
|
||
|
||
// Berechne die Basisfunktionen der Ordnung 1
|
||
for (int j=0; j<_iOrder; j++)
|
||
{
|
||
if (fParam >= _vKnotVector(iIndex+j) && fParam < _vKnotVector(iIndex+j+1))
|
||
N(j,0) = 1.0f;
|
||
else
|
||
N(j,0) = 0.0f;
|
||
}
|
||
|
||
// Berechne Dreieckstabelle der Funktionswerte
|
||
for (int k=1; k<_iOrder; k++)
|
||
{
|
||
if (N(0,k-1) == 0.0f)
|
||
saved = 0.0f;
|
||
else
|
||
saved = ((fParam - _vKnotVector(iIndex))*N(0,k-1))/(_vKnotVector(iIndex+k)-_vKnotVector(iIndex));
|
||
for (int j=0; j<p-k+1; j++)
|
||
{
|
||
double Tleft = _vKnotVector(iIndex+j+1);
|
||
double Tright = _vKnotVector(iIndex+j+k+1);
|
||
|
||
if (N(j+1,k-1) == 0.0)
|
||
{
|
||
N(j,k) = saved;
|
||
saved = 0.0f;
|
||
}
|
||
else
|
||
{
|
||
double tmp = N(j+1,k-1)/(Tright-Tleft);
|
||
N(j,k) = saved + (Tright-fParam)*tmp;
|
||
saved = (fParam-Tleft)*tmp;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Funktionswert
|
||
Derivat(0) = N(0,p);
|
||
// Berechne aus der Dreieckstabelle die Ableitungen
|
||
for (int k=1; k<=iMax; k++)
|
||
{
|
||
for (int j=0; j<=k; j++)
|
||
{
|
||
// Lade (p-k)-te Spalte
|
||
ND(j) = N(j,p-k);
|
||
}
|
||
|
||
for (int jj=1; jj<=k; jj++)
|
||
{
|
||
if (ND(0) == 0.0f)
|
||
saved = 0.0f;
|
||
else
|
||
saved = ND(0)/(_vKnotVector(iIndex+p-k+jj) - _vKnotVector(iIndex));
|
||
|
||
for (int j=0; j<k-jj+1; j++)
|
||
{
|
||
double Tleft = _vKnotVector(iIndex+j+1);
|
||
double Tright = _vKnotVector(iIndex+j+p-k+jj+1);
|
||
if (ND(j+1) == 0.0f)
|
||
{
|
||
ND(j) = (p-k+jj)*saved;
|
||
saved = 0.0f;
|
||
}
|
||
else
|
||
{
|
||
double tmp = ND(j+1)/(Tright-Tleft);
|
||
ND(j) = (p-k+jj)*(saved-tmp);
|
||
saved = tmp;
|
||
}
|
||
}
|
||
}
|
||
|
||
Derivat(k) = ND(0); //k-te Ableitung
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
double BSplineBasis::DerivativeOfBasisFunction(int iIndex, int iMaxDer, double fParam)
|
||
{
|
||
int iMax = iMaxDer;
|
||
|
||
// Funktionswert (0-te Ableitung)
|
||
if (iMax == 0)
|
||
return BasisFunction(iIndex, fParam);
|
||
|
||
//k-te Ableitungen (k>Grad) sind Null
|
||
if (iMax >= _iOrder)
|
||
{
|
||
return 0.0f;
|
||
}
|
||
|
||
TColStd_Array1OfReal ND(0, iMax);
|
||
int p = _iOrder-1;
|
||
math_Matrix N(0,p,0,p);
|
||
double saved;
|
||
|
||
// falls Wert au<61>erhalb Intervall, dann Funktionswert und Ableitungen gleich Null
|
||
if (fParam < _vKnotVector(iIndex) || fParam >= _vKnotVector(iIndex+p+1))
|
||
{
|
||
return 0.0f;
|
||
}
|
||
|
||
// Berechne die Basisfunktionen der Ordnung 1
|
||
for (int j=0; j<_iOrder; j++)
|
||
{
|
||
if (fParam >= _vKnotVector(iIndex+j) && fParam < _vKnotVector(iIndex+j+1))
|
||
N(j,0) = 1.0f;
|
||
else
|
||
N(j,0) = 0.0f;
|
||
}
|
||
|
||
// Berechne Dreieckstabelle der Funktionswerte
|
||
for (int k=1; k<_iOrder; k++)
|
||
{
|
||
if (N(0,k-1) == 0.0f)
|
||
saved = 0.0f;
|
||
else
|
||
saved = ((fParam - _vKnotVector(iIndex))*N(0,k-1))/(_vKnotVector(iIndex+k)-_vKnotVector(iIndex));
|
||
for (int j=0; j<p-k+1; j++)
|
||
{
|
||
double Tleft = _vKnotVector(iIndex+j+1);
|
||
double Tright = _vKnotVector(iIndex+j+k+1);
|
||
|
||
if (N(j+1,k-1) == 0.0)
|
||
{
|
||
N(j,k) = saved;
|
||
saved = 0.0f;
|
||
}
|
||
else
|
||
{
|
||
double tmp = N(j+1,k-1)/(Tright-Tleft);
|
||
N(j,k) = saved + (Tright-fParam)*tmp;
|
||
saved = (fParam-Tleft)*tmp;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Berechne aus der Dreieckstabelle die Ableitungen
|
||
for (int j=0; j<=iMax; j++)
|
||
{
|
||
// Lade (p-iMax)-te Spalte
|
||
ND(j) = N(j,p-iMax);
|
||
}
|
||
|
||
for (int jj=1; jj<=iMax; jj++)
|
||
{
|
||
if (ND(0) == 0.0f)
|
||
saved = 0.0f;
|
||
else
|
||
saved = ND(0)/(_vKnotVector(iIndex+p-iMax+jj) - _vKnotVector(iIndex));
|
||
|
||
for (int j=0; j<iMax-jj+1; j++)
|
||
{
|
||
double Tleft = _vKnotVector(iIndex+j+1);
|
||
double Tright = _vKnotVector(iIndex+j+p-iMax+jj+1);
|
||
if (ND(j+1) == 0.0f)
|
||
{
|
||
ND(j) = (p-iMax+jj)*saved;
|
||
saved = 0.0f;
|
||
}
|
||
else
|
||
{
|
||
double tmp = ND(j+1)/(Tright-Tleft);
|
||
ND(j) = (p-iMax+jj)*(saved-tmp);
|
||
saved = tmp;
|
||
}
|
||
}
|
||
}
|
||
|
||
return ND(0); //iMax-te Ableitung
|
||
}
|
||
|
||
double BSplineBasis::GetIntegralOfProductOfBSplines(int iIdx1, int iIdx2, int iOrd1, int iOrd2)
|
||
{
|
||
int iMax = CalcSize(iOrd1, iOrd2);
|
||
double dIntegral=0.0f;
|
||
double fMin, fMax;
|
||
|
||
TColStd_Array1OfReal vRoots(0,iMax), vWeights(0,iMax);
|
||
GenerateRootsAndWeights(vRoots, vWeights);
|
||
|
||
/*Berechne das Integral*/
|
||
// Integrationsbereich
|
||
int iBegin=0; int iEnd=0;
|
||
FindIntegrationArea(iIdx1, iIdx2, iBegin, iEnd);
|
||
|
||
for (int j=iBegin; j<iEnd; j++)
|
||
{
|
||
fMax = _vKnotVector(j+1);
|
||
fMin = _vKnotVector(j);
|
||
|
||
if (fMax > fMin)
|
||
{
|
||
for (int i=0; i<=iMax; i++)
|
||
{
|
||
double fParam = 0.5*(vRoots(i)+1)*(fMax-fMin)+fMin;
|
||
dIntegral += 0.5*(fMax-fMin)*vWeights(i) *
|
||
DerivativeOfBasisFunction(iIdx1, iOrd1, fParam) *
|
||
DerivativeOfBasisFunction(iIdx2, iOrd2, fParam);
|
||
}
|
||
}
|
||
}
|
||
|
||
return dIntegral;
|
||
}
|
||
|
||
void BSplineBasis::GenerateRootsAndWeights(TColStd_Array1OfReal& vRoots, TColStd_Array1OfReal& vWeights)
|
||
{
|
||
int iSize = vRoots.Length();
|
||
|
||
//Nullstellen der Legendre-Polynome und die zugeh. Gewichte
|
||
if (iSize == 1)
|
||
{
|
||
vRoots(0) = 0.0f; vWeights(0) = 2.0f;
|
||
}
|
||
else if (iSize == 2)
|
||
{
|
||
vRoots(0) = 0.57735; vWeights(0) = 1.0;
|
||
vRoots(1) = -vRoots(0); vWeights(1) = vWeights(0);
|
||
}
|
||
else if (iSize == 4)
|
||
{
|
||
vRoots(0) = 0.33998; vWeights(0) = 0.65214;
|
||
vRoots(1) = 0.86113; vWeights(1) = 0.34785;
|
||
vRoots(2) = -vRoots(0); vWeights(2) = vWeights(0);
|
||
vRoots(3) = -vRoots(1); vWeights(3) = vWeights(1);
|
||
}
|
||
else if (iSize == 6)
|
||
{
|
||
vRoots(0) = 0.23861; vWeights(0) = 0.46791;
|
||
vRoots(1) = 0.66120; vWeights(1) = 0.36076;
|
||
vRoots(2) = 0.93246; vWeights(2) = 0.17132;
|
||
vRoots(3) = -vRoots(0); vWeights(3) = vWeights(0);
|
||
vRoots(4) = -vRoots(1); vWeights(4) = vWeights(1);
|
||
vRoots(5) = -vRoots(2); vWeights(5) = vWeights(2);
|
||
}
|
||
else if (iSize == 8)
|
||
{
|
||
vRoots(0) = 0.18343; vWeights(0) = 0.36268;
|
||
vRoots(1) = 0.52553; vWeights(1) = 0.31370;
|
||
vRoots(2) = 0.79666; vWeights(2) = 0.22238;
|
||
vRoots(3) = 0.96028; vWeights(3) = 0.10122;
|
||
vRoots(4) = -vRoots(0); vWeights(4) = vWeights(0);
|
||
vRoots(5) = -vRoots(1); vWeights(5) = vWeights(1);
|
||
vRoots(6) = -vRoots(2); vWeights(6) = vWeights(2);
|
||
vRoots(7) = -vRoots(3); vWeights(7) = vWeights(3);
|
||
}
|
||
else if (iSize == 10)
|
||
{
|
||
vRoots(0) = 0.14887; vWeights(0) = 0.29552;
|
||
vRoots(1) = 0.43339; vWeights(1) = 0.26926;
|
||
vRoots(2) = 0.67940; vWeights(2) = 0.21908;
|
||
vRoots(3) = 0.86506; vWeights(3) = 0.14945;
|
||
vRoots(4) = 0.97390; vWeights(4) = 0.06667;
|
||
vRoots(5) = -vRoots(0); vWeights(5) = vWeights(0);
|
||
vRoots(6) = -vRoots(1); vWeights(6) = vWeights(1);
|
||
vRoots(7) = -vRoots(2); vWeights(7) = vWeights(2);
|
||
vRoots(8) = -vRoots(3); vWeights(8) = vWeights(3);
|
||
vRoots(9) = -vRoots(4); vWeights(9) = vWeights(4);
|
||
}
|
||
else
|
||
{
|
||
vRoots(0) = 0.12523; vWeights(0) = 0.24914;
|
||
vRoots(1) = 0.36783; vWeights(1) = 0.23349;
|
||
vRoots(2) = 0.58731; vWeights(2) = 0.20316;
|
||
vRoots(3) = 0.76990; vWeights(3) = 0.16007;
|
||
vRoots(4) = 0.90411; vWeights(4) = 0.10693;
|
||
vRoots(5) = 0.98156; vWeights(5) = 0.04717;
|
||
vRoots(6) = -vRoots(0); vWeights(6) = vWeights(0);
|
||
vRoots(7) = -vRoots(1); vWeights(7) = vWeights(1);
|
||
vRoots(8) = -vRoots(2); vWeights(8) = vWeights(2);
|
||
vRoots(9) = -vRoots(3); vWeights(9) = vWeights(3);
|
||
vRoots(10)= -vRoots(4); vWeights(10)= vWeights(4);
|
||
vRoots(11)= -vRoots(5); vWeights(11)= vWeights(5);
|
||
}
|
||
}
|
||
|
||
void BSplineBasis::FindIntegrationArea(int iIdx1, int iIdx2, int& iBegin, int& iEnd)
|
||
{
|
||
// nach Index ordnen
|
||
if (iIdx2 < iIdx1)
|
||
{
|
||
int tmp=iIdx1;
|
||
iIdx1 = iIdx2;
|
||
iIdx2 = tmp;
|
||
}
|
||
|
||
iBegin = iIdx2;
|
||
iEnd = iIdx1+_iOrder;
|
||
if (iEnd == _vKnotVector.Upper())
|
||
iEnd -= 1;
|
||
}
|
||
|
||
int BSplineBasis::CalcSize(int r, int s)
|
||
{
|
||
int iMaxDegree = 2*(_iOrder-1)-r-s;
|
||
|
||
if (iMaxDegree < 0)
|
||
return 0;
|
||
else if (iMaxDegree < 4)
|
||
return 1;
|
||
else if (iMaxDegree < 8)
|
||
return 3;
|
||
else if (iMaxDegree < 12)
|
||
return 5;
|
||
else if (iMaxDegree < 16)
|
||
return 7;
|
||
else if (iMaxDegree < 20)
|
||
return 9;
|
||
else
|
||
return 11;
|
||
}
|
||
|
||
/////////////////// ParameterCorrection
|
||
|
||
ParameterCorrection::ParameterCorrection(unsigned short usUOrder, unsigned short usVOrder,
|
||
unsigned short usUCtrlpoints, unsigned short usVCtrlpoints)
|
||
: _usUOrder(usUOrder),
|
||
_usVOrder(usVOrder),
|
||
_usUCtrlpoints(usUCtrlpoints),
|
||
_usVCtrlpoints(usVCtrlpoints),
|
||
_vCtrlPntsOfSurf(0,usUCtrlpoints-1,0,usVCtrlpoints-1),
|
||
_vUKnots(0,usUCtrlpoints-usUOrder+1),
|
||
_vVKnots(0,usVCtrlpoints-usVOrder+1),
|
||
_vUMults(0,usUCtrlpoints-usUOrder+1),
|
||
_vVMults(0,usVCtrlpoints-usVOrder+1)
|
||
{
|
||
_bGetUVDir = false;
|
||
_bSmoothing = false;
|
||
_fSmoothInfluence = 0.0f;
|
||
}
|
||
|
||
void ParameterCorrection::CalcEigenvectors()
|
||
{
|
||
MeshCore::PlaneFit planeFit;
|
||
//for (it = aclPoints.begin(); it!=aclPoints.end(); ++it)
|
||
// planeFit.AddPoint(*it);
|
||
for (int i=_pvcPoints->Lower(); i<=_pvcPoints->Upper(); i++) {
|
||
planeFit.AddPoint(Base::Vector3f(
|
||
(float)(*_pvcPoints)(i).X(),
|
||
(float)(*_pvcPoints)(i).Y(),
|
||
(float)(*_pvcPoints)(i).Z()));
|
||
}
|
||
|
||
|
||
planeFit.Fit();
|
||
_clU = Base::toVector<double>(planeFit.GetDirU());
|
||
_clV = Base::toVector<double>(planeFit.GetDirV());
|
||
_clW = Base::toVector<double>(planeFit.GetNormal());
|
||
}
|
||
|
||
bool ParameterCorrection::DoInitialParameterCorrection(double fSizeFactor)
|
||
{
|
||
// falls Richtungen nicht vorgegeben, selber berechnen
|
||
if (_bGetUVDir == false)
|
||
CalcEigenvectors();
|
||
if (!GetUVParameters(fSizeFactor))
|
||
return false;
|
||
if (_bSmoothing)
|
||
{
|
||
if (!SolveWithSmoothing(_fSmoothInfluence))
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
if (!SolveWithoutSmoothing())
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool ParameterCorrection::GetUVParameters(double fSizeFactor)
|
||
{
|
||
// Eigenvektoren als neue Basis
|
||
Base::Vector3d e[3];
|
||
e[0] = _clU;
|
||
e[1] = _clV;
|
||
e[2] = _clW;
|
||
|
||
//kanonische Basis des R^3
|
||
Base::Vector3d b[3];
|
||
b[0]=Base::Vector3d(1.0,0.0,0.0); b[1]=Base::Vector3d(0.0,1.0,0.0);b[2]=Base::Vector3d(0.0,0.0,1.0);
|
||
// Erzeuge ein Rechtssystem aus den orthogonalen Eigenvektoren
|
||
if ((e[0]%e[1])*e[2] < 0)
|
||
{
|
||
Base::Vector3d tmp = e[0];
|
||
e[0] = e[1];
|
||
e[1] = tmp;
|
||
}
|
||
|
||
// Nun erzeuge die transpon. Rotationsmatrix
|
||
Wm4::Matrix3d clRotMatTrans;
|
||
for (int i=0; i<3; i++)
|
||
{
|
||
for (int j=0; j<3; j++)
|
||
{
|
||
clRotMatTrans[i][j] = b[j]*e[i];
|
||
}
|
||
}
|
||
|
||
std::vector<Base::Vector2D> vcProjPts;
|
||
Base::BoundBox2D clBBox;
|
||
|
||
// Berechne die Koordinaten der transf. Punkte und projiz. diese auf die x,y-Ebene des neuen
|
||
// Koordinatensystems
|
||
for (int ii=_pvcPoints->Lower(); ii<=_pvcPoints->Upper(); ii++)
|
||
{
|
||
Wm4::Vector3d clProjPnt = clRotMatTrans * ( Wm4::Vector3d(
|
||
(*_pvcPoints)(ii).X(),
|
||
(*_pvcPoints)(ii).Y(),
|
||
(*_pvcPoints)(ii).Z()));
|
||
vcProjPts.push_back(Base::Vector2D(clProjPnt.X(), clProjPnt.Y()));
|
||
clBBox &= (Base::Vector2D(clProjPnt.X(), clProjPnt.Y()));
|
||
}
|
||
|
||
if ((clBBox.fMaxX == clBBox.fMinX) || (clBBox.fMaxY == clBBox.fMinY))
|
||
return false;
|
||
double tx = fSizeFactor*clBBox.fMinX-(fSizeFactor-1.0f)*clBBox.fMaxX;
|
||
double ty = fSizeFactor*clBBox.fMinY-(fSizeFactor-1.0f)*clBBox.fMaxY;
|
||
double fDeltaX = (2*fSizeFactor-1.0f)*(clBBox.fMaxX - clBBox.fMinX);
|
||
double fDeltaY = (2*fSizeFactor-1.0f)*(clBBox.fMaxY - clBBox.fMinY);
|
||
|
||
// Berechne die u,v-Parameter mit u,v aus [0,1]
|
||
_pvcUVParam->Init(gp_Pnt2d(0.0f, 0.0f));
|
||
int ii=0;
|
||
if (clBBox.fMaxX - clBBox.fMinX >= clBBox.fMaxY - clBBox.fMinY)
|
||
for (std::vector<Base::Vector2D>::iterator It2=vcProjPts.begin(); It2!=vcProjPts.end(); It2++)
|
||
{
|
||
(*_pvcUVParam)(ii) = gp_Pnt2d((It2->fX-tx)/fDeltaX, (It2->fY-ty)/fDeltaY);
|
||
ii++;
|
||
}
|
||
else
|
||
for (std::vector<Base::Vector2D>::iterator It2=vcProjPts.begin(); It2!=vcProjPts.end(); It2++)
|
||
{
|
||
(*_pvcUVParam)(ii) = gp_Pnt2d((It2->fY-ty)/fDeltaY, (It2->fX-tx)/fDeltaX);
|
||
ii++;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
void ParameterCorrection::SetUVW(const Base::Vector3d& clU, const Base::Vector3d& clV, const Base::Vector3d& clW, bool bUseDir)
|
||
{
|
||
_clU = clU;
|
||
_clV = clV;
|
||
_clW = clW;
|
||
_bGetUVDir = bUseDir;
|
||
}
|
||
|
||
void ParameterCorrection::GetUVW(Base::Vector3d& clU, Base::Vector3d& clV, Base::Vector3d& clW) const
|
||
{
|
||
clU = _clU;
|
||
clV = _clV;
|
||
clW = _clW;
|
||
}
|
||
|
||
Base::Vector3d ParameterCorrection::GetGravityPoint() const
|
||
{
|
||
unsigned long ulSize = _pvcPoints->Length();
|
||
double x=0.0, y=0.0, z=0.0;
|
||
for (int i=_pvcPoints->Lower(); i<=_pvcPoints->Upper(); i++)
|
||
{
|
||
x += (*_pvcPoints)(i).X();
|
||
y += (*_pvcPoints)(i).Y();
|
||
z += (*_pvcPoints)(i).Z();
|
||
}
|
||
|
||
return Base::Vector3d(x/ulSize, y/ulSize, z/ulSize);
|
||
}
|
||
|
||
Handle(Geom_BSplineSurface) ParameterCorrection::CreateSurface(const TColgp_Array1OfPnt& points,
|
||
unsigned short usIter,
|
||
bool bParaCor,
|
||
double fSizeFactor)
|
||
{
|
||
if (_pvcPoints != NULL)
|
||
{
|
||
delete _pvcPoints;
|
||
_pvcPoints = NULL;
|
||
delete _pvcUVParam;
|
||
_pvcUVParam = NULL;
|
||
}
|
||
_pvcPoints = new TColgp_Array1OfPnt(points.Lower(), points.Upper());
|
||
*_pvcPoints = points;
|
||
_pvcUVParam = new TColgp_Array1OfPnt2d(points.Lower(), points.Upper());
|
||
|
||
if (_usUCtrlpoints*_usVCtrlpoints > _pvcPoints->Length())
|
||
return NULL; //LGS unterbestimmt
|
||
if(!DoInitialParameterCorrection(fSizeFactor))
|
||
return NULL;
|
||
|
||
if (bParaCor)
|
||
DoParameterCorrection(usIter);
|
||
|
||
return new Geom_BSplineSurface
|
||
(_vCtrlPntsOfSurf,
|
||
_vUKnots,
|
||
_vVKnots,
|
||
_vUMults,
|
||
_vVMults,
|
||
_usUOrder-1,
|
||
_usVOrder-1);
|
||
}
|
||
|
||
void ParameterCorrection::EnableSmoothing(bool bSmooth, double fSmoothInfl)
|
||
{
|
||
_bSmoothing = bSmooth;
|
||
_fSmoothInfluence = fSmoothInfl;
|
||
}
|
||
|
||
/////////////////// BSplineParameterCorrection
|
||
|
||
|
||
BSplineParameterCorrection::BSplineParameterCorrection(unsigned short usUOrder, unsigned short usVOrder,
|
||
unsigned short usUCtrlpoints, unsigned short usVCtrlpoints)
|
||
: ParameterCorrection
|
||
(usUOrder, usVOrder, usUCtrlpoints, usVCtrlpoints),
|
||
_clUSpline(usUCtrlpoints+usUOrder),
|
||
_clVSpline(usVCtrlpoints+usVOrder),
|
||
_clSmoothMatrix
|
||
(0,usUCtrlpoints*usVCtrlpoints-1,
|
||
0,usUCtrlpoints*usVCtrlpoints-1),
|
||
_clFirstMatrix
|
||
(0,usUCtrlpoints*usVCtrlpoints-1,
|
||
0,usUCtrlpoints*usVCtrlpoints-1),
|
||
_clSecondMatrix
|
||
(0,usUCtrlpoints*usVCtrlpoints-1,
|
||
0,usUCtrlpoints*usVCtrlpoints-1),
|
||
_clThirdMatrix
|
||
(0,usUCtrlpoints*usVCtrlpoints-1,
|
||
0,usUCtrlpoints*usVCtrlpoints-1)
|
||
{
|
||
Init();
|
||
}
|
||
|
||
void BSplineParameterCorrection::Init()
|
||
{
|
||
// Initialisierungen
|
||
_pvcUVParam = NULL;
|
||
_pvcPoints = NULL;
|
||
_clFirstMatrix.Init(0.0);
|
||
_clSecondMatrix.Init(0.0);
|
||
_clThirdMatrix.Init(0.0);
|
||
_clSmoothMatrix.Init(0.0);
|
||
|
||
/* Berechne die Knotenvektoren */
|
||
unsigned short usUMax = _usUCtrlpoints-_usUOrder+1;
|
||
unsigned short usVMax = _usVCtrlpoints-_usVOrder+1;
|
||
|
||
// Knotenvektor f<>r die CAS.CADE-Klasse
|
||
// u-Richtung
|
||
for (int i=0;i<=usUMax; i++)
|
||
{
|
||
_vUKnots(i) = i / usUMax;
|
||
_vUMults(i) = 1;
|
||
}
|
||
_vUMults(0) = _usUOrder;
|
||
_vUMults(usUMax) = _usUOrder;
|
||
// v-Richtung
|
||
for (int i=0; i<=usVMax; i++)
|
||
{
|
||
_vVKnots(i) = i / usVMax;
|
||
_vVMults(i) = 1;
|
||
}
|
||
_vVMults(0) = _usVOrder;
|
||
_vVMults(usVMax) = _usVOrder;
|
||
|
||
// Setzen der B-Spline-Basisfunktionen
|
||
_clUSpline.SetKnots(_vUKnots, _vUMults, _usUOrder);
|
||
_clVSpline.SetKnots(_vVKnots, _vVMults, _usVOrder);
|
||
}
|
||
|
||
void BSplineParameterCorrection::SetUKnots(const std::vector<double>& afKnots)
|
||
{
|
||
if (afKnots.size() != (unsigned long)(_usUCtrlpoints+_usUOrder))
|
||
return;
|
||
|
||
unsigned short usUMax = _usUCtrlpoints-_usUOrder+1;
|
||
|
||
// Knotenvektor f<>r die CAS.CADE-Klasse
|
||
// u-Richtung
|
||
for (int i=1;i<usUMax; i++)
|
||
{
|
||
_vUKnots(i) = afKnots[_usUOrder+i-1];
|
||
_vUMults(i) = 1;
|
||
}
|
||
|
||
// Setzen der B-Spline-Basisfunktionen
|
||
_clUSpline.SetKnots(_vUKnots, _vUMults, _usUOrder);
|
||
}
|
||
|
||
void BSplineParameterCorrection::SetVKnots(const std::vector<double>& afKnots)
|
||
{
|
||
if (afKnots.size() != (unsigned long)(_usVCtrlpoints+_usVOrder))
|
||
return;
|
||
|
||
unsigned short usVMax = _usVCtrlpoints-_usVOrder+1;
|
||
|
||
// Knotenvektor f<>r die CAS.CADE-Klasse
|
||
// v-Richtung
|
||
for (int i=1; i<usVMax; i++)
|
||
{
|
||
_vVKnots(i) = afKnots[_usVOrder+i-1];
|
||
_vVMults(i) = 1;
|
||
}
|
||
|
||
// Setzen der B-Spline-Basisfunktionen
|
||
_clVSpline.SetKnots(_vVKnots, _vVMults, _usVOrder);
|
||
}
|
||
|
||
void BSplineParameterCorrection::DoParameterCorrection(unsigned short usIter)
|
||
{
|
||
int i=0;
|
||
float fMaxDiff=0.0f, fMaxScalar=1.0f;
|
||
double fWeight = _fSmoothInfluence;
|
||
|
||
Base::SequencerLauncher seq("Calc surface...", usIter*_pvcPoints->Length());
|
||
|
||
do
|
||
{
|
||
fMaxScalar = 1.0f;
|
||
fMaxDiff = 0.0f;
|
||
|
||
Geom_BSplineSurface* pclBSplineSurf = new Geom_BSplineSurface
|
||
(_vCtrlPntsOfSurf,
|
||
_vUKnots,
|
||
_vVKnots,
|
||
_vUMults,
|
||
_vVMults,
|
||
_usUOrder-1,
|
||
_usVOrder-1);
|
||
|
||
for (int ii=_pvcPoints->Lower();ii <=_pvcPoints->Upper();ii++)
|
||
{
|
||
|
||
double fDeltaU, fDeltaV, fU, fV;
|
||
gp_Vec P((*_pvcPoints)(ii).X(), (*_pvcPoints)(ii).Y(), (*_pvcPoints)(ii).Z());
|
||
gp_Pnt PntX;
|
||
gp_Vec Xu, Xv, Xuv, Xuu, Xvv;
|
||
//Berechne die ersten beiden Ableitungen und Punkt an der Stelle (u,v)
|
||
pclBSplineSurf->D2((*_pvcUVParam)(ii).X(), (*_pvcUVParam)(ii).Y(), PntX, Xu, Xv, Xuu, Xvv, Xuv);
|
||
gp_Vec X(PntX.X(), PntX.Y(), PntX.Z());
|
||
gp_Vec ErrorVec = X - P;
|
||
|
||
// Berechne Xu x Xv die Normale in X(u,v)
|
||
gp_Dir clNormal = Xu ^ Xv;
|
||
|
||
//Pr<50>fe, ob X = P
|
||
if (!(X.IsEqual(P,0.001,0.001)))
|
||
{
|
||
ErrorVec.Normalize();
|
||
if(fabs(clNormal*ErrorVec) < fMaxScalar)
|
||
fMaxScalar = (float)fabs(clNormal*ErrorVec);
|
||
}
|
||
|
||
fDeltaU = ( (P-X) * Xu ) / ( (P-X)*Xuu - Xu*Xu );
|
||
if (fabs(fDeltaU) < FLOAT_EPS)
|
||
fDeltaU = 0.0f;
|
||
fDeltaV = ( (P-X) * Xv ) / ( (P-X)*Xvv - Xv*Xv );
|
||
if (fabs(fDeltaV) < FLOAT_EPS)
|
||
fDeltaV = 0.0f;
|
||
|
||
//Ersetze die alten u/v-Werte durch die neuen
|
||
fU = (*_pvcUVParam)(ii).X() - fDeltaU;
|
||
fV = (*_pvcUVParam)(ii).Y() - fDeltaV;
|
||
if (fU <= 1.0f && fU >= 0.0f &&
|
||
fV <= 1.0f && fV >= 0.0f)
|
||
{
|
||
(*_pvcUVParam)(ii).SetX(fU);
|
||
(*_pvcUVParam)(ii).SetY(fV);
|
||
fMaxDiff = std::max<float>(float(fabs(fDeltaU)), fMaxDiff);
|
||
fMaxDiff = std::max<float>(float(fabs(fDeltaV)), fMaxDiff);
|
||
}
|
||
|
||
seq.next();
|
||
}
|
||
|
||
if (_bSmoothing)
|
||
{
|
||
fWeight *= 0.5f;
|
||
SolveWithSmoothing(fWeight);
|
||
}
|
||
else
|
||
SolveWithoutSmoothing();
|
||
|
||
i++;
|
||
}
|
||
while(i<usIter && fMaxDiff > FLOAT_EPS && fMaxScalar < 0.99);
|
||
}
|
||
|
||
bool BSplineParameterCorrection::SolveWithoutSmoothing()
|
||
{
|
||
unsigned long ulSize = _pvcPoints->Length();
|
||
math_Matrix M (0, ulSize-1, 0,_usUCtrlpoints*_usVCtrlpoints-1);
|
||
math_Matrix Xx (0, _usUCtrlpoints*_usVCtrlpoints-1,0,0);
|
||
math_Matrix Xy (0, _usUCtrlpoints*_usVCtrlpoints-1,0,0);
|
||
math_Matrix Xz (0, _usUCtrlpoints*_usVCtrlpoints-1,0,0);
|
||
math_Vector bx (0, ulSize-1);
|
||
math_Vector by (0, ulSize-1);
|
||
math_Vector bz (0, ulSize-1);
|
||
|
||
//Bestimmung der Koeffizientenmatrix des <20>berbestimmten LGS
|
||
for (unsigned long i=0; i<ulSize; i++)
|
||
{
|
||
double fU = (*_pvcUVParam)(i).X();
|
||
double fV = (*_pvcUVParam)(i).Y();
|
||
unsigned long ulIdx=0;
|
||
|
||
for (unsigned short j=0; j<_usUCtrlpoints; j++)
|
||
{
|
||
for (unsigned short k=0; k<_usVCtrlpoints; k++)
|
||
{
|
||
M(i,ulIdx) = _clUSpline.BasisFunction(j,fU)*_clVSpline.BasisFunction(k,fV);
|
||
ulIdx++;
|
||
}
|
||
}
|
||
}
|
||
|
||
//Bestimmen der rechten Seite
|
||
for (int ii=_pvcPoints->Lower(); ii<=_pvcPoints->Upper(); ii++)
|
||
{
|
||
bx(ii) = (*_pvcPoints)(ii).X(); by(ii) = (*_pvcPoints)(ii).Y(); bz(ii) = (*_pvcPoints)(ii).Z();
|
||
}
|
||
|
||
// L<>se das <20>berbest. LGS mit der Householder-Transformation
|
||
math_Householder hhX(M,bx);
|
||
math_Householder hhY(M,by);
|
||
math_Householder hhZ(M,bz);
|
||
|
||
if (!(hhX.IsDone() && hhY.IsDone() && hhZ.IsDone()))
|
||
//LGS konnte nicht gel<65>st werden
|
||
return false;
|
||
Xx = hhX.AllValues();
|
||
Xy = hhY.AllValues();
|
||
Xz = hhZ.AllValues();
|
||
|
||
unsigned long ulIdx=0;
|
||
for (unsigned short j=0;j<_usUCtrlpoints;j++)
|
||
{
|
||
for (unsigned short k=0;k<_usVCtrlpoints;k++)
|
||
{
|
||
_vCtrlPntsOfSurf(j,k) = gp_Pnt(Xx(ulIdx,0),Xy(ulIdx,0),Xz(ulIdx,0));
|
||
ulIdx++;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool BSplineParameterCorrection::SolveWithSmoothing(double fWeight)
|
||
{
|
||
unsigned long ulSize = _pvcPoints->Length();
|
||
unsigned long ulDim = _usUCtrlpoints*_usVCtrlpoints;
|
||
math_Matrix M (0, ulSize-1, 0,_usUCtrlpoints*_usVCtrlpoints-1);
|
||
math_Matrix MTM(0, _usUCtrlpoints*_usVCtrlpoints-1,
|
||
0, _usUCtrlpoints*_usVCtrlpoints-1);
|
||
math_Vector Xx (0, _usUCtrlpoints*_usVCtrlpoints-1);
|
||
math_Vector Xy (0, _usUCtrlpoints*_usVCtrlpoints-1);
|
||
math_Vector Xz (0, _usUCtrlpoints*_usVCtrlpoints-1);
|
||
math_Vector bx (0, ulSize-1);
|
||
math_Vector by (0, ulSize-1);
|
||
math_Vector bz (0, ulSize-1);
|
||
math_Vector Mbx(0, _usUCtrlpoints*_usVCtrlpoints-1);
|
||
math_Vector Mby(0, _usUCtrlpoints*_usVCtrlpoints-1);
|
||
math_Vector Mbz(0, _usUCtrlpoints*_usVCtrlpoints-1);
|
||
|
||
//Bestimmung der Koeffizientenmatrix des <20>berbestimmten LGS
|
||
for (unsigned long i=0; i<ulSize; i++)
|
||
{
|
||
double fU = (*_pvcUVParam)(i).X();
|
||
double fV = (*_pvcUVParam)(i).Y();
|
||
unsigned long ulIdx=0;
|
||
|
||
for (unsigned short j=0; j<_usUCtrlpoints; j++)
|
||
{
|
||
for (unsigned short k=0; k<_usVCtrlpoints; k++)
|
||
{
|
||
M(i,ulIdx) = _clUSpline.BasisFunction(j,fU)*_clVSpline.BasisFunction(k,fV);
|
||
ulIdx++;
|
||
}
|
||
}
|
||
}
|
||
//Das Produkt aus ihrer Transformierten und ihr selbst ergibt die quadratische Systemmatrix
|
||
for (unsigned long m=0; m<ulDim; m++)
|
||
{
|
||
for (unsigned long n=m; n<ulDim; n++)
|
||
{
|
||
MTM(m,n)=MTM(n,m)=M.Col(m)*M.Col(n);
|
||
}
|
||
}
|
||
|
||
//Bestimmen der rechten Seite
|
||
for (int ii=_pvcPoints->Lower(); ii<=_pvcPoints->Upper(); ii++)
|
||
{
|
||
bx(ii) = (*_pvcPoints)(ii).X(); by(ii) = (*_pvcPoints)(ii).Y(); bz(ii) = (*_pvcPoints)(ii).Z();
|
||
}
|
||
for (unsigned long i=0; i<ulDim; i++)
|
||
{
|
||
Mbx(i) = M.Col(i) * bx;
|
||
Mby(i) = M.Col(i) * by;
|
||
Mbz(i) = M.Col(i) * bz;
|
||
}
|
||
|
||
// L<>se das LGS mit der LU-Zerlegung
|
||
math_Gauss mgGaussX(MTM+fWeight*_clSmoothMatrix);
|
||
math_Gauss mgGaussY(MTM+fWeight*_clSmoothMatrix);
|
||
math_Gauss mgGaussZ(MTM+fWeight*_clSmoothMatrix);
|
||
|
||
mgGaussX.Solve(Mbx,Xx);
|
||
if (!mgGaussX.IsDone())
|
||
return false;
|
||
|
||
mgGaussY.Solve(Mby,Xy);
|
||
if (!mgGaussY.IsDone())
|
||
return false;
|
||
|
||
mgGaussZ.Solve(Mbz,Xz);
|
||
if (!mgGaussZ.IsDone())
|
||
return false;
|
||
|
||
unsigned long ulIdx=0;
|
||
for (unsigned short j=0;j<_usUCtrlpoints;j++)
|
||
{
|
||
for (unsigned short k=0;k<_usVCtrlpoints;k++)
|
||
{
|
||
_vCtrlPntsOfSurf(j,k) = gp_Pnt(Xx(ulIdx),Xy(ulIdx),Xz(ulIdx));
|
||
ulIdx++;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
void BSplineParameterCorrection::CalcSmoothingTerms(bool bRecalc, double fFirst, double fSecond, double fThird)
|
||
{
|
||
if (bRecalc)
|
||
{
|
||
Base::SequencerLauncher seq("Initializing...", 3 * _usUCtrlpoints * _usUCtrlpoints * _usVCtrlpoints * _usVCtrlpoints);
|
||
CalcFirstSmoothMatrix(seq);
|
||
CalcSecondSmoothMatrix(seq);
|
||
CalcThirdSmoothMatrix(seq);
|
||
}
|
||
|
||
_clSmoothMatrix = fFirst * _clFirstMatrix +
|
||
fSecond * _clSecondMatrix +
|
||
fThird * _clThirdMatrix ;
|
||
}
|
||
|
||
void BSplineParameterCorrection::CalcFirstSmoothMatrix(Base::SequencerLauncher& seq)
|
||
{
|
||
unsigned long m=0;
|
||
for (unsigned long k=0; k<_usUCtrlpoints; k++)
|
||
{
|
||
for (unsigned long l=0; l<_usVCtrlpoints; l++)
|
||
{
|
||
unsigned long n=0;
|
||
|
||
for (unsigned short i=0; i<_usUCtrlpoints; i++)
|
||
{
|
||
for (unsigned short j=0; j<_usVCtrlpoints; j++)
|
||
{
|
||
_clFirstMatrix(m,n) = _clUSpline.GetIntegralOfProductOfBSplines(i,k,1,1) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,0,0) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,0,0) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,1,1);
|
||
seq.next();
|
||
n++;
|
||
}
|
||
}
|
||
m++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void BSplineParameterCorrection::CalcSecondSmoothMatrix(Base::SequencerLauncher& seq)
|
||
{
|
||
unsigned long m=0;
|
||
for (unsigned long k=0; k<_usUCtrlpoints; k++)
|
||
{
|
||
for (unsigned long l=0; l<_usVCtrlpoints; l++)
|
||
{
|
||
unsigned long n=0;
|
||
|
||
for (unsigned short i=0; i<_usUCtrlpoints; i++)
|
||
{
|
||
for (unsigned short j=0; j<_usVCtrlpoints; j++)
|
||
{
|
||
_clSecondMatrix(m,n) = _clUSpline.GetIntegralOfProductOfBSplines(i,k,2,2) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,0,0) +
|
||
2*_clUSpline.GetIntegralOfProductOfBSplines(i,k,1,1) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,1,1) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,0,0) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,2,2);
|
||
seq.next();
|
||
n++;
|
||
}
|
||
}
|
||
m++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void BSplineParameterCorrection::CalcThirdSmoothMatrix(Base::SequencerLauncher& seq)
|
||
{
|
||
unsigned long m=0;
|
||
for (unsigned long k=0; k<_usUCtrlpoints; k++)
|
||
{
|
||
for (unsigned long l=0; l<_usVCtrlpoints; l++)
|
||
{
|
||
unsigned long n=0;
|
||
|
||
for (unsigned short i=0; i<_usUCtrlpoints; i++)
|
||
{
|
||
for (unsigned short j=0; j<_usVCtrlpoints; j++)
|
||
{
|
||
_clThirdMatrix(m,n) = _clUSpline.GetIntegralOfProductOfBSplines(i,k,3,3) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,0,0) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,3,1) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,0,2) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,1,3) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,2,0) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,1,1) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,2,2) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,2,2) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,1,1) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,0,2) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,3,1) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,2,0) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,1,3) +
|
||
_clUSpline.GetIntegralOfProductOfBSplines(i,k,0,0) *
|
||
_clVSpline.GetIntegralOfProductOfBSplines(j,l,3,3) ;
|
||
seq.next();
|
||
n++;
|
||
}
|
||
}
|
||
m++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void BSplineParameterCorrection::EnableSmoothing(bool bSmooth, double fSmoothInfl)
|
||
{
|
||
EnableSmoothing(bSmooth, fSmoothInfl, 1.0f, 0.0f, 0.0f);
|
||
}
|
||
|
||
void BSplineParameterCorrection::EnableSmoothing(bool bSmooth, double fSmoothInfl,
|
||
double fFirst, double fSec, double fThird)
|
||
{
|
||
if (_bSmoothing && bSmooth)
|
||
CalcSmoothingTerms(false, fFirst, fSec, fThird);
|
||
else if (bSmooth)
|
||
CalcSmoothingTerms(true, fFirst, fSec, fThird);
|
||
|
||
ParameterCorrection::EnableSmoothing(bSmooth, fSmoothInfl);
|
||
}
|
||
|
||
const math_Matrix& BSplineParameterCorrection::GetFirstSmoothMatrix() const
|
||
{
|
||
return _clFirstMatrix;
|
||
}
|
||
|
||
const math_Matrix& BSplineParameterCorrection::GetSecondSmoothMatrix() const
|
||
{
|
||
return _clSecondMatrix;
|
||
}
|
||
|
||
const math_Matrix& BSplineParameterCorrection::GetThirdSmoothMatrix() const
|
||
{
|
||
return _clThirdMatrix;
|
||
}
|
||
|
||
void BSplineParameterCorrection::SetFirstSmoothMatrix(const math_Matrix& rclMat)
|
||
{
|
||
_clFirstMatrix = rclMat;
|
||
}
|
||
|
||
void BSplineParameterCorrection::SetSecondSmoothMatrix(const math_Matrix& rclMat)
|
||
{
|
||
_clSecondMatrix = rclMat;
|
||
}
|
||
|
||
void BSplineParameterCorrection::SetThirdSmoothMatrix(const math_Matrix& rclMat)
|
||
{
|
||
_clThirdMatrix = rclMat;
|
||
}
|