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

#include <IntPatch_WLine.hxx>
#include <IntSurf_LineOn2S.hxx>
#include <IntSurf_PntOn2S.hxx>
#include <Standard_Type.hxx>

IMPLEMENT_STANDARD_RTTIEXT(IntPatch_WLine, IntPatch_PointLine)

#define DEBUG 0
#define DEBUGV 0

#include <Precision.hxx>
#include <stdio.h>

IntPatch_WLine::IntPatch_WLine(const Handle(IntSurf_LineOn2S)& Line,
                               const Standard_Boolean          Tang,
                               const IntSurf_TypeTrans         Trans1,
                               const IntSurf_TypeTrans         Trans2)
    : IntPatch_PointLine(Tang, Trans1, Trans2),
      fipt(Standard_False),
      lapt(Standard_False),
      hasArcOnS1(Standard_False),
      hasArcOnS2(Standard_False),
      myIsPurgerAllowed(Standard_True),
      myCreationWay(IntPatch_WLUnknown)
{
  typ      = IntPatch_Walking;
  curv     = Line;
  u1period = v1period = u2period = v2period = 0.0;
}

IntPatch_WLine::IntPatch_WLine(const Handle(IntSurf_LineOn2S)& Line,
                               const Standard_Boolean          Tang,
                               const IntSurf_Situation         Situ1,
                               const IntSurf_Situation         Situ2)
    : IntPatch_PointLine(Tang, Situ1, Situ2),
      fipt(Standard_False),
      lapt(Standard_False),
      hasArcOnS1(Standard_False),
      hasArcOnS2(Standard_False),
      myIsPurgerAllowed(Standard_True),
      myCreationWay(IntPatch_WLUnknown)
{
  typ      = IntPatch_Walking;
  curv     = Line;
  u1period = v1period = u2period = v2period = 0.0;
}

IntPatch_WLine::IntPatch_WLine(const Handle(IntSurf_LineOn2S)& Line, const Standard_Boolean Tang)
    : IntPatch_PointLine(Tang),
      fipt(Standard_False),
      lapt(Standard_False),
      hasArcOnS1(Standard_False),
      hasArcOnS2(Standard_False),
      myIsPurgerAllowed(Standard_True),
      myCreationWay(IntPatch_WLUnknown)
{
  typ      = IntPatch_Walking;
  curv     = Line;
  u1period = v1period = u2period = v2period = 0.0;
}

void IntPatch_WLine::SetPoint(const Standard_Integer Index, const IntPatch_Point& thepoint)
{
  curv->Value(Index, thepoint.PntOn2S());
}

Handle(IntSurf_LineOn2S) IntPatch_WLine::Curve() const
{
  return (curv);
}

static void RecadreMemePeriode(Standard_Real&      u1,
                               Standard_Real&      v1,
                               Standard_Real&      u2,
                               Standard_Real&      v2,
                               const Standard_Real anu1,
                               const Standard_Real anv1,
                               const Standard_Real anu2,
                               const Standard_Real anv2,
                               const Standard_Real U1Period,
                               const Standard_Real V1Period,
                               const Standard_Real U2Period,
                               const Standard_Real V2Period)
{
  if (U1Period)
  {
    while (anu1 - u1 > 0.8 * U1Period)
    {
      u1 += U1Period;
    }
    while (u1 - anu1 > 0.8 * U1Period)
    {
      u1 -= U1Period;
    }
  }
  if (U2Period)
  {
    while (anu2 - u2 > 0.8 * U2Period)
    {
      u2 += U2Period;
    }
    while (u2 - anu2 > 0.8 * U2Period)
    {
      u2 -= U2Period;
    }
  }
  if (V1Period)
  {
    while (anv1 - v1 > 0.8 * V1Period)
    {
      v1 += V1Period;
    }
    while (v1 - anv1 > 0.8 * V1Period)
    {
      v1 -= V1Period;
    }
  }
  if (V2Period)
  {
    while (anv2 - v2 > 0.8 * V2Period)
    {
      v2 += V2Period;
    }
    while (v2 - anv2 > 0.8 * V2Period)
    {
      v2 -= V2Period;
    }
  }
}

static void RecadreMemePeriode(IntSurf_PntOn2S&       POn2S,
                               const IntSurf_PntOn2S& RefPOn2S,
                               const Standard_Real    up1,
                               const Standard_Real    vp1,
                               const Standard_Real    up2,
                               const Standard_Real    vp2)
{
  Standard_Real u1, v1, u2, v2, pu1, pv1, pu2, pv2;
  POn2S.Parameters(u1, v1, u2, v2);
  RefPOn2S.Parameters(pu1, pv1, pu2, pv2);
  RecadreMemePeriode(u1, v1, u2, v2, pu1, pv1, pu2, pv2, up1, vp1, up2, vp2);
  POn2S.SetValue(u1, v1, u2, v2);
}

static Standard_Boolean CompareVertexAndPoint(const gp_Pnt&        V,
                                              const gp_Pnt&        P,
                                              const Standard_Real& Tol)
{
  const Standard_Real aSQDist = V.SquareDistance(P);
  const Standard_Real aSQTol  = Tol * Tol;
  return (aSQDist <= aSQTol);
}

void IntPatch_WLine::SetPeriod(const Standard_Real pu1,
                               const Standard_Real pv1,
                               const Standard_Real pu2,
                               const Standard_Real pv2)
{
  u1period = pu1;
  v1period = pv1;
  u2period = pu2;
  v2period = pv2;
}

Standard_Real IntPatch_WLine::U1Period() const
{
  return (u1period);
}

Standard_Real IntPatch_WLine::V1Period() const
{
  return (v1period);
}

Standard_Real IntPatch_WLine::U2Period() const
{
  return (u2period);
}

Standard_Real IntPatch_WLine::V2Period() const
{
  return (v2period);
}

//------------------------------------------------------------------------
//--  En Entree : Une ligne de cheminement     +    Une Liste de Vetex
//--
//--   LineOn2S   :       1------2-------3-------4-----5---- ----nbp
//--
//--   Vertex     :   a     b c          d    e      f
//--
//--
//--  En Sortie
//--
//--                  1--2-3-4--5--------6----7--8--9--10--------
//--
//--  avec   a de parametre 1
//--         b              3
//--
//--   etc ...
//--
//--
//-- !!!!!!!!!!!!!!! On considere que deux vertex ne peuvent pas etre
//-- !!!!!!!!!!!!!!!  a une distance inferieure a Tol
//------------------------------------------------------------------------
//--
//-- On Teste si la LineOn2S contient des points confondus.
//-- Dans ce cas, on remove ces points.
//--
//------------------------------------------------------------------------

Standard_Boolean SameVtxRst(const IntPatch_Point& vtx1, const IntPatch_Point& vtx2)
{
  if (vtx1.IsOnDomS1())
  {
    if (vtx2.IsOnDomS1())
    {
      if (vtx1.ArcOnS1() == vtx2.ArcOnS1())
      {
        if (vtx1.ParameterOnArc1() == vtx2.ParameterOnArc1())
        {
        }
        else
        {
          return (Standard_False);
        }
      }
      else
      {
        return (Standard_False);
      }
    }
    else
    {
      return (Standard_False);
    }
  }
  else
  {
    if (vtx2.IsOnDomS1())
    {
      return (Standard_False);
    }
  }
  if (vtx1.IsOnDomS2())
  {
    if (vtx2.IsOnDomS2())
    {
      if (vtx1.ArcOnS2() == vtx2.ArcOnS2())
      {
        if (vtx1.ParameterOnArc2() == vtx2.ParameterOnArc2())
        {
        }
        else
        {
          return (Standard_False);
        }
      }
      else
      {
        return (Standard_False);
      }
    }
    else
    {
      return (Standard_False);
    }
  }
  else
  {
    if (vtx2.IsOnDomS2())
    {
      return (Standard_False);
    }
  }
  return (Standard_True);
}

static Standard_Boolean CompareVerticesOnSurf(const IntPatch_Point&  vtx1,
                                              const IntPatch_Point&  vtx2,
                                              const Standard_Boolean onFirst)
{
  Standard_Real u1, v1, u2, v2, tolU, tolV;
  if (onFirst)
  {
    vtx1.ParametersOnS1(u1, v1);
    vtx2.ParametersOnS1(u2, v2);
  }
  else
  {
    vtx1.ParametersOnS2(u1, v1);
    vtx2.ParametersOnS2(u2, v2);
  }
  tolU = Precision::PConfusion();
  tolV = Precision::PConfusion();
  return (Abs(u1 - u2) <= tolU && Abs(v1 - v2) <= tolV);
}

inline Standard_Boolean CompareVerticesOnS1(const IntPatch_Point& vtx1, const IntPatch_Point& vtx2)
{
  return CompareVerticesOnSurf(vtx1, vtx2, Standard_True);
}

inline Standard_Boolean CompareVerticesOnS2(const IntPatch_Point& vtx1, const IntPatch_Point& vtx2)
{
  return CompareVerticesOnSurf(vtx1, vtx2, Standard_False);
}

void IntPatch_WLine::ComputeVertexParameters(const Standard_Real RTol)
{
  // MSV Oct 15, 2001: use tolerance of vertex instead of RTol where
  //                   it is possible

  Standard_Integer i, j, k, nbvtx, nbponline;
  Standard_Integer indicevertexonline;
  Standard_Real    indicevertex;

  Standard_Boolean APointDeleted = Standard_False;
  //----------------------------------------------------------
  //--     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
  //--
  Standard_Real Tol = RTol;
  nbvtx             = NbVertex();

#if DEBUGV
  std::cout << "\n----------- avant ComputeVertexParameters -------------" << std::endl;
  for (i = 1; i <= nbvtx; i++)
  {
    Vertex(i).Dump();
    Standard_Real polr = Vertex(i).ParameterOnLine();
    Standard_Real pol  = (Standard_Integer)polr;
    if (pol >= 1 && pol <= nbvtx)
    {
      std::cout << "----> IntSurf_PntOn2S : " << polr << "  Pnt (" << Vertex(pol).Value().X() << ","
                << Vertex(pol).Value().Y() << "," << Vertex(pol).Value().Z() << ")" << std::endl;
    }
  }
  std::cout << "\n----------------------------------------------------------" << std::endl;
#endif

  //-- ----------------------------------------------------------------------
  //-- Traitement des aretes de couture : On duplique les points situes
  //-- sur des restrictions differentes
  //--
  //-- Phase Creation de nouveaux points sur S1
  Standard_Boolean encoreunefois;
  do
  {
    nbvtx         = NbVertex();
    encoreunefois = Standard_False;
    for (i = 1; i <= nbvtx && encoreunefois == Standard_False; i++)
    {
      IntPatch_Point& VTXi = svtx.ChangeValue(i);
      for (j = 1; j <= nbvtx && encoreunefois == Standard_False; j++)
      {
        if (i != j)
        {
          IntPatch_Point& VTXj = svtx.ChangeValue(j);
          if (VTXi.ParameterOnLine() != VTXj.ParameterOnLine())
          {
            Standard_Real d      = VTXi.Value().Distance(VTXj.Value());
            Standard_Real toli   = VTXi.Tolerance();
            Standard_Real tolj   = VTXj.Tolerance();
            Standard_Real maxtol = Max(toli, tolj);
            // MSV Oct 30, 2001: compare in 2D space also;
            //                   increase tolerances
            if (d < maxtol || CompareVerticesOnS1(VTXi, VTXj) || CompareVerticesOnS2(VTXi, VTXj))
            {
              //-- Creation Vtx (REF:S1(i)  S2(j))    (On Garde S1(i))
              Standard_Real    newtoli = Max(toli, tolj + d * 1.01);
              Standard_Real    newtolj = Max(tolj, toli + d * 1.01);
              Standard_Boolean acreer  = Standard_False;
              if (VTXi.IsOnDomS1())
              {
                if (VTXj.IsOnDomS1())
                {
                  if (VTXj.ArcOnS1() != VTXi.ArcOnS1())
                  {
                    acreer = Standard_True;
                  }
                }
                else
                {
                  acreer = Standard_True;
                }
              }
              if (acreer)
              {
                IntPatch_Point vtx;
                vtx = VTXj;
                vtx.SetArc(Standard_True,
                           VTXi.ArcOnS1(),
                           VTXi.ParameterOnArc1(),
                           VTXi.TransitionLineArc1(),
                           VTXi.TransitionOnS1());
                for (k = 1; encoreunefois == Standard_False && k <= nbvtx; k++)
                {
                  const IntPatch_Point& VTXk = svtx.Value(k);
                  if (SameVtxRst(VTXk, vtx))
                  {
                    encoreunefois = Standard_True;
                  }
                }
                if (encoreunefois == Standard_False)
                {
                  VTXi.SetTolerance(newtoli);
                  VTXj.SetTolerance(newtolj);
                  vtx.SetTolerance(newtolj);
                  svtx.Append(vtx);
                  encoreunefois = Standard_True;
                }
                else
                {
                  encoreunefois = Standard_False;
                }
              }
              //-- -----------------------------------------------------
              //-- Creation Vtx (REF:S2(i)  S1(j))    (On Garde S2(i))
              acreer = Standard_False;
              if (VTXi.IsOnDomS2())
              {
                if (VTXj.IsOnDomS2())
                {
                  if (VTXj.ArcOnS2() != VTXi.ArcOnS2())
                  {
                    acreer = Standard_True;
                  }
                }
                else
                {
                  acreer = Standard_True;
                }
              }
              if (acreer)
              {
                IntPatch_Point vtx;
                vtx = VTXj;
                vtx.SetArc(Standard_False,
                           VTXi.ArcOnS2(),
                           VTXi.ParameterOnArc2(),
                           VTXi.TransitionLineArc2(),
                           VTXi.TransitionOnS2());
                for (k = 1; encoreunefois == Standard_False && k <= nbvtx; k++)
                {
                  const IntPatch_Point& VTXk = svtx.Value(k);
                  if (SameVtxRst(VTXk, vtx))
                  {
                    encoreunefois = Standard_True;
                  }
                }
                if (encoreunefois == Standard_False)
                {
                  VTXi.SetTolerance(newtoli);
                  VTXj.SetTolerance(newtolj);
                  vtx.SetTolerance(newtolj);
                  svtx.Append(vtx);
                  encoreunefois = Standard_True;
                }
                else
                {
                  encoreunefois = Standard_False;
                }
              }
            }
          }
        }
      }
    }
  } while (encoreunefois);

  //-- ----------------------------------------------------------------------

  do
  {
    APointDeleted = Standard_False;
    for (i = 1; (i <= nbvtx) && (APointDeleted == Standard_False); i++)
    {
      const IntPatch_Point& VTXi = svtx.Value(i);
      if (VTXi.Tolerance() > Tol)
        Tol = VTXi.Tolerance(); //-- 9 oct 97
      if ((VTXi.IsOnDomS1() == Standard_True) && (VTXi.IsOnDomS2() == Standard_False))
      {
        for (j = 1; (j <= nbvtx) && (APointDeleted == Standard_False); j++)
        {
          if (i != j)
          {
            const IntPatch_Point& VTXj = svtx.Value(j);
            if ((VTXj.IsOnDomS1() == Standard_True) && (VTXj.IsOnDomS2() == Standard_False))
            {
              if (VTXi.ParameterOnLine() == VTXj.ParameterOnLine())
              {
                if (VTXi.ArcOnS1() == VTXj.ArcOnS1())
                {
                  svtx.Remove(j);
                  nbvtx--;
                  if (lapt)
                  {
                    if (indl >= j)
                      indl--;
                  }
                  if (fipt)
                  {
                    if (indf >= j)
                      indf--;
                  }
                  APointDeleted = Standard_True;
                }
              }
            }
          }
        }
      }
    }
  } while (APointDeleted == Standard_True);

  do
  {
    APointDeleted = Standard_False;
    for (i = 1; (i <= nbvtx) && (APointDeleted == Standard_False); i++)
    {
      const IntPatch_Point& VTXi = svtx.Value(i);
      if ((VTXi.IsOnDomS2() == Standard_True) && (VTXi.IsOnDomS1() == Standard_False))
      {
        for (j = 1; (j <= nbvtx) && (APointDeleted == Standard_False); j++)
        {
          if (i != j)
          {
            const IntPatch_Point& VTXj = svtx.Value(j);
            if ((VTXj.IsOnDomS2() == Standard_True) && (VTXj.IsOnDomS1() == Standard_False))
            {
              if (VTXi.ParameterOnLine() == VTXj.ParameterOnLine())
              {
                if (VTXi.ArcOnS2() == VTXj.ArcOnS2())
                {
                  svtx.Remove(j);
                  nbvtx--;
                  if (lapt)
                  {
                    if (indl >= j)
                      indl--;
                  }
                  if (fipt)
                  {
                    if (indf >= j)
                      indf--;
                  }
                  APointDeleted = Standard_True;
                }
              }
            }
          }
        }
      }
    }
  } while (APointDeleted == Standard_True);

  nbvtx     = NbVertex();
  nbponline = NbPnts();

  //----------------------------------------------------
  //-- On trie les Vertex
  Standard_Boolean SortIsOK;
  do
  {
    SortIsOK = Standard_True;
    for (i = 2; i <= nbvtx; i++)
    {
      if (svtx.Value(i - 1).ParameterOnLine() > svtx.Value(i).ParameterOnLine())
      {
        SortIsOK = Standard_False;
        svtx.Exchange(i - 1, i);
      }
    }
  } while (!SortIsOK);

  //----------------------------------------------------
  //-- On detecte les points confondus dans la LineOn2S
  constexpr Standard_Real dmini = Precision::SquareConfusion();
  for (i = 2; (i <= nbponline) && (nbponline > 2); i++)
  {
    const IntSurf_PntOn2S& aPnt1 = curv->Value(i - 1);
    const IntSurf_PntOn2S& aPnt2 = curv->Value(i);
    Standard_Real          d     = (aPnt1.Value()).SquareDistance((aPnt2.Value()));
    if (d < dmini)
    {
      curv->RemovePoint(i);
      nbponline--;
      //----------------------------------------------
      //-- On recadre les Vertex si besoin
      //--
      for (j = 1; j <= nbvtx; j++)
      {
        indicevertex = svtx.Value(j).ParameterOnLine();
        if (indicevertex >= i)
        {
          svtx.ChangeValue(j).SetParameter(indicevertex - 1.0);
        }
      }
      // modified by NIZNHY-PKV Mon Feb 11 09:28:02 2002 f
      i--;
      // modified by NIZNHY-PKV Mon Feb 11 09:28:04 2002 t
    }
  }
  //----------------------------------------------------
  for (i = 1; i <= nbvtx; i++)
  {
    const gp_Pnt& P    = svtx.Value(i).Value();
    Standard_Real vTol = svtx.Value(i).Tolerance();

    indicevertex       = svtx.Value(i).ParameterOnLine();
    indicevertexonline = (Standard_Integer)indicevertex;
    //--------------------------------------------------
    //-- On Compare le vertex avec les points de la ligne
    //-- d indice   indicevertexOnLine-1
    //--            indicevertexOnLine
    //--            indicevertexOnLine+1
    //--------------------------------------------------
    if (indicevertexonline < 1)
    {
      if (CompareVertexAndPoint(P, curv->Value(1).Value(), vTol))
      {
        //-------------------------------------------------------
        //-- On remplace le point cheminement(1) par vertex(i)
        //-- et   vertex(i) prend pour parametre 1
        //-------------------------------------------------------

        IntSurf_PntOn2S POn2S = svtx.Value(i).PntOn2S();
        RecadreMemePeriode(POn2S, curv->Value(1), U1Period(), V1Period(), U2Period(), V2Period());
        if (myCreationWay == IntPatch_WLImpImp)
        {
          // Adjust first point of curve to corresponding vertex the following way:
          // set 3D point as the point of the vertex and 2D points as the points of the point on
          // curve.
          curv->SetPoint(1, POn2S.Value());
          Standard_Real mu1, mv1, mu2, mv2;
          curv->Value(1).Parameters(mu1, mv1, mu2, mv2);
          svtx.ChangeValue(i).SetParameter(1);
          svtx.ChangeValue(i).SetParameters(mu1, mv1, mu2, mv2);
        }
        else
        {
          curv->Value(1, POn2S);
        }

        //--curv->Value(1,svtx.Value(i).PntOn2S());
        svtx.ChangeValue(i).SetParameter(1.0);
      }
      else
      {
        //-------------------------------------------------------
        //-- On insere le point de cheminement Vertex(i)
        //-- On recadre les parametres des autres vertex
        //-------------------------------------------------------
        IntSurf_PntOn2S POn2S = svtx.Value(i).PntOn2S();
        RecadreMemePeriode(POn2S, curv->Value(1), U1Period(), V1Period(), U2Period(), V2Period());
        curv->InsertBefore(1, POn2S);

        //-- curv->InsertBefore(1,svtx.Value(i).PntOn2S());
        svtx.ChangeValue(i).SetParameter(1.0);
        nbponline++;
        for (j = 1; j <= nbvtx; j++)
        {
          if (j != 1)
          {
            Standard_Real t = svtx.Value(j).ParameterOnLine();
            if (t > 1.0)
            {
              svtx.ChangeValue(j).SetParameter(t + 1.0);
            }
          }
        }
      }
    } //--- fin : if(indicevertexonline<1)
    else
    {
      //---------------------------------------------------------
      //-- vertex(i)   ==   cheminement (indicevertexonline-1)
      //-- vertex(i)   ==   cheminement (indicevertexonline)
      //-- vertex(i)   ==   cheminement (indicevertexonline+1)
      //---------------------------------------------------------
      Standard_Boolean Substitution = Standard_False;
      //-- for(k=indicevertexonline+1; !Substitution && k>=indicevertexonline-1;k--) {   avant le 9
      // oct 97
      Standard_Real mu1, mv1, mu2, mv2;
      curv->Value(indicevertexonline).Parameters(mu1, mv1, mu2, mv2);

      for (k = indicevertexonline + 1; k >= indicevertexonline - 1; k--)
      {
        if (k > 0 && k <= nbponline)
        {
          if (CompareVertexAndPoint(P, curv->Value(k).Value(), vTol))
          {
            //-------------------------------------------------------
            //-- On remplace le point cheminement(k)
            //-- par vertex(i)  et vertex(i) prend pour parametre k
            //-------------------------------------------------------
            IntSurf_PntOn2S POn2S = svtx.Value(i).PntOn2S();
            RecadreMemePeriode(POn2S,
                               curv->Value(k),
                               U1Period(),
                               V1Period(),
                               U2Period(),
                               V2Period());

            if (myCreationWay == IntPatch_WLImpImp)
            {
              // Adjust a point of curve to corresponding vertex the following way:
              // set 3D point as the point of the vertex and 2D points as the points
              // of the point on curve with index <indicevertexonline>
              curv->SetPoint(k, POn2S.Value());
              curv->SetUV(k, Standard_True, mu1, mv1);
              curv->SetUV(k, Standard_False, mu2, mv2);
            }
            else
            {
              curv->Value(k, POn2S);
              POn2S.Parameters(mu1, mv1, mu2, mv2);
            }
            svtx.ChangeValue(i).SetParameter(k);
            svtx.ChangeValue(i).SetParameters(mu1, mv1, mu2, mv2);
            Substitution = Standard_True;
          }
        }
      }

      // Remove duplicating points
      if (Substitution)
      {
        Standard_Integer ind_point;
        for (ind_point = 2; (ind_point <= nbponline && nbponline > 1); ind_point++)
        {
          Standard_Real d =
            (curv->Value(ind_point - 1).Value()).SquareDistance((curv->Value(ind_point).Value()));
          if (d < dmini)
          {
            curv->RemovePoint(ind_point);
            nbponline--;
            //----------------------------------------------
            //-- On recadre les Vertex si besoin
            //--
            for (j = 1; j <= nbvtx; j++)
            {
              indicevertex = svtx.Value(j).ParameterOnLine();
              if (indicevertex >= ind_point)
              {
                svtx.ChangeValue(j).SetParameter(indicevertex - 1.0);
              }
            }
            // modified by NIZNHY-PKV Mon Feb 11 09:28:02 2002 f
            ind_point--;
            // modified by NIZNHY-PKV Mon Feb 11 09:28:04 2002 t
          }
        }
      }

      //--static int deb6nov98=1;    Ne resout rien (a part partiellement BUC60409)
      //--if(deb6nov98) {
      //--Substitution=Standard_True;
      //-- }

      if (Substitution == Standard_False)
      {
        //-------------------------------------------------------
        //-- On insere le point de cheminement Vertex(i)
        //-- On recadre les parametres des autres vertex
        //-------------------------------------------------------
        IntSurf_PntOn2S POn2S = svtx.Value(i).PntOn2S();
        if (indicevertexonline >= nbponline)
        {
          RecadreMemePeriode(POn2S,
                             curv->Value(nbponline),
                             U1Period(),
                             V1Period(),
                             U2Period(),
                             V2Period());
          curv->Add(POn2S);
        }
        else
        {
          RecadreMemePeriode(POn2S,
                             curv->Value(indicevertexonline + 1),
                             U1Period(),
                             V1Period(),
                             U2Period(),
                             V2Period());
          curv->InsertBefore(indicevertexonline + 1, POn2S);
        }
        //-- curv->InsertBefore(indicevertexonline+1,svtx.Value(i).PntOn2S());
        svtx.ChangeValue(i).SetParameter(indicevertexonline + 1);
        nbponline++;
        for (j = 1; j <= nbvtx; j++)
        {
          if (j != i)
          {
            Standard_Real t = svtx.Value(j).ParameterOnLine();
            if (t > (Standard_Real)indicevertexonline)
            {
              svtx.ChangeValue(j).SetParameter(t + 1.0);
            }
          }
        }
      } //-- Substitution
    } //-- indicevertexonline>=1

  } //-- boucle i sur vertex

  do
  {
    APointDeleted = Standard_False;
    for (i = 1; i <= nbvtx && (APointDeleted == Standard_False); i++)
    {
      const IntPatch_Point& VTX = svtx.Value(i);
      for (j = 1; j <= nbvtx && (APointDeleted == Standard_False); j++)
      {
        if (i != j)
        {
          const IntPatch_Point& VTXM1 = svtx.Value(j);

          Standard_Boolean kill   = Standard_False;
          Standard_Boolean killm1 = Standard_False;
          if (VTXM1.ParameterOnLine() == VTX.ParameterOnLine())
          {
            if (VTXM1.IsOnDomS1() && VTX.IsOnDomS1())
            { //-- OnS1    OnS1
              if (VTXM1.ArcOnS1() == VTX.ArcOnS1())
              { //-- OnS1 == OnS1
                if (VTXM1.IsOnDomS2())
                { //-- OnS1 == OnS1  OnS2
                  if (VTX.IsOnDomS2() == Standard_False)
                  { //-- OnS1 == OnS1  OnS2 PasOnS2
                    kill = Standard_True;
                  }
                  else
                  {
                    if (VTXM1.ArcOnS2() == VTX.ArcOnS2())
                    { //-- OnS1 == OnS1  OnS2 == OnS2
                      kill = Standard_True;
                    }
                  }
                }
                else
                { //-- OnS1 == OnS1  PasOnS2
                  if (VTX.IsOnDomS2())
                  { //-- OnS1 == OnS1  PasOnS2  OnS2
                    killm1 = Standard_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() == Standard_False)
                    { //-- OnS2 == OnS2  OnS1 PasOnS1
                      kill = Standard_True;
                    }
                    else
                    {
                      if (VTXM1.ArcOnS1() == VTX.ArcOnS1())
                      { //-- OnS2 == OnS2  OnS1 == OnS1
                        kill = Standard_True;
                      }
                    }
                  }
                  else
                  { //-- OnS2 == OnS2  PasOnS1
                    if (VTX.IsOnDomS1())
                    { //-- OnS2 == OnS2  PasOnS1  OnS1
                      killm1 = Standard_True;
                    }
                  }
                }
              }
            }
            if (kill)
            {
              APointDeleted = Standard_True;
              svtx.Remove(i);
              nbvtx--;
            }
            else if (killm1)
            {
              APointDeleted = Standard_True;
              svtx.Remove(j);
              nbvtx--;
            }
          }
        }
      }
    }
  } while (APointDeleted == Standard_True);

  do
  {
    SortIsOK = Standard_True;
    for (i = 2; i <= nbvtx && SortIsOK; i++)
    {
      const IntPatch_Point& Pim1 = svtx.Value(i - 1);
      const IntPatch_Point& Pii  = svtx.Value(i);
      if (Pim1.ParameterOnLine() == Pii.ParameterOnLine())
      {
        if ((Pii.IsOnDomS1() == Standard_False) && (Pii.IsOnDomS2() == Standard_False))
        {
          SortIsOK = Standard_False;
          svtx.Remove(i);
          nbvtx--;
        }
        else
        {
          if ((Pim1.IsOnDomS1() == Standard_False) && (Pim1.IsOnDomS2() == Standard_False))
          {
            SortIsOK = Standard_False;
            svtx.Remove(i - 1);
            nbvtx--;
          }
        }
      }
    }
  } while (!SortIsOK);
  //-- ----------------------------------------------------------------------------
  //-- On ajoute les vertex de debut et de fin de ligne s il ne sont pas presents.
  //--
  //-- Existe t il un vertex de debut de ligne, de fin .
  //--
  //-- Si Besoin : il faudra dedoubler les points de debut et de fin sur les periodiques ??????

  Standard_Boolean bFirst = Standard_False;
  Standard_Boolean bLast  = Standard_False;
  nbponline               = NbPnts();
  for (i = 1; i <= nbvtx; i++)
  {
    Standard_Real pol = svtx.Value(i).ParameterOnLine();
    if (pol == 1.0)
    {
      bFirst = fipt = Standard_True;
      indf          = i;
    }
    if (pol == nbponline)
    {
      bLast = lapt = Standard_True;
      indl         = i;
    }
  }
  if (bFirst == Standard_False)
  {
    Standard_Real    pu1, pv1, pu2, pv2;
    Standard_Boolean vtxfound = Standard_False;
    IntPatch_Point   vtx;
    curv->Value(1).Parameters(pu1, pv1, pu2, pv2);
    for (i = 1; (vtxfound == Standard_False) && (i <= nbvtx); i++)
    {
      const IntPatch_Point& V = svtx.Value(i);
      // jgv: to avoid loops
      // Standard_Real vTol = V.Tolerance();
      if (CompareVertexAndPoint(V.Value(), curv->Value(1).Value(), Precision::Confusion() /*vTol*/))
      {
        vtx = V;
        vtx.SetParameters(pu1, pv1, pu2, pv2);
        vtxfound = Standard_True;
      }
    }
    if (vtxfound == Standard_False)
    {
      vtx.SetValue(curv->Value(1).Value(), Tol, Standard_False);
      vtx.SetParameters(pu1, pv1, pu2, pv2);
    }
    vtx.SetParameter(1);
    svtx.Prepend(vtx);
    nbvtx++;
    fipt = Standard_True;
    indf = 1;
  }
  if (bLast == Standard_False)
  {
    Standard_Real    pu1, pv1, pu2, pv2;
    Standard_Boolean vtxfound = Standard_False;
    IntPatch_Point   vtx;
    curv->Value(nbponline).Parameters(pu1, pv1, pu2, pv2);
    for (i = 1; (vtxfound == Standard_False) && (i <= nbvtx); i++)
    {
      const IntPatch_Point& V = svtx.Value(i);
      // jgv: to avoid loops
      // Standard_Real vTol = V.Tolerance();
      if (CompareVertexAndPoint(V.Value(),
                                curv->Value(nbponline).Value(),
                                Precision::Confusion() /*vTol*/))
      {
        vtx = V;
        vtx.SetParameters(pu1, pv1, pu2, pv2);
        vtxfound = Standard_True;
      }
    }
    if (vtxfound == Standard_False)
    {
      vtx.SetValue(curv->Value(nbponline).Value(), Tol, Standard_False);
      vtx.SetParameters(pu1, pv1, pu2, pv2);
    }
    vtx.SetParameter(nbponline);
    svtx.Append(vtx);
    nbvtx++;
    lapt = Standard_True;
    indl = nbvtx;
  }

  //--------------------------------------------------------------
  //-- ** Detection de points trouves sur une meme restriction
  //--    avec la meme transition et avec des params on line
  //--    voisins.
  //-- ** Dans ce cas (-> donnerait un baillemenmt) on supprime
  //--    le point 'intermediaire'.
  //-- ** (exemple Vtx(1)  .....  Vtx(204) Vtx(205))
  //--    on supprime le Vtx(204)
  //-- ** (exemple Vtx(1) Vtx(2)  .....  Vtx(205))
  //--    on supprime le Vtx(2)
  //-- ** (exemple Vtx(1)  ...  Vtx(100) Vtx(101) ... Vtx(205))
  //--    on supprime le Vtx(100)  (Vtx(100)et101 sur m restr)

  //--------------------------------------------------------------
  nbvtx = NbVertex();
  do
  {
    APointDeleted = Standard_False;
    for (i = 1; (i <= nbvtx) && (APointDeleted == Standard_False); i++)
    {
      const IntPatch_Point& VTXi = svtx.Value(i);
      if ((VTXi.IsOnDomS1() == Standard_True) && (VTXi.IsOnDomS2() == Standard_False))
      {
        for (j = 1; (j <= nbvtx) && (APointDeleted == Standard_False); j++)
        {
          if (i != j)
          {
            const IntPatch_Point& VTXj = svtx.Value(j);
            if ((VTXj.IsOnDomS1() == Standard_True) && (VTXj.IsOnDomS2() == Standard_False))
            {
              if ((VTXi.ParameterOnLine() == VTXj.ParameterOnLine() + 1)
                  || (VTXi.ParameterOnLine() == VTXj.ParameterOnLine() - 1))
              {
                if (VTXi.ArcOnS1() == VTXj.ArcOnS1())
                {
                  IntSurf_Transition t1 = VTXi.TransitionLineArc1();
                  IntSurf_Transition t2 = VTXj.TransitionLineArc1();
                  if (t1.TransitionType() == t2.TransitionType())
                  {
                    if ((VTXj.ParameterOnLine() != 1) && (VTXj.ParameterOnLine() != NbPnts()))
                    {
                      svtx.Remove(j);
                      nbvtx--;
                      if (lapt)
                      {
                        if (indl >= j)
                          indl--;
                      }
                      if (fipt)
                      {
                        if (indf >= j)
                          indf--;
                      }
                      APointDeleted = Standard_True;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  //-- meme traitement sur les restrictions du second shape

  while (APointDeleted == Standard_True);
  nbvtx = NbVertex();
  do
  {
    APointDeleted = Standard_False;
    for (i = 1; (i <= nbvtx) && (APointDeleted == Standard_False); i++)
    {
      const IntPatch_Point& VTXi = svtx.Value(i);
      if ((VTXi.IsOnDomS1() == Standard_False) && (VTXi.IsOnDomS2() == Standard_True))
      {
        for (j = 1; (j <= nbvtx) && (APointDeleted == Standard_False); j++)
        {
          if (i != j)
          {
            const IntPatch_Point& VTXj = svtx.Value(j);
            if ((VTXj.IsOnDomS1() == Standard_False) && (VTXj.IsOnDomS2() == Standard_True))
            {
              if ((VTXi.ParameterOnLine() == VTXj.ParameterOnLine() + 1)
                  || (VTXi.ParameterOnLine() == VTXj.ParameterOnLine() - 1))
              {
                if (VTXi.ArcOnS2() == VTXj.ArcOnS2())
                {
                  IntSurf_Transition t1 = VTXi.TransitionLineArc2();
                  IntSurf_Transition t2 = VTXj.TransitionLineArc2();
                  if (t1.TransitionType() == t2.TransitionType())
                  {
                    if ((VTXj.ParameterOnLine() != 1) && (VTXj.ParameterOnLine() != NbPnts()))
                    {
                      svtx.Remove(j);
                      nbvtx--;
                      if (lapt)
                      {
                        if (indl >= j)
                          indl--;
                      }
                      if (fipt)
                      {
                        if (indf >= j)
                          indf--;
                      }
                      APointDeleted = Standard_True;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  } while (APointDeleted == Standard_True);
  //--------------------------------------------------------------

  //--------------------------------------------------------------
  //-- dans le cas de lignes periodiques du type :
  //--    Un point sur restriction R1 de param p1  -> P3d1   Vtx1
  //--    Un point sur restriction R2 de param p2  -> P3d1   Vtx2
  //--
  //--    Un point sur restriction R1 de param p1  -> P3d1   Vtx3
  //--    pas de point sur R2
  //--
  //-- On doit dans ce cas creer un nouveau Vtx4 = Vtx3 sur la
  //-- restriction R2
  //--
  //-- Ce cas se produit qd on a corrige un baillement avec le filtre
  //-- precedent
  //--

  nbvtx = NbVertex();
  do
  {
    SortIsOK = Standard_True;
    for (i = 2; i <= nbvtx; i++)
    {
      if (svtx.Value(i - 1).ParameterOnLine() > svtx.Value(i).ParameterOnLine())
      {
        SortIsOK = Standard_False;
        svtx.Exchange(i - 1, i);
      }
    }
  } while (!SortIsOK);

  //-- Dump();

#if DEBUGV
  std::cout << "\n----------- apres ComputeVertexParameters -------------" << std::endl;
  for (i = 1; i <= nbvtx; i++)
  {
    Vertex(i).Dump();
    Standard_Real polr = Vertex(i).ParameterOnLine();
    Standard_Real pol  = (Standard_Integer)polr;
    if (pol >= 1 && pol <= nbvtx)
    {
      std::cout << "----> IntSurf_PntOn2S : " << polr << "  Pnt (" << Vertex(pol).Value().X() << ","
                << Vertex(pol).Value().Y() << "," << Vertex(pol).Value().Z() << ")" << std::endl;
    }
  }
  std::cout << "\n----------------------------------------------------------" << std::endl;
#endif
}

Standard_Boolean IntPatch_WLine::HasArcOnS1() const
{
  return (hasArcOnS1);
}

void IntPatch_WLine::SetArcOnS1(const Handle(Adaptor2d_Curve2d)& A)
{
  hasArcOnS1 = Standard_True;
  theArcOnS1 = A;
}

const Handle(Adaptor2d_Curve2d)& IntPatch_WLine::GetArcOnS1() const
{
  return (theArcOnS1);
}

Standard_Boolean IntPatch_WLine::HasArcOnS2() const
{
  return (hasArcOnS2);
}

void IntPatch_WLine::SetArcOnS2(const Handle(Adaptor2d_Curve2d)& A)
{
  hasArcOnS2 = Standard_True;
  theArcOnS2 = A;
}

const Handle(Adaptor2d_Curve2d)& IntPatch_WLine::GetArcOnS2() const
{
  return (theArcOnS2);
}

void IntPatch_WLine::Dump(const Standard_Integer theMode) const
{
  std::cout << " ----------- D u m p    I n t P a t c h  _  W L i n e  -(begin)------" << std::endl;
  const Standard_Integer aNbPoints = NbPnts();
  const Standard_Integer aNbVertex = NbVertex();

  switch (theMode)
  {
    case 0:
      printf("Num    [X  Y  Z]     [U1  V1]   [U2  V2]\n");
      for (Standard_Integer i = 1; i <= aNbPoints; i++)
      {
        Standard_Real u1, v1, u2, v2;
        Point(i).Parameters(u1, v1, u2, v2);
        printf("%4d  [%+10.20f %+10.20f %+10.20f]  [%+10.20f %+10.20f]  [%+10.20f %+10.20f]\n",
               i,
               Point(i).Value().X(),
               Point(i).Value().Y(),
               Point(i).Value().Z(),
               u1,
               v1,
               u2,
               v2);
      }

      for (Standard_Integer i = 1; i <= aNbVertex; i++)
      {
        Vertex(i).Dump();
        Standard_Real    polr = Vertex(i).ParameterOnLine();
        Standard_Integer pol  = static_cast<Standard_Integer>(polr);

        if (pol >= 1 && pol <= aNbVertex)
        {
          std::cout << "----> IntSurf_PntOn2S : " << polr << ", Pnt (" << Vertex(pol).Value().X()
                    << "," << Vertex(pol).Value().Y() << "," << Vertex(pol).Value().Z() << ")"
                    << std::endl;
        }
      }

      break;
    case 1:
      for (Standard_Integer i = 1; i <= aNbPoints; i++)
      {
        Standard_Real u1, v1, u2, v2;
        Point(i).Parameters(u1, v1, u2, v2);
        printf("point p%d %+10.20f %+10.20f %+10.20f\n",
               i,
               Point(i).Value().X(),
               Point(i).Value().Y(),
               Point(i).Value().Z());
      }

      break;
    case 2:
      for (Standard_Integer i = 1; i <= aNbPoints; i++)
      {
        Standard_Real u1, v1, u2, v2;
        Point(i).Parameters(u1, v1, u2, v2);
        printf("point p%d %+10.20f %+10.20f\n", i, u1, v1);
      }

      break;
    default:
      for (Standard_Integer i = 1; i <= aNbPoints; i++)
      {
        Standard_Real u1, v1, u2, v2;
        Point(i).Parameters(u1, v1, u2, v2);
        printf("point p%d %+10.20f %+10.20f\n", i, u2, v2);
      }

      break;
  }
  std::cout << "\n--------------------------------------------------- (end) -------" << std::endl;
}
