// Created on: 1992-04-06
// Created by: Jacques GOUSSARD
// Copyright (c) 1992-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#include <gp_Circ.hxx>
#include <IntPatch_GLine.hxx>
#include <IntPatch_Point.hxx>
#include <Standard_Type.hxx>

IMPLEMENT_STANDARD_RTTIEXT(IntPatch_GLine, IntPatch_Line)

#define DEBUG 0

//  modified by Edward AGAPOV (eap) Wed Mar 6 2002 (bug occ212)
//  -- case: points with equal params == PI/2

//-- Precision::PConfusion()*1000.0  -> 1e-6
// #define PrecisionPConfusion ( Precision::PConfusion()*1000.0 )

#include <gp_Pln.hxx>

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a Line as intersection line
//           when the transitions are In or Out.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Lin&           L,
                               const bool              Tang,
                               const IntSurf_TypeTrans Trans1,
                               const IntSurf_TypeTrans Trans2)
    : IntPatch_Line(Tang, Trans1, Trans2),
      par1(0.0),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Lin;
  pos = gp_Pln(L.Location(), L.Direction()).Position().Ax2();
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a Line as intersection line
//           when the transitions are Touch.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Lin&           L,
                               const bool              Tang,
                               const IntSurf_Situation Situ1,
                               const IntSurf_Situation Situ2)
    : IntPatch_Line(Tang, Situ1, Situ2),
      par1(0.0),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Lin;
  pos = gp_Pln(L.Location(), L.Direction()).Position().Ax2();
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a Line as intersection line
//           when the transitions are Undecided.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Lin& L, const bool Tang)
    : IntPatch_Line(Tang),
      par1(0.0),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Lin;
  pos = gp_Pln(L.Location(), L.Direction()).Position().Ax2();
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a circle as intersection line
//           when the transitions are In or Out.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Circ&          C,
                               const bool              Tang,
                               const IntSurf_TypeTrans Trans1,
                               const IntSurf_TypeTrans Trans2)
    : IntPatch_Line(Tang, Trans1, Trans2),
      pos(C.Position()),
      par1(C.Radius()),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Circle;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a circle as intersection line
//           when the transitions are Touch.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Circ&          C,
                               const bool              Tang,
                               const IntSurf_Situation Situ1,
                               const IntSurf_Situation Situ2)
    : IntPatch_Line(Tang, Situ1, Situ2),
      pos(C.Position()),
      par1(C.Radius()),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Circle;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a circle as intersection line
//           when the transitions are Undecided.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Circ& C, const bool Tang)
    : IntPatch_Line(Tang),
      pos(C.Position()),
      par1(C.Radius()),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Circle;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates an ellipse as intersection line
//           when the transitions are In or Out.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Elips&         E,
                               const bool              Tang,
                               const IntSurf_TypeTrans Trans1,
                               const IntSurf_TypeTrans Trans2)
    : IntPatch_Line(Tang, Trans1, Trans2),
      pos(E.Position()),
      par1(E.MajorRadius()),
      par2(E.MinorRadius()),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Ellipse;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates an ellispe as intersection line
//           when the transitions are Touch.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Elips&         E,
                               const bool              Tang,
                               const IntSurf_Situation Situ1,
                               const IntSurf_Situation Situ2)
    : IntPatch_Line(Tang, Situ1, Situ2),
      pos(E.Position()),
      par1(E.MajorRadius()),
      par2(E.MinorRadius()),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Ellipse;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates an ellipse as intersection line
//           when the transitions are Undecided.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Elips& E, const bool Tang)
    : IntPatch_Line(Tang),
      pos(E.Position()),
      par1(E.MajorRadius()),
      par2(E.MinorRadius()),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Ellipse;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a parabola as intersection line
//           when the transitions are In or Out.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Parab&         P,
                               const bool              Tang,
                               const IntSurf_TypeTrans Trans1,
                               const IntSurf_TypeTrans Trans2)
    : IntPatch_Line(Tang, Trans1, Trans2),
      pos(P.Position()),
      par1(P.Focal()),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Parabola;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a parabola as intersection line
//           when the transitions are Touch.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Parab&         P,
                               const bool              Tang,
                               const IntSurf_Situation Situ1,
                               const IntSurf_Situation Situ2)
    : IntPatch_Line(Tang, Situ1, Situ2),
      pos(P.Position()),
      par1(P.Focal()),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Parabola;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates a parabola as intersection line
//           when the transitions are Undecided.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Parab& P, const bool Tang)
    : IntPatch_Line(Tang),
      pos(P.Position()),
      par1(P.Focal()),
      par2(0.0),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Parabola;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates an hyperbola as intersection line
//           when the transitions are In or Out.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Hypr&          H,
                               const bool              Tang,
                               const IntSurf_TypeTrans Trans1,
                               const IntSurf_TypeTrans Trans2)
    : IntPatch_Line(Tang, Trans1, Trans2),
      pos(H.Position()),
      par1(H.MajorRadius()),
      par2(H.MinorRadius()),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Hyperbola;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates an hyperbola as intersection line
//           when the transitions are Touch.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Hypr&          H,
                               const bool              Tang,
                               const IntSurf_Situation Situ1,
                               const IntSurf_Situation Situ2)
    : IntPatch_Line(Tang, Situ1, Situ2),
      pos(H.Position()),
      par1(H.MajorRadius()),
      par2(H.MinorRadius()),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Hyperbola;
}

//=======================================================================
// function : IntPatch_GLine
// purpose  : Creates an hyperbola as  intersection line
//           when the transitions are Undecided.
//=======================================================================

IntPatch_GLine::IntPatch_GLine(const gp_Hypr& H, const bool Tang)
    : IntPatch_Line(Tang),
      pos(H.Position()),
      par1(H.MajorRadius()),
      par2(H.MinorRadius()),
      fipt(false),
      lapt(false),
      indf(0),
      indl(0)
{
  typ = IntPatch_Hyperbola;
}

//=======================================================================
// function : Replace
// purpose  : To replace the element of range Index in the list
//           of points.
//=======================================================================

void IntPatch_GLine::Replace(const int /*Index*/, const IntPatch_Point& Pnt)
{
  svtx.Append(Pnt);
  //--   svtx(Index) = Pnt;
}

//=======================================================================
// function : AddVertex
// purpose  : To add a vertex in the list.
//=======================================================================

void IntPatch_GLine::AddVertex(const IntPatch_Point& Pnt)
{
  //-- On detecte le cas de 2 points 3d identiques
  //-- pour les ramener au meme parametre sur la
  //-- GLine
  if (NbVertex())
  {
    const double pf  = (fipt ? svtx.Value(indf).ParameterOnLine() : 0.0);
    const double pl  = (lapt ? svtx.Value(indl).ParameterOnLine() : 0.0);
    double       par = Pnt.ParameterOnLine();
    if (ArcType() == IntPatch_Circle || ArcType() == IntPatch_Ellipse)
    {
      if (fipt && lapt)
      {
        while (par < pf)
          par += M_PI + M_PI;
        while (par > pl)
          par -= M_PI + M_PI;
        if (par < pf)
        {
          constexpr double PrecisionPConfusion(Precision::PConfusion() * 1000.0);
          if ((pf - par) > PrecisionPConfusion)
          {
            return;
          }
        }
        IntPatch_Point ParModif = Pnt;
        ParModif.SetParameter(par);
        svtx.Append(ParModif);
        return;
      }
    }
    else
    {
      if (fipt && lapt)
      {
        if (pl < par || par < pf)
          return;
      }
    }
  }
  svtx.Append(Pnt);
}

//=======================================================================
// function : ComputeVertexParameters
// purpose  : Set the parameters of all the vertex on the line.
//           if a vertex is already in the line,
//           its parameter is modified
//           else a new point in the line is inserted.
//=======================================================================

void IntPatch_GLine::ComputeVertexParameters(const double /*Tol*/)
{
  bool         SortIsOK, APointDeleted;
  bool         SortAgain = true;
  int          i, j;
  const double ParamMinOnLine = (fipt ? Vertex(indf).ParameterOnLine() : -100000.0);
  const double ParamMaxOnLine = (lapt ? Vertex(indl).ParameterOnLine() : 100000.0);

  //----------------------------------------------------------
  //--     F i l t r e   s u r   r e s t r i c t i o n s   --
  //----------------------------------------------------------
  //-- deux vertex sur la meme restriction et seulement
  //-- sur celle ci ne doivent pas avoir le meme parametre
  //==========================================================
  //-- 2 vertices on the same restriction and only
  //-- on that one must not have the same parametres

  int nbvtx = NbVertex();

  constexpr double PrecisionPConfusion(Precision::PConfusion() * 1000.0);

  do
  {
    APointDeleted = false;
    for (i = 1; (i <= nbvtx) && (!APointDeleted); i++)
    {
      const IntPatch_Point& VTXi = svtx.Value(i);
      if (VTXi.IsOnDomS1() || VTXi.IsOnDomS2())
      {
        for (j = 1; (j <= nbvtx) && (!APointDeleted); j++)
        {
          if (i != j)
          {
            const IntPatch_Point& VTXj = svtx.Value(j);
            if ((!VTXj.IsOnDomS1()) && (!VTXj.IsOnDomS2()))
            {
              if (std::abs(VTXi.ParameterOnLine() - VTXj.ParameterOnLine()) <= PrecisionPConfusion)
              {
                svtx.Remove(j);
                nbvtx--;
                if (lapt)
                {
                  if (indl > j)
                    indl--;
                }
                if (fipt)
                {
                  if (indf > j)
                    indf--;
                }
                APointDeleted = true;
              }
            }
          }
        }
      }
    }
  } while (APointDeleted && nbvtx > 2);

  do
  {
    APointDeleted = false;
    for (i = 1; (i <= nbvtx) && (!APointDeleted); i++)
    {
      const IntPatch_Point& VTXi = svtx.Value(i);
      if (VTXi.IsOnDomS1() && (!VTXi.IsOnDomS2()))
      {
        for (j = 1; (j <= nbvtx) && (!APointDeleted); j++)
        {
          if (i != j)
          {
            const IntPatch_Point& VTXj = svtx.Value(j);
            if (VTXj.IsOnDomS1() && (!VTXj.IsOnDomS2()))
            {
              if (std::abs(VTXi.ParameterOnArc1() - VTXj.ParameterOnArc1()) <= PrecisionPConfusion)
              {
                if (VTXi.ArcOnS1() == VTXj.ArcOnS1())
                {
                  if (VTXi.IsVertexOnS1())
                  {
                    svtx.Remove(j);
                    nbvtx--;
                    if (lapt)
                    {
                      if (indl > j)
                        indl--;
                    }
                    if (fipt)
                    {
                      if (indf > j)
                        indf--;
                    }
                  }
                  else
                  {
                    svtx.Remove(i);
                    nbvtx--;
                    if (lapt)
                    {
                      if (indl > i)
                        indl--;
                    }
                    if (fipt)
                    {
                      if (indf > i)
                        indf--;
                    }
                  }
                  APointDeleted = true;
                }
              }
            }
          }
        }
      }
    }
  } while (APointDeleted);

  do
  {
    APointDeleted = false;
    for (i = 1; (i <= nbvtx) && (!APointDeleted); i++)
    {
      const IntPatch_Point& VTXi = svtx.Value(i);
      if (VTXi.IsOnDomS2() && (!VTXi.IsOnDomS1()))
      {
        for (j = 1; (j <= nbvtx) && (!APointDeleted); j++)
        {
          if (i != j)
          {
            const IntPatch_Point& VTXj = svtx.Value(j);
            if (VTXj.IsOnDomS2() && (!VTXj.IsOnDomS1()))
            {
              if (std::abs(VTXi.ParameterOnArc2() - VTXj.ParameterOnArc2()) <= PrecisionPConfusion)
              {
                if (VTXi.ArcOnS2() == VTXj.ArcOnS2())
                {
                  if (VTXi.IsVertexOnS1())
                  {
                    svtx.Remove(j);
                    nbvtx--;
                    if (lapt)
                    {
                      if (indl > j)
                        indl--;
                    }
                    if (fipt)
                    {
                      if (indf > j)
                        indf--;
                    }
                  }
                  else
                  {
                    svtx.Remove(i);
                    nbvtx--;
                    if (lapt)
                    {
                      if (indl > i)
                        indl--;
                    }
                    if (fipt)
                    {
                      if (indf > i)
                        indf--;
                    }
                  }
                  APointDeleted = true;
                }
              }
            }
          }
        }
      }
    }
  } while (APointDeleted);

  //----------------------------------------------------------
  //-- Tri des vertex et suppression des Vtx superflus
  //--
  //// modified by jgv, 2.11.01 for BUC61033 ////
  double u1min = RealLast(), u1max = RealFirst();
  double u2min = RealLast(), u2max = RealFirst();
  bool   ToBreak = false;
  ///////////////////////////////////////////////
  do
  {
    nbvtx = NbVertex();
    if (SortAgain)
    {
      do
      {
        SortIsOK = true;
        for (i = 2; i <= nbvtx; i++)
        {
          if (svtx.Value(i - 1).ParameterOnLine() > svtx.Value(i).ParameterOnLine())
          {
            SortIsOK = false;
            svtx.Exchange(i - 1, i);
            if (fipt)
            {
              if (indf == i)
                indf = i - 1;
              else if (indf == i - 1)
                indf = i;
            }
            if (lapt)
            {
              if (indl == i)
                indl = i - 1;
              else if (indl == i - 1)
                indl = i;
            }
          }
        }
      } while (!SortIsOK);
    }

    //// modified by jgv, 2.11.01 for BUC61033 ////
    if (ToBreak)
      break;
    ///////////////////////////////////////////////

    SortAgain = false;
    SortIsOK  = true;
    for (i = 2; i <= nbvtx && SortIsOK; i++)
    {
      IntPatch_Point& VTX = svtx.ChangeValue(i);
      for (j = 1; j <= nbvtx && SortIsOK; j++)
      {
        if (i != j)
        {
          IntPatch_Point& VTXM1  = svtx.ChangeValue(j);
          bool            kill   = false;
          bool            killm1 = false;
          if (std::abs(VTXM1.ParameterOnLine() - VTX.ParameterOnLine()) < PrecisionPConfusion)
          {
            if (VTXM1.IsOnDomS1() && VTX.IsOnDomS1()) //-- OnS1    OnS1
            {
              if (VTXM1.ArcOnS1() == VTX.ArcOnS1()) //-- OnS1 == OnS1
              {
                if (VTXM1.IsOnDomS2()) //-- OnS1 == OnS1  OnS2
                {
                  if (VTX.IsOnDomS2() == false) //-- OnS1 == OnS1  OnS2 PasOnS2
                  {
                    kill = true;
                  }
                  else
                  {
                    if (VTXM1.ArcOnS2() == VTX.ArcOnS2()) //-- OnS1 == OnS1  OnS2 == OnS2
                    {
                      if (VTXM1.IsVertexOnS2())
                      {
                        kill = true;
                      }
                      else
                      {
                        killm1 = true;
                      }
                    }
                  }
                }
                else //-- OnS1 == OnS1  PasOnS2
                {
                  if (VTX.IsOnDomS2()) //-- OnS1 == OnS1  PasOnS2  OnS2
                  {
                    killm1 = true;
                  }
                }
              }
            }
            else //-- Pas OnS1  et  OnS1
            {
              if (VTXM1.IsOnDomS2() == false && VTX.IsOnDomS2() == false)
              {
                if (VTXM1.IsOnDomS1() && VTX.IsOnDomS1() == false)
                {
                  kill = true;
                }
                else if (VTX.IsOnDomS1() && VTXM1.IsOnDomS1() == false)
                {
                  killm1 = true;
                }
              }
            }

            if (!(kill || killm1))
            {
              if (VTXM1.IsOnDomS2() && VTX.IsOnDomS2()) //-- OnS2    OnS2
              {
                if (VTXM1.ArcOnS2() == VTX.ArcOnS2()) //-- OnS2 == OnS2
                {
                  if (VTXM1.IsOnDomS1()) //-- OnS2 == OnS2  OnS1
                  {
                    if (VTX.IsOnDomS1() == false) //-- OnS2 == OnS2  OnS1 PasOnS1
                    {
                      kill = true;
                    }
                    else
                    {
                      if (VTXM1.ArcOnS1() == VTX.ArcOnS1()) //-- OnS2 == OnS2  OnS1 == OnS1
                      {
                        if (VTXM1.IsVertexOnS1())
                        {
                          // clang-format off
                          kill=true;              //-- OnS2 == OnS2  OnS1 == OnS1  Vtx PasVtx
                        }
                        else
                        {
                          killm1=true;            //-- OnS2 == OnS2  OnS1 == OnS1  PasVtx Vtx
                          // clang-format on
                        }
                      }
                    }
                  }
                  else
                  {                      //-- OnS2 == OnS2  PasOnS1
                    if (VTX.IsOnDomS1()) //-- OnS2 == OnS2  PasOnS1  OnS1
                    {
                      killm1 = true;
                    }
                  }
                }
              }
              else //-- Pas OnS2  et  OnS2
              {
                if (VTXM1.IsOnDomS1() == false && VTX.IsOnDomS1() == false)
                {
                  if (VTXM1.IsOnDomS2() && VTX.IsOnDomS2() == false)
                  {
                    kill = true;
                  }
                  else if (VTX.IsOnDomS2() && VTXM1.IsOnDomS2() == false)
                  {
                    killm1 = true;
                  }
                }
              }
            }

            //-- On a j < i
            if (kill)
            {
              SortIsOK = false;
              if (lapt)
              {
                if (indl > i)
                  indl--;
                else if (indl == i)
                  indl = j;
              }

              if (fipt)
              {
                if (indf > i)
                  indf--;
                else if (indf == i)
                  indf = j;
              }

              svtx.Remove(i);
              nbvtx--;
            }
            else if (killm1)
            {
              SortIsOK = false;
              if (lapt)
              {
                if (indl > j)
                  indl--;
                else if (indl == j)
                  indl = i - 1;
              }

              if (fipt)
              {
                if (indf > j)
                  indf--;
                else if (indf == j)
                  indf = i - 1;
              }

              svtx.Remove(j);
              nbvtx--;
            } //	    else
            else if (ArcType() == IntPatch_Circle || ArcType() == IntPatch_Ellipse) // eap
            {
              //-- deux points de meme parametre qui ne peuvent etre confondus
              //-- On change les parametres d un des points si les points UV sont
              //-- differents. Ceci distingue le cas des aretes de couture.
              // ==========================================================
              //-- 2 points with the same parameters
              //-- Change parametres of one point if points UV are
              //-- different. This is the case of seam edge

              double ponline = VTX.ParameterOnLine();
              // eap, =>>
              double       newParam = ponline;
              const double PiPi     = M_PI + M_PI;
              bool         is2PI    = (std::abs(ponline - PiPi) <= PrecisionPConfusion);

              if (nbvtx > 2 && // do this check if seam edge only gives vertices
                  !is2PI)      // but always change 2PI -> 0
                continue;

              if (is2PI)
                newParam = 0;
              else if (std::abs(ponline) <= PrecisionPConfusion)
                newParam = PiPi;
              else
                newParam -= PiPi;

              // 	      if(  (std::abs(ponline)<=PrecisionPConfusion)
              // 		   ||(std::abs(ponline-M_PI-M_PI) <=PrecisionPConfusion))
              // eap, <<=

              double u1a, v1a, u2a, v2a, u1b, v1b, u2b, v2b;
              VTXM1.Parameters(u1a, v1a, u2a, v2a);
              VTX.Parameters(u1b, v1b, u2b, v2b);
              int flag = 0;

              if ((std::abs(u1a - u1b) <= PrecisionPConfusion))
                flag |= 1;

              if ((std::abs(v1a - v1b) <= PrecisionPConfusion))
                flag |= 2;
              if ((std::abs(u2a - u2b) <= PrecisionPConfusion))
                flag |= 4;

              if ((std::abs(v2a - v2b) <= PrecisionPConfusion))
                flag |= 8;

              bool TestOn1 = false;
              bool TestOn2 = false;

              switch (flag)
              {
                case 3:  //-- meme point U1 V1
                case 7:  //-- meme point U1 V1   meme U2
                case 12: //--                    meme U2 V2
                case 13: //-- meme point U1      meme U2 V2
                case 10: //-- meme point    V1   meme    V2   Test si U1a=U1b Mod 2PI et Test si
                         // U2a=U2b Mod 2PI
                  break;
                case 11: //-- meme point U1 V1   meme    V2   Test si U2a=U2b Mod 2PI
                {
                  TestOn2 = true;
                  break;
                }

                case 14: //-- meme point    V1   meme U2 V2   Test si U1a=U1b Mod 2PI
                {
                  TestOn1 = true;
                  break;
                }
                default:
                  break;
              };

              // eap
              // if(ArcType()==IntPatch_Circle || ArcType()==IntPatch_Ellipse) {}
              if (TestOn1)
              {
                //// modified by jgv, 2.11.01 for BUC61033 ////
                double U1A = (u1a < u1b) ? u1a : u1b;
                double U1B = (u1a < u1b) ? u1b : u1a;

                if (u1min == RealLast())
                {
                  u1min = U1A;
                  u1max = U1B;
                }
                else
                {
                  if (std::abs(U1A - u1min) > PrecisionPConfusion)
                    ToBreak = true;
                  if (std::abs(U1B - u1max) > PrecisionPConfusion)
                    ToBreak = true;
                }
                ///////////////////////////////////////////////
                // eap, =>>
                // 		      if (std::abs(ponline) <= PrecisionPConfusion) {
                // 		      const double PiPi = M_PI+M_PI;
                if (newParam >= ParamMinOnLine && newParam <= ParamMaxOnLine
                    /*PiPi >= ParamMinOnLine && PiPi<=ParamMaxOnLine*/)
                {
                  SortAgain = true;
                  SortIsOK  = false;
                  if (newParam > ponline)
                  {
                    if (u1a < u1b)
                    {
                      VTX.SetParameter(newParam);
                    }
                    else
                    {
                      VTXM1.SetParameter(newParam);
                    }
                  }
                  else
                  {
                    if (u1a > u1b)
                    {
                      VTX.SetParameter(newParam);
                    }
                    else
                    {
                      VTXM1.SetParameter(newParam);
                    }
                  }
                }
                // 		    }
                // 		    else {
                // 		      if(0.0 >= ParamMinOnLine && 0.0<=ParamMaxOnLine) {
                // 			SortAgain = true;
                // 			SortIsOK = false;
                // 			if(u1a > u1b) { VTX.SetParameter(0.0); }
                // 			else          { VTXM1.SetParameter(0.0); }
                // 		      }
                // 		    }
                // eap, <<=
              }

              if (TestOn2)
              {
                //// modified by jgv, 2.11.01 for BUC61033 ////
                double U2A = (u2a < u2b) ? u2a : u2b;
                double U2B = (u2a < u2b) ? u2b : u2a;
                if (u2min == RealLast())
                {
                  u2min = U2A;
                  u2max = U2B;
                }
                else
                {
                  if (std::abs(U2A - u2min) > PrecisionPConfusion)
                    ToBreak = true;

                  if (std::abs(U2B - u2max) > PrecisionPConfusion)
                    ToBreak = true;
                }
                ///////////////////////////////////////////////
                // eap, =>>
                // 		    if (std::abs(ponline) <= PrecisionPConfusion) {
                // 		      const double PiPi = M_PI+M_PI;
                if (newParam >= ParamMinOnLine && newParam <= ParamMaxOnLine
                    /*PiPi >= ParamMinOnLine && PiPi<=ParamMaxOnLine*/)
                {
                  SortAgain = true;
                  SortIsOK  = false;
                  if (newParam > ponline)
                  {
                    if (u2a < u2b)
                    {
                      VTX.SetParameter(newParam);
                    }
                    else
                    {
                      VTXM1.SetParameter(newParam);
                    }
                  }
                  else
                  {
                    if (u2a > u2b)
                    {
                      VTX.SetParameter(newParam);
                    }
                    else
                    {
                      VTXM1.SetParameter(newParam);
                    }
                  }
                }
                // 		    }
                // 		    else {
                // 		      if(0.0 >= ParamMinOnLine && 0.0<=ParamMaxOnLine) {
                // 			SortAgain = true;
                // 			SortIsOK = false;
                // 			if(u2a > u2b) { VTX.SetParameter(0.0); }
                // 			else          { VTXM1.SetParameter(0.0); }
                // 		      }
                // 		    }
                // 		  }
                // 		}
                // eap, <<=
              }
            }
          }
        }
      } //-- if(i!=j)
    }
  } while (!SortIsOK);

  //-- Recalcul de fipt et lapt
  //--
  nbvtx = NbVertex();
  if (nbvtx)
  {
    do
    {
      SortIsOK = true;
      for (i = 2; i <= nbvtx; i++)
      {
        if (svtx.Value(i - 1).ParameterOnLine() > svtx.Value(i).ParameterOnLine())
        {
          SortIsOK = false;
          svtx.Exchange(i - 1, i);
        }
      }
    } while (!SortIsOK);

    indl = nbvtx;
    indf = 1;
  }
}
