// File generated by CPPExt (Transient)
//
//
//                     Copyright (C) 1991 - 2000 by  
//                      Matra Datavision SA.  All rights reserved.
//  
//                     Copyright (C) 2001 - 2004 by
//                     Open CASCADE SA.  All rights reserved.
// 
// This file is part of the Open CASCADE Technology software.
//
// This software may be distributed and/or modified under the terms and
// conditions of the Open CASCADE Public License as defined by Open CASCADE SA
// and appearing in the file LICENSE included in the packaging of this file.
//  
// This software is distributed on an "AS IS" basis, without warranty of any
// kind, and Open CASCADE SA hereby disclaims all such warranties,
// including without limitation, any warranties of merchantability, fitness
// for a particular purpose or non-infringement. Please see the License for
// the specific terms and conditions governing rights and limitations under the
// License.

#ifndef _Geom_OffsetSurface_HeaderFile
#define _Geom_OffsetSurface_HeaderFile

#ifndef _Standard_HeaderFile
#include <Standard.hxx>
#endif
#ifndef _Handle_Geom_OffsetSurface_HeaderFile
#include <Handle_Geom_OffsetSurface.hxx>
#endif

#ifndef _Handle_Geom_Surface_HeaderFile
#include <Handle_Geom_Surface.hxx>
#endif
#ifndef _Standard_Real_HeaderFile
#include <Standard_Real.hxx>
#endif
#ifndef _Geom_OsculatingSurface_HeaderFile
#include <Geom_OsculatingSurface.hxx>
#endif
#ifndef _Geom_Surface_HeaderFile
#include <Geom_Surface.hxx>
#endif
#ifndef _GeomAbs_Shape_HeaderFile
#include <GeomAbs_Shape.hxx>
#endif
#ifndef _Standard_Boolean_HeaderFile
#include <Standard_Boolean.hxx>
#endif
#ifndef _Standard_Integer_HeaderFile
#include <Standard_Integer.hxx>
#endif
#ifndef _Handle_Geom_Curve_HeaderFile
#include <Handle_Geom_Curve.hxx>
#endif
#ifndef _Handle_Geom_BSplineSurface_HeaderFile
#include <Handle_Geom_BSplineSurface.hxx>
#endif
#ifndef _Handle_Geom_Geometry_HeaderFile
#include <Handle_Geom_Geometry.hxx>
#endif
class Geom_Surface;
class Standard_ConstructionError;
class Standard_RangeError;
class Standard_NoSuchObject;
class Geom_UndefinedDerivative;
class Geom_UndefinedValue;
class Geom_Curve;
class gp_Pnt;
class gp_Vec;
class Geom_BSplineSurface;
class gp_Trsf;
class gp_GTrsf2d;
class Geom_Geometry;


//! Describes an offset surface in 3D space. <br>
//! An offset surface is defined by: <br>
//! - the basis surface to which it is parallel, and <br>
//! - the distance between the offset surface and its basis surface. <br>
//!   A point on the offset surface is built by measuring the <br>
//! offset value along the normal vector at a point on the <br>
//! basis surface. This normal vector is given by the cross <br>
//! product D1u^D1v, where D1u and D1v are the <br>
//! vectors tangential to the basis surface in the u and v <br>
//! parametric directions at this point. The side of the <br>
//! basis surface on which the offset is measured <br>
//! depends on the sign of the offset value. <br>
//! A Geom_OffsetSurface surface can be <br>
//! self-intersecting, even if the basis surface does not <br>
//! self-intersect. The self-intersecting portions are not <br>
//! deleted at the time of construction. <br>
//! Warning <br>
//! There must be only one normal vector defined at any <br>
//! point on the basis surface. This must be verified by the <br>
//! user as no check is made at the time of construction <br>
//! to detect points with multiple possible normal <br>
//! directions (for example, the top of a conical surface). <br>
class Geom_OffsetSurface : public Geom_Surface {

public:
 // Methods PUBLIC
 // 

//! Constructs a surface offset from the basis surface <br>
//! S, where Offset is the distance between the offset <br>
//! surface and the basis surface at any point. <br>
//! A point on the offset surface is built by measuring <br>
//! the offset value along a normal vector at a point on <br>
//! S. This normal vector is given by the cross product <br>
//! D1u^D1v, where D1u and D1v are the vectors <br>
//! tangential to the basis surface in the u and v <br>
//! parametric directions at this point. The side of S on <br>
//! which the offset value is measured is indicated by <br>
//! this normal vector if Offset is positive, or is the <br>
//! inverse sense if Offset is negative. <br>
//!  Warnings : <br>
//! - The offset surface is built with a copy of the <br>
//!   surface S. Therefore, when S is modified the <br>
//!   offset surface is not modified. <br>
//! - No check is made at the time of construction to <br>
//!   detect points on S with multiple possible normal directions. <br>//! Raised if S is not at least C1. <br>
//!  Warnings : <br>
//!  No check is done to verify that a unique normal direction is <br>
//!  defined at any point of the basis surface S. <br>
Standard_EXPORT Geom_OffsetSurface(const Handle(Geom_Surface)& S,const Standard_Real Offset);

//! Raised if S is not at least C1. <br>
//!  Warnings : <br>
//!  No check is done to verify that a unique normal direction is <br>
//!  defined at any point of the basis surface S. <br>
//! Exceptions <br>
//! Standard_ConstructionError if the surface S is not <br>
//! at least "C1" continuous. <br>
Standard_EXPORT   void SetBasisSurface(const Handle(Geom_Surface)& S) ;

//! Changes this offset surface by assigning D as the offset value. <br>
Standard_EXPORT   void SetOffsetValue(const Standard_Real D) ;

//! Returns the offset value of this offset surface. <br>
Standard_EXPORT   Standard_Real Offset() const;

//! Returns the basis surface of this offset surface. <br>
//!  Note: The basis surface can be an offset surface. <br>
Standard_EXPORT   Handle_Geom_Surface BasisSurface() const;

//! Changes the orientation of this offset surface in the u <br>
//! parametric direction. The bounds of the surface <br>
//! are not changed but the given parametric direction is reversed. <br>
Standard_EXPORT   void UReverse() ;

//! Computes the u  parameter on the modified <br>
//! surface, produced by reversing the u <br>
//! parametric direction of this offset surface, for any <br>
//! point of u parameter U  on this offset surface. <br>
Standard_EXPORT   Standard_Real UReversedParameter(const Standard_Real U) const;

//!  Changes the orientation of this offset surface in the v parametric direction. The bounds of the surface <br>
//! are not changed but the given parametric direction is reversed. <br>
Standard_EXPORT   void VReverse() ;

//! Computes the  v parameter on the modified <br>
//! surface, produced by reversing the or v <br>
//! parametric direction of this offset surface, for any <br>
//! point of  v parameter V on this offset surface. <br>
Standard_EXPORT   Standard_Real VReversedParameter(const Standard_Real V) const;

//! Returns the parametric bounds U1, U2, V1 and V2 of <br>
//! this offset surface. <br>
//! If the surface is infinite, this function can return: <br>
//! - Standard_Real::RealFirst(), or <br>
//! - Standard_Real::RealLast(). <br>
Standard_EXPORT   void Bounds(Standard_Real& U1,Standard_Real& U2,Standard_Real& V1,Standard_Real& V2) const;


//!  This method returns the continuity of the basis surface - 1. <br>
//!  Continuity of the Offset surface : <br>
//!  C0 : only geometric continuity, <br>
//!  C1 : continuity of the first derivative all along the Surface, <br>
//!  C2 : continuity of the second derivative all along the Surface, <br>
//!  C3 : continuity of the third derivative all along the Surface, <br>
//!  CN : the order of continuity is infinite. <br>
//! Example : <br>
//!  If the basis surface is C2 in the V direction and C3 in the U <br>
//!  direction Shape = C1. <br>
//! Warnings : <br>
//!  If the basis surface has a unique normal direction defined at <br>
//!  any point this method gives the continuity of the offset <br>
//!  surface otherwise the effective continuity can be lower than <br>
//!  the continuity of the basis surface - 1. <br>
Standard_EXPORT   GeomAbs_Shape Continuity() const;


//!  This method answer True if the continuity of the basis surface <br>
//!  is N + 1 in the U parametric direction. We suppose in this <br>
//!  class that a unique normal is defined at any point on the basis <br>
//!  surface. <br>//! Raised if N <0. <br>
Standard_EXPORT   Standard_Boolean IsCNu(const Standard_Integer N) const;


//!  This method answer True if the continuity of the basis surface <br>
//!  is N + 1 in the V parametric direction. We suppose in this <br>
//!  class that a unique normal is defined at any point on the basis <br>
//!  surface. <br>//! Raised if N <0. <br>
Standard_EXPORT   Standard_Boolean IsCNv(const Standard_Integer N) const;

//! Checks whether this offset surface is closed in the u <br>
//!  parametric direction. <br>
//! Returns true if, taking uFirst and uLast as <br>
//!   the parametric bounds in the u parametric direction, <br>
//!   the distance between the points P(uFirst,v) <br>
//!   and P(uLast,v) is less than or equal to <br>
//!   gp::Resolution() for each value of the   parameter v. <br>
Standard_EXPORT   Standard_Boolean IsUClosed() const;

//! Checks whether this offset surface is closed in the u <br>
//! or v parametric direction. Returns true if taking vFirst and vLast as the <br>
//!   parametric bounds in the v parametric direction, the <br>
//!   distance between the points P(u,vFirst) and <br>
//!   P(u,vLast) is less than or equal to <br>
//!   gp::Resolution() for each value of the parameter u. <br>
Standard_EXPORT   Standard_Boolean IsVClosed() const;


//! Returns true if this offset surface is periodic in the u <br>
//! parametric direction, i.e. if the basis <br>
//! surface of this offset surface is periodic in this direction. <br>
Standard_EXPORT   Standard_Boolean IsUPeriodic() const;

//! Returns the period of this offset surface in the u <br>
//! parametric direction respectively, i.e. the period of the <br>
//! basis surface of this offset surface in this parametric direction. <br>//! raises if the surface is not uperiodic. <br>
Standard_EXPORT virtual  Standard_Real UPeriod() const;


//! Returns true if this offset surface is periodic in the v <br>
//! parametric direction, i.e. if the basis <br>
//! surface of this offset surface is periodic in this direction. <br>
Standard_EXPORT   Standard_Boolean IsVPeriodic() const;

//! Returns the period of this offset surface in the v <br>
//! parametric direction respectively, i.e. the period of the <br>
//! basis surface of this offset surface in this parametric direction. <br>//! raises if the surface is not vperiodic. <br>
Standard_EXPORT virtual  Standard_Real VPeriod() const;

//! Computes the U isoparametric curve. <br>
Standard_EXPORT   Handle_Geom_Curve UIso(const Standard_Real U) const;

//! Computes the V isoparametric curve. <br>
//!  Te followings methods compute value and derivatives. <br>
//! <br>
//! Warnings <br>
//!  An exception is raised if a unique normal vector is <br>
//!  not defined on the basis surface for the parametric <br>
//!  value (U,V). <br>
//!  No check is done at the creation time and we suppose <br>
//!  in this package that the offset surface can be defined <br>
//!  at any point. <br>
Standard_EXPORT   Handle_Geom_Curve VIso(const Standard_Real V) const;


//!  P (U, V) = Pbasis + Offset * Ndir   where <br>
//!  Ndir = D1Ubasis ^ D1Vbasis / ||D1Ubasis ^ D1Vbasis|| is the <br>
//!  normal direction of the basis surface. Pbasis, D1Ubasis, <br>
//!  D1Vbasis are the point and the first derivatives on the basis <br>
//!  surface. <br>
//!  If Ndir is undefined this method computes an approched normal <br>
//!  direction using the following limited development : <br>
//!  Ndir = N0 + DNdir/DU + DNdir/DV + Eps with Eps->0 which <br>
//!  requires to compute the second derivatives on the basis surface. <br>
//!  If the normal direction cannot be approximate for this order <br>
//!  of derivation the exception UndefinedValue is raised. <br>
//!  Raised if the continuity of the basis surface is not C1. <br>
//!  Raised if the order of derivation required to compute the <br>
//!  normal direction is greater than the second order. <br>
Standard_EXPORT   void D0(const Standard_Real U,const Standard_Real V,gp_Pnt& P) const;


//!  Raised if the continuity of the basis surface is not C2. <br>
Standard_EXPORT   void D1(const Standard_Real U,const Standard_Real V,gp_Pnt& P,gp_Vec& D1U,gp_Vec& D1V) const;

//!---Purpose ; <br>
//!  Raised if the continuity of the basis surface is not C3. <br>
Standard_EXPORT   void 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;


//!  Raised if the continuity of the basis surface is not C4. <br>
Standard_EXPORT   void 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;


//!  Computes the derivative of order Nu in the direction u and Nv <br>
//!  in the direction v. <br>//!---Purpose ; <br>
//!  Raised if the continuity of the basis surface is not CNu + 1 <br>
//!  in the U direction and CNv + 1 in the V direction. <br>//! Raised if Nu + Nv < 1 or Nu < 0 or Nv < 0. <br>
//!  The following methods compute the value and derivatives <br>
//!  on the offset surface and returns the derivatives on the <br>
//!  basis surface too. <br>
//!  The computation of the value and derivatives on the basis <br>
//!  surface are used to evaluate the offset surface. <br>
//! <br>
//!  Warnings : <br>
//!  The exception UndefinedValue or UndefinedDerivative is <br>
//!  raised if it is not possible to compute a unique offset <br>
//!  direction. <br>
Standard_EXPORT   gp_Vec DN(const Standard_Real U,const Standard_Real V,const Standard_Integer Nu,const Standard_Integer Nv) const;


//!  P (U, V) = Pbasis + Offset * Ndir   where <br>
//!  Ndir = D1Ubasis ^ D1Vbasis / ||D1Ubasis ^ D1Vbasis|| is <br>
//!  the normal direction of the surface. <br>
//!  If Ndir is undefined this method computes an approched normal <br>
//!  direction using the following limited development : <br>
//!  Ndir = N0 + DNdir/DU + DNdir/DV + Eps with Eps->0 which <br>
//!  requires to compute the second derivatives on the basis surface. <br>
//!  If the normal direction cannot be approximate for this order <br>
//!  of derivation the exception UndefinedValue is raised. <br>
//!  Raised if the continuity of the basis surface is not C1. <br>
//!  Raised if the order of derivation required to compute the normal <br>
//!  direction is greater than the second order. <br>
Standard_EXPORT   void Value(const Standard_Real U,const Standard_Real V,gp_Pnt& P,gp_Pnt& Pbasis,gp_Vec& D1Ubasis,gp_Vec& D1Vbasis) const;


//!  Raised if the continuity of the basis surface is not C2. <br>
Standard_EXPORT   void 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;


//!  Raised if the continuity of the basis surface is not C3. <br>//!  The  following  private  methods <br>
//!  includes common part of local  and  global methods <br>
//!  of  derivative  evaluations. <br>
Standard_EXPORT   void 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;


Standard_EXPORT   void LocalD0(const Standard_Real U,const Standard_Real V,const Standard_Integer USide,const Standard_Integer VSide,gp_Pnt& P) const;


Standard_EXPORT   void 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;


Standard_EXPORT   void 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;


Standard_EXPORT   void 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;


Standard_EXPORT   gp_Vec 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;


//! Applies the transformation T to this offset surface. <br>
//! Note: the basis surface is also modified. <br>
Standard_EXPORT   void Transform(const gp_Trsf& T) ;

//! Computes the  parameters on the  transformed  surface for <br>
//!          the transform of the point of parameters U,V on <me>. <br>
//! <br>
//!          me->Transformed(T)->Value(U',V') <br>
//! <br>
//!          is the same point as <br>
//! <br>
//!          me->Value(U,V).Transformed(T) <br>
//! <br>
//!          Where U',V' are the new values of U,V after calling <br>
//! <br>
//!          me->TranformParameters(U,V,T) <br>
//!          This methods calls the basis surface method. <br>
Standard_EXPORT virtual  void TransformParameters(Standard_Real& U,Standard_Real& V,const gp_Trsf& T) const;

//! Returns a 2d transformation  used to find the  new <br>
//!          parameters of a point on the transformed surface. <br>
//! <br>
//!          me->Transformed(T)->Value(U',V') <br>
//! <br>
//!          is the same point as <br>
//! <br>
//!          me->Value(U,V).Transformed(T) <br>
//! <br>
//!          Where U',V' are  obtained by transforming U,V with <br>
//!          th 2d transformation returned by <br>
//! <br>
//!          me->ParametricTransformation(T) <br>
//! <br>
//!          This methods calls the basis surface method. <br>
Standard_EXPORT virtual  gp_GTrsf2d ParametricTransformation(const gp_Trsf& T) const;

//! Creates a new object which is a copy of this offset surface. <br>
Standard_EXPORT   Handle_Geom_Geometry Copy() const;

//! returns an  equivalent surface of the offset surface <br>
//!          when  the basis surface   is a canonic  surface or a <br>
//!          rectangular  limited surface on canonic surface or if <br>
//!          the offset is null. <br>
Standard_EXPORT   Handle_Geom_Surface Surface() const;

//! if Standard_True, L is  the local osculating surface <br>
//!          along U at  the point U,V.   It means that  DL/DU is <br>
//!          collinear to DS/DU .  If IsOpposite == Standard_True <br>
//!          these vectors have opposite direction. <br>
//! <br>
Standard_EXPORT   Standard_Boolean UOsculatingSurface(const Standard_Real U,const Standard_Real V,Standard_Boolean& IsOpposite,Handle(Geom_BSplineSurface)& UOsculSurf) const;

//! if Standard_True, L is the local osculating surface <br>
//!          along V at the point U,V. <br>
//!          It means that  DL/DV is <br>
//!          collinear to DS/DV .  If IsOpposite == Standard_True <br>
//!          these vectors have opposite direction. <br>
Standard_EXPORT   Standard_Boolean VOsculatingSurface(const Standard_Real U,const Standard_Real V,Standard_Boolean& IsOpposite,Handle(Geom_BSplineSurface)& VOsculSurf) const;
//Standard_EXPORT ~Geom_OffsetSurface();




 // Type management
 //
 Standard_EXPORT const Handle(Standard_Type)& DynamicType() const;
 //Standard_EXPORT Standard_Boolean	       IsKind(const Handle(Standard_Type)&) const;

protected:

 // Methods PROTECTED
 // 


 // Fields PROTECTED
 //


private: 

 // Methods PRIVATE
 // 


Standard_EXPORT   void SetD0(const Standard_Real U,const Standard_Real V,gp_Pnt& P,const gp_Vec& D1U,const gp_Vec& D1V) const;


Standard_EXPORT   void SetD1(const Standard_Real U,const Standard_Real V,gp_Pnt& P,gp_Vec& D1U,gp_Vec& D1V,const gp_Vec& d2u,const gp_Vec& d2v,const gp_Vec& d2uv) const;


Standard_EXPORT   void 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;


Standard_EXPORT   void 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;

//! The following  functions  evaluates the  local <br>
//! derivatives on surface. Useful to manage discontinuities <br>
//! on the surface. <br>
//!           if    Side  =  1  ->  P  =  S( U+,V ) <br>
//!           if    Side  = -1  ->  P  =  S( U-,V ) <br>
//!           else  P  is betveen discontinuities <br>
//!           can be evaluated using methods  of <br>
//!           global evaluations    P  =  S( U ,V ) <br>
Standard_EXPORT   gp_Vec 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;

//! This  method locates U,V parameters on basis BSpline surface <br>
//! and calls LocalDi or Di methods corresponding an order <br>
//! of derivative and  position <br>
//! of UV-point relatively the surface discontinuities. <br>
Standard_EXPORT   void 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;


 // Fields PRIVATE
 //
Handle_Geom_Surface basisSurf;
Handle_Geom_Surface equivSurf;
Standard_Real offsetValue;
Geom_OsculatingSurface myOscSurf;


};





// other Inline functions and methods (like "C++: function call" methods)
//


#endif
