1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-26 10:19:45 +03:00
occt/src/GeomFill/GeomFill_CorrectedFrenet.cxx
abv d5f74e42d6 0024624: Lost word in license statement in source files
License statement text corrected; compiler warnings caused by Bison 2.41 disabled for MSVC; a few other compiler warnings on 54-bit Windows eliminated by appropriate type cast
Wrong license statements corrected in several files.
Copyright and license statements added in XSD and GLSL files.
Copyright year updated in some files.
Obsolete documentation files removed from DrawResources.
2014-02-20 16:15:17 +04:00

1021 lines
30 KiB
C++

// Created on: 1997-12-19
// Created by: Roman BORISOV /Philippe MANGIN
// Copyright (c) 1997-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <stdio.h>
#include <GeomFill_CorrectedFrenet.ixx>
#include <GeomAbs_CurveType.hxx>
#include <Adaptor3d_HCurve.hxx>
#include <gp_Trsf.hxx>
#include <Precision.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <Law_Interpolate.hxx>
#include <TColStd_SequenceOfReal.hxx>
#include <gp_Vec2d.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <Bnd_Box.hxx>
#include <GeomLib.hxx>
#include <Law_Composite.hxx>
#include <Law_Constant.hxx>
#include <Law_BSpFunc.hxx>
#include <Law_BSpline.hxx>
#include <GeomFill_SnglrFunc.hxx>
//Patch
#include <Geom_Plane.hxx>
#include <Geom_BezierCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#ifdef DEB
static Standard_Boolean Affich=0;
#endif
#ifdef DRAW
static Standard_Integer CorrNumber = 0;
#include <Draw_Appli.hxx>
#include <DrawTrSurf.hxx>
#include <Draw_Segment2D.hxx>
//#include <Draw.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_HArray1OfInteger.hxx>
#endif
#ifdef DRAW
static void draw(const Handle(Law_Function)& law)
{
Standard_Real Step, u, v, tmin;
Standard_Integer NbInt, i, j, jmax;
NbInt = law->NbIntervals(GeomAbs_C3);
TColStd_Array1OfReal Int(1, NbInt+1);
law->Intervals(Int, GeomAbs_C3);
gp_Pnt2d old;
Handle(Draw_Segment2D) tg2d;
for(i = 1; i <= NbInt; i++){
tmin = Int(i);
Step = (Int(i+1)-Int(i))/4;
if (i == NbInt) jmax = 4;
else jmax = 3;
for (j=1; j<=jmax; j++) {
u = tmin + (j-1)*Step;
v = law->Value(u);
gp_Pnt2d point2d(u,v);
if ((i>1)||(j>1)) {
tg2d = new Draw_Segment2D(old, point2d,Draw_kaki);
dout << tg2d;
}
old = point2d;
}
}
dout.Flush();
}
#endif
static Standard_Real ComputeTorsion(const Standard_Real Param,
const Handle(Adaptor3d_HCurve)& aCurve)
{
Standard_Real Torsion;
gp_Pnt aPoint;
gp_Vec DC1, DC2, DC3;
aCurve->D3(Param, aPoint, DC1, DC2, DC3);
gp_Vec DC1crossDC2 = DC1 ^ DC2;
Standard_Real Norm_DC1crossDC2 = DC1crossDC2.Magnitude();
Standard_Real DC1DC2DC3 = DC1crossDC2 * DC3 ; //mixed product
Standard_Real Tol = gp::Resolution();
Standard_Real SquareNorm_DC1crossDC2 = Norm_DC1crossDC2 * Norm_DC1crossDC2;
if (SquareNorm_DC1crossDC2 <= Tol)
Torsion = 0.;
else
Torsion = DC1DC2DC3 / SquareNorm_DC1crossDC2 ;
return Torsion;
}
//===============================================================
// Function : smoothlaw
// Purpose : to smooth a law : Reduce the number of knots
//===============================================================
static void smoothlaw(Handle(Law_BSpline)& Law,
const Handle(TColStd_HArray1OfReal)& Points,
const Handle(TColStd_HArray1OfReal)& Param,
const Standard_Real Tol)
{
Standard_Real tol, d;
Standard_Integer ii, Nbk;
Standard_Boolean B, Ok;
Handle(Law_BSpline) BS = Law->Copy();
Nbk = BS->NbKnots();
tol = Tol/10;
Ok = Standard_False;
for (ii=Nbk-1; ii>1; ii--) { // Une premiere passe tolerance serres
B = BS->RemoveKnot(ii, 0, tol);
if (B) Ok = Standard_True;
}
if (Ok) { // controle
tol = 0.;
for (ii=1; ii<=Param->Length() && Ok; ii++) {
d = Abs(BS->Value(Param->Value(ii))-Points->Value(ii));
if (d > tol) tol = d;
Ok = (tol <= Tol);
}
if (Ok)
tol = (Tol-tol)/2;
else {
#if DEB
cout << "smooth law echec" << endl;
#endif
return; // Echec
}
}
else {
tol = Tol/2;
}
if (Ok) Law = BS;
Ok = Standard_False; // Une deuxieme passe tolerance desserre
Nbk = BS->NbKnots();
for (ii=Nbk-1; ii>1; ii--) {
B = BS->RemoveKnot(ii, 0, tol);
if (B) Ok = Standard_True;
}
if (Ok) { // controle
tol = 0.;
for (ii=1; ii<=Param->Length() && Ok; ii++) {
d = Abs(BS->Value(Param->Value(ii))-Points->Value(ii));
if (d > tol) tol = d;
Ok = (tol <= Tol);
}
if (!Ok) {
#if DEB
cout << "smooth law echec" << endl;
#endif
}
}
if (Ok) Law = BS;
#if DEB
if (Affich) {
cout << "Knots Law : " << endl;
for (ii=1; ii<=BS->NbKnots(); ii++) {
cout << ii << " : " << BS->Knot(ii) << endl;
}
}
#endif
}
//===============================================================
// Function : FindPlane
// Purpose :
//===============================================================
static Standard_Boolean FindPlane ( const Handle(Adaptor3d_HCurve)& c,
Handle( Geom_Plane )& P )
{
Standard_Boolean found = Standard_True;
Handle(TColgp_HArray1OfPnt) TabP;
switch (c->GetType()) {
case GeomAbs_Line:
{
found = Standard_False;
}
break;
case GeomAbs_Circle:
P = new Geom_Plane(gp_Ax3(c->Circle().Position()));
break;
case GeomAbs_Ellipse:
P = new Geom_Plane(gp_Ax3(c->Ellipse().Position()));
break;
case GeomAbs_Hyperbola:
P = new Geom_Plane(gp_Ax3(c->Hyperbola().Position()));
break;
case GeomAbs_Parabola:
P = new Geom_Plane(gp_Ax3(c->Parabola().Position()));
break;
case GeomAbs_BezierCurve:
{
Handle(Geom_BezierCurve) GC = c->Bezier();
Standard_Integer nbp = GC->NbPoles();
if ( nbp < 2)
found = Standard_False;
else if ( nbp == 2) {
found = Standard_False;
}
else {
TabP = new (TColgp_HArray1OfPnt) (1, nbp);
GC->Poles(TabP->ChangeArray1());
}
}
break;
case GeomAbs_BSplineCurve:
{
Handle(Geom_BSplineCurve) GC = c->BSpline();
Standard_Integer nbp = GC->NbPoles();
if ( nbp < 2)
found = Standard_False;
else if ( nbp == 2) {
found = Standard_False;
}
else {
TabP = new (TColgp_HArray1OfPnt) (1, nbp);
GC->Poles(TabP->ChangeArray1());
}
}
break;
default:
{ // On utilise un echantillonage
Standard_Integer nbp = 15 + c->NbIntervals(GeomAbs_C3);
Standard_Real f, l, t, inv;
Standard_Integer ii;
f = c->FirstParameter();
l = c->LastParameter();
inv = 1./(nbp-1);
for (ii=1; ii<=nbp; ii++) {
t = ( f*(nbp-ii) + l*(ii-1));
t *= inv;
TabP->SetValue(ii, c->Value(t));
}
}
}
if (! TabP.IsNull()) { // Recherche d'un plan moyen et controle
Standard_Boolean issingular;
gp_Ax2 inertia;
GeomLib::AxeOfInertia(TabP->Array1(), inertia, issingular);
if (issingular) {
found = Standard_False;
}
else {
P = new Geom_Plane(inertia);
}
if (found)
{
//control = Controle(TabP->Array1(), P, myTolerance);
// Standard_Boolean isOnPlane;
Standard_Real a,b,c,d, dist;
Standard_Integer ii;
P->Coefficients(a,b,c,d);
for (ii=1; ii<=TabP->Length() && found; ii++) {
const gp_XYZ& xyz = TabP->Value(ii).XYZ();
dist = a*xyz.X() + b*xyz.Y() + c*xyz.Z() + d;
found = (Abs(dist) <= Precision::Confusion());
}
return found;
}
}
return found;
}
//===============================================================
// Function : Constructor
// Purpose :
//===============================================================
GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet()
: isFrenet(Standard_False)
{
frenet = new GeomFill_Frenet();
myForEvaluation = Standard_False;
}
//===============================================================
// Function : Constructor
// Purpose :
//===============================================================
GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet(const Standard_Boolean ForEvaluation)
: isFrenet(Standard_False)
{
frenet = new GeomFill_Frenet();
myForEvaluation = ForEvaluation;
}
Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
{
Handle(GeomFill_CorrectedFrenet) copy = new (GeomFill_CorrectedFrenet)();
if (!myCurve.IsNull()) copy->SetCurve(myCurve);
return copy;
}
void GeomFill_CorrectedFrenet::SetCurve(const Handle(Adaptor3d_HCurve)& C)
{
GeomFill_TrihedronLaw::SetCurve(C);
if (! C.IsNull()) {
frenet->SetCurve(C);
GeomAbs_CurveType type;
type = C->GetType();
switch (type) {
case GeomAbs_Circle:
case GeomAbs_Ellipse:
case GeomAbs_Hyperbola:
case GeomAbs_Parabola:
case GeomAbs_Line:
{
// No probleme isFrenet
isFrenet = Standard_True;
break;
}
default :
{
// We have to search singulaties
isFrenet = Standard_True;
Init();
}
}
}
}
//===============================================================
// Function : Init
// Purpose : Compute angle's law
//===============================================================
void GeomFill_CorrectedFrenet::Init()
{
EvolAroundT = new Law_Composite();
Standard_Integer NbI = frenet->NbIntervals(GeomAbs_C0), i;
TColStd_Array1OfReal T(1, NbI + 1);
frenet->Intervals(T, GeomAbs_C0);
Handle(Law_Function) Func;
//OCC78
TColStd_SequenceOfReal SeqPoles, SeqAngle;
TColgp_SequenceOfVec SeqTangent, SeqNormal;
gp_Vec Tangent, Normal, BN;
frenet->D0(myTrimmed->FirstParameter(), Tangent, Normal, BN);
Standard_Integer NbStep;
// Standard_Real StartAng = 0, AvStep, Step, t;
Standard_Real StartAng = 0, AvStep, Step;
#if DRAW
Standard_Real t;
if (Affich) { // Display the curve C'^C''(t)
GeomFill_SnglrFunc CS(myCurve);
NbStep = 99;
AvStep = (myTrimmed->LastParameter() -
myTrimmed->FirstParameter())/NbStep;
TColgp_Array1OfPnt TabP(1, NbStep+1);
TColStd_Array1OfReal TI(1, NbStep+1);
TColStd_Array1OfInteger M(1,NbStep+1);
M.Init(1);
M(1) = M(NbStep+1) = 2;
for (i=1; i<=NbStep+1; i++) {
t = (myTrimmed->FirstParameter()+ (i-1)*AvStep);
CS.D0(t, TabP(i));
TI(i) = t;
}
char tname[100];
Standard_CString name = tname ;
sprintf(name,"Binorm_%d", ++CorrNumber);
Handle(Geom_BSplineCurve) BS = new
(Geom_BSplineCurve) (TabP, TI, M, 1);
// DrawTrSurf::Set(&name[0], BS);
DrawTrSurf::Set(name, BS);
}
#endif
NbStep = 10;
AvStep = (myTrimmed->LastParameter() - myTrimmed->FirstParameter())/NbStep;
for(i = 1; i <= NbI; i++) {
NbStep = Max(Standard_Integer((T(i+1) - T(i))/AvStep), 3);
Step = (T(i+1) - T(i))/NbStep;
if(!InitInterval(T(i), T(i+1), Step, StartAng, Tangent, Normal, AT, AN, Func,
SeqPoles, SeqAngle, SeqTangent, SeqNormal))
{
if(isFrenet)
isFrenet = Standard_False;
}
Handle(Law_Composite)::DownCast(EvolAroundT)->ChangeLaws().Append(Func);
}
if(myTrimmed->IsPeriodic())
Handle(Law_Composite)::DownCast(EvolAroundT)->SetPeriodic();
TLaw = EvolAroundT;
//OCC78
Standard_Integer iEnd = SeqPoles.Length();
HArrPoles = new TColStd_HArray1OfReal(1, iEnd);
HArrAngle = new TColStd_HArray1OfReal(1, iEnd);
HArrTangent = new TColgp_HArray1OfVec(1, iEnd);
HArrNormal = new TColgp_HArray1OfVec(1, iEnd);
for(i = 1; i <= iEnd; i++){
HArrPoles->ChangeValue(i) = SeqPoles(i);
HArrAngle->ChangeValue(i) = SeqAngle(i);
HArrTangent->ChangeValue(i) = SeqTangent(i);
HArrNormal->ChangeValue(i) = SeqNormal(i);
};
#if DRAW
if (Affich) {
draw(EvolAroundT);
}
#endif
}
//===============================================================
// Function : InitInterval
// Purpose : Compute the angle law on a span
//===============================================================
Standard_Boolean GeomFill_CorrectedFrenet::
InitInterval(const Standard_Real First, const Standard_Real Last,
const Standard_Real Step,
Standard_Real& startAng, gp_Vec& prevTangent,
gp_Vec& prevNormal, gp_Vec& aT, gp_Vec& aN,
Handle(Law_Function)& FuncInt,
TColStd_SequenceOfReal& SeqPoles,
TColStd_SequenceOfReal& SeqAngle,
TColgp_SequenceOfVec& SeqTangent,
TColgp_SequenceOfVec& SeqNormal) const
{
Bnd_Box Boite;
gp_Vec Tangent, Normal, BN, cross;
TColStd_SequenceOfReal parameters;
TColStd_SequenceOfReal EvolAT;
Standard_Real Param = First, L, norm;
Standard_Boolean isZero = Standard_True, isConst = Standard_True;
const Standard_Real minnorm = 1.e-16;
Standard_Integer i;
gp_Pnt PonC;
gp_Vec D1;
frenet->SetInterval(First, Last); //To have the rigth evaluation at bounds
GeomFill_SnglrFunc CS(myCurve);
BndLib_Add3dCurve::Add(CS, First, Last, 1.e-2, Boite);
aT = gp_Vec(0, 0, 0);
aN = gp_Vec(0, 0, 0);
Standard_Real angleAT = 0., currParam, currStep = Step;
Handle( Geom_Plane ) aPlane;
Standard_Boolean isPlanar = Standard_False;
if (!myForEvaluation)
isPlanar = FindPlane( myCurve, aPlane );
i = 1;
currParam = Param;
Standard_Real DLast = Last - Precision::PConfusion();
while (Param < Last) {
if (currParam > DLast) {
currStep = DLast - Param;
currParam = Last;
}
if (isPlanar)
currParam = Last;
frenet->D0(currParam, Tangent, Normal, BN);
if (prevTangent.Angle(Tangent) < M_PI/3 || i == 1) {
parameters.Append(currParam);
//OCC78
SeqPoles.Append(Param);
SeqAngle.Append(i > 1? EvolAT(i-1) : startAng);
SeqTangent.Append(prevTangent);
SeqNormal.Append(prevNormal);
angleAT = CalcAngleAT(Tangent,Normal,prevTangent,prevNormal);
if(isConst && i > 1)
if(Abs(angleAT) > Precision::PConfusion())
isConst = Standard_False;
angleAT += (i > 1) ? EvolAT(i-1) : startAng;
EvolAT.Append(angleAT);
prevNormal = Normal;
if(isZero)
if(Abs(angleAT) > Precision::PConfusion())
isZero = Standard_False;
aT += Tangent;
cross = Tangent.Crossed(Normal);
aN.SetLinearForm(Sin(angleAT), cross,
1 - Cos(angleAT), Tangent.Crossed(cross),
Normal+aN);
prevTangent = Tangent;
Param = currParam;
i++;
//Evaluate the Next step
CS.D1(Param, PonC, D1);
L = PonC.XYZ().Modulus()/2;
norm = D1.Magnitude();
if (norm <= gp::Resolution())
{
//norm = 2.*gp::Resolution();
norm = minnorm;
}
currStep = L / norm;
if (currStep <= gp::Resolution()) //L = 0 => curvature = 0, linear segment
currStep = Step;
if (currStep < Precision::Confusion()) //too small step
currStep = Precision::Confusion();
if (currStep > Step) //too big step
currStep = Step;//default value
}
else
currStep /= 2; // Step too long !
currParam = Param + currStep;
}
if (! isPlanar)
{
aT /= parameters.Length() - 1;
aN /= parameters.Length() - 1;
}
startAng = angleAT;
// Interpolation
if (isConst || isPlanar) {
FuncInt = new Law_Constant();
Handle(Law_Constant)::DownCast(FuncInt)->Set( angleAT, First, Last );
}
else {
Standard_Integer Length = parameters.Length();
Handle(TColStd_HArray1OfReal) pararr =
new TColStd_HArray1OfReal(1, Length);
Handle(TColStd_HArray1OfReal) angleATarr =
new TColStd_HArray1OfReal(1, Length);
for (i = 1; i <= Length; i++) {
pararr->ChangeValue(i) = parameters(i);
angleATarr->ChangeValue(i) = EvolAT(i);
}
#if DEB
if (Affich) {
cout<<"NormalEvolution"<<endl;
for (i = 1; i <= Length; i++) {
cout<<"("<<pararr->Value(i)<<", "<<angleATarr->Value(i)<<")" << endl;
}
cout<<endl;
}
#endif
Law_Interpolate lawAT(angleATarr, pararr,
Standard_False, Precision::PConfusion());
lawAT.Perform();
Handle(Law_BSpline) BS = lawAT.Curve();
smoothlaw(BS, angleATarr, pararr, 0.1);
FuncInt = new Law_BSpFunc(BS, First, Last);
}
return isZero;
}
//===============================================================
// Function : CalcAngleAT (OCC78)
// Purpose : Calculate angle of rotation of trihedron normal and its derivatives relative
// at any position on his curve
//===============================================================
Standard_Real GeomFill_CorrectedFrenet::CalcAngleAT(const gp_Vec& Tangent, const gp_Vec& Normal,
const gp_Vec& prevTangent, const gp_Vec& prevNormal) const
{
Standard_Real angle;
gp_Vec Normal_rot, cross;
angle = Tangent.Angle(prevTangent);
if (Abs(angle) > Precision::Angular()) {
cross = Tangent.Crossed(prevTangent).Normalized();
Normal_rot = Normal + sin(angle)*cross.Crossed(Normal) +
(1 - cos(angle))*cross.Crossed(cross.Crossed(Normal));
}
else
Normal_rot = Normal;
Standard_Real angleAT = Normal_rot.Angle(prevNormal);
if(angleAT > Precision::Angular() && M_PI - angleAT > Precision::Angular())
if (Normal_rot.Crossed(prevNormal).IsOpposite(prevTangent, Precision::Angular()))
angleAT = -angleAT;
return angleAT;
};
//===============================================================
// Function : ... (OCC78)
// Purpose : This family of functions produce conversion of angle utility
//===============================================================
static Standard_Real corr2PI_PI(Standard_Real Ang){
return Ang = (Ang < M_PI? Ang: Ang-2*M_PI);
};
static Standard_Real diffAng(Standard_Real A, Standard_Real Ao){
Standard_Real dA = (A-Ao) - Floor((A-Ao)/2.0/M_PI)*2.0*M_PI;
return dA = dA >= 0? corr2PI_PI(dA): -corr2PI_PI(-dA);
};
//===============================================================
// Function : CalcAngleAT (OCC78)
// Purpose : Calculate angle of rotation of trihedron normal and its derivatives relative
// at any position on his curve
//===============================================================
Standard_Real GeomFill_CorrectedFrenet::GetAngleAT(const Standard_Real Param) const{
// Search index of low margin from poles of TLaw by bisection method
Standard_Integer iB = 1, iE = HArrPoles->Length(), iC = (iE+iB)/2;
if(Param == HArrPoles->Value(iB)) return TLaw->Value(Param);
if(Param > HArrPoles->Value(iE)) iC = iE;
if(iC < iE){
while(!(HArrPoles->Value(iC) <= Param && Param <= HArrPoles->Value(iC+1))){
if(HArrPoles->Value(iC) < Param) iB = iC; else iE = iC;
iC = (iE+iB)/2;
};
if(HArrPoles->Value(iC) == Param || Param == HArrPoles->Value(iC+1)) return TLaw->Value(Param);
};
// Calculate differenciation between apporoximated and local values of AngleAT
Standard_Real AngP = TLaw->Value(Param), AngPo = HArrAngle->Value(iC), dAng = AngP - AngPo;
gp_Vec Tangent, Normal, BN;
frenet->D0(Param, Tangent, Normal, BN);
Standard_Real DAng = CalcAngleAT(Tangent, Normal, HArrTangent->Value(iC), HArrNormal->Value(iC));
Standard_Real DA = diffAng(DAng,dAng);
// The correction (there is core of OCC78 bug)
if(Abs(DA) > M_PI/2.0){
AngP = AngPo + DAng;
};
return AngP;
};
//===============================================================
// Function : D0
// Purpose :
//===============================================================
Standard_Boolean GeomFill_CorrectedFrenet::D0(const Standard_Real Param,
gp_Vec& Tangent,
gp_Vec& Normal,
gp_Vec& BiNormal)
{
frenet->D0(Param, Tangent, Normal, BiNormal);
if (isFrenet) return Standard_True;
Standard_Real angleAT;
//angleAT = TLaw->Value(Param);
angleAT = GetAngleAT(Param); //OCC78
// rotation around Tangent
gp_Vec cross;
cross = Tangent.Crossed(Normal);
Normal.SetLinearForm(Sin(angleAT), cross,
(1 - Cos(angleAT)), Tangent.Crossed(cross),
Normal);
BiNormal = Tangent.Crossed(Normal);
return Standard_True;
}
//===============================================================
// Function : D1
// Purpose :
//===============================================================
Standard_Boolean GeomFill_CorrectedFrenet::D1(const Standard_Real Param,
gp_Vec& Tangent,
gp_Vec& DTangent,
gp_Vec& Normal,
gp_Vec& DNormal,
gp_Vec& BiNormal,
gp_Vec& DBiNormal)
{
frenet->D1(Param, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal);
if (isFrenet) return Standard_True;
Standard_Real angleAT, d_angleAT;
Standard_Real sina, cosa;
TLaw->D1(Param, angleAT, d_angleAT);
angleAT = GetAngleAT(Param); //OCC78
gp_Vec cross, dcross, tcross, dtcross, aux;
sina = Sin(angleAT);
cosa = Cos(angleAT);
cross = Tangent.Crossed(Normal);
dcross.SetLinearForm(1, DTangent.Crossed(Normal),
Tangent.Crossed(DNormal));
tcross = Tangent.Crossed(cross);
dtcross.SetLinearForm(1, DTangent.Crossed(cross),
Tangent.Crossed(dcross));
aux.SetLinearForm(sina, dcross,
cosa*d_angleAT, cross);
aux.SetLinearForm(1 - cosa, dtcross,
sina*d_angleAT, tcross,
aux);
DNormal+=aux;
Normal.SetLinearForm( sina, cross,
(1 - cosa), tcross,
Normal);
BiNormal = Tangent.Crossed(Normal);
DBiNormal.SetLinearForm(1, DTangent.Crossed(Normal),
Tangent.Crossed(DNormal));
// for test
/* gp_Vec FDN, Tf, Nf, BNf;
Standard_Real h;
h = 1.0e-8;
if (Param + h > myTrimmed->LastParameter()) h = -h;
D0(Param + h, Tf, Nf, BNf);
FDN = (Nf - Normal)/h;
cout<<"Param = "<<Param<<endl;
cout<<"DN = ("<<DNormal.X()<<", "<<DNormal.Y()<<", "<<DNormal.Z()<<")"<<endl;
cout<<"FDN = ("<<FDN.X()<<", "<<FDN.Y()<<", "<<FDN.Z()<<")"<<endl;
*/
return Standard_True;
}
//===============================================================
// Function : D2
// Purpose :
//===============================================================
Standard_Boolean GeomFill_CorrectedFrenet::D2(const Standard_Real Param,
gp_Vec& Tangent,
gp_Vec& DTangent,
gp_Vec& D2Tangent,
gp_Vec& Normal,
gp_Vec& DNormal,
gp_Vec& D2Normal,
gp_Vec& BiNormal,
gp_Vec& DBiNormal,
gp_Vec& D2BiNormal)
{
frenet->D2(Param, Tangent, DTangent, D2Tangent,
Normal, DNormal, D2Normal,
BiNormal, DBiNormal, D2BiNormal);
if (isFrenet) return Standard_True;
Standard_Real angleAT, d_angleAT, d2_angleAT;
Standard_Real sina, cosa;
TLaw->D2(Param, angleAT, d_angleAT, d2_angleAT);
angleAT = GetAngleAT(Param); //OCC78
gp_Vec cross, dcross, d2cross, tcross, dtcross, d2tcross, aux;
sina = Sin(angleAT);
cosa = Cos(angleAT);
cross = Tangent.Crossed(Normal);
dcross.SetLinearForm(1, DTangent.Crossed(Normal),
Tangent.Crossed(DNormal));
d2cross.SetLinearForm(1, D2Tangent.Crossed(Normal),
2, DTangent.Crossed(DNormal),
Tangent.Crossed(D2Normal));
tcross = Tangent.Crossed(cross);
dtcross.SetLinearForm(1, DTangent.Crossed(cross),
Tangent.Crossed(dcross));
d2tcross.SetLinearForm(1, D2Tangent.Crossed(cross),
2, DTangent.Crossed(dcross),
Tangent.Crossed(d2cross));
aux.SetLinearForm(sina, d2cross,
2*cosa*d_angleAT, dcross,
cosa*d2_angleAT - sina*d_angleAT*d_angleAT, cross);
aux.SetLinearForm(1 - cosa, d2tcross,
2*sina*d_angleAT, dtcross,
cosa*d_angleAT*d_angleAT + sina*d2_angleAT, tcross,
aux);
D2Normal += aux;
/* D2Normal += sina*(D2Tangent.Crossed(Normal) + 2*DTangent.Crossed(DNormal) + Tangent.Crossed(D2Normal)) +
2*cosa*d_angleAT*(DTangent.Crossed(Normal) + Tangent.Crossed(DNormal)) +
(cosa*d2_angleAT - sina*d_angleAT*d_angleAT)*Tangent.Crossed(Normal) +
2*sina*d_angleAT*(DTangent.Crossed(Tangent.Crossed(Normal)) + Tangent.Crossed(DTangent.Crossed(Normal)) + Tangent.Crossed(Tangent.Crossed(DNormal))) +
(1 - cosa)*(D2Tangent.Crossed(Tangent.Crossed(Normal)) + Tangent.Crossed(D2Tangent.Crossed(Normal)) + Tangent.Crossed(Tangent.Crossed(D2Normal)) + 2*DTangent.Crossed(DTangent.Crossed(Normal)) + 2*DTangent.Crossed(Tangent.Crossed(DNormal)) + 2*Tangent.Crossed(DTangent.Crossed(DNormal)))
+
(cosa*d_angleAT*d_angleAT + sina*d2_angleAT)*Tangent.Crossed(Tangent.Crossed(Normal));*/
aux.SetLinearForm(sina, dcross,
cosa*d_angleAT, cross);
aux.SetLinearForm(1 - cosa, dtcross,
sina*d_angleAT, tcross,
aux);
DNormal+=aux;
Normal.SetLinearForm( sina, cross,
(1 - cosa), tcross,
Normal);
BiNormal = Tangent.Crossed(Normal);
DBiNormal.SetLinearForm(1, DTangent.Crossed(Normal),
Tangent.Crossed(DNormal));
D2BiNormal.SetLinearForm(1, D2Tangent.Crossed(Normal),
2, DTangent.Crossed(DNormal),
Tangent.Crossed(D2Normal));
// for test
/* gp_Vec FD2N, FD2T, FD2BN, Tf, DTf, Nf, DNf, BNf, DBNf;
Standard_Real h;
h = 1.0e-8;
if (Param + h > myTrimmed->LastParameter()) h = -h;
D1(Param + h, Tf, DTf, Nf, DNf, BNf, DBNf);
FD2N = (DNf - DNormal)/h;
FD2T = (DTf - DTangent)/h;
FD2BN = (DBNf - DBiNormal)/h;
cout<<"Param = "<<Param<<endl;
cout<<"D2N = ("<<D2Normal.X()<<", "<<D2Normal.Y()<<", "<<D2Normal.Z()<<")"<<endl;
cout<<"FD2N = ("<<FD2N.X()<<", "<<FD2N.Y()<<", "<<FD2N.Z()<<")"<<endl<<endl;
cout<<"D2T = ("<<D2Tangent.X()<<", "<<D2Tangent.Y()<<", "<<D2Tangent.Z()<<")"<<endl;
cout<<"FD2T = ("<<FD2T.X()<<", "<<FD2T.Y()<<", "<<FD2T.Z()<<")"<<endl<<endl;
cout<<"D2BN = ("<<D2BiNormal.X()<<", "<<D2BiNormal.Y()<<", "<<D2BiNormal.Z()<<")"<<endl;
cout<<"FD2BN = ("<<FD2BN.X()<<", "<<FD2BN.Y()<<", "<<FD2BN.Z()<<")"<<endl<<endl;
*/
//
return Standard_True;
}
//===============================================================
// Function : NbIntervals
// Purpose :
//===============================================================
Standard_Integer GeomFill_CorrectedFrenet::NbIntervals(const GeomAbs_Shape S) const
{
Standard_Integer NbFrenet, NbLaw;
NbFrenet = frenet->NbIntervals(S);
if (isFrenet) return NbFrenet;
NbLaw = EvolAroundT->NbIntervals(S);
if (NbFrenet == 1)
return NbLaw;
TColStd_Array1OfReal FrenetInt(1, NbFrenet + 1);
TColStd_Array1OfReal LawInt(1, NbLaw + 1);
TColStd_SequenceOfReal Fusion;
frenet->Intervals(FrenetInt, S);
EvolAroundT->Intervals(LawInt, S);
GeomLib::FuseIntervals(FrenetInt, LawInt, Fusion);
return Fusion.Length()-1;
}
//===============================================================
// Function : Intervals
// Purpose :
//===============================================================
void GeomFill_CorrectedFrenet::Intervals(TColStd_Array1OfReal& T,
const GeomAbs_Shape S) const
{
Standard_Integer NbFrenet, NbLaw;
if (isFrenet) {
frenet->Intervals(T, S);
return;
}
NbFrenet = frenet->NbIntervals(S);
if(NbFrenet==1) {
EvolAroundT->Intervals(T, S);
}
NbLaw = EvolAroundT->NbIntervals(S);
TColStd_Array1OfReal FrenetInt(1, NbFrenet + 1);
TColStd_Array1OfReal LawInt(1, NbLaw + 1);
TColStd_SequenceOfReal Fusion;
frenet->Intervals(FrenetInt, S);
EvolAroundT->Intervals(LawInt, S);
GeomLib::FuseIntervals(FrenetInt, LawInt, Fusion);
for(Standard_Integer i = 1; i <= Fusion.Length(); i++)
T.ChangeValue(i) = Fusion.Value(i);
}
//===============================================================
// Function : SetInterval
// Purpose :
//===============================================================
void GeomFill_CorrectedFrenet::SetInterval(const Standard_Real First,
const Standard_Real Last)
{
GeomFill_TrihedronLaw::SetInterval(First, Last);
frenet->SetInterval(First, Last);
if (!isFrenet) TLaw = EvolAroundT->Trim(First, Last,
Precision::PConfusion()/2);
}
//===============================================================
// Function : EvaluateBestMode
// Purpose :
//===============================================================
GeomFill_Trihedron GeomFill_CorrectedFrenet::EvaluateBestMode()
{
if (EvolAroundT.IsNull())
return GeomFill_IsFrenet; //Frenet
const Standard_Real MaxAngle = 3.*M_PI/4.;
const Standard_Real MaxTorsion = 100.;
Standard_Real Step, u, v, tmin, tmax;
Standard_Integer NbInt, i, j, k = 1;
NbInt = EvolAroundT->NbIntervals(GeomAbs_CN);
TColStd_Array1OfReal Int(1, NbInt+1);
EvolAroundT->Intervals(Int, GeomAbs_CN);
gp_Pnt2d old;
gp_Vec2d aVec, PrevVec;
Standard_Integer NbSamples = 10;
for(i = 1; i <= NbInt; i++){
tmin = Int(i);
tmax = Int(i+1);
Standard_Real Torsion = ComputeTorsion(tmin, myTrimmed);
if (Abs(Torsion) > MaxTorsion)
return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron
Handle(Law_Function) trimmedlaw = EvolAroundT->Trim(tmin, tmax, Precision::PConfusion()/2);
Step = (Int(i+1)-Int(i))/NbSamples;
for (j = 0; j <= NbSamples; j++) {
u = tmin + j*Step;
v = trimmedlaw->Value(u);
gp_Pnt2d point2d(u,v);
if (j != 0)
{
aVec.SetXY(point2d.XY() - old.XY());
if (k > 2)
{
Standard_Real theAngle = PrevVec.Angle(aVec);
if (Abs(theAngle) > MaxAngle)
return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron
}
PrevVec = aVec;
}
old = point2d;
k++;
}
}
return GeomFill_IsCorrectedFrenet; //CorrectedFrenet
}
//===============================================================
// Function : GetAverageLaw
// Purpose :
//===============================================================
void GeomFill_CorrectedFrenet::GetAverageLaw(gp_Vec& ATangent,
gp_Vec& ANormal,
gp_Vec& ABiNormal)
{
if (isFrenet) frenet->GetAverageLaw(ATangent, ANormal, ABiNormal);
else {
ATangent = AT;
ANormal = AN;
ABiNormal = ATangent;
ABiNormal.Cross(ANormal);
}
}
//===============================================================
// Function : IsConstant
// Purpose :
//===============================================================
Standard_Boolean GeomFill_CorrectedFrenet::IsConstant() const
{
return (myCurve->GetType() == GeomAbs_Line);
}
//===============================================================
// Function : IsOnlyBy3dCurve
// Purpose :
//===============================================================
Standard_Boolean GeomFill_CorrectedFrenet::IsOnlyBy3dCurve() const
{
return Standard_True;
}