mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-08 18:40:55 +03:00
Clean-up in code causing warnings when OCCT_DEBUG is enabled Minor corrections: - new compiler warnings on VC++ 14 - rename of "PPC" variables that are said to caused conflicts on PowerPC - removal of unused header TopOpeBRep/TopOpeBRep_tools.hxx
1908 lines
62 KiB
C++
1908 lines
62 KiB
C++
// Created on: 1991-06-25
|
|
// Created by: JCV
|
|
// 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.
|
|
|
|
// Modified 04/10/96 : JCT : derivee des surfaces offset utilisation de
|
|
// CSLib
|
|
// Modified 15/11/96 : JPI : ajout equivalent surface pour les surfaces canoniques et modif des methodes D0 D1, ... UIso,VIso
|
|
// Modified 18/11/96 : JPI : inversion de l'offsetValue dans UReverse et Vreverse
|
|
|
|
#include <AdvApprox_ApproxAFunction.hxx>
|
|
#include <BSplCLib.hxx>
|
|
#include <BSplSLib.hxx>
|
|
#include <Convert_GridPolynomialToPoles.hxx>
|
|
#include <CSLib.hxx>
|
|
#include <Geom_BezierSurface.hxx>
|
|
#include <Geom_BSplineCurve.hxx>
|
|
#include <Geom_BSplineSurface.hxx>
|
|
#include <Geom_Circle.hxx>
|
|
#include <Geom_ConicalSurface.hxx>
|
|
#include <Geom_Curve.hxx>
|
|
#include <Geom_CylindricalSurface.hxx>
|
|
#include <Geom_ElementarySurface.hxx>
|
|
#include <Geom_Ellipse.hxx>
|
|
#include <Geom_Geometry.hxx>
|
|
#include <Geom_OffsetCurve.hxx>
|
|
#include <Geom_OffsetSurface.hxx>
|
|
#include <Geom_Plane.hxx>
|
|
#include <Geom_RectangularTrimmedSurface.hxx>
|
|
#include <Geom_SphericalSurface.hxx>
|
|
#include <Geom_Surface.hxx>
|
|
#include <Geom_SurfaceOfLinearExtrusion.hxx>
|
|
#include <Geom_SurfaceOfRevolution.hxx>
|
|
#include <Geom_ToroidalSurface.hxx>
|
|
#include <Geom_TrimmedCurve.hxx>
|
|
#include <Geom_UndefinedDerivative.hxx>
|
|
#include <Geom_UndefinedValue.hxx>
|
|
#include <GeomAbs_CurveType.hxx>
|
|
#include <GeomAbs_IsoType.hxx>
|
|
#include <GeomAbs_Shape.hxx>
|
|
#include <gp.hxx>
|
|
#include <gp_Dir.hxx>
|
|
#include <gp_GTrsf2d.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <gp_Trsf.hxx>
|
|
#include <gp_Vec.hxx>
|
|
#include <gp_XYZ.hxx>
|
|
#include <Precision.hxx>
|
|
#include <Standard_ConstructionError.hxx>
|
|
#include <Standard_NoSuchObject.hxx>
|
|
#include <Standard_NotImplemented.hxx>
|
|
#include <Standard_RangeError.hxx>
|
|
#include <Standard_Type.hxx>
|
|
#include <TColgp_Array1OfPnt.hxx>
|
|
#include <TColgp_Array2OfVec.hxx>
|
|
#include <TColgp_HArray2OfPnt.hxx>
|
|
#include <TColStd_Array1OfInteger.hxx>
|
|
#include <TColStd_Array1OfReal.hxx>
|
|
#include <TColStd_HArray1OfInteger.hxx>
|
|
#include <TColStd_HArray1OfReal.hxx>
|
|
#include <TColStd_HArray2OfInteger.hxx>
|
|
|
|
static const Standard_Real MyAngularToleranceForG1 = Precision::Angular();
|
|
|
|
//=======================================================================
|
|
//function : derivatives
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
static void derivatives(Standard_Integer MaxOrder,
|
|
Standard_Integer MinOrder,
|
|
const Standard_Real U,
|
|
const Standard_Real V,
|
|
const Handle(Geom_Surface)& basisSurf,
|
|
const Standard_Integer Nu,
|
|
const Standard_Integer Nv,
|
|
const Standard_Boolean AlongU,
|
|
const Standard_Boolean AlongV,
|
|
const Handle(Geom_BSplineSurface)& L,
|
|
TColgp_Array2OfVec& DerNUV,
|
|
TColgp_Array2OfVec& DerSurf)
|
|
{
|
|
Standard_Integer i,j;
|
|
gp_Pnt P;
|
|
gp_Vec DL1U, DL1V, DL2U , DL2V , DL2UV ,DL3U, DL3UUV, DL3UVV, DL3V;
|
|
|
|
if (AlongU || AlongV)
|
|
{
|
|
MaxOrder=0;
|
|
TColgp_Array2OfVec DerSurfL(0,MaxOrder+Nu+1,0,MaxOrder+Nv+1);
|
|
switch (MinOrder)
|
|
{
|
|
case 1 :
|
|
L->D1(U, V, P, DL1U, DL1V);
|
|
DerSurfL.SetValue(1, 0, DL1U);
|
|
DerSurfL.SetValue(0, 1, DL1V);
|
|
break;
|
|
case 2 :
|
|
L->D2(U, V, P, DL1U, DL1V, DL2U , DL2V , DL2UV);
|
|
DerSurfL.SetValue(1, 0, DL1U);
|
|
DerSurfL.SetValue(0, 1, DL1V);
|
|
DerSurfL.SetValue(1, 1, DL2UV);
|
|
DerSurfL.SetValue(2, 0, DL2U);
|
|
DerSurfL.SetValue(0, 2, DL2V);
|
|
break;
|
|
case 3 :
|
|
L->D3(U, V, P, DL1U, DL1V, DL2U , DL2V , DL2UV ,DL3U, DL3V ,DL3UUV, DL3UVV);
|
|
DerSurfL.SetValue(1, 0, DL1U);
|
|
DerSurfL.SetValue(0, 1, DL1V);
|
|
DerSurfL.SetValue(1, 1, DL2UV);
|
|
DerSurfL.SetValue(2, 0, DL2U);
|
|
DerSurfL.SetValue(0, 2, DL2V);
|
|
DerSurfL.SetValue(3, 0, DL3U);
|
|
DerSurfL.SetValue(2, 1, DL3UUV);
|
|
DerSurfL.SetValue(1, 2, DL3UVV);
|
|
DerSurfL.SetValue(0, 3, DL3V);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if(Nu <= Nv)
|
|
{
|
|
for(i=0;i<=MaxOrder+1+Nu;i++)
|
|
for(j=i;j<=MaxOrder+Nv+1;j++)
|
|
if(i+j> MinOrder)
|
|
{
|
|
DerSurfL.SetValue(i,j,L->DN(U,V,i,j));
|
|
DerSurf.SetValue(i,j,basisSurf->DN(U,V,i,j));
|
|
if (i!=j && j <= Nu+1)
|
|
{
|
|
DerSurf.SetValue(j,i,basisSurf->DN(U,V,j,i));
|
|
DerSurfL.SetValue(j,i,L->DN(U,V,j,i));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(j=0;j<=MaxOrder+1+Nv;j++)
|
|
for(i=j;i<=MaxOrder+Nu+1;i++)
|
|
if(i+j> MinOrder)
|
|
{
|
|
DerSurfL.SetValue(i,j,L->DN(U,V,i,j));
|
|
DerSurf.SetValue(i,j,basisSurf->DN(U,V,i,j));
|
|
if (i!=j && i <= Nv+1)
|
|
{
|
|
DerSurf.SetValue(j,i,basisSurf->DN(U,V,j,i));
|
|
DerSurfL.SetValue(j,i,L->DN(U,V,j,i));
|
|
}
|
|
}
|
|
}
|
|
for(i=0;i<=MaxOrder+Nu;i++)
|
|
for(j=0;j<=MaxOrder+Nv;j++)
|
|
{
|
|
if (AlongU)
|
|
DerNUV.SetValue(i,j,CSLib::DNNUV(i,j,DerSurfL,DerSurf));
|
|
if (AlongV)
|
|
DerNUV.SetValue(i,j,CSLib::DNNUV(i,j,DerSurf,DerSurfL));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
for(i=0;i<=MaxOrder+Nu+1;i++)
|
|
for(j=i;j<=MaxOrder+Nv+1;j++)
|
|
if(i+j>MinOrder)
|
|
{
|
|
|
|
DerSurf.SetValue(i,j,basisSurf->DN(U,V,i,j));
|
|
if (i!=j) DerSurf.SetValue(j,i,basisSurf->DN(U,V,j,i));
|
|
}
|
|
for(i=0;i<=MaxOrder+Nu;i++)
|
|
for(j=0;j<=MaxOrder+Nv;j++)
|
|
{
|
|
DerNUV.SetValue(i,j,CSLib::DNNUV(i,j,DerSurf));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Copy
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Handle(Geom_Geometry) Geom_OffsetSurface::Copy () const
|
|
{
|
|
Handle(Geom_OffsetSurface) S(new Geom_OffsetSurface(basisSurf, offsetValue, Standard_True));
|
|
return S;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Geom_OffsetSurface
|
|
//purpose : Basis surface cannot be an Offset surface or trimmed from
|
|
// offset surface.
|
|
//=======================================================================
|
|
|
|
Geom_OffsetSurface::Geom_OffsetSurface (const Handle(Geom_Surface)& theSurf,
|
|
const Standard_Real theOffset,
|
|
const Standard_Boolean isNotCheckC0)
|
|
: offsetValue (theOffset)
|
|
{
|
|
SetBasisSurface(theSurf, isNotCheckC0);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetBasisSurface
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::SetBasisSurface (const Handle(Geom_Surface)& S,
|
|
const Standard_Boolean isNotCheckC0)
|
|
{
|
|
Standard_Real aUf, aUl, aVf, aVl;
|
|
S->Bounds(aUf, aUl, aVf, aVl);
|
|
|
|
Handle(Geom_Surface) aCheckingSurf = Handle(Geom_Surface)::DownCast(S->Copy());
|
|
Standard_Boolean isTrimmed = Standard_False;
|
|
|
|
while(aCheckingSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
|
|
aCheckingSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
|
|
{
|
|
if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
|
|
{
|
|
Handle(Geom_RectangularTrimmedSurface) aTrimS =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(aCheckingSurf);
|
|
aCheckingSurf = aTrimS->BasisSurface();
|
|
isTrimmed = Standard_True;
|
|
}
|
|
|
|
if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
|
|
{
|
|
Handle(Geom_OffsetSurface) aOS =
|
|
Handle(Geom_OffsetSurface)::DownCast(aCheckingSurf);
|
|
aCheckingSurf = aOS->BasisSurface();
|
|
offsetValue += aOS->Offset();
|
|
}
|
|
}
|
|
|
|
myBasisSurfContinuity = aCheckingSurf->Continuity();
|
|
|
|
Standard_Boolean isC0 = !isNotCheckC0 && (myBasisSurfContinuity == GeomAbs_C0);
|
|
|
|
// Basis surface must be at least C1
|
|
if (isC0)
|
|
{
|
|
Handle(Geom_Curve) aCurve;
|
|
|
|
if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)))
|
|
{
|
|
Handle(Geom_SurfaceOfRevolution) aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aCheckingSurf);
|
|
aCurve = aRevSurf->BasisCurve();
|
|
}
|
|
else if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)))
|
|
{
|
|
Handle(Geom_SurfaceOfLinearExtrusion) aLESurf = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aCheckingSurf);
|
|
aCurve = aLESurf->BasisCurve();
|
|
}
|
|
|
|
if(!aCurve.IsNull())
|
|
{
|
|
while(aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)) ||
|
|
aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
|
|
{
|
|
if (aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
|
|
{
|
|
Handle(Geom_TrimmedCurve) aTrimC =
|
|
Handle(Geom_TrimmedCurve)::DownCast(aCurve);
|
|
aCurve = aTrimC->BasisCurve();
|
|
}
|
|
|
|
if (aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
|
|
{
|
|
Handle(Geom_OffsetCurve) aOC =
|
|
Handle(Geom_OffsetCurve)::DownCast(aCurve);
|
|
aCurve = aOC->BasisCurve();
|
|
}
|
|
}
|
|
}
|
|
|
|
const Standard_Real aUIsoPar = (aUf + aUl)/2.0, aVIsoPar = (aVf + aVl)/2.0;
|
|
Standard_Boolean isUG1 = Standard_False, isVG1 = Standard_False;
|
|
|
|
const Handle(Geom_Curve) aCurv1 = aCurve.IsNull() ? aCheckingSurf->UIso(aUIsoPar) : aCurve;
|
|
const Handle(Geom_Curve) aCurv2 = aCheckingSurf->VIso(aVIsoPar);
|
|
isUG1 = !aCurv1->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
|
|
isVG1 = !aCurv2->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
|
|
|
|
if(!isUG1)
|
|
{
|
|
Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCurv1);
|
|
isUG1 = aBC->IsG1(aVf, aVl, MyAngularToleranceForG1);
|
|
}
|
|
//
|
|
if(!isVG1)
|
|
{
|
|
Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCurv2);
|
|
isVG1 = aBC->IsG1(aUf, aUl, MyAngularToleranceForG1);
|
|
}
|
|
//
|
|
if(isUG1 && isVG1)
|
|
{
|
|
myBasisSurfContinuity = GeomAbs_G1;
|
|
isC0 = Standard_False;
|
|
}
|
|
|
|
// Raise exception if still C0
|
|
if (isC0)
|
|
Standard_ConstructionError::Raise("Offset with no C1 Surface");
|
|
}
|
|
|
|
if(isTrimmed)
|
|
{
|
|
basisSurf =
|
|
new Geom_RectangularTrimmedSurface(aCheckingSurf, aUf, aUl, aVf, aVl);
|
|
}
|
|
else
|
|
{
|
|
basisSurf = aCheckingSurf;
|
|
}
|
|
|
|
equivSurf = Surface();
|
|
//
|
|
// Tolerance en dur pour l'instant ,mais on devrait la proposer dans le constructeur
|
|
// et la mettre en champ, on pourrait utiliser par exemple pour l'extraction d'iso
|
|
// et aussi pour les singularite. Pour les surfaces osculatrices, on l'utilise pour
|
|
// detecter si une iso est degeneree.
|
|
const Standard_Real Tol = Precision::Confusion(); //0.0001;
|
|
myOscSurf.Init(basisSurf,Tol);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetOffsetValue
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::SetOffsetValue (const Standard_Real D)
|
|
{
|
|
offsetValue = D;
|
|
equivSurf = Surface();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UReverse
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::UReverse ()
|
|
{
|
|
basisSurf->UReverse();
|
|
offsetValue = -offsetValue;
|
|
if(!equivSurf.IsNull()) equivSurf->UReverse();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UReversedParameter
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Real Geom_OffsetSurface::UReversedParameter(const Standard_Real U) const
|
|
{
|
|
return basisSurf->UReversedParameter(U);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : VReverse
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::VReverse ()
|
|
{
|
|
basisSurf->VReverse();
|
|
offsetValue = -offsetValue;
|
|
if(!equivSurf.IsNull()) equivSurf->VReverse();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : VReversedParameter
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Real Geom_OffsetSurface::VReversedParameter(const Standard_Real V) const
|
|
{
|
|
return basisSurf->VReversedParameter(V);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Bounds
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::Bounds (Standard_Real& U1, Standard_Real& U2,
|
|
Standard_Real& V1, Standard_Real& V2) const
|
|
{
|
|
basisSurf->Bounds (U1, U2 ,V1, V2);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Continuity
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
GeomAbs_Shape Geom_OffsetSurface::Continuity () const
|
|
{
|
|
switch (myBasisSurfContinuity) {
|
|
case GeomAbs_C2 : return GeomAbs_C1;
|
|
case GeomAbs_C3 : return GeomAbs_C2;
|
|
case GeomAbs_CN : return GeomAbs_CN;
|
|
default : break;
|
|
}
|
|
return GeomAbs_C0;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : D0
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::D0 (const Standard_Real U, const Standard_Real V, gp_Pnt& P) const
|
|
{
|
|
gp_Vec D1U, D1V;
|
|
#ifdef CHECK
|
|
if (myBasisSurfContinuity == GeomAbs_C0)
|
|
Geom_UndefinedValue::Raise();
|
|
#endif
|
|
if (equivSurf.IsNull()){
|
|
basisSurf->D1(U, V, P, D1U, D1V);
|
|
SetD0(U,V,P,D1U,D1V);
|
|
}
|
|
else
|
|
equivSurf->D0(U,V,P);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : D1
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::D1 (const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V) const
|
|
{
|
|
#ifdef CHECK
|
|
if (myBasisSurfContinuity == GeomAbs_C0 ||
|
|
myBasisSurfContinuity == GeomAbs_C1)
|
|
Geom_UndefinedDerivative::Raise();
|
|
#endif
|
|
if (equivSurf.IsNull())
|
|
{
|
|
gp_Vec d2u, d2v, d2uv;
|
|
basisSurf->D2(U, V, P, D1U, D1V, d2u, d2v, d2uv);
|
|
SetD1(U,V,P,D1U,D1V,d2u,d2v,d2uv);
|
|
}
|
|
else
|
|
equivSurf->D1(U,V,P,D1U,D1V);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : D2
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::D2 (const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V,
|
|
gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV) const
|
|
{
|
|
#ifdef CHECK
|
|
if (myBasisSurfContinuity == GeomAbs_C0 ||
|
|
myBasisSurfContinuity == GeomAbs_C1 ||
|
|
myBasisSurfContinuity == GeomAbs_C2)
|
|
Geom_UndefinedDerivative::Raise();
|
|
#endif
|
|
if (equivSurf.IsNull())
|
|
{
|
|
gp_Vec d3u, d3uuv, d3uvv, d3v;
|
|
basisSurf->D3(U, V, P, D1U, D1V, D2U, D2V, D2UV, d3u, d3v, d3uuv, d3uvv);
|
|
SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,d3u,d3v,d3uuv,d3uvv);
|
|
}
|
|
else
|
|
equivSurf->D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : D3
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::D3 (const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V,
|
|
gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
|
|
gp_Vec& D3U, gp_Vec& D3V, gp_Vec& D3UUV, gp_Vec& D3UVV) const
|
|
{
|
|
#ifdef CHECK
|
|
if (!(basisSurf->IsCNu (4) && basisSurf->IsCNv (4))) {
|
|
Geom_UndefinedDerivative::Raise();
|
|
}
|
|
#endif
|
|
if (equivSurf.IsNull())
|
|
{
|
|
basisSurf->D3(U, V, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
|
|
SetD3(U, V, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
|
|
}
|
|
else
|
|
equivSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : DN
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
gp_Vec Geom_OffsetSurface::DN (const Standard_Real U, const Standard_Real V,
|
|
const Standard_Integer Nu, const Standard_Integer Nv) const
|
|
{
|
|
Standard_RangeError_Raise_if (Nu < 0 || Nv < 0 || Nu + Nv < 1, " ");
|
|
#ifdef CHECK
|
|
if (!(basisSurf->IsCNu (Nu) && basisSurf->IsCNv (Nv))) {
|
|
Geom_UndefinedDerivative::Raise();
|
|
}
|
|
#endif
|
|
gp_Vec D(0,0,0);
|
|
|
|
if (equivSurf.IsNull())
|
|
{
|
|
gp_Pnt P;
|
|
gp_Vec D1U,D1V;
|
|
basisSurf->D1 (U, V, P, D1U, D1V);
|
|
|
|
D = SetDN(U,V,Nu,Nv,D1U,D1V);
|
|
}
|
|
else
|
|
D = equivSurf->DN(U,V,Nu,Nv);
|
|
return D;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : D1
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::D1
|
|
(const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P, gp_Pnt& Pbasis,
|
|
gp_Vec& D1U, gp_Vec& D1V, gp_Vec& D1Ubasis, gp_Vec& D1Vbasis,
|
|
gp_Vec& D2Ubasis, gp_Vec& D2Vbasis, gp_Vec& D2UVbasis) const
|
|
{
|
|
const GeomAbs_Shape basisCont = basisSurf->Continuity();
|
|
if (basisCont == GeomAbs_C0 || basisCont == GeomAbs_C1)
|
|
Geom_UndefinedDerivative::Raise();
|
|
basisSurf->D2 (U, V, Pbasis, D1Ubasis, D1Vbasis, D2Ubasis, D2Vbasis, D2UVbasis);
|
|
gp_Vec Ndir = D1Ubasis.Crossed (D1Vbasis);
|
|
const Standard_Real R2 = Ndir.SquareMagnitude();
|
|
const Standard_Real R = Sqrt (R2);
|
|
const Standard_Real R3 = R * R2;
|
|
gp_Vec DUNdir = D2Ubasis.Crossed (D1Vbasis);
|
|
DUNdir.Add (D1Ubasis.Crossed (D2UVbasis));
|
|
gp_Vec DVNdir = D2UVbasis.Crossed (D1Vbasis);
|
|
DVNdir.Add (D1Ubasis.Crossed (D2Vbasis));
|
|
const Standard_Real DRu = Ndir.Dot (DUNdir);
|
|
const Standard_Real DRv = Ndir.Dot (DVNdir);
|
|
if (R3 <= gp::Resolution()) {
|
|
if (R2 <= gp::Resolution())
|
|
Geom_UndefinedDerivative::Raise();
|
|
DUNdir.Multiply(R);
|
|
DUNdir.Subtract (Ndir.Multiplied (DRu/R));
|
|
DUNdir.Multiply (offsetValue/R2);
|
|
D1U = D1Ubasis.Added (DUNdir);
|
|
DVNdir.Multiply(R);
|
|
DVNdir.Subtract (Ndir.Multiplied (DRv/R));
|
|
DVNdir.Multiply (offsetValue/R2);
|
|
D1V = D1Vbasis.Added (DVNdir);
|
|
}
|
|
else {
|
|
DUNdir.Multiply (offsetValue / R);
|
|
DUNdir.Subtract (Ndir.Multiplied (offsetValue*DRu/R3));
|
|
D1U = D1Ubasis.Added (DUNdir);
|
|
DVNdir.Multiply (offsetValue / R);
|
|
DVNdir.Subtract (Ndir.Multiplied (offsetValue*DRv/R3));
|
|
D1V = D1Vbasis.Added (DVNdir);
|
|
}
|
|
Ndir.Multiply (offsetValue/R);
|
|
P.SetXYZ ((Ndir.XYZ()).Added (Pbasis.XYZ()));
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : D2
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::D2
|
|
(const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P, gp_Pnt& Pbasis,
|
|
gp_Vec& D1U, gp_Vec& D1V, gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
|
|
gp_Vec& D1Ubasis, gp_Vec& D1Vbasis,
|
|
gp_Vec& D2Ubasis, gp_Vec& D2Vbasis, gp_Vec& D2UVbasis,
|
|
gp_Vec& D3Ubasis, gp_Vec& D3Vbasis, gp_Vec& D3UUVbasis, gp_Vec& D3UVVbasis) const
|
|
{
|
|
const GeomAbs_Shape basisCont = basisSurf->Continuity();
|
|
if (basisCont == GeomAbs_C0 || basisCont == GeomAbs_C1 || basisCont == GeomAbs_C2)
|
|
Geom_UndefinedDerivative::Raise();
|
|
basisSurf->D3 (U, V, P, D1Ubasis, D1Vbasis, D2Ubasis, D2Vbasis, D2UVbasis, D3Ubasis, D3Vbasis, D3UUVbasis, D3UVVbasis);
|
|
gp_Vec Ndir = D1Ubasis.Crossed (D1Vbasis);
|
|
const Standard_Real R2 = Ndir.SquareMagnitude();
|
|
const Standard_Real R = Sqrt (R2);
|
|
const Standard_Real R3 = R2 * R;
|
|
const Standard_Real R4 = R2 * R2;
|
|
const Standard_Real R5 = R3 * R2;
|
|
gp_Vec DUNdir = D2Ubasis.Crossed (D1Vbasis);
|
|
DUNdir.Add (D1Ubasis.Crossed (D2UVbasis));
|
|
gp_Vec DVNdir = D2UVbasis.Crossed (D1Vbasis);
|
|
DVNdir.Add (D1Ubasis.Crossed (D2Vbasis));
|
|
const Standard_Real DRu = Ndir.Dot (DUNdir);
|
|
const Standard_Real DRv = Ndir.Dot (DVNdir);
|
|
gp_Vec D2UNdir = D3Ubasis.Crossed (D1Vbasis);
|
|
D2UNdir.Add (D1Ubasis.Crossed (D3UUVbasis));
|
|
D2UNdir.Add (2.0 * (D2Ubasis.Crossed (D2UVbasis)));
|
|
gp_Vec D2VNdir = D3UVVbasis.Crossed (D1Vbasis);
|
|
D2VNdir.Add (D1Ubasis.Crossed (D3Vbasis));
|
|
D2VNdir.Add (2.0 * (D2UVbasis.Crossed (D2Vbasis)));
|
|
gp_Vec D2UVNdir = D2UVbasis.Crossed (D1Vbasis);
|
|
D2UVNdir.Add (D1Ubasis.Crossed (D3UVVbasis));
|
|
D2UVNdir.Add (D2Ubasis.Crossed (D2Vbasis));
|
|
const Standard_Real D2Ru = Ndir.Dot (D2UNdir) + DUNdir.Dot (DUNdir);
|
|
const Standard_Real D2Rv = Ndir.Dot (D2VNdir) + DVNdir.Dot (DVNdir);
|
|
const Standard_Real D2Ruv = DVNdir.Dot (DUNdir) + Ndir.Dot (D2UVNdir);
|
|
|
|
if (R5 <= gp::Resolution()) {
|
|
//We try another computation but the stability is not very good
|
|
//dixit ISG.
|
|
if (R4 <= gp::Resolution()) Geom_UndefinedDerivative::Raise();
|
|
// V2 = P" (U) :
|
|
// Standard_Real R4 = R2 * R2;
|
|
D2UNdir.Subtract (DUNdir.Multiplied (2.0 * DRu / R2));
|
|
D2UNdir.Subtract (Ndir.Multiplied (D2Ru/R2));
|
|
D2UNdir.Add (Ndir.Multiplied (3.0 * DRu * DRu / R4));
|
|
D2UNdir.Multiply (offsetValue / R);
|
|
D2U = D2Ubasis.Added (D2UNdir);
|
|
D2VNdir.Subtract (DVNdir.Multiplied (2.0 * DRv / R2));
|
|
D2VNdir.Subtract (Ndir.Multiplied (D2Rv/R2));
|
|
D2VNdir.Add (Ndir.Multiplied (3.0 * DRv * DRv / R4));
|
|
D2VNdir.Multiply (offsetValue / R);
|
|
D2V = D2Vbasis.Added (D2VNdir);
|
|
|
|
D2UVNdir.Subtract (DUNdir.Multiplied (DRv / R2));
|
|
D2UVNdir.Subtract (DVNdir.Multiplied (DRu / R2));
|
|
D2UVNdir.Subtract (Ndir.Multiplied (D2Ruv / R2));
|
|
D2UVNdir.Add (Ndir.Multiplied (3.0 * DRu * DRv / R4));
|
|
D2UVNdir.Multiply (offsetValue / R);
|
|
D2UV = D2UVbasis.Added (D2UVNdir);
|
|
|
|
DUNdir.Multiply(R);
|
|
DUNdir.Subtract (Ndir.Multiplied (DRu/R));
|
|
DUNdir.Multiply (offsetValue/R2);
|
|
D1U = D1Ubasis.Added (DUNdir);
|
|
DVNdir.Multiply(R);
|
|
DVNdir.Subtract (Ndir.Multiplied (DRv/R));
|
|
DVNdir.Multiply (offsetValue/R2);
|
|
D1V = D1Vbasis.Added (DVNdir);
|
|
}
|
|
else {
|
|
D2UNdir.Multiply (offsetValue/R);
|
|
D2UNdir.Subtract (DUNdir.Multiplied (2.0 * offsetValue * DRu / R3));
|
|
D2UNdir.Subtract (Ndir.Multiplied (offsetValue * D2Ru / R3));
|
|
D2UNdir.Add (Ndir.Multiplied (offsetValue * 3.0 * DRu * DRu / R5));
|
|
D2U = D2Ubasis.Added (D2UNdir);
|
|
|
|
D2VNdir.Multiply (offsetValue/R);
|
|
D2VNdir.Subtract (DVNdir.Multiplied (2.0 * offsetValue * DRv / R3));
|
|
D2VNdir.Subtract (Ndir.Multiplied (offsetValue * D2Rv / R3));
|
|
D2VNdir.Add (Ndir.Multiplied (offsetValue * 3.0 * DRv * DRv / R5));
|
|
D2V = D2Vbasis.Added (D2VNdir);
|
|
|
|
D2UVNdir.Multiply (offsetValue/R);
|
|
D2UVNdir.Subtract (DUNdir.Multiplied (offsetValue * DRv / R3));
|
|
D2UVNdir.Subtract (DVNdir.Multiplied (offsetValue * DRu / R3));
|
|
D2UVNdir.Subtract (Ndir.Multiplied (offsetValue * D2Ruv / R3));
|
|
D2UVNdir.Add (Ndir.Multiplied (3.0 * offsetValue * DRu * DRv / R5));
|
|
D2UV = D2UVbasis.Added (D2UVNdir);
|
|
|
|
DUNdir.Multiply (offsetValue / R);
|
|
DUNdir.Subtract (Ndir.Multiplied (offsetValue*DRu/R3));
|
|
D1U = D1Ubasis.Added (DUNdir);
|
|
DVNdir.Multiply (offsetValue / R);
|
|
DVNdir.Subtract (Ndir.Multiplied (offsetValue*DRv/R3));
|
|
D1V = D1Vbasis.Added (DVNdir);
|
|
}
|
|
Ndir.Multiply (offsetValue/R);
|
|
P.SetXYZ ((Ndir.XYZ()).Added (Pbasis.XYZ()));
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : LocalD0
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::LocalD0 (const Standard_Real U, const Standard_Real V,
|
|
const Standard_Integer USide, const Standard_Integer VSide,
|
|
gp_Pnt& P) const
|
|
{
|
|
if (equivSurf.IsNull()) {
|
|
gp_Vec D1U, D1V;
|
|
Handle(Geom_Surface) Basis = basisSurf;
|
|
|
|
// if Basis is Trimmed we take the basis's basis
|
|
Handle(Geom_RectangularTrimmedSurface) RTS =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
|
|
if (!RTS.IsNull())
|
|
Basis = RTS->BasisSurface();
|
|
|
|
// BSpline case
|
|
Handle(Geom_BSplineSurface) BSplS =
|
|
Handle(Geom_BSplineSurface)::DownCast(Basis);
|
|
if (!BSplS.IsNull()) {
|
|
gp_Vec D2U,D2V,D2UV, D3U,D3V,D3UUV,D3UVV;
|
|
LocateSides(U,V,USide,VSide,BSplS,1,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD0(U,V,P,D1U,D1V);
|
|
return;
|
|
}
|
|
|
|
// Extrusion case
|
|
Handle( Geom_SurfaceOfLinearExtrusion) SE =
|
|
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
|
|
if (!SE.IsNull()) {
|
|
SE->LocalD1(U,V,USide,P,D1U,D1V);
|
|
SetD0(U,V,P,D1U,D1V);
|
|
return;
|
|
}
|
|
|
|
// Revolution case
|
|
Handle(Geom_SurfaceOfRevolution) SR =
|
|
Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
|
|
if (!SR.IsNull()) {
|
|
SR->LocalD1(U,V,VSide,P,D1U,D1V);
|
|
SetD0(U,V,P,D1U,D1V);
|
|
return;
|
|
}
|
|
|
|
// General cases
|
|
basisSurf->D1(U, V, P, D1U, D1V);
|
|
SetD0(U,V,P,D1U,D1V);
|
|
}
|
|
else
|
|
equivSurf-> D0(U,V,P);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : LocalD1
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::LocalD1 (const Standard_Real U, const Standard_Real V,
|
|
const Standard_Integer USide, const Standard_Integer VSide,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V) const
|
|
{
|
|
if (equivSurf.IsNull()) {
|
|
gp_Vec D2U,D2V,D2UV ;
|
|
Handle(Geom_Surface) Basis = basisSurf;
|
|
|
|
// if Basis is Trimmed we take the basis's basis
|
|
Handle(Geom_RectangularTrimmedSurface) RTS =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
|
|
if (!RTS.IsNull())
|
|
Basis = RTS->BasisSurface();
|
|
|
|
// BSpline case
|
|
Handle(Geom_BSplineSurface) BSplS =
|
|
Handle(Geom_BSplineSurface)::DownCast(Basis);
|
|
if (!BSplS.IsNull()) {
|
|
gp_Vec D3U,D3V,D3UUV,D3UVV;
|
|
LocateSides(U,V,USide,VSide,BSplS,2,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD1(U,V,P,D1U,D1V,D2U,D2V,D2UV);
|
|
return;
|
|
}
|
|
|
|
// Extrusion case
|
|
Handle( Geom_SurfaceOfLinearExtrusion) SE =
|
|
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
|
|
if (!SE.IsNull()) {
|
|
SE->LocalD2(U,V,USide,P,D1U,D1V,D2U,D2V,D2UV);
|
|
SetD1(U,V,P,D1U,D1V,D2U,D2V,D2UV);
|
|
return;
|
|
}
|
|
|
|
// Revolution case
|
|
Handle(Geom_SurfaceOfRevolution) SR =
|
|
Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
|
|
if (!SR.IsNull()) {
|
|
SR->LocalD2(U,V,VSide,P,D1U,D1V,D2U,D2V,D2UV);
|
|
SetD1(U,V,P,D1U,D1V,D2U,D2V,D2UV);
|
|
return;
|
|
}
|
|
|
|
// General cases
|
|
basisSurf->D2(U, V, P, D1U, D1V, D2U, D2V, D2UV);
|
|
SetD1(U,V,P,D1U,D1V,D2U,D2V,D2UV);
|
|
}
|
|
else
|
|
equivSurf->D1(U,V,P,D1U,D1V);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : LocalD2
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::LocalD2 (const Standard_Real U, const Standard_Real V,
|
|
const Standard_Integer USide, const Standard_Integer VSide,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V,
|
|
gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV) const
|
|
{
|
|
if (equivSurf.IsNull()) {
|
|
Handle(Geom_Surface) Basis = basisSurf;
|
|
gp_Vec D3U,D3V,D3UUV,D3UVV;
|
|
|
|
// if Basis is Trimmed we take the basis's basis
|
|
Handle(Geom_RectangularTrimmedSurface) RTS =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
|
|
if (!RTS.IsNull())
|
|
Basis = RTS->BasisSurface();
|
|
|
|
// BSpline case
|
|
Handle(Geom_BSplineSurface) BSplS =
|
|
Handle(Geom_BSplineSurface)::DownCast(Basis);
|
|
if (!BSplS.IsNull()) {
|
|
LocateSides(U,V,USide,VSide,BSplS,3,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
return;
|
|
}
|
|
|
|
// Extrusion case
|
|
Handle(Geom_SurfaceOfLinearExtrusion) SE =
|
|
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
|
|
if (!SE.IsNull()) {
|
|
SE->LocalD3(U,V,USide,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
return;
|
|
}
|
|
|
|
// Revolution case
|
|
Handle(Geom_SurfaceOfRevolution) SR =
|
|
Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
|
|
if (!SR.IsNull()) {
|
|
SR->LocalD3(U,V,VSide,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
return;
|
|
}
|
|
|
|
// General cases
|
|
basisSurf->D3(U, V, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
|
|
SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
}
|
|
else
|
|
equivSurf->D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : LocalD3
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::LocalD3 (const Standard_Real U, const Standard_Real V,
|
|
const Standard_Integer USide, const Standard_Integer VSide,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V,
|
|
gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
|
|
gp_Vec& D3U, gp_Vec& D3V, gp_Vec& D3UUV, gp_Vec& D3UVV) const
|
|
{
|
|
if (equivSurf.IsNull()) {
|
|
Handle(Geom_Surface) Basis = basisSurf;
|
|
|
|
// if Basis is Trimmed we take the basis's basis
|
|
Handle(Geom_RectangularTrimmedSurface) RTS =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
|
|
if (!RTS.IsNull())
|
|
Basis = RTS->BasisSurface();
|
|
|
|
// BSpline case
|
|
Handle(Geom_BSplineSurface) BSplS =
|
|
Handle(Geom_BSplineSurface)::DownCast(Basis);
|
|
if (!BSplS.IsNull()) {
|
|
LocateSides(U,V,USide,VSide,BSplS,3,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
return;
|
|
}
|
|
|
|
// Extrusion case
|
|
Handle(Geom_SurfaceOfLinearExtrusion) SE =
|
|
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
|
|
if (!SE.IsNull()) {
|
|
SE->LocalD3(U,V,USide,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
return;
|
|
}
|
|
|
|
// Revolution case
|
|
Handle(Geom_SurfaceOfRevolution) SR =
|
|
Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
|
|
if (!SR.IsNull()) {
|
|
SR->LocalD3(U,V,VSide,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
return;
|
|
}
|
|
|
|
// General cases
|
|
basisSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
SetD3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
}
|
|
else
|
|
equivSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : LocalDN
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
gp_Vec Geom_OffsetSurface::LocalDN (const Standard_Real U, const Standard_Real V,
|
|
const Standard_Integer USide, const Standard_Integer VSide,
|
|
const Standard_Integer Nu, const Standard_Integer Nv) const
|
|
{
|
|
if(equivSurf.IsNull()) {
|
|
|
|
gp_Vec D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV;
|
|
gp_Pnt P;
|
|
Handle(Geom_Surface) Basis = basisSurf;
|
|
|
|
// if Basis is Trimmed we make the basis`s basis
|
|
Handle(Geom_RectangularTrimmedSurface) RTS =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
|
|
if (!RTS.IsNull())
|
|
Basis = RTS -> BasisSurface();
|
|
|
|
//BSpline case
|
|
Handle(Geom_BSplineSurface) BSplS =
|
|
Handle(Geom_BSplineSurface)::DownCast(Basis);
|
|
if(!BSplS.IsNull()) {
|
|
LocateSides(U,V,USide,VSide,BSplS,1,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
|
|
return SetDN(U,V,Nu,Nv,D1U,D1V);
|
|
}
|
|
|
|
//Extrusion case
|
|
Handle( Geom_SurfaceOfLinearExtrusion) SE =
|
|
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
|
|
if(!SE.IsNull()) {
|
|
SE->LocalD1(U,V,USide,P,D1U,D1V);
|
|
return SetDN(U,V,Nu,Nv,D1U,D1V);
|
|
}
|
|
|
|
//Revolution case
|
|
Handle(Geom_SurfaceOfRevolution) SR =
|
|
Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
|
|
if(!SR.IsNull()) {
|
|
SR->LocalDN(U,V,VSide,Nu,Nv);
|
|
return SetDN(U,V,Nu,Nv,D1U,D1V);
|
|
}
|
|
|
|
//General cases
|
|
basisSurf->DN(U,V,Nu,Nv);
|
|
return SetDN(U,V,Nu,Nv,D1U,D1V);
|
|
}
|
|
else
|
|
return equivSurf->DN(U,V,Nu,Nv);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : LocateSides
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::LocateSides(const Standard_Real U, const Standard_Real V,
|
|
const Standard_Integer USide, const Standard_Integer VSide,
|
|
const Handle(Geom_BSplineSurface)& BSplS,
|
|
const Standard_Integer NDir,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U,gp_Vec& D1V,
|
|
gp_Vec& D2U,gp_Vec& D2V,gp_Vec& D2UV,
|
|
gp_Vec& D3U,gp_Vec& D3V,gp_Vec& D3UUV,gp_Vec& D3UVV) const
|
|
{
|
|
Standard_Boolean UIsKnot=Standard_False, VIsKnot=Standard_False;
|
|
Standard_Integer Ideb, Ifin, IVdeb, IVfin;
|
|
const Standard_Real ParTol=Precision::PConfusion()/10.;
|
|
BSplS->Geom_BSplineSurface::LocateU(U,ParTol,Ideb, Ifin, Standard_False);
|
|
BSplS->Geom_BSplineSurface::LocateV(V,ParTol,IVdeb,IVfin,Standard_False);
|
|
|
|
if(Ideb == Ifin ) { //knot
|
|
|
|
if(USide == 1) {Ifin++; UIsKnot=Standard_True;}
|
|
else if(USide == -1) {Ideb--; UIsKnot=Standard_True;}
|
|
else {Ideb--; Ifin++;} //USide == 0
|
|
|
|
}
|
|
|
|
if(Ideb < BSplS->FirstUKnotIndex()) {Ideb = BSplS->FirstUKnotIndex(); Ifin = Ideb + 1;}
|
|
|
|
if(Ifin > BSplS->LastUKnotIndex()) {Ifin = BSplS->LastUKnotIndex(); Ideb = Ifin - 1;}
|
|
|
|
if(IVdeb == IVfin ) { //knot
|
|
|
|
if(VSide == 1) {IVfin++; VIsKnot=Standard_True;}
|
|
else if(VSide == -1) {IVdeb--; VIsKnot=Standard_True;}
|
|
else {IVdeb--; IVfin++;} //VSide == 0
|
|
|
|
}
|
|
|
|
if(IVdeb < BSplS->FirstVKnotIndex()) {IVdeb = BSplS->FirstVKnotIndex(); IVfin = IVdeb + 1;}
|
|
|
|
if(IVfin > BSplS->LastVKnotIndex()) {IVfin = BSplS->LastVKnotIndex(); IVdeb = IVfin - 1;}
|
|
|
|
if((UIsKnot)||(VIsKnot))
|
|
switch(NDir)
|
|
{
|
|
case 0 : BSplS->Geom_BSplineSurface::LocalD0(U,V,Ideb,Ifin,IVdeb,IVfin,P); break;
|
|
case 1 : BSplS->Geom_BSplineSurface::LocalD1(U,V,Ideb,Ifin,IVdeb,IVfin,P,D1U,D1V); break;
|
|
case 2 : BSplS->Geom_BSplineSurface::LocalD2(U,V,Ideb,Ifin,IVdeb,IVfin,P,D1U,D1V,D2U,D2V,D2UV); break;
|
|
case 3 : BSplS->Geom_BSplineSurface::LocalD3(U,V,Ideb,Ifin,IVdeb,IVfin,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV); break;
|
|
}
|
|
else
|
|
switch(NDir)
|
|
{
|
|
case 0 : basisSurf->D0(U,V,P); break;
|
|
case 1 : basisSurf->D1(U,V,P,D1U,D1V); break;
|
|
case 2 : basisSurf->D2(U,V,P,D1U,D1V,D2U,D2V,D2UV); break;
|
|
case 3 : basisSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV); break;
|
|
}
|
|
}
|
|
|
|
////*************************************************
|
|
////
|
|
//// EVALUATOR FOR THE ISO-CURVE APPROXIMATION
|
|
////
|
|
////*************************************************
|
|
|
|
class Geom_OffsetSurface_UIsoEvaluator : public AdvApprox_EvaluatorFunction
|
|
{
|
|
public:
|
|
Geom_OffsetSurface_UIsoEvaluator (const Handle(Geom_Surface)& theSurface, const Standard_Real theU)
|
|
: CurrentSurface(theSurface), IsoPar(theU) {}
|
|
|
|
virtual void Evaluate (Standard_Integer *Dimension,
|
|
Standard_Real StartEnd[2],
|
|
Standard_Real *Parameter,
|
|
Standard_Integer *DerivativeRequest,
|
|
Standard_Real *Result, // [Dimension]
|
|
Standard_Integer *ErrorCode);
|
|
|
|
private:
|
|
Handle(Geom_Surface) CurrentSurface;
|
|
Standard_Real IsoPar;
|
|
};
|
|
|
|
void Geom_OffsetSurface_UIsoEvaluator::Evaluate(Standard_Integer *,/*Dimension*/
|
|
Standard_Real /*StartEnd*/[2],
|
|
Standard_Real *Parameter,
|
|
Standard_Integer *DerivativeRequest,
|
|
Standard_Real *Result,
|
|
Standard_Integer *ReturnCode)
|
|
{
|
|
gp_Pnt P;
|
|
if (*DerivativeRequest == 0) {
|
|
P = CurrentSurface->Value(IsoPar,*Parameter);
|
|
Result[0] = P.X();
|
|
Result[1] = P.Y();
|
|
Result[2] = P.Z();
|
|
}
|
|
else {
|
|
gp_Vec DU,DV;
|
|
CurrentSurface->D1(IsoPar,*Parameter,P,DU,DV);
|
|
Result[0] = DV.X();
|
|
Result[1] = DV.Y();
|
|
Result[2] = DV.Z();
|
|
}
|
|
*ReturnCode = 0;
|
|
}
|
|
|
|
class Geom_OffsetSurface_VIsoEvaluator : public AdvApprox_EvaluatorFunction
|
|
{
|
|
public:
|
|
Geom_OffsetSurface_VIsoEvaluator (const Handle(Geom_Surface)& theSurface, const Standard_Real theV)
|
|
: CurrentSurface(theSurface), IsoPar(theV) {}
|
|
|
|
virtual void Evaluate (Standard_Integer *Dimension,
|
|
Standard_Real StartEnd[2],
|
|
Standard_Real *Parameter,
|
|
Standard_Integer *DerivativeRequest,
|
|
Standard_Real *Result, // [Dimension]
|
|
Standard_Integer *ErrorCode);
|
|
|
|
private:
|
|
Handle(Geom_Surface) CurrentSurface;
|
|
Standard_Real IsoPar;
|
|
};
|
|
|
|
void Geom_OffsetSurface_VIsoEvaluator::Evaluate(Standard_Integer *,/*Dimension*/
|
|
Standard_Real /*StartEnd*/[2],
|
|
Standard_Real *Parameter,
|
|
Standard_Integer *DerivativeRequest,
|
|
Standard_Real *Result,
|
|
Standard_Integer *ReturnCode)
|
|
{
|
|
gp_Pnt P;
|
|
if (*DerivativeRequest == 0) {
|
|
P = CurrentSurface->Value(*Parameter,IsoPar);
|
|
Result[0] = P.X();
|
|
Result[1] = P.Y();
|
|
Result[2] = P.Z();
|
|
}
|
|
else {
|
|
gp_Vec DU,DV;
|
|
CurrentSurface->D1(*Parameter,IsoPar,P,DU,DV);
|
|
Result[0] = DU.X();
|
|
Result[1] = DU.Y();
|
|
Result[2] = DU.Z();
|
|
}
|
|
*ReturnCode = 0;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UIso
|
|
//purpose : The Uiso or the VIso of an OffsetSurface can't be clearly
|
|
// exprimed as a curve from Geom. So, to extract the U or VIso
|
|
// an Approximation is needed. This approx always will return a
|
|
// BSplineCurve from Geom.
|
|
//=======================================================================
|
|
|
|
Handle(Geom_Curve) Geom_OffsetSurface::UIso (const Standard_Real UU) const
|
|
{
|
|
if (equivSurf.IsNull()) {
|
|
const Standard_Integer Num1 = 0, Num2 = 0, Num3 = 1;
|
|
Handle(TColStd_HArray1OfReal) T1, T2, T3 = new TColStd_HArray1OfReal(1,Num3);
|
|
T3->Init(Precision::Approximation());
|
|
Standard_Real U1,U2,V1,V2;
|
|
Bounds(U1,U2,V1,V2);
|
|
const GeomAbs_Shape Cont = GeomAbs_C1;
|
|
const Standard_Integer MaxSeg = 100, MaxDeg = 14;
|
|
|
|
Handle(Geom_OffsetSurface) me (this);
|
|
Geom_OffsetSurface_UIsoEvaluator ev (me, UU);
|
|
AdvApprox_ApproxAFunction Approx(Num1, Num2, Num3, T1, T2, T3,
|
|
V1, V2, Cont, MaxDeg, MaxSeg, ev);
|
|
|
|
Standard_ConstructionError_Raise_if (!Approx.IsDone(), " Geom_OffsetSurface : UIso");
|
|
|
|
const Standard_Integer NbPoles = Approx.NbPoles();
|
|
|
|
TColgp_Array1OfPnt Poles( 1, NbPoles);
|
|
TColStd_Array1OfReal Knots( 1, Approx.NbKnots());
|
|
TColStd_Array1OfInteger Mults( 1, Approx.NbKnots());
|
|
|
|
Approx.Poles(1, Poles);
|
|
Knots = Approx.Knots()->Array1();
|
|
Mults = Approx.Multiplicities()->Array1();
|
|
|
|
Handle(Geom_BSplineCurve) C =
|
|
new Geom_BSplineCurve( Poles, Knots, Mults, Approx.Degree());
|
|
return C;
|
|
}
|
|
else
|
|
return equivSurf->UIso(UU);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Value
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::Value
|
|
(const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P, gp_Pnt& ,
|
|
gp_Vec& D1Ubasis, gp_Vec& D1Vbasis) const
|
|
{
|
|
if (myBasisSurfContinuity == GeomAbs_C0)
|
|
Geom_UndefinedValue::Raise();
|
|
|
|
SetD0(U,V,P,D1Ubasis,D1Vbasis);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : VIso
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Handle(Geom_Curve) Geom_OffsetSurface::VIso (const Standard_Real VV) const
|
|
{
|
|
if (equivSurf.IsNull()) {
|
|
const Standard_Integer Num1 = 0, Num2 = 0, Num3 = 1;
|
|
Handle(TColStd_HArray1OfReal) T1, T2, T3 = new TColStd_HArray1OfReal(1,Num3);
|
|
T3->Init(Precision::Approximation());
|
|
Standard_Real U1,U2,V1,V2;
|
|
Bounds(U1,U2,V1,V2);
|
|
const GeomAbs_Shape Cont = GeomAbs_C1;
|
|
const Standard_Integer MaxSeg = 100, MaxDeg = 14;
|
|
|
|
Handle(Geom_OffsetSurface) me (this);
|
|
Geom_OffsetSurface_VIsoEvaluator ev (me, VV);
|
|
AdvApprox_ApproxAFunction Approx (Num1, Num2, Num3, T1, T2, T3,
|
|
U1, U2, Cont, MaxDeg, MaxSeg, ev);
|
|
|
|
Standard_ConstructionError_Raise_if (!Approx.IsDone(), " Geom_OffsetSurface : VIso");
|
|
|
|
TColgp_Array1OfPnt Poles( 1, Approx.NbPoles());
|
|
TColStd_Array1OfReal Knots( 1, Approx.NbKnots());
|
|
TColStd_Array1OfInteger Mults( 1, Approx.NbKnots());
|
|
|
|
Approx.Poles(1, Poles);
|
|
Knots = Approx.Knots()->Array1();
|
|
Mults = Approx.Multiplicities()->Array1();
|
|
|
|
Handle(Geom_BSplineCurve) C =
|
|
new Geom_BSplineCurve( Poles, Knots, Mults, Approx.Degree());
|
|
return C;
|
|
}
|
|
else
|
|
return equivSurf->VIso(VV);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsCNu
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Geom_OffsetSurface::IsCNu (const Standard_Integer N) const
|
|
{
|
|
Standard_RangeError_Raise_if (N < 0, " ");
|
|
return basisSurf->IsCNu (N+1);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsCNv
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Geom_OffsetSurface::IsCNv (const Standard_Integer N) const
|
|
{
|
|
Standard_RangeError_Raise_if (N < 0, " ");
|
|
return basisSurf->IsCNv (N+1);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsUPeriodic
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Geom_OffsetSurface::IsUPeriodic () const
|
|
{
|
|
return basisSurf->IsUPeriodic();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UPeriod
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Real Geom_OffsetSurface::UPeriod() const
|
|
{
|
|
return basisSurf->UPeriod();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsVPeriodic
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Geom_OffsetSurface::IsVPeriodic () const
|
|
{
|
|
return basisSurf->IsVPeriodic();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : VPeriod
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Real Geom_OffsetSurface::VPeriod() const
|
|
{
|
|
return basisSurf->VPeriod();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsUClosed
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Geom_OffsetSurface::IsUClosed () const
|
|
{
|
|
Standard_Boolean UClosed;
|
|
Handle(Geom_Surface) SBasis = BasisSurface();
|
|
|
|
if (SBasis->IsKind (STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
|
|
Handle(Geom_RectangularTrimmedSurface) St =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(SBasis);
|
|
|
|
Handle(Geom_Surface) S = Handle(Geom_Surface)::DownCast(St->BasisSurface());
|
|
if (S->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
|
|
UClosed = SBasis->IsUClosed();
|
|
}
|
|
else if (S->IsKind (STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
|
|
Handle(Geom_SurfaceOfLinearExtrusion) Extru =
|
|
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S);
|
|
|
|
Handle(Geom_Curve) C = Extru->BasisCurve();
|
|
if (C->IsKind (STANDARD_TYPE(Geom_Circle)) || C->IsKind (STANDARD_TYPE(Geom_Ellipse))) {
|
|
UClosed = SBasis->IsUClosed();
|
|
}
|
|
else { UClosed = Standard_False; }
|
|
}
|
|
else if (S->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
|
|
UClosed = SBasis->IsUClosed();
|
|
}
|
|
else { UClosed = Standard_False; }
|
|
}
|
|
else {
|
|
if (SBasis->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
|
|
UClosed = SBasis->IsUClosed();
|
|
}
|
|
else if (SBasis->IsKind (STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
|
|
Handle(Geom_SurfaceOfLinearExtrusion) Extru =
|
|
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(SBasis);
|
|
|
|
Handle(Geom_Curve) C = Extru->BasisCurve();
|
|
UClosed = (C->IsKind(STANDARD_TYPE(Geom_Circle)) || C->IsKind(STANDARD_TYPE(Geom_Ellipse)));
|
|
}
|
|
else if (SBasis->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
|
|
UClosed = Standard_True;
|
|
}
|
|
else { UClosed = Standard_False; }
|
|
}
|
|
return UClosed;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsVClosed
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Geom_OffsetSurface::IsVClosed () const
|
|
{
|
|
Standard_Boolean VClosed;
|
|
Handle(Geom_Surface) SBasis = BasisSurface();
|
|
|
|
if (SBasis->IsKind (STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
|
|
Handle(Geom_RectangularTrimmedSurface) St =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(SBasis);
|
|
|
|
Handle(Geom_Surface) S = Handle(Geom_Surface)::DownCast(St->BasisSurface());
|
|
if (S->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
|
|
VClosed = SBasis->IsVClosed();
|
|
}
|
|
else { VClosed = Standard_False; }
|
|
}
|
|
else {
|
|
if (SBasis->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
|
|
VClosed = SBasis->IsVClosed();
|
|
}
|
|
else { VClosed = Standard_False; }
|
|
}
|
|
return VClosed;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Transform
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::Transform (const gp_Trsf& T)
|
|
{
|
|
basisSurf->Transform (T);
|
|
offsetValue *= T.ScaleFactor();
|
|
equivSurf.Nullify();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : TransformParameters
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::TransformParameters(Standard_Real& U, Standard_Real& V,
|
|
const gp_Trsf& T) const
|
|
{
|
|
basisSurf->TransformParameters(U,V,T);
|
|
if(!equivSurf.IsNull()) equivSurf->TransformParameters(U,V,T);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ParametricTransformation
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
gp_GTrsf2d Geom_OffsetSurface::ParametricTransformation (const gp_Trsf& T) const
|
|
{
|
|
return basisSurf->ParametricTransformation(T);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Surface
|
|
//purpose : Trouve si elle existe, une surface non offset, equivalente
|
|
// a l'offset surface.
|
|
//=======================================================================
|
|
|
|
Handle(Geom_Surface) Geom_OffsetSurface::Surface() const
|
|
{
|
|
if (offsetValue == 0.0) return basisSurf; // Cas direct
|
|
|
|
Standard_Real Tol = Precision::Confusion();
|
|
Handle(Geom_Surface) Result, Base;
|
|
Result.Nullify();
|
|
Handle(Standard_Type) TheType = basisSurf->DynamicType();
|
|
Standard_Boolean IsTrimmed;
|
|
Standard_Real U1 = 0., V1 = 0., U2 = 0., V2 = 0.;
|
|
|
|
// Preambule pour les surface trimmes
|
|
if (TheType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
|
|
Handle(Geom_RectangularTrimmedSurface) S =
|
|
Handle(Geom_RectangularTrimmedSurface)::DownCast(basisSurf);
|
|
Base = S->BasisSurface();
|
|
TheType = Base->DynamicType();
|
|
S->Bounds(U1,U2,V1,V2);
|
|
IsTrimmed = Standard_True;
|
|
}
|
|
else {
|
|
IsTrimmed = Standard_False;
|
|
Base = basisSurf;
|
|
}
|
|
|
|
// Traite les surfaces cannonique
|
|
if (TheType == STANDARD_TYPE(Geom_Plane))
|
|
{
|
|
Handle(Geom_Plane) P =
|
|
Handle(Geom_Plane)::DownCast(Base);
|
|
gp_Vec T = P->Position().XDirection()^P->Position().YDirection();
|
|
T *= offsetValue;
|
|
Result = Handle(Geom_Plane)::DownCast(P->Translated(T));
|
|
}
|
|
else if (TheType == STANDARD_TYPE(Geom_CylindricalSurface))
|
|
{
|
|
Handle(Geom_CylindricalSurface) C =
|
|
Handle(Geom_CylindricalSurface)::DownCast(Base);
|
|
Standard_Real Radius = C->Radius();
|
|
gp_Ax3 Axis = C->Position();
|
|
if (Axis.Direct())
|
|
Radius += offsetValue;
|
|
else
|
|
Radius -= offsetValue;
|
|
if ( Radius >= Tol ) {
|
|
Result = new Geom_CylindricalSurface( Axis, Radius);
|
|
}
|
|
else if ( Radius <= -Tol ){
|
|
Axis.Rotate(gp_Ax1(Axis.Location(),Axis.Direction()),M_PI);
|
|
Result = new Geom_CylindricalSurface( Axis, Abs(Radius));
|
|
Result->UReverse();
|
|
}
|
|
else
|
|
{
|
|
// surface degeneree
|
|
}
|
|
}
|
|
else if (TheType == STANDARD_TYPE(Geom_ConicalSurface))
|
|
{
|
|
Handle(Geom_ConicalSurface) C =
|
|
Handle(Geom_ConicalSurface)::DownCast(Base);
|
|
gp_Ax3 anAxis = C->Position();
|
|
Standard_Boolean isDirect = anAxis.Direct();
|
|
Standard_Real anAlpha = C->SemiAngle();
|
|
Standard_Real aRadius;
|
|
if (isDirect)
|
|
{
|
|
aRadius = C->RefRadius() + offsetValue * Cos (anAlpha);
|
|
}
|
|
else
|
|
{
|
|
aRadius = C->RefRadius() - offsetValue * Cos (anAlpha);
|
|
}
|
|
if (aRadius >= 0.)
|
|
{
|
|
gp_Vec aZ (anAxis.Direction());
|
|
if (isDirect)
|
|
{
|
|
aZ *= -offsetValue * Sin (anAlpha);
|
|
}
|
|
else
|
|
{
|
|
aZ *= offsetValue * Sin (anAlpha);
|
|
}
|
|
anAxis.Translate (aZ);
|
|
Result = new Geom_ConicalSurface (anAxis, anAlpha, aRadius);
|
|
}
|
|
else
|
|
{
|
|
// surface degeneree
|
|
}
|
|
}
|
|
else if (TheType == STANDARD_TYPE(Geom_SphericalSurface)) {
|
|
Handle(Geom_SphericalSurface) S =
|
|
Handle(Geom_SphericalSurface)::DownCast(Base);
|
|
Standard_Real Radius = S->Radius();
|
|
gp_Ax3 Axis = S->Position();
|
|
if (Axis.Direct())
|
|
Radius += offsetValue;
|
|
else
|
|
Radius -= offsetValue;
|
|
if ( Radius >= Tol) {
|
|
Result = new Geom_SphericalSurface(Axis, Radius);
|
|
}
|
|
else if ( Radius <= -Tol ) {
|
|
Axis.Rotate(gp_Ax1(Axis.Location(),Axis.Direction()),M_PI);
|
|
Axis.ZReverse();
|
|
Result = new Geom_SphericalSurface(Axis, -Radius);
|
|
Result->UReverse();
|
|
}
|
|
else {
|
|
// surface degeneree
|
|
}
|
|
}
|
|
else if (TheType == STANDARD_TYPE(Geom_ToroidalSurface))
|
|
|
|
{
|
|
Handle(Geom_ToroidalSurface)
|
|
S = Handle(Geom_ToroidalSurface)::DownCast(Base);
|
|
Standard_Real MajorRadius = S->MajorRadius();
|
|
Standard_Real MinorRadius = S->MinorRadius();
|
|
gp_Ax3 Axis = S->Position();
|
|
if (MinorRadius <= MajorRadius)
|
|
{
|
|
if (Axis.Direct())
|
|
MinorRadius += offsetValue;
|
|
else
|
|
MinorRadius -= offsetValue;
|
|
if (MinorRadius >= Tol)
|
|
Result = new Geom_ToroidalSurface(Axis,MajorRadius,MinorRadius);
|
|
// else if (MinorRadius <= -Tol)
|
|
// Result->UReverse();
|
|
else
|
|
{
|
|
// surface degeneree
|
|
}
|
|
}
|
|
}
|
|
|
|
// S'il le faut on trimme le resultat
|
|
if (IsTrimmed && !Result.IsNull()) {
|
|
Base = Result;
|
|
Result = new Geom_RectangularTrimmedSurface (Base, U1, U2, V1,V2);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UOsculatingSurface
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Geom_OffsetSurface::UOsculatingSurface(const Standard_Real U, const Standard_Real V,
|
|
Standard_Boolean& t, Handle(Geom_BSplineSurface)& L) const
|
|
{
|
|
return myOscSurf.UOscSurf(U,V,t,L);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : VOsculatingSurface
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Geom_OffsetSurface::VOsculatingSurface(const Standard_Real U, const Standard_Real V,
|
|
Standard_Boolean& t, Handle(Geom_BSplineSurface)& L) const
|
|
{
|
|
return myOscSurf.VOscSurf(U,V,t,L);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function :
|
|
//purpose : private
|
|
//=======================================================================
|
|
|
|
void Geom_OffsetSurface::SetD0(const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P,
|
|
const gp_Vec& D1U, const gp_Vec& D1V) const // First Derivative
|
|
{
|
|
const Standard_Real MagTol=0.000000001;
|
|
|
|
gp_Vec aNorm = D1U.Crossed(D1V);
|
|
if (aNorm.SquareMagnitude() > MagTol * MagTol)
|
|
{
|
|
// Non singular case. Simple computations.
|
|
aNorm.Normalize();
|
|
P.SetXYZ(P.XYZ() + offsetValue * aNorm.XYZ());
|
|
}
|
|
else
|
|
{
|
|
Standard_Boolean AlongU = Standard_False,
|
|
AlongV = Standard_False;
|
|
Handle(Geom_BSplineSurface) L;
|
|
Standard_Boolean IsOpposite=Standard_False;
|
|
AlongU = UOsculatingSurface(U,V,IsOpposite,L);
|
|
AlongV = VOsculatingSurface(U,V,IsOpposite,L);
|
|
gp_Dir Normal;
|
|
CSLib_NormalStatus NStatus;
|
|
Standard_Integer MaxOrder=3;
|
|
TColgp_Array2OfVec DerNUV(0,MaxOrder,0,MaxOrder);
|
|
TColgp_Array2OfVec DerSurf(0,MaxOrder+1,0,MaxOrder+1);
|
|
Standard_Integer OrderU,OrderV;
|
|
Standard_Real Umin,Umax,Vmin,Vmax;
|
|
Bounds(Umin,Umax,Vmin,Vmax);
|
|
DerSurf.SetValue(1, 0, D1U);
|
|
DerSurf.SetValue(0, 1, D1V);
|
|
derivatives(MaxOrder,1,U,V,basisSurf,0,0,AlongU,AlongV,L,DerNUV,DerSurf);
|
|
|
|
Standard_Real signe = 1.0;
|
|
if ((AlongV || AlongU) && IsOpposite)
|
|
signe = -1;
|
|
|
|
CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
|
|
if (NStatus == CSLib_Defined)
|
|
P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
|
|
else
|
|
{
|
|
if (NStatus == CSLib_InfinityOfSolutions &&
|
|
D1U.SquareMagnitude() + D1V.SquareMagnitude() > MagTol * MagTol)
|
|
{
|
|
// Use non-null derivative as normal direction in degenerated case.
|
|
aNorm = D1U.SquareMagnitude() > MagTol * MagTol ? D1U : D1V;
|
|
aNorm.Normalize();
|
|
|
|
P.SetXYZ(P.XYZ() + offsetValue * signe * aNorm.XYZ());
|
|
return;
|
|
}
|
|
Geom_UndefinedValue::Raise();
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function :
|
|
//purpose : private
|
|
//=======================================================================/
|
|
|
|
void Geom_OffsetSurface::SetD1(const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V, // First derivative
|
|
const gp_Vec& D2UU, const gp_Vec& D2VV, const gp_Vec& D2UV) const // Second derivative
|
|
{
|
|
const Standard_Real MagTol=0.000000001;
|
|
|
|
// Check offset side.
|
|
Handle(Geom_BSplineSurface) L;
|
|
Standard_Boolean AlongU = Standard_False,
|
|
AlongV = Standard_False;
|
|
Standard_Boolean IsOpposite=Standard_False;
|
|
AlongU = UOsculatingSurface(U,V,IsOpposite,L);
|
|
AlongV = VOsculatingSurface(U,V,IsOpposite,L);
|
|
Standard_Real signe = 1.0;
|
|
if ((AlongV || AlongU) && IsOpposite)
|
|
signe = -1.0;
|
|
|
|
Standard_Integer MaxOrder = 0;
|
|
gp_Vec aNorm = D1U.Crossed(D1V);
|
|
if (aNorm.SquareMagnitude() > MagTol * MagTol)
|
|
{
|
|
MaxOrder=0;
|
|
|
|
if (!AlongV && !AlongU)
|
|
{
|
|
// AlongU or AlongV leads to more complex D1 computations,
|
|
// try to compute D0 and D1 much simpler.
|
|
aNorm.Normalize();
|
|
P.SetXYZ(P.XYZ() + offsetValue * signe * aNorm.XYZ());
|
|
|
|
gp_Vec aN0(aNorm.XYZ()), aN1U, aN1V;
|
|
Standard_Real aScale = (D1U^D1V).Dot(aN0);
|
|
aN1U.SetX(D2UU.Y() * D1V.Z() + D1U.Y() * D2UV.Z()
|
|
- D2UU.Z() * D1V.Y() - D1U.Z() * D2UV.Y());
|
|
aN1U.SetY((D2UU.X() * D1V.Z() + D1U.X() * D2UV.Z()
|
|
- D2UU.Z() * D1V.X() - D1U.Z() * D2UV.X() ) * -1.0);
|
|
aN1U.SetZ(D2UU.X() * D1V.Y() + D1U.X() * D2UV.Y()
|
|
- D2UU.Y() * D1V.X() - D1U.Y() * D2UV.X());
|
|
Standard_Real aScaleU = aN1U.Dot(aN0);
|
|
aN1U.Subtract(aScaleU * aN0);
|
|
aN1U /= aScale;
|
|
|
|
aN1V.SetX(D2UV.Y() * D1V.Z() + D2VV.Z() * D1U.Y()
|
|
- D2UV.Z() * D1V.Y() - D2VV.Y() * D1U.Z());
|
|
aN1V.SetY((D2UV.X() * D1V.Z() + D2VV.Z() * D1U.X()
|
|
- D2UV.Z() * D1V.X() - D2VV.X() * D1U.Z()) * -1.0);
|
|
aN1V.SetZ(D2UV.X() * D1V.Y() + D2VV.Y() * D1U.X()
|
|
- D2UV.Y() * D1V.X() - D2VV.X() * D1U.Y());
|
|
Standard_Real aScaleV = aN1V.Dot(aN0);
|
|
aN1V.Subtract(aScaleV * aN0);
|
|
aN1V /= aScale;
|
|
|
|
D1U += offsetValue * signe * aN1U;
|
|
D1V += offsetValue * signe * aN1V;
|
|
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
MaxOrder=3;
|
|
|
|
Standard_Integer OrderU,OrderV;
|
|
TColgp_Array2OfVec DerNUV(0,MaxOrder+1,0,MaxOrder+1);
|
|
TColgp_Array2OfVec DerSurf(0,MaxOrder+2,0,MaxOrder+2);
|
|
Standard_Real Umin,Umax,Vmin,Vmax;
|
|
Bounds(Umin,Umax,Vmin,Vmax);
|
|
DerSurf.SetValue(1, 0, D1U);
|
|
DerSurf.SetValue(0, 1, D1V);
|
|
DerSurf.SetValue(1, 1, D2UV);
|
|
DerSurf.SetValue(2, 0, D2UU);
|
|
DerSurf.SetValue(0, 2, D2VV);
|
|
derivatives(MaxOrder,2,U,V,basisSurf,1,1,AlongU,AlongV,L,DerNUV,DerSurf);
|
|
|
|
gp_Dir Normal;
|
|
CSLib_NormalStatus NStatus;
|
|
CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
|
|
if (NStatus != CSLib_Defined) Geom_UndefinedValue::Raise();
|
|
|
|
P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
|
|
|
|
D1U = DerSurf(1,0)
|
|
+ offsetValue * signe * CSLib::DNNormal(1,0,DerNUV,OrderU,OrderV);
|
|
D1V = DerSurf(0,1)
|
|
+ offsetValue * signe * CSLib::DNNormal(0,1,DerNUV,OrderU,OrderV);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function :
|
|
//purpose : private
|
|
//=======================================================================/
|
|
|
|
void Geom_OffsetSurface::SetD2(const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V,
|
|
gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
|
|
const gp_Vec& d3u, const gp_Vec& d3v,
|
|
const gp_Vec& d3uuv, const gp_Vec& d3uvv) const
|
|
{
|
|
const Standard_Real MagTol=0.000000001;
|
|
|
|
gp_Dir Normal;
|
|
CSLib_NormalStatus NStatus;
|
|
CSLib::Normal (D1U, D1V, MagTol, NStatus, Normal);
|
|
|
|
const Standard_Integer MaxOrder = (NStatus == CSLib_Defined)? 0 : 3;
|
|
Standard_Integer OrderU,OrderV;
|
|
TColgp_Array2OfVec DerNUV(0,MaxOrder+2,0,MaxOrder+2);
|
|
TColgp_Array2OfVec DerSurf(0,MaxOrder+3,0,MaxOrder+3);
|
|
Standard_Real Umin,Umax,Vmin,Vmax;
|
|
Bounds(Umin,Umax,Vmin,Vmax);
|
|
DerSurf.SetValue(1, 0, D1U);
|
|
DerSurf.SetValue(0, 1, D1V);
|
|
DerSurf.SetValue(1, 1, D2UV);
|
|
DerSurf.SetValue(2, 0, D2U);
|
|
DerSurf.SetValue(0, 2, D2V);
|
|
DerSurf.SetValue(3, 0, d3u);
|
|
DerSurf.SetValue(2, 1, d3uuv);
|
|
DerSurf.SetValue(1, 2, d3uvv);
|
|
DerSurf.SetValue(0, 3, d3v);
|
|
//*********************
|
|
|
|
Handle(Geom_BSplineSurface) L;
|
|
Standard_Boolean IsOpposite=Standard_False;
|
|
const Standard_Boolean AlongU = UOsculatingSurface(U,V,IsOpposite,L);
|
|
const Standard_Boolean AlongV = VOsculatingSurface(U,V,IsOpposite,L);
|
|
const Standard_Real signe = ((AlongV || AlongU) && IsOpposite)? -1. : 1.;
|
|
derivatives(MaxOrder,3,U,V,basisSurf,2,2,AlongU,AlongV,L,DerNUV,DerSurf);
|
|
|
|
CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
|
|
if (NStatus != CSLib_Defined) Geom_UndefinedValue::Raise();
|
|
|
|
P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
|
|
|
|
D1U = DerSurf(1,0)
|
|
+ offsetValue * signe * CSLib::DNNormal(1,0,DerNUV,OrderU,OrderV);
|
|
D1V = DerSurf(0,1)
|
|
+ offsetValue * signe * CSLib::DNNormal(0,1,DerNUV,OrderU,OrderV);
|
|
|
|
D2U = basisSurf->DN(U,V,2,0)
|
|
+ signe * offsetValue * CSLib::DNNormal(2,0,DerNUV,OrderU,OrderV);
|
|
D2V = basisSurf->DN(U,V,0,2)
|
|
+ signe * offsetValue * CSLib::DNNormal(0,2,DerNUV,OrderU,OrderV);
|
|
D2UV = basisSurf->DN(U,V,1,1)
|
|
+ signe * offsetValue * CSLib::DNNormal(1,1,DerNUV,OrderU,OrderV);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function :
|
|
//purpose : private
|
|
//=======================================================================/
|
|
|
|
void Geom_OffsetSurface::SetD3(const Standard_Real U, const Standard_Real V,
|
|
gp_Pnt& P,
|
|
gp_Vec& D1U, gp_Vec& D1V,
|
|
gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
|
|
gp_Vec& D3U, gp_Vec& D3V, gp_Vec& D3UUV, gp_Vec& D3UVV) const
|
|
{
|
|
const Standard_Real MagTol=0.000000001;
|
|
|
|
gp_Dir Normal;
|
|
CSLib_NormalStatus NStatus;
|
|
CSLib::Normal (D1U, D1V, MagTol, NStatus, Normal);
|
|
const Standard_Integer MaxOrder = (NStatus == CSLib_Defined)? 0 : 3;
|
|
Standard_Integer OrderU,OrderV;
|
|
TColgp_Array2OfVec DerNUV(0,MaxOrder+3,0,MaxOrder+3);
|
|
TColgp_Array2OfVec DerSurf(0,MaxOrder+4,0,MaxOrder+4);
|
|
Standard_Real Umin,Umax,Vmin,Vmax;
|
|
Bounds(Umin,Umax,Vmin,Vmax);
|
|
|
|
DerSurf.SetValue(1, 0, D1U);
|
|
DerSurf.SetValue(0, 1, D1V);
|
|
DerSurf.SetValue(1, 1, D2UV);
|
|
DerSurf.SetValue(2, 0, D2U);
|
|
DerSurf.SetValue(0, 2, D2V);
|
|
DerSurf.SetValue(3, 0, D3U);
|
|
DerSurf.SetValue(2, 1, D3UUV);
|
|
DerSurf.SetValue(1, 2, D3UVV);
|
|
DerSurf.SetValue(0, 3, D3V);
|
|
|
|
|
|
//*********************
|
|
Handle(Geom_BSplineSurface) L;
|
|
Standard_Boolean IsOpposite=Standard_False;
|
|
const Standard_Boolean AlongU = UOsculatingSurface(U,V,IsOpposite,L);
|
|
const Standard_Boolean AlongV = VOsculatingSurface(U,V,IsOpposite,L);
|
|
const Standard_Real signe = ((AlongV || AlongU) && IsOpposite)? -1. : 1.;
|
|
derivatives(MaxOrder,3,U,V,basisSurf,3,3,AlongU,AlongV,L,DerNUV,DerSurf);
|
|
|
|
CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
|
|
if (NStatus != CSLib_Defined) Geom_UndefinedValue::Raise();
|
|
|
|
P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
|
|
|
|
D1U = DerSurf(1,0)
|
|
+ offsetValue * signe * CSLib::DNNormal(1,0,DerNUV,OrderU,OrderV);
|
|
D1V = DerSurf(0,1)
|
|
+ offsetValue * signe * CSLib::DNNormal(0,1,DerNUV,OrderU,OrderV);
|
|
|
|
D2U = basisSurf->DN(U,V,2,0)
|
|
+ signe * offsetValue * CSLib::DNNormal(2,0,DerNUV,OrderU,OrderV);
|
|
D2V = basisSurf->DN(U,V,0,2)
|
|
+ signe * offsetValue * CSLib::DNNormal(0,2,DerNUV,OrderU,OrderV);
|
|
D2UV = basisSurf->DN(U,V,1,1)
|
|
+ signe * offsetValue * CSLib::DNNormal(1,1,DerNUV,OrderU,OrderV);
|
|
D3U = basisSurf->DN(U,V,3,0)
|
|
+ signe * offsetValue * CSLib::DNNormal(3,0,DerNUV,OrderU,OrderV);
|
|
D3V = basisSurf->DN(U,V,0,3)
|
|
+ signe * offsetValue * CSLib::DNNormal(0,3,DerNUV,OrderU,OrderV);
|
|
D3UUV = basisSurf->DN(U,V,2,1)
|
|
+ signe * offsetValue * CSLib::DNNormal(2,1,DerNUV,OrderU,OrderV);
|
|
D3UVV = basisSurf->DN(U,V,1,2)
|
|
+ signe * offsetValue * CSLib::DNNormal(1,2,DerNUV,OrderU,OrderV);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetDN
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
gp_Vec Geom_OffsetSurface::SetDN ( const Standard_Real U, const Standard_Real V,
|
|
const Standard_Integer Nu, const Standard_Integer Nv,
|
|
const gp_Vec& D1U, const gp_Vec& D1V) const
|
|
{
|
|
const Standard_Real MagTol=0.000000001;
|
|
|
|
gp_Dir Normal;
|
|
CSLib_NormalStatus NStatus;
|
|
CSLib::Normal (D1U, D1V, MagTol, NStatus, Normal);
|
|
const Standard_Integer MaxOrder = (NStatus == CSLib_Defined)? 0 : 3;
|
|
Standard_Integer OrderU,OrderV;
|
|
TColgp_Array2OfVec DerNUV(0,MaxOrder+Nu,0,MaxOrder+Nu);
|
|
TColgp_Array2OfVec DerSurf(0,MaxOrder+Nu+1,0,MaxOrder+Nv+1);
|
|
Standard_Real Umin,Umax,Vmin,Vmax;
|
|
Bounds(Umin,Umax,Vmin,Vmax);
|
|
|
|
DerSurf.SetValue(1, 0, D1U);
|
|
DerSurf.SetValue(0, 1, D1V);
|
|
|
|
//*********************
|
|
Handle(Geom_BSplineSurface) L;
|
|
// Is there any osculatingsurface along U or V;
|
|
Standard_Boolean IsOpposite=Standard_False;
|
|
const Standard_Boolean AlongU = UOsculatingSurface(U,V,IsOpposite,L);
|
|
const Standard_Boolean AlongV = VOsculatingSurface(U,V,IsOpposite,L);
|
|
const Standard_Real signe = ((AlongV || AlongU) && IsOpposite)? -1. : 1.;
|
|
derivatives(MaxOrder,1,U,V,basisSurf,Nu,Nv,AlongU,AlongV,L,DerNUV,DerSurf);
|
|
|
|
CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
|
|
if (NStatus != CSLib_Defined) Geom_UndefinedValue::Raise();
|
|
|
|
gp_Vec D = basisSurf->DN(U,V,Nu,Nv)
|
|
+ signe * offsetValue * CSLib::DNNormal(Nu,Nv,DerNUV,OrderU,OrderV);
|
|
|
|
return D;
|
|
}
|