+ unify DLL export defines to namespace names

git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5000 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d
This commit is contained in:
wmayer
2011-10-10 13:44:52 +00:00
commit 120ca87015
4155 changed files with 2965978 additions and 0 deletions

648
src/Mod/Cam/App/routine.cpp Normal file
View File

@@ -0,0 +1,648 @@
/***************************************************************************
* Copyright (c) 2007 *
* Joachim Zettler <Joachim.Zettler@gmx.de> * *
* Mohamad Najib Muhammad Noor <najib_bean@yahoo.co.uk> *
* *
* 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 *
* *
***************************************************************************/
/*********ROUTINE.CPP*********/
#include "PreCompiled.h"
#include <cmath>
#include "routine.h"
///*********BINDINGS********/
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/bindings/traits/ublas_matrix.hpp>
#include <boost/numeric/bindings/atlas/clapack.hpp>
using namespace boost::numeric::bindings;
using namespace boost::numeric;
/*! \brief Numerical Intergration according to trapezoid rules
This routine assumes that the Intergral values are already corresponding with WithRespectTo
i.e: Intergral[i] == Intergral(WithRespectTo[i]);
Also, it is assumed that WithRespectTo are evenly spaced with it's stepWidth
*/
double Routines::TrapezoidIntergration(const std::vector<double> &WithRespectTo, const std::vector<double> &Integral)
{
m_h = 0;
m_result = 0;
m_N = Integral.size();
if (m_N==1) // trapzf(x,y) returns zero for a scalar x
{
m_result = 0;
return m_result;
}
m_h = WithRespectTo[1] - WithRespectTo[0]; /* the integration stepsize */
for (int i=1; i< m_N - 1; i++)
m_result = m_result + Integral[i];
m_result = m_h/2 * (Integral[0] + 2*(m_result) + Integral[m_N -1]);
return m_result;
}
std::vector<double> Routines::NewtonStep(std::vector<double> &F,std::vector<std::vector<double> > &DF)
{
// löst folgendes Gleichungssystem: DF*x = F
int siz = (int) F.size();
std::vector<double> x_new(siz);
std::vector<int> piv(siz); // pivotelement
ublas::matrix<double> A(siz, siz);
ublas::matrix<double> b(1, siz);
// füllt blas-matrizen
for (unsigned int i=0; i<siz; ++i)
{
b(0,i) = -F[i];
for (unsigned int j=0; j<siz; ++j)
{
A(i,j) = DF[i][j];
}
}
/*cout << b(0,0) << "," << b(0,1) << "," << b(0,2) << endl;
cout << A(0,0) << "," << A(0,1) << "," << A(0,2) << endl;
cout << A(1,0) << "," << A(1,1) << "," << A(1,2) << endl;
cout << A(2,0) << "," << A(2,1) << "," << A(2,2) << endl;*/
atlas::lu_factor(A,piv); // führt LU-Zerlegung durch
atlas::getrs(A,piv,b); // löst Gl.system A*x = b (b wird mit der Lösung überschrieben)
for (unsigned int i=0; i<siz; ++i)
{
x_new[i] = b(0,i);
}
return x_new;
}
/*! \brief Cramer-Rule Solver
Cramer-Rule solver for 2x2 Matrix.
RHS1 * LHS = RHS2, LHS will be computed
*/
void Routines::CramerSolve(std::vector< std::vector<double> > &RHS1, std::vector<double>& RHS2, std::vector<double> &LHS)
{
double MainMatrixDet = det2(RHS1);
std::vector< std::vector<double> > Temp(2,std::vector<double>(2,0.0));
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
Temp[i][j] = RHS1[i][j];
//first pass
for (int i = 0; i < 2; i++)
Temp[i][0] = RHS2[i];
LHS[0] = det2(Temp) / MainMatrixDet;
//restore
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
Temp[i][j] = RHS1[i][j];
//second pass
for (int i = 0; i < 2; i++)
Temp[i][1] = RHS2[i];
LHS[1] = det2(Temp) / MainMatrixDet;
}
/*! \brief Calculate angle between two vectors
Dependancies: Vector3D definitions and routines
*/
double Routines::CalcAngle(Base::Vector3f a,Base::Vector3f b,Base::Vector3f c)
{
Base::Vector3f First = a - b;
Base::Vector3f Second = c - b;
Base::Vector3f Third = c - a;
//double test1 = First.Length(), test2 = Second.Length(), test3 = Third.Length();
double UpperTerm = (First.Length() * First.Length()) + (Second.Length() *Second.Length()) - (Third.Length() * Third.Length() );
double LowerTerm = 2 * First.Length() * Second.Length() ;
double ang = acos( UpperTerm / LowerTerm );
return ang;
}
/*! \brief Algorithim A2.1 from NURBS Book Page 68*/
int Routines::FindSpan(int n, int p, double u, std::vector<double> KnotSequence)
{
if (u == KnotSequence[n+1])
return n;
int low, high, mid, i;
i = 0;
low = p;
high = n+1;
mid = (low+high) / 2;
while (u < KnotSequence[mid] || u >= KnotSequence[mid+1])
{
if (u < KnotSequence[mid])
high = mid;
else
low = mid;
mid = (low + high) / 2;
i++;
}
return mid;
}
/*! \brief Algorithim A2.4 from NURBS Book page 70*/
void Routines::Basisfun(int i, double u, int p, std::vector<double> &KnotSequence, std::vector<double> &output)
{
double temp, saved;
std::vector<double> leftie(p+1, 0.0);
std::vector<double> rightie(p+1, 0.0);
output[0] = 1.0;
for (int j = 1; j <= p; j++)
{
leftie[j] = u - KnotSequence[i+1-j];
rightie[j] = KnotSequence[i+j] - u;
saved = 0.0;
for (int r = 0; r < j; r++)
{
temp = output[r] / (rightie[r+1] + leftie[j-r]);
output[r] = saved + (rightie[r+1]*temp);
saved = leftie[j-r]*temp;
}
output[j] = saved;
}
}
/*! \brief Algorithim A2.3 from NURBS Book Page 72 */
void Routines::DersBasisFuns(int i, double u, int p, int n,
std::vector<double> &KnotSequence, std::vector< std::vector<double> > &Derivate)
{
std::vector< std::vector<double> > ndu(p+1, std::vector<double>(p+1,0.0));
std::vector< std::vector<double> > a(2, std::vector<double>(p+1,0.0));
std::vector<double> leftie(p+1, 0.0);
std::vector<double> rightie(p+1, 0.0);
ndu[0][0] = 1.0;
for (int j = 1; j <= p; j++)
{
leftie[j] = u - KnotSequence[i+1-j];
rightie[j] = KnotSequence[i+j] - u;
double saved = 0.0;
for (int r = 0; r < j; r++)
{
ndu[j][r] = rightie[r+1] + leftie[j-r];
double temp = ndu[r][j-1] / ndu[j][r];
ndu[r][j] = saved + rightie[r+1]*temp;
saved = leftie[j-r]*temp;
}
ndu[j][j] = saved;
}
for (int j = 0; j <= p; j++)
Derivate[0][j] = ndu[j][p];
for (int r = 0; r <= p; r++)
{
int j1, j2;
int s1 = 0;
int s2 = 1;
a[0][0] = 1.0;
for (int k = 1; k <= n; k++)
{
double d = 0.0;
int j;
int rk = r - k;
int pk = p - k;
if (r >= k)
{
a[s2][0] = a[s1][0] / ndu[pk+1][rk];
d += a[s2][0] * ndu[rk][pk];
}
if (rk >= -1)
j1 = 1;
else j1 = -rk;
if (r -1 <= pk)
j2 = k -1;
else j2 = p - r;
for (j = j1; j <= j2; j++)
{
a[s2][j] = (a[s1][j]-a[s1][j-1]) / ndu[pk+1][rk+j];
d += a[s2][j] * ndu[rk+j][pk];
}
if (r <= pk)
{
a[s2][k] = -a[s1][k-1] / ndu[pk+1][r];
d += a[s2][k] * ndu[r][pk];
}
Derivate[k][r] = d;
j = s1;
s1 = s2;
s2 = j;
}
}
int r = p;
for (int k = 1; k <= n; k++)
{
for (int j = 0; j <= p; j++)
Derivate[k][j] *= r;
r*= (p-k);
}
}
/*! \brief Translation from nrbeval.m from NURBS Toolbox. WARNING: ONLY POINT EVALUATION ARE CONSIDERED!!!! */
void Routines::PointNrbEval(std::vector<double> &p, std::vector<double> &CurPoint, NURBS &MainNurb)
{
if (!p.empty())
p.clear();
int i = 0, j = 0;
//val = reshape(nurbs.coefs,4*num1,num2);
std::vector< std::vector<double> > CntrlPoints(((MainNurb.MaxU+1)*3), std::vector<double>((MainNurb.MaxV+1), 0.0));
for (unsigned int a = 0; a < MainNurb.CntrlArray.size(); )
{
CntrlPoints[i][j] = MainNurb.CntrlArray[a];
CntrlPoints[i+1][j] = MainNurb.CntrlArray[a+1];
CntrlPoints[i+2][j] = MainNurb.CntrlArray[a+2];
i += 3;
a += 3;
if (i == ((MainNurb.MaxU+1)*3))
{
i = 0;
j++;
}
}
//v direction...?
i = 0;
std::vector<double> Output(CntrlPoints.size(), 0.0);
PointBSPEval(MainNurb.DegreeV, CntrlPoints, MainNurb.KnotV, Output, CurPoint[1]);
std::vector< std::vector<double> > RedoneOutput(3, std::vector<double>(MainNurb.MaxU+1, 0.0));
for (unsigned int a = 0; a < Output.size(); )
{
RedoneOutput[0][i] = Output[a];
RedoneOutput[1][i] = Output[a+1];
RedoneOutput[2][i] = Output[a+2];
a += 3;
i++;
}
std::vector<double> OutVect(4,0.0);
PointBSPEval(MainNurb.DegreeU, RedoneOutput, MainNurb.KnotU, OutVect,CurPoint[0]);
p.push_back(OutVect[0]);
p.push_back(OutVect[1]);
p.push_back(OutVect[2]);
}
/*! \brief Translation from bspeval.m from NURBS Toolbox. WARNING: ONLY POINT EVALUATION ARE CONSIDERED!!!! */
void Routines::PointBSPEval(int Degree, std::vector< std::vector<double> > &Cntrl, std::vector<double> &KnotSequence,
std::vector< double > &Output, double CurEvalPoint)
{
std::vector<double> Basis(Degree+1, 0.0);
int s = FindSpan(Cntrl[0].size() - 1,Degree,CurEvalPoint,KnotSequence);
Basisfun(s,CurEvalPoint,Degree,KnotSequence,Basis);
int tmp1 = s - Degree;
for (unsigned int row = 0;row < Cntrl.size();row++)
{
double tmp2 = 0.0;
for (int i = 0; i <= Degree; i++)
tmp2 += Basis[i] *Cntrl[row][tmp1+i];
Output[row] = tmp2;
}
}
/*! \brief Translation from nrbderivate.m from NURBS Toolbox. WARNING: ONLY POINT EVALUATION ARE CONSIDERED!!!! */
void Routines::PointNrbDerivate(NURBS MainNurb, std::vector<NURBS> &OutNurbs)
{
if (!OutNurbs.empty())
OutNurbs.clear();
NURBS Temp;
int i = 0, j = 0, k = 0;
std::vector< std::vector<double> > ControlDerivate;
std::vector<double> KnotDerivate;
std::vector< std::vector<double> > CntrlPoints(((MainNurb.MaxV+1)*3), std::vector<double>((MainNurb.MaxU+1), 0.0));
for (unsigned int a = 0; a < MainNurb.CntrlArray.size(); )
{
CntrlPoints[i][j] = MainNurb.CntrlArray[a];
CntrlPoints[i+1][j] = MainNurb.CntrlArray[a+1];
CntrlPoints[i+2][j] = MainNurb.CntrlArray[a+2];
j++;
a += 3;
i = k*3;
if (j == (MainNurb.MaxU+1))
{
j = 0;
k++;
i = k*3;
}
}
//U derivate
bspderiv(MainNurb.DegreeU, CntrlPoints, MainNurb.KnotU, ControlDerivate, KnotDerivate);
Temp.CntrlArray.resize(ControlDerivate.size() * ControlDerivate[0].size());
i = 0, j = 0, k = 0;
for (unsigned int a = 0; a < Temp.CntrlArray.size(); )
{
Temp.CntrlArray[a] = ControlDerivate[i][j];
Temp.CntrlArray[a+1] = ControlDerivate[i+1][j];
Temp.CntrlArray[a+2] = ControlDerivate[i+2][j];
j++;
a += 3;
i = k*3;
if (j == (int)ControlDerivate[i].size())
{
j = 0;
k++;
i = k*3;
}
}
Temp.KnotU = KnotDerivate;
Temp.KnotV = MainNurb.KnotV;
Temp.MaxKnotU = Temp.KnotU.size();
Temp.MaxKnotV = Temp.KnotV.size();
Temp.MaxU = ControlDerivate[0].size();
Temp.MaxV = ControlDerivate.size() / 3;
Temp.DegreeU = Temp.MaxKnotU - Temp.MaxU - 1;
Temp.DegreeV = Temp.MaxKnotV - Temp.MaxV - 1;
Temp.MaxU--;
Temp.MaxV--;
OutNurbs.push_back(Temp);
//reset
i = 0, j = 0, k = 0;
CntrlPoints.clear();
ControlDerivate.clear();
KnotDerivate.clear();
CntrlPoints.resize((MainNurb.MaxU+1)*3);
for (unsigned int a = 0; a < CntrlPoints.size(); a++)
CntrlPoints[a].resize(MainNurb.MaxV+1);
for (unsigned int a = 0; a < MainNurb.CntrlArray.size(); )
{
CntrlPoints[i][j] = MainNurb.CntrlArray[a];
CntrlPoints[i+1][j] = MainNurb.CntrlArray[a+1];
CntrlPoints[i+2][j] = MainNurb.CntrlArray[a+2];
i += 3;
a += 3;
if (i == ((MainNurb.MaxU+1)*3))
{
i = 0;
j++;
}
}
//V derivate
bspderiv(MainNurb.DegreeV, CntrlPoints, MainNurb.KnotV, ControlDerivate, KnotDerivate);
Temp.CntrlArray.resize(ControlDerivate.size() * ControlDerivate[0].size());
i = 0, j = 0, k = 0;
for (unsigned int a = 0; a < Temp.CntrlArray.size(); )
{
Temp.CntrlArray[a] = ControlDerivate[i][j];
Temp.CntrlArray[a+1] = ControlDerivate[i+1][j];
Temp.CntrlArray[a+2] = ControlDerivate[i+2][j];
a += 3;
i += 3;
if (i == (int)ControlDerivate.size())
{
j++;
i = 0;
}
}
Temp.KnotU = MainNurb.KnotU;
Temp.KnotV = KnotDerivate;
Temp.MaxKnotU = Temp.KnotU.size();
Temp.MaxKnotV = Temp.KnotV.size();
Temp.MaxU = ControlDerivate.size() / 3;
Temp.MaxV = ControlDerivate[0].size();
Temp.DegreeU = Temp.MaxKnotU - Temp.MaxU - 1;
Temp.DegreeV = Temp.MaxKnotV - Temp.MaxV - 1;
Temp.MaxU--;
Temp.MaxV--;
OutNurbs.push_back(Temp);
}
/*! \brief Translation from bspderiv.m from NURBS Toolbox. WARNING: ONLY POINT EVALUATION ARE CONSIDERED!!!! */
void Routines::bspderiv(int d, std::vector< std::vector<double> > &c, std::vector<double> &k,
std::vector< std::vector<double> > &OutputC, std::vector<double> &Outputk)
{
OutputC.resize(c.size());
for (unsigned int i = 0; i < OutputC.size(); i++)
OutputC[i].resize(c[i].size()-1);
double tmp = 0.0;
for (unsigned int i = 0; i < OutputC[0].size(); i++)
{
tmp = d / (k[i+d+1]-k[i+1]);
for (unsigned int j = 0; j < OutputC.size(); j++)
OutputC[j][i] = tmp * (c[j][i+1] - c[j][i]);
}
Outputk.resize(k.size() - 2);
for (unsigned int i = 0; i < Outputk.size(); i++)
Outputk[i] = k[i+1];
}
/*! \brief Translation from nrbdeval.m from NURBS Toolbox. WARNING: ONLY POINT EVALUATION ARE CONSIDERED!!!! */
void Routines::NrbDEval(NURBS &MainNurb, std::vector<NURBS> &DerivNurb, std::vector<double> &Point,
std::vector<double> &EvalPoint, std::vector<std::vector<double> > &jac)
{
if (!EvalPoint.empty())
EvalPoint.clear();
if (!jac.empty())
jac.clear();
std::vector<double> TempoPointDeriv;
PointNrbEval(EvalPoint, Point, MainNurb);
for (unsigned int i = 0; i < DerivNurb.size(); i++)
{
PointNrbEval(TempoPointDeriv, Point, DerivNurb[i]);
jac.push_back(TempoPointDeriv);
TempoPointDeriv.clear();
}
}
/*! \brief Uniform Knot Generator */
void Routines::GenerateUniformKnot(int MaxCntrl, int NurbDegree, std::vector<double> &KnotSequence)
{
if (!KnotSequence.empty())
KnotSequence.clear();
for (int i = 0; i < (MaxCntrl + NurbDegree + 2); i++)
KnotSequence.push_back(0);
for (int i = NurbDegree; i < MaxCntrl; i++)
KnotSequence[i+1] = (double)(i - NurbDegree + 1.0) / (double)(MaxCntrl - NurbDegree + 1.0);
for (unsigned int i = MaxCntrl+1; i < KnotSequence.size(); i++)
KnotSequence[i] = 1;
}
/*! \brief Find the corner points
Idea: From the neighbour list, find the shortest distance of a point to the given parameter X and Y.
Parameter X and Y are the bounding boxes parameter of the mesh (combinations of Min and Max of X and Y)
*/
unsigned long Routines::FindCorner(float ParamX, float ParamY, std::vector<unsigned long> &v_neighbour, std::vector <Base::Vector3f> &v_pnts)
{
unsigned int j = 0;
bool change = false;
//double distance = sqrt(((ParamX - ParameterMesh.GetPoint(v_neighbour[0])[0])*(ParamX - ParameterMesh.GetPoint(v_neighbour[0])[0])) +
// ((ParamY - ParameterMesh.GetPoint(v_neighbour[0])[1])*(ParamY - ParameterMesh.GetPoint(v_neighbour[0])[1])));
double distance = sqrt(((ParamX - v_pnts[0][0])*(ParamX - v_pnts[0][0])) +
((ParamY - v_pnts[0][1])*(ParamY - v_pnts[0][1])));
for (unsigned int k = 1; k < v_neighbour.size(); ++k)
{
double eps= sqrt(((ParamX - v_pnts[k][0])*(ParamX - v_pnts[k][0])) +
((ParamY - v_pnts[k][1])*(ParamY - v_pnts[k][1])));
if (eps < distance)
{
distance = eps;
j = k;
change = true;
}
}
if (change)
return v_neighbour[j];
else return v_neighbour[0];
}
/*! \brief Calculate the Area of the triangle, bounded by three vectors from origin. A (bad) diagram is included in source
code */
double Routines::AreaTriangle(Base::Vector3f &a, Base::Vector3f &b, Base::Vector3f &c)
{
/* a
* x----->x b
* \ /
* \ /
* \/
* V
* x c
*/
Base::Vector3f First = b - a;
Base::Vector3f Second = c - a;
std::vector < std::vector<double> > Matrix(2, std::vector<double>(2));
Matrix[0][0] = First.x;
Matrix[1][0] = First.y;
Matrix[0][1] = Second.x;
Matrix[1][1] = Second.y;
return (0.5 * det2(Matrix));
}
/*! \brief Knot Extension
This method will extend the knots by 2. ErrPnt will tell where the knots should be inserted, NurbDegree
and MaxCntrl will make sure that the amount of 0's and 1's are left untouched.
The new values will be calculated here and will be inserted in Extension function
*/
void Routines::ExtendKnot(double ErrPnt, int NurbDegree, int MaxCntrl, std::vector<double> &KnotSequence)
{
double tol_knot = 0.02;
int ind_1 = 0;
double new1 = 0;
int ind_2 = 0;
double new2 = 0;
bool flag = false;
if (KnotSequence.size()>40)
tol_knot = 0.015;
for (unsigned int i = NurbDegree; i < (KnotSequence.size() - NurbDegree); i++)
{
if ((KnotSequence[i] > ErrPnt) && (ErrPnt >= KnotSequence[i-1]))
{
ind_1 = i;
new1 = (KnotSequence[ind_1] + KnotSequence[ind_1-1]) / 2;
}
}
//START CHANGE
if (!flag)
{
double mid = (double)KnotSequence.size() / 2.0;
if (ind_1 == mid)
{
KnotSequence.resize(KnotSequence.size() + 2);
//MainNurb.MaxKnotU += 2;
for (int i = KnotSequence.size() - 1; i > ind_1; i--)
KnotSequence[i] = KnotSequence[i-2];
KnotSequence[ind_1] = KnotSequence[ind_1-1] + ((new1 - KnotSequence[ind_1-1]) / 2.0);
KnotSequence[ind_1+1] = new1 +((new1 - KnotSequence[ind_1-1]) / 2.0);
}
else
{
double temp = mid - ((double)ind_1);
ind_2 = (int)(mid + temp);
new2 = (KnotSequence[ind_2-1] + KnotSequence[ind_2]) / 2.0;
if (ind_1 < ind_2)
Extension(KnotSequence,ind_1,ind_2,new1,new2);
else
Extension(KnotSequence,ind_2,ind_1,new2,new1);
}
}
else
{
if (ind_1 < ind_2)
Extension(KnotSequence,ind_1,ind_2,new1,new2);
else
Extension(KnotSequence,ind_2,ind_1,new2,new1);
}
}
/*! \brief This routine is because it is done over and over again...
*/
void Routines::Extension(std::vector<double> &KnotSequence, int SmallerIndex, int LargerIndex, double SmallerIndNewValue,
double LargerIndNewValue)
{
KnotSequence.resize(KnotSequence.size() + 1);
for (int i = KnotSequence.size() - 1; i > SmallerIndex; i--)
KnotSequence[i] = KnotSequence[i-1];
KnotSequence[SmallerIndex] = SmallerIndNewValue;
LargerIndex++;
KnotSequence.resize(KnotSequence.size() + 1);
for (int i = KnotSequence.size() - 1; i > LargerIndex; i--)
KnotSequence[i] = KnotSequence[i-1];
KnotSequence[LargerIndex] = LargerIndNewValue;
}