// 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.

// Evolutions   JCV Dec 1991 ajout de calculs de derivees et traitement
//              d'entites 2d
//              JCV Mars 1992 ajout method SetLinearForm

#define No_Standard_OutOfRange

#include <ElCLib.hxx>
#include <gp.hxx>
#include <gp_Ax1.hxx>
#include <gp_Ax2.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Ax22d.hxx>
#include <gp_Circ.hxx>
#include <gp_Circ2d.hxx>
#include <gp_Dir.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Elips.hxx>
#include <gp_Elips2d.hxx>
#include <gp_Hypr.hxx>
#include <gp_Hypr2d.hxx>
#include <gp_Lin.hxx>
#include <gp_Lin2d.hxx>
#include <gp_Parab.hxx>
#include <gp_Parab2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec.hxx>
#include <gp_Vec2d.hxx>
#include <Standard_NumericError.hxx>

namespace
{
static constexpr double PIPI = M_PI + M_PI;
// Threshold for angle normalization to avoid discontinuity near zero
static constexpr double NEGATIVE_RESOLUTION = -Precision::Computational();

// Normalize angle to [0, 2*PI] range, with special handling
// for values very close to zero to avoid discontinuity.
// Preserves values at exactly 2*PI for proper seam handling.
static inline void normalizeAngle(double& theAngle)
{
  while (theAngle < NEGATIVE_RESOLUTION)
  {
    theAngle += PIPI;
  }
  // Only normalize angles strictly greater than 2*PI (with small tolerance)
  // to preserve the closing seam value of exactly 2*PI
  while (theAngle > PIPI * (1.0 + gp::Resolution()))
  {
    theAngle -= PIPI;
  }
  if (theAngle < 0.)
  {
    theAngle = 0.;
  }
}
} // namespace

//=======================================================================
// function : InPeriod
// purpose  : Value theULast is never returned.
//          Example of some case (checked on WIN64 platform)
//          with some surface having period 2*PI = 6.2831853071795862.
//            Let theUFirst be equal to 6.1645624650899675. Then,
//          theULast must be equal to
//              6.1645624650899675+6.2831853071795862=12.4477477722695537.
//
//          However, real result is 12.447747772269555.
//          Therefore, new period value to adjust will be equal to
//              12.447747772269555-6.1645624650899675=6.2831853071795871.
//
//          As we can see, (6.2831853071795871 != 6.2831853071795862).
//
//          According to above said, this method should be used carefully.
//          In order to increase reliability of this method, input arguments
//          needs to be replaced with following:
//            (theU, theUFirst, thePeriod). theULast parameter is excess.
//=======================================================================
double ElCLib::InPeriod(const double theU, const double theUFirst, const double theULast)
{
  if (Precision::IsInfinite(theU) || Precision::IsInfinite(theUFirst)
      || Precision::IsInfinite(theULast))
  { // In order to avoid FLT_Overflow exception
    return theU;
  }

  const double aPeriod = theULast - theUFirst;

  if (aPeriod < Epsilon(theULast))
  {
    return theU;
  }

  return std::max(theUFirst, theU + aPeriod * std::ceil((theUFirst - theU) / aPeriod));
}

//=================================================================================================

void ElCLib::AdjustPeriodic(const double UFirst,
                            const double ULast,
                            const double Preci,
                            double&      U1,
                            double&      U2)
{
  if (Precision::IsInfinite(UFirst) || Precision::IsInfinite(ULast))
  {
    U1 = UFirst;
    U2 = ULast;
    return;
  }

  const double aPeriod = ULast - UFirst;

  if (aPeriod < Epsilon(ULast))
  {
    // In order to avoid FLT_Overflow exception
    // (test bugs moddata_1 bug22757)
    U1 = UFirst;
    U2 = ULast;
    return;
  }

  U1 -= std::floor((U1 - UFirst) / aPeriod) * aPeriod;
  if (ULast - U1 < Preci)
  {
    U1 -= aPeriod;
  }
  U2 -= std::floor((U2 - U1) / aPeriod) * aPeriod;
  if (U2 - U1 < Preci)
  {
    U2 += aPeriod;
  }
}

//=================================================================================================

gp_Pnt ElCLib::LineValue(const double U, const gp_Ax1& Pos)
{
  const gp_XYZ& ZDir = Pos.Direction().XYZ();
  const gp_XYZ& PLoc = Pos.Location().XYZ();
  return gp_Pnt(U * ZDir.X() + PLoc.X(), U * ZDir.Y() + PLoc.Y(), U * ZDir.Z() + PLoc.Z());
}

//=================================================================================================

gp_Pnt ElCLib::CircleValue(const double U, const gp_Ax2& Pos, const double Radius)
{
  const gp_XYZ& XDir = Pos.XDirection().XYZ();
  const gp_XYZ& YDir = Pos.YDirection().XYZ();
  const gp_XYZ& PLoc = Pos.Location().XYZ();
  const double  A1   = Radius * cos(U);
  const double  A2   = Radius * sin(U);
  return gp_Pnt(A1 * XDir.X() + A2 * YDir.X() + PLoc.X(),
                A1 * XDir.Y() + A2 * YDir.Y() + PLoc.Y(),
                A1 * XDir.Z() + A2 * YDir.Z() + PLoc.Z());
}

//=================================================================================================

gp_Pnt ElCLib::EllipseValue(const double  U,
                            const gp_Ax2& Pos,
                            const double  MajorRadius,
                            const double  MinorRadius)
{
  const gp_XYZ& XDir = Pos.XDirection().XYZ();
  const gp_XYZ& YDir = Pos.YDirection().XYZ();
  const gp_XYZ& PLoc = Pos.Location().XYZ();
  const double  A1   = MajorRadius * cos(U);
  const double  A2   = MinorRadius * sin(U);
  return gp_Pnt(A1 * XDir.X() + A2 * YDir.X() + PLoc.X(),
                A1 * XDir.Y() + A2 * YDir.Y() + PLoc.Y(),
                A1 * XDir.Z() + A2 * YDir.Z() + PLoc.Z());
}

//=================================================================================================

gp_Pnt ElCLib::HyperbolaValue(const double  U,
                              const gp_Ax2& Pos,
                              const double  MajorRadius,
                              const double  MinorRadius)
{
  const gp_XYZ& XDir = Pos.XDirection().XYZ();
  const gp_XYZ& YDir = Pos.YDirection().XYZ();
  const gp_XYZ& PLoc = Pos.Location().XYZ();
  const double  A1   = MajorRadius * std::cosh(U);
  const double  A2   = MinorRadius * std::sinh(U);
  return gp_Pnt(A1 * XDir.X() + A2 * YDir.X() + PLoc.X(),
                A1 * XDir.Y() + A2 * YDir.Y() + PLoc.Y(),
                A1 * XDir.Z() + A2 * YDir.Z() + PLoc.Z());
}

//=================================================================================================

gp_Pnt ElCLib::ParabolaValue(const double U, const gp_Ax2& Pos, const double Focal)
{
  if (Focal == 0.0)
  {
    const gp_XYZ& XDir = Pos.XDirection().XYZ();
    const gp_XYZ& PLoc = Pos.Location().XYZ();
    return gp_Pnt(U * XDir.X() + PLoc.X(), U * XDir.Y() + PLoc.Y(), U * XDir.Z() + PLoc.Z());
  }
  const gp_XYZ& XDir = Pos.XDirection().XYZ();
  const gp_XYZ& YDir = Pos.YDirection().XYZ();
  const gp_XYZ& PLoc = Pos.Location().XYZ();
  const double  A1   = U * U / (4.0 * Focal);
  return gp_Pnt(A1 * XDir.X() + U * YDir.X() + PLoc.X(),
                A1 * XDir.Y() + U * YDir.Y() + PLoc.Y(),
                A1 * XDir.Z() + U * YDir.Z() + PLoc.Z());
}

//=================================================================================================

void ElCLib::LineD1(const double U, const gp_Ax1& Pos, gp_Pnt& P, gp_Vec& V1)
{
  gp_XYZ Coord = Pos.Direction().XYZ();
  V1.SetXYZ(Coord);
  Coord.SetLinearForm(U, Coord, Pos.Location().XYZ());
  P.SetXYZ(Coord);
}

//=================================================================================================

void ElCLib::CircleD1(const double U, const gp_Ax2& Pos, const double Radius, gp_Pnt& P, gp_Vec& V1)
{
  const double  Xc = Radius * std::cos(U);
  const double  Yc = Radius * std::sin(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;
  // Point courant :
  Coord0.SetLinearForm(Xc, Coord1, Yc, Coord2, Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 :
  Coord0.SetLinearForm(-Yc, Coord1, Xc, Coord2);
  V1.SetXYZ(Coord0);
}

//=================================================================================================

void ElCLib::EllipseD1(const double  U,
                       const gp_Ax2& Pos,
                       const double  MajorRadius,
                       const double  MinorRadius,
                       gp_Pnt&       P,
                       gp_Vec&       V1)
{
  const double  Xc = std::cos(U);
  const double  Yc = std::sin(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;
  // Point courant :
  Coord0.SetLinearForm(Xc * MajorRadius, Coord1, Yc * MinorRadius, Coord2, Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 :
  Coord0.SetLinearForm(-Yc * MajorRadius, Coord1, Xc * MinorRadius, Coord2);
  V1.SetXYZ(Coord0);
}

//=================================================================================================

void ElCLib::HyperbolaD1(const double  U,
                         const gp_Ax2& Pos,
                         const double  MajorRadius,
                         const double  MinorRadius,
                         gp_Pnt&       P,
                         gp_Vec&       V1)
{
  const double  Xc = std::cosh(U);
  const double  Yc = std::sinh(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;
  // Point courant :
  Coord0.SetLinearForm(Xc * MajorRadius, Coord1, Yc * MinorRadius, Coord2, Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 :
  Coord0.SetLinearForm(Yc * MajorRadius, Coord1, Xc * MinorRadius, Coord2);
  V1.SetXYZ(Coord0);
}

//=================================================================================================

void ElCLib::ParabolaD1(const double  U,
                        const gp_Ax2& Pos,
                        const double  Focal,
                        gp_Pnt&       P,
                        gp_Vec&       V1)
{
  gp_XYZ Coord1(Pos.XDirection().XYZ());
  if (Focal == 0.0)
  { // Parabole degenere en une droite
    V1.SetXYZ(Coord1);
    Coord1.Multiply(U);
    Coord1.Add(Pos.Location().XYZ());
    P.SetXYZ(Coord1);
  }
  else
  {
    gp_XYZ        Coord0;
    const gp_XYZ& Coord2(Pos.YDirection().XYZ());
    Coord0.SetLinearForm(U / (2.0 * Focal), Coord1, Coord2);
    V1.SetXYZ(Coord0);
    Coord0.SetLinearForm((U * U) / (4.0 * Focal), Coord1, U, Coord2, Pos.Location().XYZ());
    P.SetXYZ(Coord0);
  }
}

//=================================================================================================

void ElCLib::CircleD2(const double  U,
                      const gp_Ax2& Pos,
                      const double  Radius,
                      gp_Pnt&       P,
                      gp_Vec&       V1,
                      gp_Vec&       V2)
{
  const double  Xc = Radius * cos(U);
  const double  Yc = Radius * sin(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;
  // Point courant :
  Coord0.SetLinearForm(Xc, Coord1, Yc, Coord2, Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 :
  Coord0.SetLinearForm(-Yc, Coord1, Xc, Coord2);
  V1.SetXYZ(Coord0);
  // D2 :
  Coord0.SetLinearForm(-Xc, Coord1, -Yc, Coord2);
  V2.SetXYZ(Coord0);
}

//=================================================================================================

void ElCLib::EllipseD2(const double  U,
                       const gp_Ax2& Pos,
                       const double  MajorRadius,
                       const double  MinorRadius,
                       gp_Pnt&       P,
                       gp_Vec&       V1,
                       gp_Vec&       V2)
{
  const double  Xc = cos(U);
  const double  Yc = sin(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;
  // Point courant :
  Coord0.SetLinearForm(Xc * MajorRadius, Coord1, Yc * MinorRadius, Coord2, Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 :
  Coord0.SetLinearForm(-Yc * MajorRadius, Coord1, Xc * MinorRadius, Coord2);
  V1.SetXYZ(Coord0);
  // D2 :
  Coord0.SetLinearForm(-Xc * MajorRadius, Coord1, -Yc * MinorRadius, Coord2);
  V2.SetXYZ(Coord0);
}

//=================================================================================================

void ElCLib::HyperbolaD2(const double  U,
                         const gp_Ax2& Pos,
                         const double  MajorRadius,
                         const double  MinorRadius,
                         gp_Pnt&       P,
                         gp_Vec&       V1,
                         gp_Vec&       V2)
{
  const double  Xc = std::cosh(U);
  const double  Yc = std::sinh(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;

  // Point courant et D2:
  Coord0.SetLinearForm(Xc * MajorRadius, Coord1, Yc * MinorRadius, Coord2);
  V2.SetXYZ(Coord0);
  Coord0.Add(Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 :
  Coord0.SetLinearForm(Yc * MajorRadius, Coord1, Xc * MinorRadius, Coord2);
  V1.SetXYZ(Coord0);
}

//=================================================================================================

void ElCLib::ParabolaD2(const double  U,
                        const gp_Ax2& Pos,
                        const double  Focal,
                        gp_Pnt&       P,
                        gp_Vec&       V1,
                        gp_Vec&       V2)
{
  gp_XYZ Coord1(Pos.XDirection().XYZ());
  if (Focal == 0.0)
  {
    V2.SetCoord(0.0, 0.0, 0.0);
    V1.SetXYZ(Coord1);
    Coord1.Multiply(U);
    Coord1.Add(Pos.Location().XYZ());
    P.SetXYZ(Coord1); // was: P.SetXYZ (Coord0);
  }
  else
  {
    gp_XYZ        Coord0;
    const gp_XYZ& Coord2(Pos.YDirection().XYZ());
    Coord0.SetLinearForm((U * U) / (4.0 * Focal), Coord1, U, Coord2, Pos.Location().XYZ());
    P.SetXYZ(Coord0);
    Coord0.SetLinearForm(U / (2.0 * Focal), Coord1, Coord2);
    V1.SetXYZ(Coord0);
    Coord1.Multiply(1.0 / (2.0 * Focal));
    V2.SetXYZ(Coord1);
  }
}

//=================================================================================================

void ElCLib::CircleD3(const double  U,
                      const gp_Ax2& Pos,
                      const double  Radius,
                      gp_Pnt&       P,
                      gp_Vec&       V1,
                      gp_Vec&       V2,
                      gp_Vec&       V3)
{
  const double  Xc = Radius * cos(U);
  const double  Yc = Radius * sin(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;
  // Point Courant :
  Coord0.SetLinearForm(Xc, Coord1, Yc, Coord2, Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 :
  Coord0.SetLinearForm(-Yc, Coord1, Xc, Coord2);
  V1.SetXYZ(Coord0);
  // D2 :
  Coord0.SetLinearForm(-Xc, Coord1, -Yc, Coord2);
  V2.SetXYZ(Coord0);
  // D3 :
  Coord0.SetLinearForm(Yc, Coord1, -Xc, Coord2);
  V3.SetXYZ(Coord0);
}

//=================================================================================================

void ElCLib::EllipseD3(const double  U,
                       const gp_Ax2& Pos,
                       const double  MajorRadius,
                       const double  MinorRadius,
                       gp_Pnt&       P,
                       gp_Vec&       V1,
                       gp_Vec&       V2,
                       gp_Vec&       V3)
{
  const double  Xc = cos(U);
  const double  Yc = sin(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;
  // Point Courant :
  Coord0.SetLinearForm(Xc * MajorRadius, Coord1, Yc * MinorRadius, Coord2, Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 :
  Coord0.SetLinearForm(-Yc * MajorRadius, Coord1, Xc * MinorRadius, Coord2);
  V1.SetXYZ(Coord0);
  // D2 :
  Coord0.SetLinearForm(-Xc * MajorRadius, Coord1, -Yc * MinorRadius, Coord2);
  V2.SetXYZ(Coord0);
  // D3
  Coord0.SetLinearForm(Yc * MajorRadius, Coord1, -Xc * MinorRadius, Coord2);
  V3.SetXYZ(Coord0);
}

//=================================================================================================

void ElCLib::HyperbolaD3(const double  U,
                         const gp_Ax2& Pos,
                         const double  MajorRadius,
                         const double  MinorRadius,
                         gp_Pnt&       P,
                         gp_Vec&       V1,
                         gp_Vec&       V2,
                         gp_Vec&       V3)
{
  const double  Xc = std::cosh(U);
  const double  Yc = std::sinh(U);
  const gp_XYZ& Coord1(Pos.XDirection().XYZ());
  const gp_XYZ& Coord2(Pos.YDirection().XYZ());
  gp_XYZ        Coord0;
  // Point courant et D2 :
  Coord0.SetLinearForm(Xc * MajorRadius, Coord1, Yc * MinorRadius, Coord2);
  V2.SetXYZ(Coord0);
  Coord0.Add(Pos.Location().XYZ());
  P.SetXYZ(Coord0);
  // D1 et D3 :
  Coord0.SetLinearForm(Yc * MajorRadius, Coord1, Xc * MinorRadius, Coord2);
  V1.SetXYZ(Coord0);
  V3.SetXYZ(Coord0);
}

//=================================================================================================

gp_Pnt2d ElCLib::LineValue(const double U, const gp_Ax2d& Pos)
{
  const gp_XY& ZDir = Pos.Direction().XY();
  const gp_XY& PLoc = Pos.Location().XY();
  return gp_Pnt2d(U * ZDir.X() + PLoc.X(), U * ZDir.Y() + PLoc.Y());
}

//=================================================================================================

gp_Pnt2d ElCLib::CircleValue(const double U, const gp_Ax22d& Pos, const double Radius)
{
  const gp_XY& XDir = Pos.XDirection().XY();
  const gp_XY& YDir = Pos.YDirection().XY();
  const gp_XY& PLoc = Pos.Location().XY();
  const double A1   = Radius * cos(U);
  const double A2   = Radius * sin(U);
  return gp_Pnt2d(A1 * XDir.X() + A2 * YDir.X() + PLoc.X(),
                  A1 * XDir.Y() + A2 * YDir.Y() + PLoc.Y());
}

//=================================================================================================

gp_Pnt2d ElCLib::EllipseValue(const double    U,
                              const gp_Ax22d& Pos,
                              const double    MajorRadius,
                              const double    MinorRadius)
{
  const gp_XY& XDir = Pos.XDirection().XY();
  const gp_XY& YDir = Pos.YDirection().XY();
  const gp_XY& PLoc = Pos.Location().XY();
  const double A1   = MajorRadius * cos(U);
  const double A2   = MinorRadius * sin(U);
  return gp_Pnt2d(A1 * XDir.X() + A2 * YDir.X() + PLoc.X(),
                  A1 * XDir.Y() + A2 * YDir.Y() + PLoc.Y());
}

//=================================================================================================

gp_Pnt2d ElCLib::HyperbolaValue(const double    U,
                                const gp_Ax22d& Pos,
                                const double    MajorRadius,
                                const double    MinorRadius)
{
  const gp_XY& XDir = Pos.XDirection().XY();
  const gp_XY& YDir = Pos.YDirection().XY();
  const gp_XY& PLoc = Pos.Location().XY();
  const double A1   = MajorRadius * std::cosh(U);
  const double A2   = MinorRadius * std::sinh(U);
  return gp_Pnt2d(A1 * XDir.X() + A2 * YDir.X() + PLoc.X(),
                  A1 * XDir.Y() + A2 * YDir.Y() + PLoc.Y());
}

//=================================================================================================

gp_Pnt2d ElCLib::ParabolaValue(const double U, const gp_Ax22d& Pos, const double Focal)
{
  if (Focal == 0.0)
  {
    const gp_XY& XDir = Pos.XDirection().XY();
    const gp_XY& PLoc = Pos.Location().XY();
    return gp_Pnt2d(U * XDir.X() + PLoc.X(), U * XDir.Y() + PLoc.Y());
  }
  const gp_XY& XDir = Pos.XDirection().XY();
  const gp_XY& YDir = Pos.YDirection().XY();
  const gp_XY& PLoc = Pos.Location().XY();
  const double A1   = U * U / (4.0 * Focal);
  return gp_Pnt2d(A1 * XDir.X() + U * YDir.X() + PLoc.X(), A1 * XDir.Y() + U * YDir.Y() + PLoc.Y());
}

//=================================================================================================

void ElCLib::LineD1(const double U, const gp_Ax2d& Pos, gp_Pnt2d& P, gp_Vec2d& V1)
{
  gp_XY Coord = Pos.Direction().XY();
  V1.SetXY(Coord);
  Coord.SetLinearForm(U, Coord, Pos.Location().XY());
  P.SetXY(Coord);
}

//=================================================================================================

void ElCLib::CircleD1(const double    U,
                      const gp_Ax22d& Pos,
                      const double    Radius,
                      gp_Pnt2d&       P,
                      gp_Vec2d&       V1)
{
  const double Xc = Radius * cos(U);
  const double Yc = Radius * sin(U);
  const gp_XY& Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  gp_XY        Vxy;
  // Point courant :
  Vxy.SetLinearForm(Xc, Xdir, Yc, Ydir, Pos.Location().XY());
  P.SetXY(Vxy);
  // V1 :
  Vxy.SetLinearForm(-Yc, Xdir, Xc, Ydir);
  V1.SetXY(Vxy);
}

//=================================================================================================

void ElCLib::EllipseD1(const double    U,
                       const gp_Ax22d& Pos,
                       const double    MajorRadius,
                       const double    MinorRadius,
                       gp_Pnt2d&       P,
                       gp_Vec2d&       V1)
{
  const double Xc = cos(U);
  const double Yc = sin(U);
  const gp_XY& Xdir((Pos.XDirection()).XY());
  const gp_XY& Ydir((Pos.YDirection()).XY());
  gp_XY        Vxy;
  // Point courant :
  Vxy.SetLinearForm(Xc * MajorRadius, Xdir, Yc * MinorRadius, Ydir, Pos.Location().XY());
  P.SetXY(Vxy);

  // V1 :
  Vxy.SetLinearForm(-Yc * MajorRadius, Xdir, Xc * MinorRadius, Ydir);
  V1.SetXY(Vxy);
}

//=================================================================================================

void ElCLib::HyperbolaD1(const double    U,
                         const gp_Ax22d& Pos,
                         const double    MajorRadius,
                         const double    MinorRadius,
                         gp_Pnt2d&       P,
                         gp_Vec2d&       V1)
{
  const double Xc = std::cosh(U);
  const double Yc = std::sinh(U);
  const gp_XY& Xdir((Pos.XDirection()).XY());
  const gp_XY& Ydir((Pos.YDirection()).XY());
  gp_XY        Vxy;
  // Point courant :
  Vxy.SetLinearForm(Xc * MajorRadius, Xdir, Yc * MinorRadius, Ydir, Pos.Location().XY());
  P.SetXY(Vxy);

  // V1 :
  Vxy.SetLinearForm(Yc * MajorRadius, Xdir, Xc * MinorRadius, Ydir);
  V1.SetXY(Vxy);
}

//=================================================================================================

void ElCLib::ParabolaD1(const double    U,
                        const gp_Ax22d& Pos,
                        const double    Focal,
                        gp_Pnt2d&       P,
                        gp_Vec2d&       V1)
{
  gp_XY        Vxy;
  const gp_XY& Xdir(Pos.XDirection().XY());
  if (Focal == 0.0)
  { // Parabole degenere en une droite
    V1.SetXY(Xdir);
    Vxy.SetLinearForm(U, Xdir, Pos.Location().XY());
  }
  else
  {
    const gp_XY& Ydir(Pos.YDirection().XY());
    Vxy.SetLinearForm(U / (2.0 * Focal), Xdir, Ydir);
    V1.SetXY(Vxy);
    Vxy.SetLinearForm((U * U) / (4.0 * Focal), Xdir, U, Ydir, Pos.Location().XY());
  }
  P.SetXY(Vxy);
}

//=================================================================================================

void ElCLib::CircleD2(const double    U,
                      const gp_Ax22d& Pos,
                      const double    Radius,
                      gp_Pnt2d&       P,
                      gp_Vec2d&       V1,
                      gp_Vec2d&       V2)
{
  const gp_XY& Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  const double Xc = Radius * cos(U);
  const double Yc = Radius * sin(U);
  gp_XY        Vxy;
  // V2 :
  Vxy.SetLinearForm(Xc, Xdir, Yc, Ydir);
  V2.SetXY(Vxy);
  V2.Reverse();
  Vxy.Add(Pos.Location().XY());
  P.SetXY(Vxy);

  // V1 :
  Vxy.SetLinearForm(-Yc, Xdir, Xc, Ydir);
  V1.SetXY(Vxy);
}

//=================================================================================================

void ElCLib::EllipseD2(const double    U,
                       const gp_Ax22d& Pos,
                       const double    MajorRadius,
                       const double    MinorRadius,
                       gp_Pnt2d&       P,
                       gp_Vec2d&       V1,
                       gp_Vec2d&       V2)
{
  const gp_XY& Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  const double Xc = cos(U);
  const double Yc = sin(U);
  gp_XY        Vxy;

  // V2 :
  Vxy.SetLinearForm(Xc * MajorRadius, Xdir, Yc * MinorRadius, Ydir);
  V2.SetXY(Vxy);
  V2.Reverse();

  // Point courant :
  Vxy.Add(Pos.Location().XY());
  P.SetXY(Vxy);

  // V1 :
  Vxy.SetLinearForm(-Yc * MajorRadius, Xdir, Xc * MinorRadius, Ydir);
  V1.SetXY(Vxy);
}

//=================================================================================================

void ElCLib::HyperbolaD2(const double    U,
                         const gp_Ax22d& Pos,
                         const double    MajorRadius,
                         const double    MinorRadius,
                         gp_Pnt2d&       P,
                         gp_Vec2d&       V1,
                         gp_Vec2d&       V2)
{
  const gp_XY& Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  const double Xc = std::cosh(U);
  const double Yc = std::sinh(U);
  gp_XY        Vxy;

  // V2 :
  Vxy.SetLinearForm(Xc * MajorRadius, Xdir, Yc * MinorRadius, Ydir);
  V2.SetXY(Vxy);

  // Point courant :
  Vxy.Add(Pos.Location().XY());
  P.SetXY(Vxy);

  // V1 :
  Vxy.SetLinearForm(Yc * MajorRadius, Xdir, Xc * MinorRadius, Ydir);
  V1.SetXY(Vxy);
}

//=================================================================================================

void ElCLib::ParabolaD2(const double    U,
                        const gp_Ax22d& Pos,
                        const double    Focal,
                        gp_Pnt2d&       P,
                        gp_Vec2d&       V1,
                        gp_Vec2d&       V2)
{
  gp_XY        Vxy;
  const gp_XY& Xdir(Pos.XDirection().XY());
  if (Focal == 0.0)
  {
    V2.SetCoord(0.0, 0.0);
    V1.SetXY(Xdir);
    Vxy.SetLinearForm(U, Xdir, Pos.Location().XY());
  }
  else
  {
    const gp_XY& Ydir(Pos.YDirection().XY());
    Vxy = Xdir.Multiplied(1.0 / (2.0 * Focal));
    V2.SetXY(Vxy);
    Vxy.SetLinearForm(U, Vxy, Ydir);
    V1.SetXY(Vxy);
    Vxy.SetLinearForm(U * U / (4.0 * Focal), Xdir, U, Ydir);
    Vxy.Add(Pos.Location().XY());
  }
  P.SetXY(Vxy);
}

//=================================================================================================

void ElCLib::CircleD3(const double    U,
                      const gp_Ax22d& Pos,
                      const double    Radius,
                      gp_Pnt2d&       P,
                      gp_Vec2d&       V1,
                      gp_Vec2d&       V2,
                      gp_Vec2d&       V3)
{
  gp_XY        Vxy;
  const gp_XY& Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  const double Xc = Radius * cos(U);
  const double Yc = Radius * sin(U);

  // V2 :
  Vxy.SetLinearForm(Xc, Xdir, Yc, Ydir);
  V2.SetXY(Vxy);
  V2.Reverse();

  // Point courant :
  Vxy.Add(Pos.Location().XY());
  P.SetXY(Vxy);

  // V1 :
  Vxy.SetLinearForm(-Yc, Xdir, Xc, Ydir);
  V1.SetXY(Vxy);

  // V3 :
  V3.SetXY(Vxy);
  V3.Reverse();
}

//=================================================================================================

void ElCLib::EllipseD3(const double    U,
                       const gp_Ax22d& Pos,
                       const double    MajorRadius,
                       const double    MinorRadius,
                       gp_Pnt2d&       P,
                       gp_Vec2d&       V1,
                       gp_Vec2d&       V2,
                       gp_Vec2d&       V3)
{
  const gp_XY& Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  const double Xc = cos(U);
  const double Yc = sin(U);
  gp_XY        Vxy;

  // V2 :
  Vxy.SetLinearForm(Xc * MajorRadius, Xdir, Yc * MinorRadius, Ydir);
  V2.SetXY(Vxy);
  V2.Reverse();

  // Point courant :
  Vxy.Add(Pos.Location().XY());
  P.SetXY(Vxy);

  // V1 :
  Vxy.SetLinearForm(-Yc * MajorRadius, Xdir, Xc * MinorRadius, Ydir);
  V1.SetXY(Vxy);

  // V3 :
  V3.SetXY(Vxy);
  V3.Reverse();
}

//=================================================================================================

void ElCLib::HyperbolaD3(const double    U,
                         const gp_Ax22d& Pos,
                         const double    MajorRadius,
                         const double    MinorRadius,
                         gp_Pnt2d&       P,
                         gp_Vec2d&       V1,
                         gp_Vec2d&       V2,
                         gp_Vec2d&       V3)
{
  const gp_XY& Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  const double Xc = std::cosh(U);
  const double Yc = std::sinh(U);
  gp_XY        Vxy;

  // V2 :
  Vxy.SetLinearForm(Xc * MajorRadius, Xdir, Yc * MinorRadius, Ydir);
  V2.SetXY(Vxy);

  // Point courant :
  Vxy.Add(Pos.Location().XY());
  P.SetXY(Vxy);

  // V1 :
  Vxy.SetLinearForm(Yc * MajorRadius, Xdir, Xc * MinorRadius, Ydir);
  V1.SetXY(Vxy);

  // V3 :
  V3.SetXY(Vxy);
}

//=================================================================================================

gp_Vec ElCLib::LineDN(const double, const gp_Ax1& Pos, const int N)
{
  if (N == 1)
  {
    return gp_Vec(Pos.Direction());
  }
  return gp_Vec(0., 0., 0.);
}

//=================================================================================================

gp_Vec ElCLib::CircleDN(const double U, const gp_Ax2& Pos, const double Radius, const int N)
{
  double Xc = 0, Yc = 0;
  if (N == 1)
  {
    Xc = Radius * -sin(U);
    Yc = Radius * cos(U);
  }
  else if ((N + 2) % 4 == 0)
  {
    Xc = Radius * -cos(U);
    Yc = Radius * -sin(U);
  }
  else if ((N + 1) % 4 == 0)
  {
    Xc = Radius * sin(U);
    Yc = Radius * -cos(U);
  }
  else if (N % 4 == 0)
  {
    Xc = Radius * cos(U);
    Yc = Radius * sin(U);
  }
  else if ((N - 1) % 4 == 0)
  {
    Xc = Radius * -sin(U);
    Yc = Radius * cos(U);
  }
  gp_XYZ Coord1(Pos.XDirection().XYZ());
  Coord1.SetLinearForm(Xc, Coord1, Yc, Pos.YDirection().XYZ());
  return gp_Vec(Coord1);
}

//=================================================================================================

gp_Vec ElCLib::EllipseDN(const double  U,
                         const gp_Ax2& Pos,
                         const double  MajorRadius,
                         const double  MinorRadius,
                         const int     N)
{
  double Xc = 0, Yc = 0;
  if (N == 1)
  {
    Xc = MajorRadius * -sin(U);
    Yc = MinorRadius * cos(U);
  }
  else if ((N + 2) % 4 == 0)
  {
    Xc = MajorRadius * -cos(U);
    Yc = MinorRadius * -sin(U);
  }
  else if ((N + 1) % 4 == 0)
  {
    Xc = MajorRadius * sin(U);
    Yc = MinorRadius * -cos(U);
  }
  else if (N % 4 == 0)
  {
    Xc = MajorRadius * cos(U);
    Yc = MinorRadius * sin(U);
  }
  else if ((N - 1) % 4 == 0)
  {
    Xc = MajorRadius * -sin(U);
    Yc = MinorRadius * cos(U);
  }
  gp_XYZ Coord1(Pos.XDirection().XYZ());
  Coord1.SetLinearForm(Xc, Coord1, Yc, Pos.YDirection().XYZ());
  return gp_Vec(Coord1);
}

//=================================================================================================

gp_Vec ElCLib::HyperbolaDN(const double  U,
                           const gp_Ax2& Pos,
                           const double  MajorRadius,
                           const double  MinorRadius,
                           const int     N)
{
  double Xc = 0, Yc = 0;
  if (IsOdd(N))
  {
    Xc = MajorRadius * std::sinh(U);
    Yc = MinorRadius * std::cosh(U);
  }
  else if (IsEven(N))
  {
    Xc = MajorRadius * std::cosh(U);
    Yc = MinorRadius * std::sinh(U);
  }
  gp_XYZ Coord1(Pos.XDirection().XYZ());
  Coord1.SetLinearForm(Xc, Coord1, Yc, Pos.YDirection().XYZ());
  return gp_Vec(Coord1);
}

//=================================================================================================

gp_Vec ElCLib::ParabolaDN(const double U, const gp_Ax2& Pos, const double Focal, const int N)
{
  if (N > 2 || N <= 0)
  {
    return gp_Vec(0., 0., 0.);
  }

  gp_XYZ Coord1(Pos.XDirection().XYZ());
  if (N == 1)
  {
    if (Focal == 0.0)
    {
      return gp_Vec(Coord1);
    }
    Coord1.SetLinearForm(U / (2.0 * Focal), Coord1, Pos.YDirection().XYZ());
    return gp_Vec(Coord1);
  }

  if (Focal == 0.0)
  {
    return gp_Vec(0.0, 0.0, 0.0);
  }

  Coord1.Multiply(1.0 / (2.0 * Focal));
  return gp_Vec(Coord1);
}

//=================================================================================================

gp_Vec2d ElCLib::LineDN(const double, const gp_Ax2d& Pos, const int N)
{
  if (N == 1)
  {
    return gp_Vec2d(Pos.Direction());
  }
  return gp_Vec2d(0.0, 0.0);
}

//=================================================================================================

gp_Vec2d ElCLib::CircleDN(const double U, const gp_Ax22d& Pos, const double Radius, const int N)
{
  double Xc = 0, Yc = 0;
  if (N == 1)
  {
    Xc = Radius * -sin(U);
    Yc = Radius * cos(U);
  }
  else if ((N + 2) % 4 == 0)
  {
    Xc = Radius * -cos(U);
    Yc = Radius * -sin(U);
  }
  else if ((N + 1) % 4 == 0)
  {
    Xc = Radius * sin(U);
    Yc = Radius * -cos(U);
  }
  else if (N % 4 == 0)
  {
    Xc = Radius * cos(U);
    Yc = Radius * sin(U);
  }
  else if ((N - 1) % 4 == 0)
  {
    Xc = Radius * -sin(U);
    Yc = Radius * cos(U);
  }
  gp_XY        Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  Xdir.SetLinearForm(Xc, Xdir, Yc, Ydir);
  return gp_Vec2d(Xdir);
}

//=================================================================================================

gp_Vec2d ElCLib::EllipseDN(const double    U,
                           const gp_Ax22d& Pos,
                           const double    MajorRadius,
                           const double    MinorRadius,
                           const int       N)
{
  double Xc = 0, Yc = 0;
  if (N == 1)
  {
    Xc = MajorRadius * -sin(U);
    Yc = MinorRadius * cos(U);
  }
  else if ((N + 2) % 4 == 0)
  {
    Xc = MajorRadius * -cos(U);
    Yc = MinorRadius * -sin(U);
  }
  else if ((N + 1) % 4 == 0)
  {
    Xc = MajorRadius * sin(U);
    Yc = MinorRadius * -cos(U);
  }
  else if (N % 4 == 0)
  {
    Xc = MajorRadius * cos(U);
    Yc = MinorRadius * sin(U);
  }
  else if ((N - 1) % 4 == 0)
  {
    Xc = MajorRadius * -sin(U);
    Yc = MinorRadius * cos(U);
  }
  gp_XY        Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  Xdir.SetLinearForm(Xc, Xdir, Yc, Ydir);
  return gp_Vec2d(Xdir);
}

//=================================================================================================

gp_Vec2d ElCLib::HyperbolaDN(const double    U,
                             const gp_Ax22d& Pos,
                             const double    MajorRadius,
                             const double    MinorRadius,
                             const int       N)
{
  double Xc = 0, Yc = 0;
  if (IsOdd(N))
  {
    Xc = MajorRadius * std::sinh(U);
    Yc = MinorRadius * std::cosh(U);
  }
  else if (IsEven(N))
  {
    Xc = MajorRadius * std::cosh(U);
    Yc = MinorRadius * std::sinh(U);
  }
  gp_XY        Xdir(Pos.XDirection().XY());
  const gp_XY& Ydir(Pos.YDirection().XY());
  Xdir.SetLinearForm(Xc, Xdir, Yc, Ydir);
  return gp_Vec2d(Xdir);
}

//=================================================================================================

gp_Vec2d ElCLib::ParabolaDN(const double U, const gp_Ax22d& Pos, const double Focal, const int N)
{
  if (N > 2 || N <= 0)
  {
    return gp_Vec2d(0.0, 0.0);
  }

  gp_XY Xdir(Pos.XDirection().XY());
  if (N == 1)
  {
    if (Focal == 0.0)
    {
      return gp_Vec2d(Xdir);
    }

    gp_XY Ydir(Pos.YDirection().XY());
    Xdir.SetLinearForm(U / (2.0 * Focal), Xdir, Ydir);
    return gp_Vec2d(Xdir);
  }

  if (Focal == 0.0)
  {
    return gp_Vec2d(0.0, 0.0);
  }

  Xdir.Multiply(1.0 / (2.0 * Focal));
  return gp_Vec2d(Xdir);
}

//=================================================================================================

double ElCLib::LineParameter(const gp_Ax1& L, const gp_Pnt& P)
{
  return (P.XYZ() - L.Location().XYZ()).Dot(L.Direction().XYZ());
}

//=================================================================================================

double ElCLib::CircleParameter(const gp_Ax2& Pos, const gp_Pnt& P)
{
  const gp_Vec aVec(Pos.Location(), P);
  if (aVec.SquareMagnitude() < gp::Resolution())
    // coinciding points -> infinite number of parameters
    return 0.0;

  const gp_Dir& dir = Pos.Direction();
  // Project vector on circle's plane
  const gp_XYZ aVProj = dir.XYZ().CrossCrossed(aVec.XYZ(), dir.XYZ());

  if (aVProj.SquareModulus() < gp::Resolution())
    return 0.0;

  // Angle between X direction and projected vector
  double Teta = (Pos.XDirection()).AngleWithRef(aVProj, dir);

  normalizeAngle(Teta);
  return Teta;
}

//=================================================================================================

double ElCLib::EllipseParameter(const gp_Ax2& Pos,
                                const double  MajorRadius,
                                const double  MinorRadius,
                                const gp_Pnt& P)
{
  const gp_XYZ& OP    = P.XYZ() - Pos.Location().XYZ();
  const gp_XYZ& xaxis = Pos.XDirection().XYZ();
  gp_XYZ        yaxis = Pos.YDirection().XYZ();
  const double  NY    = OP.Dot(yaxis);
  const double  NX    = OP.Dot(xaxis);

  if ((std::abs(NX) <= gp::Resolution()) && (std::abs(NY) <= gp::Resolution()))
    //-- The point P is on the Axis of the Ellipse.
    return (0.0);

  yaxis.Multiply(NY * (MajorRadius / MinorRadius));
  gp_XYZ Om = xaxis.Multiplied(NX);
  Om.Add(yaxis);
  double Teta = gp_Vec(xaxis).AngleWithRef(gp_Vec(Om), gp_Vec(Pos.Direction()));
  normalizeAngle(Teta);
  return Teta;
}

//=================================================================================================

double ElCLib::HyperbolaParameter(const gp_Ax2& Pos,
                                  const double,
                                  const double  MinorRadius,
                                  const gp_Pnt& P)
{
  const double sht = gp_Vec(Pos.Location(), P).Dot(gp_Vec(Pos.YDirection())) / MinorRadius;

#if defined(__QNX__)
  return std::asinh(sht);
#else
  return asinh(sht);
#endif
}

//=================================================================================================

double ElCLib::ParabolaParameter(const gp_Ax2& Pos, const gp_Pnt& P)
{
  return gp_Vec(Pos.Location(), P).Dot(gp_Vec(Pos.YDirection()));
}

//=================================================================================================

double ElCLib::LineParameter(const gp_Ax2d& L, const gp_Pnt2d& P)
{
  gp_XY Coord = P.XY();
  Coord.Subtract(L.Location().XY());
  return Coord.Dot(L.Direction().XY());
}

//=================================================================================================

double ElCLib::CircleParameter(const gp_Ax22d& Pos, const gp_Pnt2d& P)
{
  double Teta = (Pos.XDirection()).Angle(gp_Vec2d(Pos.Location(), P));
  Teta        = ((Pos.XDirection() ^ Pos.YDirection()) >= 0.0) ? Teta : -Teta;
  normalizeAngle(Teta);
  return Teta;
}

//=================================================================================================

double ElCLib::EllipseParameter(const gp_Ax22d& Pos,
                                const double    MajorRadius,
                                const double    MinorRadius,
                                const gp_Pnt2d& P)
{
  gp_XY OP = P.XY();
  OP.Subtract(Pos.Location().XY());
  const gp_XY& xaxis = Pos.XDirection().XY();
  gp_XY        yaxis = Pos.YDirection().XY();
  gp_XY        Om    = xaxis.Multiplied(OP.Dot(xaxis));
  yaxis.Multiply((OP.Dot(yaxis)) * (MajorRadius / MinorRadius));
  Om.Add(yaxis);
  double Teta = gp_Vec2d(xaxis).Angle(gp_Vec2d(Om));
  Teta        = ((Pos.XDirection() ^ Pos.YDirection()) >= 0.0) ? Teta : -Teta;
  normalizeAngle(Teta);
  return Teta;
}

//=================================================================================================

double ElCLib::HyperbolaParameter(const gp_Ax22d& Pos,
                                  const double,
                                  const double    MinorRadius,
                                  const gp_Pnt2d& P)
{
  const gp_Vec2d& V(Pos.YDirection().XY());
  const double    sht = gp_Vec2d(Pos.Location(), P).Dot(V) / MinorRadius;
#if defined(__QNX__)
  return std::asinh(sht);
#else
  return asinh(sht);
#endif
}

//=================================================================================================

double ElCLib::ParabolaParameter(const gp_Ax22d& Pos, const gp_Pnt2d& P)
{
  const gp_Vec2d Directrix(Pos.YDirection().XY());
  return gp_Vec2d(Pos.Location(), P).Dot(Directrix);
}

//=================================================================================================

gp_Pnt ElCLib::To3d(const gp_Ax2& Pos, const gp_Pnt2d& P)
{
  gp_XYZ Vxy = Pos.XDirection().XYZ();
  Vxy.SetLinearForm(P.X(), Vxy, P.Y(), Pos.YDirection().XYZ(), Pos.Location().XYZ());
  return gp_Pnt(Vxy);
}

//=================================================================================================

gp_Dir ElCLib::To3d(const gp_Ax2& Pos, const gp_Dir2d& V)
{
  gp_Vec Vx = Pos.XDirection();
  gp_Vec Vy = Pos.YDirection();
  Vx.Multiply(V.X());
  Vy.Multiply(V.Y());
  Vx.Add(Vy);
  return gp_Dir(Vx);
}

//=================================================================================================

gp_Vec ElCLib::To3d(const gp_Ax2& Pos, const gp_Vec2d& V)
{
  gp_Vec Vx = Pos.XDirection();
  gp_Vec Vy = Pos.YDirection();
  Vx.Multiply(V.X());
  Vy.Multiply(V.Y());
  Vx.Add(Vy);
  return Vx;
}

//=================================================================================================

gp_Ax1 ElCLib::To3d(const gp_Ax2& Pos, const gp_Ax2d& A)
{
  const gp_Pnt P = ElCLib::To3d(Pos, A.Location());
  const gp_Vec V = ElCLib::To3d(Pos, A.Direction());
  return gp_Ax1(P, V);
}

//=================================================================================================

gp_Ax2 ElCLib::To3d(const gp_Ax2& Pos, const gp_Ax22d& A)
{
  const gp_Pnt P  = ElCLib::To3d(Pos, A.Location());
  const gp_Vec VX = ElCLib::To3d(Pos, A.XDirection());
  const gp_Vec VY = ElCLib::To3d(Pos, A.YDirection());
  return gp_Ax2(P, VX.Crossed(VY), VX);
}

//=================================================================================================

gp_Lin ElCLib::To3d(const gp_Ax2& Pos, const gp_Lin2d& L)
{
  return gp_Lin(ElCLib::To3d(Pos, L.Position()));
}

//=================================================================================================

gp_Circ ElCLib::To3d(const gp_Ax2& Pos, const gp_Circ2d& C)
{
  return gp_Circ(ElCLib::To3d(Pos, C.Axis()), C.Radius());
}

//=================================================================================================

gp_Elips ElCLib::To3d(const gp_Ax2& Pos, const gp_Elips2d& E)
{
  return gp_Elips(ElCLib::To3d(Pos, E.Axis()), E.MajorRadius(), E.MinorRadius());
}

//=================================================================================================

gp_Hypr ElCLib::To3d(const gp_Ax2& Pos, const gp_Hypr2d& H)
{
  return gp_Hypr(ElCLib::To3d(Pos, H.Axis()), H.MajorRadius(), H.MinorRadius());
}

//=================================================================================================

gp_Parab ElCLib::To3d(const gp_Ax2& Pos, const gp_Parab2d& Prb)
{
  return gp_Parab(ElCLib::To3d(Pos, Prb.Axis()), Prb.Focal());
}
