Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
b079fb987This 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;
}
//=======================================================================
//function : DNNUV
//purpose :
//=======================================================================
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);
}