Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1991-09-09
// Created by: Michel Chauvat
// Copyright (c) 1991-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 <CSLib.hxx>
#include <CSLib_NormalPolyDef.hxx>
#include <gp.hxx>
#include <gp_Dir.hxx>
#include <gp_Vec.hxx>
#include <math_FunctionRoots.hxx>
#include <PLib.hxx>
#include <Precision.hxx>
#include <TColgp_Array2OfVec.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array2OfReal.hxx>
void CSLib::Normal(
const gp_Vec& D1U,
const gp_Vec& D1V,
const Standard_Real SinTol,
CSLib_DerivativeStatus& theStatus,
gp_Dir& Normal)
{
// Function: Calculation of the normal from tangents by u and by v.
Standard_Real D1UMag = D1U.SquareMagnitude();
Standard_Real D1VMag = D1V.SquareMagnitude();
gp_Vec D1UvD1V = D1U.Crossed(D1V);
if (D1UMag <= gp::Resolution() && D1VMag <= gp::Resolution())
{
theStatus = CSLib_D1IsNull;
}
else if (D1UMag <= gp::Resolution())
theStatus = CSLib_D1uIsNull;
else if (D1VMag <= gp::Resolution())
theStatus = CSLib_D1vIsNull;
// else if ((D1VMag / D1UMag) <= RealEpsilon()) theStatus = CSLib_D1vD1uRatioIsNull;
// else if ((D1UMag / D1VMag) <= RealEpsilon()) theStatus = CSLib_D1uD1vRatioIsNull;
else
{
Standard_Real Sin2 = D1UvD1V.SquareMagnitude() / (D1UMag * D1VMag);
if (Sin2 < (SinTol * SinTol))
{
theStatus = CSLib_D1uIsParallelD1v;
}
else
{
Normal = gp_Dir(D1UvD1V);
theStatus = CSLib_Done;
}
}
}
void CSLib::Normal(
const gp_Vec& D1U,
const gp_Vec& D1V,
const gp_Vec& D2U,
const gp_Vec& D2V,
const gp_Vec& DUV,
const Standard_Real SinTol,
Standard_Boolean& Done,
CSLib_NormalStatus& theStatus,
gp_Dir& Normal)
{
// Calculation of an approximate normale in case of a null normal.
// Use limited development of the normal of order 1:
// N(u0+du,v0+dv) = N0 + dN/du(u0,v0) * du + dN/dv(u0,v0) * dv + epsilon
// -> N ~ dN/du + dN/dv.
gp_Vec D1Nu = D2U.Crossed(D1V);
D1Nu.Add(D1U.Crossed(DUV));
gp_Vec D1Nv = DUV.Crossed(D1V);
D1Nv.Add(D1U.Crossed(D2V));
Standard_Real LD1Nu = D1Nu.SquareMagnitude();
Standard_Real LD1Nv = D1Nv.SquareMagnitude();
if (LD1Nu <= RealEpsilon() && LD1Nv <= RealEpsilon())
{
theStatus = CSLib_D1NIsNull;
Done = Standard_False;
}
else if (LD1Nu < RealEpsilon())
{
theStatus = CSLib_D1NuIsNull;
Done = Standard_True;
Normal = gp_Dir(D1Nv);
}
else if (LD1Nv < RealEpsilon())
{
theStatus = CSLib_D1NvIsNull;
Done = Standard_True;
Normal = gp_Dir(D1Nu);
}
else if ((LD1Nv / LD1Nu) <= RealEpsilon())
{
theStatus = CSLib_D1NvNuRatioIsNull;
Done = Standard_False;
}
else if ((LD1Nu / LD1Nv) <= RealEpsilon())
{
theStatus = CSLib_D1NuNvRatioIsNull;
Done = Standard_False;
}
else
{
gp_Vec D1NCross = D1Nu.Crossed(D1Nv);
Standard_Real Sin2 = D1NCross.SquareMagnitude() / (LD1Nu * LD1Nv);
if (Sin2 < (SinTol * SinTol))
{
theStatus = CSLib_D1NuIsParallelD1Nv;
Done = Standard_True;
Normal = gp_Dir(D1Nu);
}
else
{
theStatus = CSLib_InfinityOfSolutions;
Done = Standard_False;
}
}
}
void CSLib::Normal(
const gp_Vec& D1U,
const gp_Vec& D1V,
const Standard_Real MagTol,
CSLib_NormalStatus& theStatus,
gp_Dir& Normal)
{
// Function: Calculate the normal from tangents by u and by v.
Standard_Real D1UMag = D1U.Magnitude();
Standard_Real D1VMag = D1V.Magnitude();
gp_Vec D1UvD1V = D1U.Crossed(D1V);
Standard_Real NMag = D1UvD1V.Magnitude();
if (NMag <= MagTol || D1UMag <= MagTol || D1VMag <= MagTol)
{
theStatus = CSLib_Singular;
// if (D1UMag <= MagTol || D1VMag <= MagTol && NMag > MagTol) MagTol = 2* NMag;
}
else
{
// Firstly normalize tangent vectors D1U and D1V (this method is more stable)
gp_Dir aD1U(D1U);
gp_Dir aD1V(D1V);
Normal = gp_Dir(aD1U.Crossed(aD1V));
theStatus = CSLib_Defined;
}
}
// Calculate normal vector in singular cases
//
void CSLib::Normal(const Standard_Integer MaxOrder,
const TColgp_Array2OfVec& DerNUV,
const Standard_Real SinTol,
const Standard_Real U,
const Standard_Real V,
const Standard_Real Umin,
const Standard_Real Umax,
const Standard_Real Vmin,
const Standard_Real Vmax,
CSLib_NormalStatus& theStatus,
gp_Dir& Normal,
Standard_Integer& OrderU,
Standard_Integer& OrderV)
{
// Standard_Integer i,l,Order=-1;
Standard_Integer i = 0, Order = -1;
Standard_Boolean Trouve = Standard_False;
// theStatus = Singular;
Standard_Real Norme;
gp_Vec D;
// Find k0 such that all derivatives N=dS/du ^ dS/dv are null
// till order k0-1
while (!Trouve && Order < MaxOrder)
{
Order++;
i = Order;
while ((i >= 0) && (!Trouve))
{
Standard_Integer j = Order - i;
D = DerNUV(i, j);
Norme = D.Magnitude();
Trouve = (Trouve || (Norme >= SinTol));
i--;
}
}
OrderU = i + 1;
OrderV = Order - OrderU;
// Vko first non null derivative of N : reference
if (Trouve)
{
if (Order == 0)
{
theStatus = CSLib_Defined;
Normal = D.Normalized();
}
else
{
gp_Vec Vk0;
Vk0 = DerNUV(OrderU, OrderV);
TColStd_Array1OfReal Ratio(0, Order);
// Calculate lambda i
i = 0;
Standard_Boolean definie = Standard_False;
while (i <= Order && !definie)
{
if (DerNUV(i, Order - i).Magnitude() <= SinTol)
Ratio(i) = 0;
else
{
if (DerNUV(i, Order - i).IsParallel(Vk0, 1e-6))
{
// Ratio(i) = DerNUV(i,Order-i).Magnitude() / Vk0.Magnitude();
// if(DerNUV(i,Order-i).IsOpposite(Vk0,1e-6)) Ratio(i)=-Ratio(i);
Standard_Real r = DerNUV(i, Order - i).Magnitude() / Vk0.Magnitude();
if (DerNUV(i, Order - i).IsOpposite(Vk0, 1e-6))
r = -r;
Ratio(i) = r;
}
else
{
definie = Standard_True;
//
}
}
i++;
} // end while
if (!definie)
{ // All lambda i exist
Standard_Integer SP;
Standard_Real inf, sup;
inf = 0.0 - M_PI;
sup = 0.0 + M_PI;
Standard_Boolean FU, LU, FV, LV;
// Creation of the domain of definition depending on the position
// of a single point (medium, border, corner).
FU = (Abs(U - Umin) < Precision::PConfusion());
LU = (Abs(U - Umax) < Precision::PConfusion());
FV = (Abs(V - Vmin) < Precision::PConfusion());
LV = (Abs(V - Vmax) < Precision::PConfusion());
if (LU)
{
inf = M_PI / 2;
sup = 3 * inf;
if (LV)
{
inf = M_PI;
}
if (FV)
{
sup = M_PI;
}
}
else if (FU)
{
sup = M_PI / 2;
inf = -sup;
if (LV)
{
sup = 0;
}
if (FV)
{
inf = 0;
}
}
else if (LV)
{
inf = 0.0 - M_PI;
sup = 0;
}
else if (FV)
{
inf = 0;
sup = M_PI;
}
Standard_Boolean CS = 0;
Standard_Real Vprec = 0., Vsuiv = 0.;
// Creation of the polynom
CSLib_NormalPolyDef Poly(Order, Ratio);
// Find zeros of SAPS
math_FunctionRoots
FindRoots(Poly, inf, sup, 200, 1e-5, Precision::Confusion(), Precision::Confusion());
// If there are zeros
if (FindRoots.IsDone() && FindRoots.NbSolutions() > 0)
{
// ranking by increasing order of roots of SAPS in Sol0
TColStd_Array1OfReal Sol0(0, FindRoots.NbSolutions() + 1);
Sol0(1) = FindRoots.Value(1);
Standard_Integer n = 1;
while (n <= FindRoots.NbSolutions())
{
Standard_Real ASOL = FindRoots.Value(n);
Standard_Integer j = n - 1;
while ((j >= 1) && (Sol0(j) > ASOL))
{
Sol0(j + 1) = Sol0(j);
j--;
}
Sol0(j + 1) = ASOL;
n++;
} // end while(n
// Add limits of the domains
Sol0(0) = inf;
Sol0(FindRoots.NbSolutions() + 1) = sup;
// Find change of sign of SAPS in comparison with its
// values to the left and right of each root
Standard_Integer ifirst = 0;
for (i = 0; i <= FindRoots.NbSolutions(); i++)
{
if (Abs(Sol0(i + 1) - Sol0(i)) > Precision::PConfusion())
{
Poly.Value((Sol0(i) + Sol0(i + 1)) / 2.0, Vsuiv);
if (ifirst == 0)
{
ifirst = i;
CS = Standard_False;
Vprec = Vsuiv;
}
else
{
CS = (Vprec * Vsuiv) < 0;
Vprec = Vsuiv;
}
}
}
}
else
{
// SAPS has no root, so forcedly do not change the sign
CS = Standard_False;
Poly.Value(inf, Vsuiv);
}
// fin if(MFR.IsDone() && MFR.NbSolutions()>0)
if (CS)
// Polynom changes the sign
SP = 0;
else if (Vsuiv > 0)
// Polynom is always positive
SP = 1;
else
// Polynom is always negative
SP = -1;
if (SP == 0)
theStatus = CSLib_InfinityOfSolutions;
else
{
theStatus = CSLib_Defined;
Normal = SP * Vk0.Normalized();
}
}
else
{
theStatus = CSLib_Defined;
Normal = D.Normalized();
}
}
}
}
//
// Calculate the derivative of the non-normed normal vector
//
gp_Vec CSLib::DNNUV(const Standard_Integer Nu,
const Standard_Integer Nv,
const TColgp_Array2OfVec& DerSurf)
{
Standard_Integer i, j;
gp_Vec D(0, 0, 0), VG, VD, PV;
for (i = 0; i <= Nu; i++)
for (j = 0; j <= Nv; j++)
{
VG = DerSurf.Value(i + 1, j);
VD = DerSurf.Value(Nu - i, Nv + 1 - j);
PV = VG ^ VD;
D = D + PLib::Bin(Nu, i) * PLib::Bin(Nv, j) * PV;
}
return D;
}
//=================================================================================================
gp_Vec CSLib::DNNUV(const Standard_Integer Nu,
const Standard_Integer Nv,
const TColgp_Array2OfVec& DerSurf1,
const TColgp_Array2OfVec& DerSurf2)
{
Standard_Integer i, j;
gp_Vec D(0, 0, 0), VG, VD, PV;
for (i = 0; i <= Nu; i++)
for (j = 0; j <= Nv; j++)
{
VG = DerSurf1.Value(i + 1, j);
VD = DerSurf2.Value(Nu - i, Nv + 1 - j);
PV = VG ^ VD;
D = D + PLib::Bin(Nu, i) * PLib::Bin(Nv, j) * PV;
}
return D;
}
//
// Calculate the derivatives of the normed normal vector depending on the derivatives
// of the non-normed normal vector
//
gp_Vec CSLib::DNNormal(const Standard_Integer Nu,
const Standard_Integer Nv,
const TColgp_Array2OfVec& DerNUV,
const Standard_Integer Iduref,
const Standard_Integer Idvref)
{
const Standard_Integer Kderiv = Nu + Nv;
TColgp_Array2OfVec DerVecNor(0, Kderiv, 0, Kderiv);
TColStd_Array2OfReal TabScal(0, Kderiv, 0, Kderiv);
TColStd_Array2OfReal TabNorm(0, Kderiv, 0, Kderiv);
gp_Vec DerNor = (DerNUV.Value(Iduref, Idvref)).Normalized();
DerVecNor.SetValue(0, 0, DerNor);
Standard_Real Dnorm = DerNUV.Value(Iduref, Idvref) * DerVecNor.Value(0, 0);
TabNorm.SetValue(0, 0, Dnorm);
TabScal.SetValue(0, 0, 0.);
for (Standard_Integer Mderiv = 1; Mderiv <= Kderiv; Mderiv++)
{
for (Standard_Integer Pderiv = 0; Pderiv <= Mderiv; Pderiv++)
{
const Standard_Integer Qderiv = Mderiv - Pderiv;
if (Pderiv > Nu || Qderiv > Nv)
{
continue;
}
// Compute n . derivee(p,q) of n
Standard_Real Scal = 0.;
if (Pderiv > Qderiv)
{
for (Standard_Integer Jderiv = 1; Jderiv <= Qderiv; Jderiv++)
{
Scal = Scal
- PLib::Bin(Qderiv, Jderiv)
* (DerVecNor.Value(0, Jderiv) * DerVecNor.Value(Pderiv, Qderiv - Jderiv));
}
for (Standard_Integer Jderiv = 0; Jderiv < Qderiv; Jderiv++)
{
Scal = Scal
- PLib::Bin(Qderiv, Jderiv)
* (DerVecNor.Value(Pderiv, Jderiv) * DerVecNor.Value(0, Qderiv - Jderiv));
}
for (Standard_Integer Ideriv = 1; Ideriv < Pderiv; Ideriv++)
{
for (Standard_Integer Jderiv = 0; Jderiv <= Qderiv; Jderiv++)
{
Scal = Scal
- PLib::Bin(Pderiv, Ideriv) * PLib::Bin(Qderiv, Jderiv)
* (DerVecNor.Value(Ideriv, Jderiv)
* DerVecNor.Value(Pderiv - Ideriv, Qderiv - Jderiv));
}
}
}
else
{
for (Standard_Integer Ideriv = 1; Ideriv <= Pderiv; Ideriv++)
{
Scal = Scal
- PLib::Bin(Pderiv, Ideriv) * DerVecNor.Value(Ideriv, 0)
* DerVecNor.Value(Pderiv - Ideriv, Qderiv);
}
for (Standard_Integer Ideriv = 0; Ideriv < Pderiv; Ideriv++)
{
Scal = Scal
- PLib::Bin(Pderiv, Ideriv) * DerVecNor.Value(Ideriv, Qderiv)
* DerVecNor.Value(Pderiv - Ideriv, 0);
}
for (Standard_Integer Ideriv = 0; Ideriv <= Pderiv; Ideriv++)
{
for (Standard_Integer Jderiv = 1; Jderiv < Qderiv; Jderiv++)
{
Scal = Scal
- PLib::Bin(Pderiv, Ideriv) * PLib::Bin(Qderiv, Jderiv)
* (DerVecNor.Value(Ideriv, Jderiv)
* DerVecNor.Value(Pderiv - Ideriv, Qderiv - Jderiv));
}
}
}
TabScal.SetValue(Pderiv, Qderiv, Scal / 2.);
// Compute the derivative (n,p) of NUV Length
Dnorm = (DerNUV.Value(Pderiv + Iduref, Qderiv + Idvref)) * DerVecNor.Value(0, 0);
for (Standard_Integer Jderiv = 0; Jderiv < Qderiv; Jderiv++)
{
Dnorm = Dnorm
- PLib::Bin(Qderiv + Idvref, Jderiv + Idvref) * TabNorm.Value(Pderiv, Jderiv)
* TabScal.Value(0, Qderiv - Jderiv);
}
for (Standard_Integer Ideriv = 0; Ideriv < Pderiv; Ideriv++)
{
for (Standard_Integer Jderiv = 0; Jderiv <= Qderiv; Jderiv++)
{
Dnorm = Dnorm
- PLib::Bin(Pderiv + Iduref, Ideriv + Iduref)
* PLib::Bin(Qderiv + Idvref, Jderiv + Idvref) * TabNorm.Value(Ideriv, Jderiv)
* TabScal.Value(Pderiv - Ideriv, Qderiv - Jderiv);
}
}
TabNorm.SetValue(Pderiv, Qderiv, Dnorm);
// Compute derivative (p,q) of n
DerNor = DerNUV.Value(Pderiv + Iduref, Qderiv + Idvref);
for (Standard_Integer Jderiv = 1; Jderiv <= Qderiv; Jderiv++)
{
DerNor = DerNor
- PLib::Bin(Pderiv + Iduref, Iduref) * PLib::Bin(Qderiv + Idvref, Jderiv + Idvref)
* TabNorm.Value(0, Jderiv) * DerVecNor.Value(Pderiv, Qderiv - Jderiv);
}
for (Standard_Integer Ideriv = 1; Ideriv <= Pderiv; Ideriv++)
{
for (Standard_Integer Jderiv = 0; Jderiv <= Qderiv; Jderiv++)
{
DerNor = DerNor
- PLib::Bin(Pderiv + Iduref, Ideriv + Iduref)
* PLib::Bin(Qderiv + Idvref, Jderiv + Idvref) * TabNorm.Value(Ideriv, Jderiv)
* DerVecNor.Value(Pderiv - Ideriv, Qderiv - Jderiv);
}
}
DerNor = DerNor / PLib::Bin(Pderiv + Iduref, Iduref) / PLib::Bin(Qderiv + Idvref, Idvref)
/ TabNorm.Value(0, 0);
DerVecNor.SetValue(Pderiv, Qderiv, DerNor);
}
}
return DerVecNor.Value(Nu, Nv);
}
c5f20409cThis file is pinned to the selected release. Download the original to open it in your design tool.