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

// Modified by  MPS (14-04-97)  traitement des cas  ou il n'y a pas
//                              d'intersection entre les stripes 
//  Modified by  MPS (16-06-97) : on tient compte du fait que GeomPlate
//                                rend les courbes 2d dans meme ordre que les
//                                courbes frontieres passees en entree   
//  Modified by JLR (20-08-97) mise en place des nouveaux constructeurs de GeomPlate
//  Modified by MPS (03-11-97) on ne cree pas un  batten lorsque le rapport
//  entre les deux resolutions sur la surface est trop grand (PRO10649)  
//  Modified by MPS (05-12-97) on ne tient pas compte des aretes degenerees
//                             lors du calcul du nombre d'aretes.
//  Modified by JCT (08-12-97) traitement des aretes vives consecutives ou non
//                             (grille EDC412 sauf D2, L1, L2, L3)
//  Modified by JCT (11-12-97) pb osf avec indpoint + orientation de plate
//                             ( --> D2, L1, L2, L3 valides mais laids)
//  Modified by MPS (24-02-98)  traitement des aretes de regularite 
//  Modified by MPS (01-06-98)  traitement des aretes de couture 
//  Modified by MPS (01-12-98)  traitement des bords libres 
//  Modified by MPS (01-02-99)  traitement des aretes de regularite 
//                              consecutives   
// Traitement des coins  		 

#include <Adaptor2d_Curve2d.hxx>
#include <AppBlend_Approx.hxx>
#include <Blend_FuncInv.hxx>
#include <Bnd_Box2d.hxx>
#include <BndLib_Add2dCurve.hxx>
#include <BRepAlgo_NormalProjection.hxx>
#include <BRepBlend_Line.hxx>
#include <BRepLib_MakeEdge.hxx>
#include <BRepLib_MakeFace.hxx>
#include <BRepTools.hxx>
#include <ChFi3d_Builder.hxx>
#include <ChFi3d_Builder_0.hxx>
#include <ChFiDS_CommonPoint.hxx>
#include <ChFiDS_FaceInterference.hxx>
#include <ChFiDS_HData.hxx>
#include <ChFiDS_ListIteratorOfListOfStripe.hxx>
#include <ChFiDS_Regul.hxx>
#include <ChFiDS_SequenceOfSurfData.hxx>
#include <ChFiDS_Spine.hxx>
#include <ChFiDS_Stripe.hxx>
#include <ChFiDS_StripeArray1.hxx>
#include <ChFiDS_SurfData.hxx>
#include <Extrema_ExtCC.hxx>
#include <Extrema_ExtPC.hxx>
#include <Extrema_POnCurv.hxx>
#include <FairCurve_Batten.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dLProp_CLProps2d.hxx>
#include <Geom_BezierCurve.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomInt_IntSS.hxx>
#include <GeomLib.hxx>
#include <GeomPlate_BuildPlateSurface.hxx>
#include <GeomPlate_CurveConstraint.hxx>
#include <GeomPlate_MakeApprox.hxx>
#include <GeomPlate_PlateG0Criterion.hxx>
#include <GeomPlate_Surface.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <math_Matrix.hxx>
#include <PLib.hxx>
#include <Precision.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_OutOfRange.hxx>
#include <TColGeom2d_Array1OfCurve.hxx>
#include <TColGeom2d_HArray1OfCurve.hxx>
#include <TColGeom2d_SequenceOfCurve.hxx>
#include <TColGeom_Array1OfCurve.hxx>
#include <TColGeom_SequenceOfCurve.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfXYZ.hxx>
#include <TColgp_SequenceOfXY.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
#include <TColStd_Array1OfBoolean.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array2OfInteger.hxx>
#include <TColStd_Array2OfReal.hxx>
#include <TColStd_ListOfInteger.hxx>
#include <TopAbs_Orientation.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopOpeBRepBuild_HBuilder.hxx>
#include <TopOpeBRepDS_Curve.hxx>
#include <TopOpeBRepDS_CurvePointInterference.hxx>
#include <TopOpeBRepDS_DataStructure.hxx>
#include <TopOpeBRepDS_HDataStructure.hxx>
#include <TopOpeBRepDS_Kind.hxx>
#include <TopOpeBRepDS_ListOfInterference.hxx>
#include <TopOpeBRepDS_Point.hxx>
#include <TopOpeBRepDS_SolidSurfaceInterference.hxx>
#include <TopOpeBRepDS_Surface.hxx>
#include <TopOpeBRepDS_SurfaceCurveInterference.hxx>
#include <TopOpeBRepDS_Transition.hxx>
#include <TopTools_Array2OfShape.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <ChFi3d.hxx>

// performances 
#ifdef OCCT_DEBUG
#include <OSD_Chronometer.hxx>
extern Standard_Real  t_plate ,t_approxplate,t_batten; 
extern void ChFi3d_InitChron(OSD_Chronometer& ch);
extern void ChFi3d_ResultChron(OSD_Chronometer & ch,Standard_Real& time);
#endif


//=======================================================================
//function : Indices
//purpose  : 
//=======================================================================

static void Indices (     const  Standard_Integer n,
                   const Standard_Integer ic,
                   Standard_Integer & icplus,
                   Standard_Integer & icmoins)
{
  if (ic== (n-1)) icplus=0;
  else icplus=ic+1;  
  if (ic==0) icmoins=n-1;
  else icmoins=ic-1;
}

//=======================================================================
//function : Calcul_Param
//purpose  : 
//=======================================================================

static void Calcul_Param (const Handle(ChFiDS_Stripe)& stripe,
			  const Standard_Integer jfposit,
			  const Standard_Integer indice,
			  const Standard_Boolean isfirst,
			  Standard_Real & param)
{
  if (jfposit==2 ) 
    param=stripe->SetOfSurfData()->Value(indice)->InterferenceOnS2().Parameter(isfirst);   
  else 
    param=stripe->SetOfSurfData()->Value(indice)->InterferenceOnS1().Parameter(isfirst);
}

//=======================================================================
//function : Calcul_P2dOnSurf
//purpose  : 
//=======================================================================

static void Calcul_P2dOnSurf(const Handle(ChFiDS_Stripe)& stripe,
			     const Standard_Integer jfposit,
			     const Standard_Integer indice,
			     const Standard_Real param,
			     gp_Pnt2d & p2)

{
  if (jfposit==1) 
    stripe->SetOfSurfData()->Value(indice)
      ->InterferenceOnS1().PCurveOnSurf()->D0(param,p2);   
  else
    stripe->SetOfSurfData()->Value(indice)
      ->InterferenceOnS2().PCurveOnSurf()->D0(param,p2);        
}

//=======================================================================
//function : Calcul_C2dOnFace
//purpose  : 
//=======================================================================

static void Calcul_C2dOnFace (const Handle(ChFiDS_Stripe)& stripe,
			      const Standard_Integer jfposit,
			      const Standard_Integer indice,
			      Handle(Geom2d_Curve) & c2d)

{
  if (jfposit==1) 
    c2d = stripe->SetOfSurfData()->Value(indice)
      ->InterferenceOnS1().PCurveOnFace();   
  else
    c2d = stripe->SetOfSurfData()->Value(indice)
      ->InterferenceOnS2().PCurveOnFace();        
}

//=======================================================================
//function : Calcul_Orientation
//purpose  : 
//=======================================================================

static void Calcul_Orientation(const Handle(ChFiDS_Stripe)& stripe,
                               const Standard_Integer jfposit,
                               const Standard_Integer indice,
                               TopAbs_Orientation & orient)
{
  if (jfposit==1)
    orient = stripe->SetOfSurfData()->Value(indice)
      ->InterferenceOnS1().Transition();       
  else
    orient = stripe->SetOfSurfData()->Value(indice)
      ->InterferenceOnS2().Transition();
}

//=======================================================================
//function : RemoveSD
//purpose  : 
//=======================================================================

static void RemoveSD(Handle(ChFiDS_Stripe)& Stripe,
                     const Standard_Integer num1,
                     const Standard_Integer num2     )
{
  ChFiDS_SequenceOfSurfData& Seq = 
    Stripe->ChangeSetOfSurfData()->ChangeSequence();
  if(Seq.IsEmpty()) return;
  if (num1==num2) 
    Seq.Remove(num1);
  else
    Seq.Remove(num1,num2);
}

//=======================================================================
//function : cherche_edge1
//purpose  : find common edge of faces F1 and F2 
//=======================================================================

static void cherche_edge1 (const TopoDS_Face & F1,
                           const TopoDS_Face & F2,
                           TopoDS_Edge & Edge)
{ Standard_Integer i,j; 
  TopoDS_Edge Ecur1,Ecur2;
  Standard_Boolean trouve=Standard_False;
  TopTools_IndexedMapOfShape  MapE1,MapE2;
  TopExp::MapShapes( F1,TopAbs_EDGE,MapE1);
  TopExp::MapShapes( F2,TopAbs_EDGE,MapE2);
  for ( i=1; i<= MapE1.Extent()&&!trouve; i++)
  { 
    TopoDS_Shape aLocalShape = TopoDS_Shape (MapE1(i));
    Ecur1=TopoDS::Edge(aLocalShape);
    //  Ecur1=TopoDS::Edge(TopoDS_Shape (MapE1(i)));
    for ( j=1; j<= MapE2.Extent()&&!trouve; j++)
    { 
      aLocalShape = TopoDS_Shape (MapE2(j));
      Ecur2=TopoDS::Edge(aLocalShape);
      //              Ecur2=TopoDS::Edge(TopoDS_Shape (MapE2(j)));
      if (Ecur2.IsSame(Ecur1))
      {Edge=Ecur1;trouve=Standard_True;}
    }
  }
  if (Edge.IsNull()) {
    throw Standard_ConstructionError ("Failed to find edge");
  }
}

//=======================================================================
//function : CurveHermite
//purpose  : calculate a  curve 3d using polynoms of Hermite.
//           the edge is a regular edge. Curve 3D is constructed  
//           between edges icmoins and icplus. 
//=======================================================================

static void CurveHermite (const TopOpeBRepDS_DataStructure& DStr,
                          const Handle(ChFiDS_Stripe)&   CDicmoins,
                          const Standard_Integer jficmoins,
                          const Standard_Integer icmoins,
                          const Standard_Real    picmoins,
                          const Standard_Integer sensicmoins,
                          const Standard_Boolean sharpicmoins,
                          const TopoDS_Edge & Eviveicmoins,
                          const Handle(ChFiDS_Stripe)&   CDicplus,
                          const Standard_Integer jficplus,
                          const Standard_Integer icplus,
                          const Standard_Real    picplus,
                          const Standard_Integer sensicplus,
                          const Standard_Boolean sharpicplus,
                          const TopoDS_Edge & Eviveicplus,
                          const Standard_Integer nbface,
                          TopTools_SequenceOfShape & Ecom,
                          const TopTools_SequenceOfShape & Face,
                          TColGeom2d_SequenceOfCurve & proj2d,
                          TColGeom_SequenceOfCurve & cproj,  
                          TopTools_SequenceOfShape & Eproj,     
                          TColStd_SequenceOfReal & param,
                          Standard_Real & error)
{  
  gp_Pnt p01,p02;
  gp_Vec d11,d12;
  Standard_Integer ii,jj;
  Standard_Real up1,up2;
  Standard_Integer ilin,jfp;
  Handle (Geom_Curve) c1,c2;
  if (sharpicmoins) {
    c1=BRep_Tool::Curve(Eviveicmoins,up1,up2);
  }
  else {
    if (jficmoins==1) 
      ilin= CDicmoins->SetOfSurfData()->Value( icmoins)->InterferenceOnS1().LineIndex();
    else ilin= CDicmoins->SetOfSurfData()->Value(icmoins)->InterferenceOnS2().LineIndex();
    c1=DStr.Curve(ilin).Curve();
  }
  if (sharpicplus){
    c2=BRep_Tool::Curve(Eviveicplus,up1,up2);
  }
  else {
    jfp=3-jficplus;   
    if (jfp==1) 
      ilin= CDicplus->SetOfSurfData()->Value( icplus)->InterferenceOnS1().LineIndex();
    else  ilin=CDicplus->SetOfSurfData()->Value(icplus)->InterferenceOnS2().LineIndex();
    c2=DStr.Curve(ilin ).Curve();
  }
  if (c1.IsNull()) 
    throw Standard_ConstructionError ("Failed to get 3D curve of edge");
  if (c2.IsNull()) 
    throw Standard_ConstructionError ("Failed to get 3D curve of edge");
  c1->D1(picmoins,p01,d11);
  c2->D1(picplus,p02,d12);
  Standard_Integer size = 4;
  math_Matrix  MatCoefs(1,size, 1,size);
  TColgp_Array1OfXYZ Cont(1,size);
  PLib::HermiteCoefficients(0, 1,1,1,MatCoefs);
  Standard_Real L1=p01.Distance(p02);
  Standard_Real lambda= ((Standard_Real)1) / Max (d11.Magnitude() / L1, 1.e-6);
  Cont(1) = p01.XYZ();
  if (sensicmoins==1) Cont(2) = d11.XYZ()*(-lambda) ;
  else Cont(2) = d11.XYZ()*(lambda) ;
  lambda= ((Standard_Real)1) / Max (d12.Magnitude() / L1, 1.e-6);
  Cont(3) = p02.XYZ();
  if (sensicplus==1) Cont(4) =  d12.XYZ()*(lambda);
  else Cont(4) =  d12.XYZ()*(-lambda);
  TColgp_Array1OfPnt ExtrapPoles(1, size);
  TColgp_Array1OfPnt ExtraCoeffs(1, size);
  gp_Pnt p0(0,0,0);
  ExtraCoeffs.Init(p0);
  for (ii=1; ii<=size; ii++) {
    for (jj=1; jj<=size; jj++) {
      ExtraCoeffs(jj).ChangeCoord() += MatCoefs(ii,jj)*Cont(ii);
    }
  }
  PLib::CoefficientsPoles(ExtraCoeffs,  PLib::NoWeights(),
                          ExtrapPoles,  PLib::NoWeights());
  Handle(Geom_BezierCurve) Bezier = new (Geom_BezierCurve) (ExtrapPoles);
  BRepLib_MakeEdge Bedge (Bezier);
  TopoDS_Edge edg =Bedge. Edge();
  TopoDS_Face F;
  error=1.e-30;
  Standard_Integer nb;
  for(nb=1;nb<=nbface;nb++){
    F=TopoDS::Face(Face.Value(nb));
    TopTools_IndexedMapOfShape MapE1;
    TopoDS_Edge E1;
    Handle(Geom2d_Curve) proj1;
    Handle(Geom_Curve) proj1c,proj2c;
    BRepAlgo_NormalProjection OrtProj;
    OrtProj.Init(F);
    OrtProj.Add(edg);
    OrtProj.SetParams(1.e-4, 1.e-4, GeomAbs_C1, 14, 16);
    OrtProj.Build();
    if ( OrtProj.IsDone()){
      TopExp::MapShapes(OrtProj.Projection() , TopAbs_EDGE, MapE1);
        if (MapE1.Extent()!=0){
          if (MapE1.Extent()!=1) {
            BRepLib_MakeFace Bface (BRep_Tool::Surface(F), Precision::Confusion());
            F=Bface.Face();
            OrtProj.Init(F);
            OrtProj.Build();
            MapE1.Clear();
            if ( OrtProj.IsDone()) 
              TopExp::MapShapes(OrtProj.Projection() ,TopAbs_EDGE, MapE1);
          }
          if (MapE1.Extent()!=0) { 
            Standard_Boolean trouve=Standard_False;
            for (Standard_Integer ind=1;ind<=MapE1.Extent()&&!trouve;ind++){
              TopoDS_Shape aLocalShape = TopoDS_Shape( MapE1(ind));  
              E1=TopoDS::Edge( aLocalShape );
              //           E1=TopoDS::Edge( TopoDS_Shape (MapE1(ind)));
              if (!BRep_Tool::Degenerated(E1)) trouve=Standard_True;
            }
            Eproj.Append(E1);
            proj1=BRep_Tool::CurveOnSurface(E1,F,up1,up2);
            if (proj1.IsNull()) 
              throw Standard_ConstructionError ("Failed to get p-curve of edge");
            proj2d.Append(new Geom2d_TrimmedCurve(proj1,up1,up2));
            proj1c=BRep_Tool::Curve(E1,up1,up2);
            if (proj1c.IsNull()) 
              throw Standard_ConstructionError ("Failed to get 3D curve of edge");
            cproj.Append(new Geom_TrimmedCurve(proj1c,up1,up2));
            if (error>BRep_Tool::Tolerance(E1)) error=BRep_Tool::Tolerance(E1);
          }
          else {
            Eproj.Append(E1);
            proj2d.Append(proj1);
            cproj.Append(proj1c);
          } 
        }
        else {
          Eproj.Append(E1);
          proj2d.Append(proj1);
          cproj.Append(proj1c);
        }
      }
  }
  for (nb=1;nb<=nbface-1;nb++) {
    BRepAdaptor_Curve C(TopoDS::Edge(Ecom.Value(nb)));
    C.D0(param.Value(nb),p02);
    GeomAdaptor_Curve L (Bezier);
    Extrema_ExtCC ext (C,L);
    if (ext.IsDone()){ 
      if (!ext.IsParallel() && ext.NbExt()!=0){ 
        Extrema_POnCurv POnC, POnL;
        ext.Points(1, POnC, POnL);
        if (POnC.Value().Distance(POnL.Value()) < Precision::Confusion())
          param.ChangeValue(nb) =POnC.Parameter();
        else
        {
          if (!cproj.Value(nb).IsNull()) {
            cproj.Value(nb)->D0(cproj.Value(nb)->LastParameter(),p01);
          }
          else if (!cproj.Value(nb+1).IsNull()) {
            cproj.Value(nb+1)->D0(cproj.Value(nb+1)->FirstParameter(),p01);
          }
        }
      }
    }
    if (!ext.IsDone()||ext.NbExt()==0) {
      if (!cproj.Value(nb).IsNull()) {
        cproj.Value(nb)->D0(cproj.Value(nb)->LastParameter(),p01); 
      }
      else if (!cproj.Value(nb+1).IsNull()) {
        cproj.Value(nb+1)->D0(cproj.Value(nb+1)->FirstParameter(),p01);  
      } 
      if (p01.Distance(p02)>1.e-4 ){
        Extrema_ExtPC ext1 (p01,C);
        if (ext1.IsDone()){ 
          if (ext1.NbExt()!=0){  
            Extrema_POnCurv POnC(ext1.Point(1));
            param.ChangeValue(nb) =POnC.Parameter();
          }
        }
      }
    }       
  }
}

//=======================================================================
//function : CalculDroite
//purpose  : calculate a 2D straight line passing through point p2d1 and direction xdir ydir 
//=======================================================================

static void CalculDroite(const gp_Pnt2d & p2d1,
                         const Standard_Real  xdir,
                         const Standard_Real  ydir,
                         Handle (Geom2d_Curve) & pcurve) 
{ gp_Dir2d dir1 (xdir, ydir);
  Handle(Geom2d_Line) l= new Geom2d_Line (p2d1,dir1);
  Standard_Real l0 = sqrt(xdir*xdir+ ydir*ydir );
  pcurve = new Geom2d_TrimmedCurve(l,0,l0);
}

//=======================================================================
//function : CalculBatten
//purpose  : calcule a batten between curves 2d  curv2d1 and curv2d2 at points p2d1 and p2d2  
//=======================================================================

static void CalculBatten (const Handle (GeomAdaptor_Surface)& ASurf, 
                          const TopoDS_Face& Face ,
                          const Standard_Real xdir,
                          const Standard_Real  ydir,
                          const gp_Pnt2d & p2d1,
                          const gp_Pnt2d & p2d2,
                          const Standard_Boolean contraint1,
                          const Standard_Boolean contraint2,
                          Handle (Geom2d_Curve) & curv2d1,
                          Handle (Geom2d_Curve) & curv2d2,
                          const Standard_Real  picicplus,
                          const Standard_Real   picplusic,
                          const Standard_Boolean inverseic,
                          const Standard_Boolean inverseicplus,
                          Handle (Geom2d_Curve)& pcurve)
{  
  Standard_Boolean isplane;
  Standard_Boolean anglebig = Standard_False;
  isplane=ASurf->GetType()==GeomAbs_Plane;
  gp_Dir2d dir1 (xdir, ydir);
  Geom2dLProp_CLProps2d CL1(curv2d1, picicplus, 1, 1.e-4);
  Geom2dLProp_CLProps2d CL2( curv2d2, picplusic, 1, 1.e-4);
  gp_Dir2d dir3,dir4 ;
  CL1.Tangent(dir3);
  CL2.Tangent(dir4);
  if (inverseic)  dir3.Reverse();
  if (inverseicplus)  dir4.Reverse();
  Standard_Real h =  p2d2.Distance(p2d1)/20;
  FairCurve_Batten Bat(p2d1,p2d2,h);
  Bat.SetFreeSliding (Standard_True);
  Standard_Real ang1,ang2;
  ang1=dir1.Angle(dir3);
  if (dir1.Angle(dir4) >0 ) ang2=M_PI-dir1.Angle(dir4);
  else ang2=-M_PI-dir1.Angle(dir4);
  if (contraint1&&contraint2) 
  anglebig=(Abs(ang1)>1.2)|| (Abs(ang2)>1.2 );
  else if (contraint1) 
  anglebig=Abs(ang1)>1.2;
  else if (contraint2)
  anglebig=Abs(ang2)>1.2; 
  if (isplane && (Abs(ang1)>M_PI/2 || Abs(ang2)>M_PI/2))
    isplane=Standard_False;
  if (anglebig && !isplane) {
    CalculDroite(p2d1,xdir,ydir,pcurve);
  }
  else {
    if (contraint1) Bat.SetAngle1(ang1);
    else  Bat.SetConstraintOrder1(0);
    if (contraint2) Bat.SetAngle2(ang2);
    else Bat.SetConstraintOrder2(0);
    FairCurve_AnalysisCode Iana; 
    Standard_Boolean Ok;
    Ok = Bat.Compute(Iana,25,1.e-2);
#ifdef OCCT_DEBUG
    if (!Ok) { 
      std::cout<<"no batten :";
      Bat.Dump(std::cout);
    }    
#endif  
    if (Ok) {
       pcurve = Bat.Curve();
       Standard_Real umin,vmin,umax,vmax;
       BRepTools::UVBounds(Face,umin,umax,vmin,vmax);
       Bnd_Box2d bf,bc;
       Geom2dAdaptor_Curve acur(pcurve);
       BndLib_Add2dCurve::Add(acur,0,bc);
       bf.Update(umin,vmin,umax,vmax);
       Standard_Real uminc,vminc,umaxc,vmaxc;
       bc.Get(uminc,vminc,umaxc,vmaxc);
       if (uminc<umin-1.e-7) Ok=Standard_False;
       if (umaxc>umax+1.e-7) Ok=Standard_False;
       if (vminc<vmin-1.e-7) Ok=Standard_False;
       if (vmaxc>vmax+1.e-7) Ok=Standard_False;       
    } 
    if (!Ok) CalculDroite(p2d1, xdir,ydir, pcurve);    
  }
}

//=======================================================================
//function : OrientationIcNonVive
//purpose  : calculate the orientation of the curve between ic and icplus knowing that ic 
//           is not a living edge.
//=======================================================================

static void OrientationIcNonVive (const Handle(ChFiDS_Stripe) & CDic,
                                  const Standard_Integer jfic,
                                  const Standard_Integer icicplus,
                                  const Standard_Integer  sensic,
                                  TopAbs_Orientation  & orien )
{
  TopAbs_Orientation orinterf; 
  Calcul_Orientation(CDic,jfic,icicplus,orinterf);
  if (sensic!=1){
    if (orinterf==TopAbs_FORWARD) orien=TopAbs_FORWARD;
    else orien=TopAbs_REVERSED; 		
  }
  else {
    if (orinterf==TopAbs_FORWARD) orien=TopAbs_REVERSED;
    else orien=TopAbs_FORWARD;
  }		
}

//=======================================================================
//function : OrientationIcplusNonVive
//purpose  : calculate the orientation of the curve between ic and icplus knowing that icplus
//           is not a living edge;
//=======================================================================

static void OrientationIcplusNonVive (const Handle(ChFiDS_Stripe) & CDicplus,
                                      const Standard_Integer jficplus,
                                      const Standard_Integer icplusic,
                                      const Standard_Integer sensicplus,
                                      TopAbs_Orientation & orien )
{
  TopAbs_Orientation orinterf; 
  Standard_Integer  jfp = 3 -jficplus;
  Calcul_Orientation(CDicplus,jfp,icplusic,orinterf);
  if (sensicplus==1){
    if (orinterf==TopAbs_FORWARD) orien=TopAbs_FORWARD;
    else orien=TopAbs_REVERSED; 		
  }
  else {
    if (orinterf==TopAbs_FORWARD) orien=TopAbs_REVERSED;
    else orien=TopAbs_FORWARD;
  }		
}

//=======================================================================
//function : OrientationAreteViveConsecutive
//purpose  : calculate the orientation of the curve between edges ic and icplus 
//           where ic and icplus are consecutively living 
//=======================================================================

static void OrientationAreteViveConsecutive (const TopoDS_Shape & Fviveicicplus,
                                             const TopoDS_Shape & Eviveic,
                                             const TopoDS_Vertex & V1,
                                             TopAbs_Orientation & orien)

{ // orinterf is orientation of edge ic corresponding to face Fviveicicplus taken FORWARD
  TopAbs_Orientation orinterf = TopAbs_FORWARD;
  TopoDS_Face F=TopoDS::Face( Fviveicicplus);
  TopoDS_Edge E=TopoDS::Edge( Eviveic);  
  TopExp_Explorer ex;
  for(ex.Init(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE);ex.More(); ex.Next()){
    if(E.IsSame(ex.Current())) {
      orinterf = ex.Current().Orientation();
      break;
    }
  }
  // if V1 is vertex REVERSED of edge ic the curve  
  // has the same orientation as ic 
  TopoDS_Vertex vl;
  vl=TopExp::LastVertex(E);
  if (vl.IsSame(V1)){ 
    if (orinterf==TopAbs_FORWARD) orien=TopAbs_FORWARD;
    else orien=TopAbs_REVERSED;
  }
  else {
    if (orinterf==TopAbs_FORWARD) orien=TopAbs_REVERSED;
    else orien=TopAbs_FORWARD;
  }
}

//=======================================================================
//function : PerformTwoCornerSameExt
//purpose  : calculate intersection between two stripes stripe1 and stripe2 
//=======================================================================

static void PerformTwoCornerSameExt(TopOpeBRepDS_DataStructure& DStr,
                                    const Handle(ChFiDS_Stripe)& stripe1,
                                    const Standard_Integer index1,
                                    const Standard_Integer sens1,
                                    const Handle(ChFiDS_Stripe) &stripe2,
                                    const Standard_Integer index2,
                                    const Standard_Integer sens2,
                                    Standard_Boolean & trouve)
                     
{ Handle (TopOpeBRepDS_CurvePointInterference) Interfp1, Interfp2;
  Handle (TopOpeBRepDS_SurfaceCurveInterference) Interfc;
  TopAbs_Orientation orpcurve,trafil1,orsurf1,orsurf2;
  Standard_Boolean isfirst;
  Standard_Integer indic1,indic2, indpoint1,indpoint2,ind,indcurve;
  Standard_Real tol;
  gp_Pnt P1,P2,P3,P4;
  gp_Pnt2d p2d;
  Handle(Geom_Curve)cint;
  Handle(Geom2d_Curve) C2dint1,C2dint2;
  isfirst=sens1==1;
  ChFiDS_CommonPoint& Com11= stripe1->SetOfSurfData()->Value(index1)->ChangeVertex (isfirst,1);
  ChFiDS_CommonPoint& Com12= stripe1->SetOfSurfData()->Value(index1)->ChangeVertex (isfirst,2);
  isfirst=sens2==1;
  ChFiDS_CommonPoint& Com21= stripe2->SetOfSurfData()->Value(index2)->ChangeVertex (isfirst,1);
#ifdef OCCT_DEBUG
//  ChFiDS_CommonPoint& Com22= 
//    stripe2->SetOfSurfData()->Value(index2)->ChangeVertex (isfirst,2);
#endif
  indic1=stripe1->SetOfSurfData()->Value(index1)->Surf();
  indic2=stripe2->SetOfSurfData()->Value(index2)->Surf();
  const Handle(ChFiDS_SurfData) Fd1=stripe1->SetOfSurfData()->Value(index1);
  const Handle(ChFiDS_SurfData) Fd2=stripe2->SetOfSurfData()->Value(index2);

  TColStd_Array1OfReal Pardeb(1,4),Parfin(1,4);
  const ChFiDS_FaceInterference& Fi11 = Fd1->InterferenceOnS1();
  const ChFiDS_FaceInterference& Fi12 = Fd1->InterferenceOnS2();
  const ChFiDS_FaceInterference& Fi21 = Fd2->InterferenceOnS1();
  const ChFiDS_FaceInterference& Fi22 = Fd2->InterferenceOnS2();
  gp_Pnt2d pfi11,pfi12,pfi21,pfi22;
  isfirst=sens1==1;
  pfi11 = Fi11.PCurveOnSurf()->Value(Fi11.Parameter(isfirst));
  pfi12 = Fi12.PCurveOnSurf()->Value(Fi12.Parameter(isfirst));
  isfirst=sens2==1;
  if (Com11.Point().Distance(Com21.Point()) <1.e-4) { 
    pfi21 = Fi21.PCurveOnSurf()->Value(Fi21.Parameter(isfirst)); 
    pfi22 = Fi22.PCurveOnSurf()->Value(Fi22.Parameter(isfirst));
  }
  else {
    pfi22 = Fi21.PCurveOnSurf()->Value(Fi21.Parameter(isfirst));  	
    pfi21 = Fi22.PCurveOnSurf()->Value(Fi22.Parameter(isfirst));
  }
  
  Pardeb(1)= pfi11.X();Pardeb(2) = pfi11.Y();
  Pardeb(3)= pfi21.X();Pardeb(4) = pfi21.Y();
  Parfin(1)= pfi12.X();Parfin(2) = pfi12.Y();
  Parfin(3)= pfi22.X();Parfin(4) = pfi22.Y();

  Handle(GeomAdaptor_Surface) HS1= ChFi3d_BoundSurf(DStr,Fd1,1,2);
  Handle(GeomAdaptor_Surface) HS2= ChFi3d_BoundSurf(DStr,Fd2,1,2);
  trouve=Standard_False;
  if (ChFi3d_ComputeCurves(HS1,HS2,Pardeb,Parfin,cint,
			   C2dint1,C2dint2,1.e-4,1.e-5,tol)){
    cint->D0(cint->FirstParameter(),P1);
    cint->D0(cint->LastParameter(),P2);
    trouve=((Com11.Point().Distance(P1) <1.e-4 || Com11.Point().Distance(P2)<1.e-4)&&
	    (Com12.Point().Distance(P1) <1.e-4 || Com12.Point().Distance(P2)<1.e-4));
  }

  if (trouve) {
    isfirst=sens1==1;
    stripe1->InDS(isfirst);
    indpoint1=ChFi3d_IndexPointInDS(Com11,DStr);
    indpoint2=ChFi3d_IndexPointInDS(Com12,DStr);
    stripe1->SetIndexPoint(indpoint1,isfirst,1);
    stripe1->SetIndexPoint(indpoint2,isfirst,2);
    isfirst=sens2==1;
    stripe2->InDS(isfirst); 
    if (Com11.Point().Distance(Com21.Point()) <1.e-4) {
      stripe2->SetIndexPoint(indpoint1,isfirst,1);
      stripe2->SetIndexPoint(indpoint2,isfirst,2);
    }
    else {
      stripe2->SetIndexPoint(indpoint2,isfirst,1);
      stripe2->SetIndexPoint(indpoint1,isfirst,2);
    }
    
    orsurf1=Fd1->Orientation();
    trafil1 = DStr.Shape(Fd1->IndexOfS1()).Orientation();
    trafil1 = TopAbs::Compose(trafil1,Fd1->Orientation());
    trafil1 = TopAbs::Compose(TopAbs::Reverse(Fi11.Transition()),trafil1);
    orsurf2=Fd2->Orientation();
    TopOpeBRepDS_Curve tcurv3d(cint,tol);
    indcurve= DStr.AddCurve(tcurv3d);
    cint->D0(cint->FirstParameter(),P1);
    cint->D0(cint->LastParameter(),P2);
    Fi11.PCurveOnFace()->D0(Fi11.LastParameter(),p2d);
    const Handle(Geom_Surface) Stemp = 
      BRep_Tool::Surface(TopoDS::Face(DStr.Shape(Fd1->IndexOfS1())));
    Stemp ->D0(p2d.X(),p2d.Y(),P4);
    Fi11.PCurveOnFace()->D0(Fi11.FirstParameter(),p2d);
    Stemp ->D0(p2d.X(),p2d.Y(),P3);
    if (P1.Distance(P4)<1.e-4  || P2.Distance(P3)<1.e-4)
      orpcurve=trafil1;
    else  orpcurve=TopAbs::Reverse(trafil1);
    if (Com11.Point().Distance(P1) >1.e-4) {
      ind=indpoint1;
      indpoint1=indpoint2;
      indpoint2=ind;
    }    
    Interfp1=ChFi3d_FilPointInDS(TopAbs_FORWARD,indcurve, indpoint1, cint->FirstParameter());
    Interfp2=ChFi3d_FilPointInDS(TopAbs_REVERSED,indcurve,indpoint2, cint->LastParameter());
    DStr.ChangeCurveInterferences(indcurve).Append(Interfp1);
    DStr.ChangeCurveInterferences(indcurve).Append(Interfp2);
    Interfc=ChFi3d_FilCurveInDS(indcurve,indic1,C2dint1,orpcurve);
    DStr.ChangeSurfaceInterferences(indic1).Append(Interfc);
    if (orsurf1==orsurf2) orpcurve=TopAbs::Reverse(orpcurve);
    Interfc=ChFi3d_FilCurveInDS(indcurve,indic2,C2dint2,orpcurve);
    DStr.ChangeSurfaceInterferences(indic2).Append(Interfc);
  }   
}

//=======================================================================
//function : CpOnEdge
//purpose  : determine if surfdata num has a common point on Eadj1 or Eadj2
//=======================================================================

static void  CpOnEdge (const  Handle(ChFiDS_Stripe) & stripe,
                       Standard_Integer num,
                       Standard_Boolean isfirst,
                       const TopoDS_Edge & Eadj1,
                       const TopoDS_Edge & Eadj2,
                       Standard_Boolean & compoint)

{ ChFiDS_CommonPoint cp1,cp2;
  compoint=Standard_False;  
  cp1 = stripe->SetOfSurfData()->Value(num)->ChangeVertex (isfirst,1);
  cp2 = stripe->SetOfSurfData()->Value(num)->ChangeVertex (isfirst,2);
  if(cp1.IsOnArc()){
    if (cp1.Arc().IsSame(Eadj1)||cp1.Arc().IsSame(Eadj2))
      compoint=Standard_True;
  } 
  if(cp2.IsOnArc()){
    if (cp2.Arc().IsSame(Eadj1)||cp2.Arc().IsSame(Eadj2))
      compoint=Standard_True; 
  } 
}

//=======================================================================
//function : RemoveSurfData
//purpose  : for each stripe removal of unused surfdatas 
//=======================================================================

static void RemoveSurfData (const ChFiDS_StripeMap & myVDataMap,
                            const ChFiDS_Map & myEFMap,
                            const TopoDS_Edge &edgecouture,
                            const TopoDS_Face & facecouture,
                            const TopoDS_Vertex &V1)
{ ChFiDS_ListIteratorOfListOfStripe It;
  Standard_Boolean isfirst;
  TopoDS_Edge Ecur,Eadj1,Eadj2;
  TopoDS_Face Fg,Fd,F1,F2;
  TopoDS_Vertex Vbid;
  Standard_Integer nbsurf,nbedge,sense,num;
  for (It.Initialize(myVDataMap(V1));It.More();It.Next()) {
    nbsurf= It.Value()->SetOfSurfData()->Length();
    nbedge = It.Value()->Spine()->NbEdges();
    if  (nbsurf!=1){
      num=ChFi3d_IndexOfSurfData(V1,It.Value(),sense);
      if (sense==1) 
	Ecur = It.Value()->Spine()->Edges(1);
      else  
	Ecur = It.Value()->Spine()->Edges(nbedge);
      ChFi3d_edge_common_faces(myEFMap(Ecur),F1,F2);
      if (F1.IsSame(facecouture)) Eadj1=edgecouture; 
      else ChFi3d_cherche_element(V1,Ecur,F1,Eadj1,Vbid);
      ChFi3d_edge_common_faces(myEFMap(Eadj1),Fg,Fd);
      if (F2.IsSame(facecouture)) Eadj2=edgecouture;
      else ChFi3d_cherche_element(V1,Ecur,F2,Eadj2,Vbid);
      ChFi3d_edge_common_faces(myEFMap(Eadj2),Fg,Fd); 
      Standard_Boolean compoint=Standard_False;
      isfirst=(sense==1); 
      Standard_Integer ind;
      if (sense==1) {
        ind=0;
	// among surfdatas find the greatest indice ind so that 
	// surfdata could have one of commonpoint on Eadj1 and Eadj2
	// remove surfdata from 1 to ind-1   
	for (Standard_Integer i=1;i<=nbsurf;i++) {
	  CpOnEdge (It.Value(),i,isfirst,Eadj1,Eadj2,compoint);
	  if (compoint) ind=i;
	}
	if (ind>=2) RemoveSD(It.ChangeValue(),1,ind-1);
      }
      else {
        ind=num;
	// among surfdatas find the smallest indice ind so that 
	// surfdata could have one of commonpoint on Eadj1 and Eadj2
	// remove surfdata from ind+1 to num   
	for (Standard_Integer i=num;i>=1;i--) {
	  CpOnEdge (It.Value(),i,isfirst,Eadj1,Eadj2,compoint);
	  if (compoint) ind=i;
	}
	if (ind<num) RemoveSD(It.ChangeValue(),ind+1,num);
      }
    }
  }
}

//=======================================================================
//function : ParametrePlate
//purpose  : 
//=======================================================================

static void ParametrePlate(const Standard_Integer n3d,
                           const GeomPlate_BuildPlateSurface & PSurf,
                           const Handle(Geom_Surface) & Surf,
                           const gp_Pnt & point,
                           const Standard_Real apperror,
                           gp_Pnt2d & uv)
{  Standard_Integer ip;
   gp_Pnt P1;
   Standard_Real par;
   Standard_Boolean trouve=Standard_False;
   for (ip=1;ip<=n3d && !trouve;ip++){
     par=PSurf.Curves2d()->Value(ip)->FirstParameter();
     PSurf.Curves2d()->Value(ip)->D0(par,uv);
     Surf->D0(uv.X(),uv.Y(),P1);       
     trouve=P1.IsEqual(point,apperror);
     if (!trouve) {
        par=PSurf.Curves2d()->Value(ip)->LastParameter();
        PSurf.Curves2d()->Value(ip)->D0(par,uv);
        Surf->D0(uv.X(),uv.Y(),P1);       
        trouve=P1.IsEqual(point,apperror); 
     } 
  }
}

//=======================================================================
//function : SummarizeNormal
//purpose  : 
//=======================================================================

static void SummarizeNormal(const TopoDS_Vertex& V1,
			    const TopoDS_Face& Fcur,
			    const TopoDS_Edge& Ecur,
			    gp_Vec& SumFaceNormalAtV1)
{
  gp_Pnt2d uv1, uv2;
  BRep_Tool::UVPoints(Ecur,Fcur,uv1,uv2);
  if ( ! V1.IsSame(TopExp::FirstVertex(Ecur))) uv1 = uv2;
  
  gp_Pnt P;
  gp_Vec d1U, d1V;
  BRep_Tool::Surface(Fcur)->D1( uv1.X(), uv1.Y(), P, d1U, d1V);
  gp_Vec N = d1U.Crossed(d1V);
  if (Fcur.Orientation() == TopAbs_REVERSED) N.Reverse();
  
  if (N.SquareMagnitude() <= Precision::PConfusion()) return;
  
  SumFaceNormalAtV1 += N.Normalized();
  SumFaceNormalAtV1.Normalize();
}

enum ChFi3d_SurfType { ChFiSURFACE, FACE1, FACE2 }; // for call SurfIndex(...)

//=======================================================================
//function : SurfIndex
//purpose  : 
//=======================================================================

static Standard_Integer SurfIndex(const ChFiDS_StripeArray1& StripeArray1,
				  const Standard_Integer     StripeIndex,
				  const Standard_Integer     SurfDataIndex,
				  const ChFi3d_SurfType      SurfType)
{
  const Handle(ChFiDS_SurfData)& aSurfData =
    StripeArray1(StripeIndex)->SetOfSurfData()->Value(SurfDataIndex);
  switch (SurfType) {
  case ChFiSURFACE: return aSurfData->Surf();
  case FACE1:       return aSurfData->IndexOfS1();
  case FACE2:       return aSurfData->IndexOfS2();
  default:          return -1;
  }
}

//=======================================================================
//function : PlateOrientation
//purpose  : Define Plate orientation compared to <theRefDir> previewing
//           that Plate surface can have a sharp angle with adjacent 
//           filet (bug occ266: 2 chamfs, OnSame and OnDiff) and
//           can be even twisted (grid tests cfi900 B1)
//=======================================================================

static TopAbs_Orientation PlateOrientation(const Handle(Geom_Surface)& thePlateSurf,
					   const Handle(TColGeom2d_HArray1OfCurve)& thePCArr,
					   const gp_Vec& theRefDir)
{
  gp_Vec du,dv;
  gp_Pnt pp1,pp2,pp3;
  gp_Pnt2d uv;
  Standard_Real fpar, lpar;
  Standard_Real SumScal1 = 0, SumScal2 = 0;
  
  Standard_Integer i, nb = thePCArr->Upper();
  Handle(Geom2d_Curve) aPC = thePCArr->Value(nb);
  fpar = aPC->FirstParameter();
  lpar = aPC->LastParameter();
  aPC->D0( (fpar + lpar) / 2., uv);
  thePlateSurf-> D0(uv.X(),uv.Y(),pp1);
  aPC->D0( lpar ,uv);
  thePlateSurf-> D0(uv.X(),uv.Y(),pp2);
  
  for (i=1; i<=nb; i++) {
    aPC = thePCArr->Value(i);
    fpar = aPC->FirstParameter();
    lpar = aPC->LastParameter();
    aPC->D0( fpar ,uv);
    thePlateSurf -> D1(uv.X(),uv.Y(),pp2,du,dv);
    gp_Vec n1 = du^dv;
    n1.Normalize();
    
    aPC->D0( (fpar + lpar) / 2., uv);
    thePlateSurf-> D0(uv.X(),uv.Y(),pp3);
    
    gp_Vec vv1(pp2,pp1), vv2(pp2,pp3);
    gp_Vec n2 = vv2^vv1;
    n2.Normalize();
    
    SumScal1 += n1*n2;
    SumScal2 += n2*theRefDir;

    pp1 = pp3;
  }
  if (SumScal2*SumScal1>0) return TopAbs_FORWARD;
  else                     return TopAbs_REVERSED;
}
                                          
//=======================================================================
//function : PerformMoreThreeCorner
//purpose  : Process case of a top with n edges.      
//=======================================================================

void  ChFi3d_Builder::PerformMoreThreeCorner(const Standard_Integer Jndex,
                                             const Standard_Integer nconges)
{ 
//    ========================================
//             Initialisations
//     ========================================
#ifdef OCCT_DEBUG
  OSD_Chronometer ch;
#endif 
  TopOpeBRepDS_DataStructure& DStr=myDS->ChangeDS();  
  const TopoDS_Vertex& V1 = myVDataMap.FindKey(Jndex);
  Standard_Integer nedge;
  Standard_Boolean bordlibre;
  TopoDS_Edge edgelibre1,edgelibre2;
//  TopTools_ListIteratorOfListOfShape ItE;
  nedge=ChFi3d_NbNotDegeneratedEdges(V1,myVEMap);
  ChFi3d_ChercheBordsLibres(myVEMap,V1,bordlibre,edgelibre1,edgelibre2);
  Standard_Boolean droit=Standard_False;
  if (bordlibre) {nedge=(nedge-2)/2 +2;
     Standard_Real angedg=Abs(ChFi3d_AngleEdge(V1,edgelibre1,edgelibre2));
     droit=Abs(angedg-M_PI)<0.01;   
  }
  else  nedge=nedge/2;
  Standard_Integer size=nedge*2;
  ChFiDS_StripeArray1 CD(0,size);
  TColStd_Array1OfInteger jf(0,size);
  TColStd_Array1OfInteger Index(0,size);
  TColStd_Array1OfInteger Indice(0,size);
  TColStd_Array1OfInteger sens(0,size);
  TColStd_Array1OfInteger indcurve3d(0,size);
  TColStd_Array2OfInteger numfa( 0,size,0,size);
  TColStd_Array1OfInteger Order( 0,size);
  TColStd_Array2OfInteger i(0,size,0,size);
  TColStd_Array2OfInteger indpoint(0,size,0,1);
  TColStd_Array1OfBoolean  oksea(0,size);
  TColStd_Array1OfBoolean  sharp(0,size);
  TColStd_Array1OfBoolean regul(0,size);
  TColStd_Array2OfReal p (0,size,0,size);
  TColStd_Array1OfReal errapp (0,size);
  TopTools_Array1OfShape Evive(0,size);
  TopTools_Array2OfShape Fvive(0,size,0,size);
  TColStd_Array1OfBoolean ponctuel (0,size);
  TColStd_Array1OfBoolean samedge (0,size);
  TColStd_Array1OfBoolean moresurf (0,size);
  TColStd_Array1OfBoolean libre(0,size);
  TColStd_Array1OfBoolean tangentregul (0,size);
  TColStd_Array1OfBoolean isG1(0,size);
//  for(Standard_Integer ind=0;ind<=size;ind++){
  Standard_Integer ind;
  for(ind=0;ind<=size;ind++){
   indpoint.SetValue(ind,0,0);
    indpoint.SetValue(ind,1,0);
    Indice.SetValue(ind,0);
    oksea.SetValue(ind,Standard_False);
    sharp.SetValue(ind,Standard_False);
    regul.SetValue(ind,Standard_False);
    ponctuel.SetValue(ind,Standard_False);
    samedge.SetValue(ind,Standard_False);
    moresurf.SetValue(ind,Standard_False);
    libre.SetValue(ind,Standard_False);
    tangentregul.SetValue(ind,Standard_False);
    isG1.SetValue(ind,Standard_False);
  }
  ChFiDS_ListIteratorOfListOfStripe It;
  Handle(ChFiDS_Stripe) cd2,cdbid,cnext;
  TopoDS_Face face;
  Standard_Integer jfp = 0,ii;
  Standard_Integer ic,icplus,icmoins,icplus2,
                   sense,index = 0,indice,isurf1,isurf2;
  Standard_Integer n3d=0,IVtx = 0,nb;
  Standard_Boolean sameside,trouve,isfirst;
  Standard_Real pardeb ,parfin,xdir,ydir;
  Standard_Real tolapp=1.e-4,maxapp = 0.,maxapp1 = 0.,avedev;
  Handle (TopOpeBRepDS_CurvePointInterference) Interfp1, Interfp2;
  Handle (TopOpeBRepDS_SurfaceCurveInterference) Interfc;
  Handle(Geom_Curve) Curv3d;
  ChFiDS_Regul regular;
  TopTools_SequenceOfShape Fproj;
  Standard_Integer num;
  TopoDS_Edge Ecur; 
  TopTools_ListIteratorOfListOfShape ItF;
#ifdef OCCT_DEBUG
//  Standard_Integer nface=ChFi3d_nbface(myVFMap(V1));
#endif
  TopoDS_Face F1,F2;
  gp_Vec SumFaceNormalAtV1(0,0,0); // is used to define Plate orientation 

  // it is determined if there is a sewing edge
  Standard_Boolean couture=Standard_False;
  TopoDS_Face facecouture;
  TopoDS_Edge edgecouture;
  for(ItF.Initialize(myVFMap(V1));ItF.More()&&!couture;ItF.Next()) {
    TopoDS_Face fcur = TopoDS::Face(ItF.Value());
    ChFi3d_CoutureOnVertex(fcur,V1,couture,edgecouture);
    if (couture)
      facecouture=fcur;
  }

// unused surfdata are removed 
  RemoveSurfData (myVDataMap, myEFMap,edgecouture,facecouture,V1);

 // parse edges and faces
  trouve=Standard_False;
  TopoDS_Edge Enext;
  TopoDS_Vertex VV;
  TopoDS_Face Fcur,Fnext;
  for (It.Initialize(myVDataMap(Jndex));It.More()&&!trouve;It.Next()) {
    cnext=It.Value();
    CD.SetValue(0,cnext);
    Index.SetValue(0,ChFi3d_IndexOfSurfData(V1,cnext,sense));
    sens.SetValue(0,sense);
    numfa.SetValue(0 ,1,SurfIndex(CD, 0, Index.Value(0), FACE2));
    numfa.SetValue(1 ,0, numfa.Value(0 ,1));
    Fcur=TopoDS::Face(DStr.Shape(numfa.Value(0,1)));
    Fvive.SetValue(0,1,Fcur);
    Fvive.SetValue(1,0,Fcur);
    jf.SetValue(0,2);
    if (sens.Value(0)==1) 
      Ecur = CD.Value(0)->Spine()->Edges(1);
    else  
      Ecur = CD.Value(0)->Spine()->Edges(CD.Value(0)->Spine()->NbEdges());
    Evive.SetValue(0,Ecur);
    ChFi3d_cherche_edge(V1,Evive,Fcur,Enext,VV);
    trouve= !Enext.IsNull();
  }
  // find sum of all face normals at V1
  SummarizeNormal(V1, Fcur, Ecur, SumFaceNormalAtV1);
  
  Standard_Integer nbcouture=0;
  for ( ii=1; ii<nedge; ii++) {
    if (Fcur.IsSame(facecouture)&& nbcouture==0) {
      Enext=edgecouture;
      nbcouture++;
    }
    else ChFi3d_cherche_edge(V1,Evive,Fcur,Enext,VV);
    if (Enext.IsNull())
      throw Standard_ConstructionError ("PerformMoreThreeCorner: pb in the parsing of edges and faces");
    if (Enext.IsSame(edgelibre1)|| Enext.IsSame(edgelibre2)) {
      CD.SetValue(ii, cdbid);
      Index.SetValue(ii, 0);
      sens.SetValue(ii, -1);
      TopoDS_Vertex Vref;
      Vref = TopExp::FirstVertex(Enext);
      if (Vref.IsSame(V1)) sens.SetValue(ii, 1);   
      sharp.SetValue(ii, Standard_True);
      Evive.SetValue(ii, Enext);
      jf.SetValue(ii, 0);
      Indices(nedge,ii,icplus,icmoins);
      Fvive.SetValue(ii,icplus, Fcur);
      Fvive.SetValue(icplus,ii, Fcur);
      numfa.SetValue(ii,icplus, DStr.AddShape(Fcur));
      numfa.SetValue(icplus,ii,numfa.Value(ii,icplus));
      ii++;
      if (Enext.IsSame (edgelibre1)) Ecur=edgelibre2;
      else Ecur=edgelibre1;
      ChFi3d_edge_common_faces(myEFMap(Ecur),Fcur,Fcur);
      Indices(nedge,ii,icplus,icmoins);
      Fvive.SetValue(ii,icplus, Fcur);
      Fvive.SetValue(icplus,ii, Fcur);
      numfa.SetValue(ii,icplus, DStr.AddShape(Fcur));
      numfa.SetValue(icplus,ii,numfa.Value(ii,icplus));
      CD.SetValue(ii, cdbid);
      Index.SetValue(ii, 0);
      sens.SetValue(ii, -1);
      Vref = TopExp::FirstVertex(Ecur);
      if (Vref.IsSame(V1)) sens.SetValue(ii, 1);   
      sharp.SetValue(ii, Standard_True);
      Evive.SetValue(ii, Ecur);
      jf.SetValue(ii, 0); 
    }
    else {
// it is found if Enext is in the map of stripes 
      TopoDS_Edge EE;
      /*Standard_Boolean */trouve = Standard_False;
      for (It.Initialize(myVDataMap(Jndex));It.More()&&!trouve;It.Next()) {
	index = ChFi3d_IndexOfSurfData(V1,It.Value(),sense);
	if (sense==1) 
	  EE = It.Value()->Spine()->Edges(1);
	else  
	  EE = It.Value()->Spine()->Edges(It.Value()->Spine()->NbEdges());
	if (Enext.IsSame(EE)) {
	  cnext=It.Value();
	  trouve=Standard_True;
	}
      }
      if (trouve) {
	CD.SetValue(ii, cnext);
	Index.SetValue(ii, index);
	sens.SetValue(ii, sense);
	sharp.SetValue(ii, Standard_False);
	Evive.SetValue(ii, Enext);
      }
      else {
	//      edge ii is alive
	CD.SetValue(ii, cdbid);
	Index.SetValue(ii, 0);
	sens.SetValue(ii, -1);
	TopoDS_Vertex Vref;
	Vref = TopExp::FirstVertex(Enext);
	if (Vref.IsSame(V1)) sens.SetValue(ii, 1);   
	sharp.SetValue(ii, Standard_True);
	Evive.SetValue(ii, Enext);
	jf.SetValue(ii, 0);
      }
      // Face Fnext!=Fcur containing Enext 
      Fnext=Fcur;
      ChFi3d_cherche_face1(myEFMap(Enext),Fcur,Fnext);
      Indices(nedge,ii,icplus,icmoins);
      Fvive.SetValue(ii,icplus, Fnext);
      Fvive.SetValue(icplus,ii, Fnext);
      numfa.SetValue(ii,icplus, DStr.AddShape(Fnext));
      numfa.SetValue(icplus,ii,numfa.Value(ii,icplus));
      Standard_Integer numface1,numface2;
      if (trouve) {
	// it is checked if numfa corresponds to IndexOfS1 or IndexOfS2 
	// jf is updated is consequently updated
        // if it is not the case among the previous faces are found 
        // those which correspond to  IndexOfs1 IndexOfS2  and  
        // numfa and Fvive are reupdated (cts16288)  
	numface2 = SurfIndex(CD, ii, Index.Value(ii), FACE2);
	if (numface2==numfa.Value(ii,icplus))
	  jf.SetValue(ii, 2);
	else {
	  numface1 = SurfIndex(CD, ii, Index.Value(ii), FACE1);
	  if (numface1==numfa.Value(ii,icplus))
	    jf.SetValue(ii, 1);
	  else {
	    if (numface1==numfa.Value(icmoins,ii))  {
	      jf.SetValue(ii, 2);
	      Fvive.SetValue(ii,icplus,TopoDS::Face(DStr.Shape(numface2)));
	      Fvive.SetValue(icplus,ii,TopoDS::Face(DStr.Shape(numface2)));
	      numfa.SetValue(ii,icplus, DStr.AddShape(TopoDS::Face(DStr.Shape(numface2))));
	      numfa.SetValue(icplus,ii, numfa.Value (ii,icplus));
	    }
	    if (numface2==numfa.Value(icmoins,ii)) {
	      jf.SetValue(ii, 1);
	      Fvive.SetValue(ii,icplus,TopoDS::Face(DStr.Shape(numface1)));
	      Fvive.SetValue(icplus,ii,TopoDS::Face(DStr.Shape(numface1)));
	      numfa.SetValue(ii,icplus, DStr.AddShape(TopoDS::Face(DStr.Shape(numface1))));
	      numfa.SetValue(icplus,ii, numfa.Value (ii,icplus));
	    }
	  }
	}
      }
      Ecur = Enext;
      Fcur = Fnext;
      // find sum of all face normales at V1
      SummarizeNormal(V1, Fcur, Ecur, SumFaceNormalAtV1);
    }
  }
  // mise a jour du tableau regul 
  for (ic=0;ic<nedge;ic++) {
    if (sharp.Value(ic)) {
      Ecur=TopoDS::Edge(Evive.Value(ic));
      if (!Ecur.IsSame(edgecouture)) {
	ChFi3d_edge_common_faces(myEFMap(Ecur),F1,F2);   
//  Modified by Sergey KHROMOV - Fri Dec 21 18:11:02 2001 Begin
// 	regul.SetValue(ic,BRep_Tool::Continuity(TopoDS::Edge(Evive.Value(ic)),F1,F2)
// 		     !=GeomAbs_C0); 
	regul.SetValue(ic, ChFi3d::IsTangentFaces(TopoDS::Edge(Evive.Value(ic)),F1,F2)); 
//  Modified by Sergey KHROMOV - Fri Dec 21 18:11:07 2001 End
      }
    }
  }
  // it is checked if a regular edge is not tangent to another edge
  // in case if it is not considered regular (cts60072)
  for (ic=0;ic<nedge;ic++) {
    if (regul.Value(ic) ) {
      trouve=Standard_False;
      TopoDS_Edge ereg=TopoDS::Edge(Evive.Value(ic));
      for( ind=0;ind<nedge &&!trouve;ind++) {
	if (ind!=ic) {
	  TopoDS_Edge ecur=TopoDS::Edge(Evive.Value(ind));
	  Standard_Real ang=Abs(ChFi3d_AngleEdge(V1,ecur,ereg)); 
	  if (ang<0.01 || Abs(ang-M_PI) <0.01) {
	    regul.SetValue(ic,Standard_False);
	    tangentregul.SetValue(ic,Standard_True);
	    trouve=Standard_True;
	  }  
	}
      }   
    }
  }

  // variable deuxconges allows detecting cases when there is a top with 
  // n edges and two fillets on two tangent edges that are not free borders
  // the connecting curves start from the fillet and end on top 
  
  Standard_Boolean deuxconges,deuxcgnontg;
  deuxconges=Standard_False;
  trouve=Standard_False;
  if (nconges==2) {
    TopoDS_Edge E1,E2; 
    for (ic=0;ic<nedge&&!trouve;ic++) {
      Indices(nedge,ic,icplus,icmoins);
      if (!sharp.Value(ic) && !sharp.Value(icplus)){
	E1=TopoDS::Edge(Evive.Value(ic));
	E2=TopoDS::Edge(Evive.Value(icplus));                                   
	deuxconges=(Abs(ChFi3d_AngleEdge(V1 ,E1,E2)   )<0.01) ;
        trouve=deuxconges;
      }
    }
  }

  // variable deuxconges is used in the special case when there are 
  // two fillets and if two other living edges are tangent (cts60072) 
  if (nconges==2 && nedge==4) {
    TopoDS_Edge E1,E2; 
     for (ic=0;ic<nedge&&!deuxconges;ic++) {
       Indices(nedge,ic,icplus,icmoins);
       if (sharp.Value(ic) && sharp.Value(icplus)){
	 E1=TopoDS::Edge(Evive.Value(ic));
	 E2=TopoDS::Edge(Evive.Value(icplus));
         if ( !E1.IsSame(edgelibre1) && !E1.IsSame(edgelibre2) &&
              !E2.IsSame(edgelibre1) && !E2.IsSame(edgelibre2)){ 
	   Standard_Real ang=Abs(ChFi3d_AngleEdge(V1 ,E1,E2));
	   deuxconges=(ang<0.01 || Abs(ang-M_PI)<0.01);
         }
       }
     }
  }
  
  deuxcgnontg=nconges==2&& nedge==3 && !deuxconges; // pro12305 

  if (deuxconges )
  for  (ic=0;ic<nedge;ic++){
   regul.SetValue(ic,Standard_False);
  }

  // Detect case of 3 edges & 2 conges: OnSame + OnDiff
  // (eap, Arp 9 2002, occ266)
  Standard_Boolean isOnSameDiff = Standard_False;
  if (deuxcgnontg) {
    Standard_Boolean isOnSame = Standard_False, isOnDiff = Standard_False;
    for (ic=0; ic<nedge; ic++) {
      if (sharp.Value(ic)) continue;
      ChFiDS_State stat;
      if ( sens(ic) == 1 )
	stat = CD.Value(ic)->Spine()->FirstStatus();
      else
	stat = CD.Value(ic)->Spine()->LastStatus();
      
      if      (stat == ChFiDS_OnSame) isOnSame = Standard_True;
      else if (stat == ChFiDS_OnDiff) isOnDiff = Standard_True;
    }
    isOnSameDiff = isOnSame && isOnDiff;
  }
  if ( isOnSameDiff ) {
#ifdef OCCT_DEBUG
    std::cout << "OnSame + OnDiff, PerformMoreThreeCorner() calls PerformOneCorner()" << std::endl;
#endif
    PerformOneCorner (Jndex, Standard_True);
  }

// if the commonpoint is on an edge that does not have a 
// vertex at the extremity, Evive is found anew    
// Fvive is found anew if it does not correspond 
// to two faces adjacent to Evive (cts16288)

  if (!deuxconges && !isOnSameDiff) 
    for (ic=0;ic<nedge;ic++) { 
      if (sharp.Value(ic)) {
	Indices(nedge,ic,icplus,icmoins);
        TopoDS_Edge Arc=TopoDS::Edge(Evive.Value(ic));
	ChFiDS_CommonPoint cp1, cp2;
        Standard_Real angedg=M_PI;
        TopoDS_Vertex Vcom;
	if (!sharp.Value(icplus)) {
	  isfirst=(sens.Value(icplus)==1);
	  jfp = 3 - jf.Value(icplus);
	  cp1 = CD.Value(icplus)->SetOfSurfData()->Value(Index.Value(icplus))->
	    ChangeVertex (isfirst,jfp);
	  if (cp1.IsOnArc()){
            ChFi3d_cherche_vertex(Arc,cp1.Arc(),Vcom,trouve);
            if (trouve) angedg=Abs(ChFi3d_AngleEdge(Vcom,Arc,cp1.Arc()));
      if (!cp1.Arc().IsSame(Arc) && Abs(angedg-M_PI)<0.01){
	      Evive.SetValue(ic,cp1.Arc());
	      ChFi3d_edge_common_faces(myEFMap(cp1.Arc()),F1,F2);
     if (!Fvive.Value(ic,icplus).IsSame(F1) && !Fvive.Value(ic,icplus).IsSame(F2)) {
	        if (Fvive.Value(ic,icmoins).IsSame(F2))  {
		  Fvive.SetValue(ic,icplus,F1);
                  Fvive.SetValue(icplus,ic,F1);
		  numfa.SetValue(ic,icplus,DStr.AddShape(F1)); 
                  numfa.SetValue(icplus,ic,DStr.AddShape(F1)); 
      }
      else  {
		  Fvive.SetValue(ic,icplus,F2);
                  Fvive.SetValue(icplus,ic,F2);
		  numfa.SetValue(ic,icplus,DStr.AddShape(F2)); 
                  numfa.SetValue(icplus,ic,DStr.AddShape(F2)); 
		}
	      }
	      samedge.SetValue(ic,Standard_True);
	      p.SetValue(ic,icplus,cp1.ParameterOnArc());
	      p.SetValue(ic,icmoins,cp1.ParameterOnArc());  
	      i.SetValue(ic,icplus,1);	      
	    }
	  }
	}
	if (!sharp.Value(icmoins)) {
	  isfirst=(sens.Value(icmoins)==1);
	  cp2 = CD.Value(icmoins)->SetOfSurfData()->Value(Index.Value(icmoins))->
	    ChangeVertex (isfirst,jf.Value(icmoins));
	  if (cp2.IsOnArc()) {
            angedg=M_PI;
            ChFi3d_cherche_vertex(Arc,cp2.Arc(),Vcom,trouve);
            if (trouve) angedg=Abs(ChFi3d_AngleEdge(Vcom,Arc,cp2.Arc()));
	    if (!cp2.Arc().IsSame(Arc)&&Abs(angedg-M_PI)<0.01) {
	      Evive.SetValue(ic,cp2.Arc());
	      ChFi3d_edge_common_faces(myEFMap(cp2.Arc()),F1,F2);
	      if (!Fvive.Value(ic,icmoins).IsSame(F1) && !Fvive.Value(ic,icmoins).IsSame(F2)) {
	        if (Fvive.Value(ic,icplus).IsSame(F2))  {
		  Fvive.SetValue(ic,icmoins,F1);
		  numfa.SetValue(ic,icmoins,DStr.AddShape(F1));
                  Fvive.SetValue(icmoins,ic,F1);
		  numfa.SetValue(icmoins,ic,DStr.AddShape(F1)); 
                }
		else  {
		  Fvive.SetValue(ic,icmoins,F2);
		  numfa.SetValue(ic,icmoins,DStr.AddShape(F2));
                  Fvive.SetValue(icmoins,ic,F2);
		  numfa.SetValue(icmoins,ic,DStr.AddShape(F2)); 
		}
	      }
	      samedge.SetValue(ic,Standard_True);
	      p.SetValue(ic,icmoins,cp2.ParameterOnArc());
	      p.SetValue(ic,icplus,cp2.ParameterOnArc());
	      i.SetValue(ic,icmoins,1);   
	    }
	  }
	}     
      }
    } 

// the first free edge is restored if it exists
  trouve=Standard_False;
  for (ic=0; ic<nedge&&!trouve;ic++) {  
    TopoDS_Edge ecom;
    ecom=TopoDS::Edge(Evive.Value(ic));
    if (ecom.IsSame(edgelibre1)||ecom.IsSame(edgelibre2)){ 
      libre.SetValue(ic,Standard_True);
      trouve=Standard_True;
    }
  }  

// determine the minimum recoil distance that can't be exceeded 
  Standard_Boolean distmini=Standard_False;
  gp_Pnt som=BRep_Tool::Pnt(V1),pic;  
  gp_Pnt2d p2;
  TopoDS_Edge edgemin;
  TopoDS_Vertex V,V2;
  Standard_Real dst,distmin;
  distmin=1.e30;
  for (ic=0;ic<nedge;ic++) {
    if (sharp.Value(ic))
      edgemin=TopoDS::Edge(Evive.Value(ic));
    else {
      if (sens.Value(ic)==1) 
	edgemin= CD.Value(ic)->Spine()->Edges(1);
      else  
	edgemin = CD.Value(ic)->Spine()->Edges(CD.Value(ic)->Spine()->NbEdges());
    }
    V=TopExp::FirstVertex(edgemin);
    V2=TopExp::LastVertex(edgemin);
    dst=(BRep_Tool::Pnt(V)).Distance(BRep_Tool::Pnt(V2))/1.5;
    if (dst<distmin) distmin=dst;
  }

//  calculate intersections between stripes and determine the parameters on each pcurve  
  Standard_Boolean inters=Standard_True;
  for (ic=0;ic<nedge;ic++) {
    Indices(nedge,ic,icplus,icmoins);
    if (sharp.Value(ic)||sharp.Value(icplus)) {
      oksea.SetValue(ic, Standard_False);
    }
    else {
      Standard_Integer jf1 = 0;
      Standard_Integer i1 = 0,i2 = 0;
      Standard_Real pa1 = 0.,pa2;
      Standard_Boolean ok;
      Handle(ChFiDS_Stripe) strip;
      Standard_Real angedg;
      Standard_Integer iface;
      // if two edges are tangent the intersection is not attempted (cts60046)
      angedg=Abs(ChFi3d_AngleEdge(V1,TopoDS::Edge(Evive.Value(ic)),TopoDS::Edge(Evive.Value(icplus))));
      if (Abs(angedg-M_PI)>0.01)
	ok = ChFi3d_SearchFD(DStr,CD.Value(ic),CD.Value(icplus),sens.Value(ic),sens.Value(icplus),
				  i1,i2,pa1,pa2,
				  Index.Value(ic),Index.Value(icplus),
				  face,sameside,jf1,jfp);
      else ok=Standard_False;
     // if there is an intersection it is checked if surfdata with the intersection
     // corresponds to the first or the last 
     // if this is not the case, the surfdata are removed from SD 
      
      if (ok) {
	if (i1!=Index.Value(ic) ){
          Standard_Integer ideb,ifin;
          strip=CD.Value(ic);
          if (sens.Value(ic)==1) {
	    ideb=Index.Value(ic);
	    ifin=i1-1;
          }
          else {
	    ifin=Index.Value(ic);
	    ideb=i1+1;
          }
          if (i1<Index.Value(ic)) {
	    for (nb=Index.Value(ic);nb>=i1;nb--) {
	      if ((3-jf1)==1) 
		iface=SurfIndex(CD, ic, nb , FACE1);
	      else    iface=SurfIndex(CD, ic, nb , FACE2);
	      Fproj.Append(TopoDS::Face(myDS->Shape(iface)));  
	    }
          }
          if (i1>Index.Value(ic)) {
	    for (nb=Index.Value(ic);nb<=i1;nb++) {
	      if ((3-jf1)==1) 
		iface=SurfIndex(CD, ic, nb , FACE1);
	      else    iface=SurfIndex(CD, ic, nb , FACE2);
               Fproj.Append(TopoDS::Face(myDS->Shape(iface)));  
	    }
          }    
          strip=CD.Value(ic);
	  RemoveSD(strip,ideb,ifin);
	  num=ChFi3d_IndexOfSurfData(V1,CD.Value(ic),sense);
	  Index.SetValue(ic,num);
	  i1=num; 
	}
	if (i2!=Index.Value(icplus) ){
          Standard_Integer ideb,ifin;
          strip=CD.Value(icplus);
          if (sens.Value(icplus)==1) {
	    ideb=Index.Value(icplus);
	    ifin=i2-1;
          }
          else {
	    ifin=Index.Value(icplus);
	    ideb=i2+1;
          }
	  
          if (i2<Index.Value(icplus)) {
	    for (nb=i2;nb<=Index.Value(icplus);nb++) {
	      if ((3-jfp)==1) 
		iface=SurfIndex(CD, icplus, nb , FACE1);
	      else    iface=SurfIndex(CD, icplus, nb , FACE2);
	      Fproj.Append(TopoDS::Face(myDS->Shape(iface)));  
	    }
          }
          if (i2>Index.Value(icplus)) {
	    for (nb=i2;nb>=Index.Value(icplus);nb--) {
	      if ((3-jfp)==1) 
		iface=SurfIndex(CD, icplus, nb , FACE1);
	      else    iface=SurfIndex(CD, icplus, nb , FACE2);
	      Fproj.Append(TopoDS::Face(myDS->Shape(iface)));  
	    }
          }    
	  RemoveSD(strip,ideb,ifin);
	  num=ChFi3d_IndexOfSurfData(V1,CD.Value(icplus),sense);
	  Index.SetValue(icplus,num);
	  i2=num; 
      }
	Calcul_P2dOnSurf(CD.Value(ic),jf1,i1,pa1,p2);
	indice=SurfIndex(CD, ic, i1, ChFiSURFACE);
	DStr.Surface(indice).Surface()->D0(p2.X(),p2.Y(),pic);
	if (pic.Distance(som)>distmin) distmini =Standard_True;
	jf.SetValue(ic,jf1);
	i.SetValue(ic,icplus,i1);
	i.SetValue(icplus,ic,i2);
	p.SetValue(ic,icplus,pa1);
	p.SetValue(icplus,ic,pa2);
      }
      oksea.SetValue(ic, ok);
    }
    if (!oksea.Value(ic) ) inters=Standard_False; 
  }

  // case if there are only intersections 
  // the parametres on Pcurves are the extremities of the stripe
  Standard_Real para;
  if (!inters) {
    for (ic=0;ic<nedge;ic++) {
      Indices(nedge,ic,icplus,icmoins);
      Indices(nedge,icplus,icplus2,ic);
      if (!oksea.Value(ic)) {
	if (sharp.Value(ic)) {
          if (!samedge.Value(ic)){
            para=BRep_Tool::Parameter(V1,TopoDS::Edge(Evive.Value(ic)));
	    p.SetValue(ic,icplus,para);
	    i.SetValue(ic,icplus,1);
          }
	}
	else {
	  isfirst= (sens.Value(ic)==1);
	  i.SetValue(ic,icplus,ChFi3d_IndexOfSurfData(V1,CD.Value(ic),sense));
	  if (oksea.Value(icmoins)) {
           para=p.Value(ic,icmoins);
	   p.SetValue(ic,icplus,para);
          }
	  else {
	    Calcul_Param(CD.Value(ic),jf.Value(ic),i.Value(ic,icplus),isfirst,para);
            p.SetValue(ic,icplus,para);
          }
   	}
	if (sharp.Value(icplus)) {
          if (!samedge.Value(icplus)) {
            para=BRep_Tool::Parameter(V1,TopoDS::Edge(Evive.Value(icplus)));
	    p.SetValue(icplus,ic, para);
	    i.SetValue(icplus,ic,1);
          }
	}
	else {
	  isfirst= (sens.Value(icplus)==1);
	  i.SetValue(icplus,ic,ChFi3d_IndexOfSurfData(V1,CD.Value(icplus),sense));
	  if (oksea.Value(icplus)){
          para=p.Value(icplus,icplus2);
	  p.SetValue(icplus,ic,para);
          }
	  else {
	    jfp = 3 - jf.Value(icplus);
	    Calcul_Param(CD.Value(icplus),jfp,i.Value(icplus,ic),isfirst,para);
            p.SetValue(icplus,ic,para);
	  }
   	}
      }
    }
      
//  calculate max distance to the top at each point  
    TColStd_Array1OfReal dist1(0,size);
    TColStd_Array1OfReal dist2(0,size);
    Standard_Real distance=0.;
    gp_Pnt sommet=BRep_Tool::Pnt(V1);
    if (!deuxconges)
    for (ic=0;ic<nedge;ic++) {
      Indices(nedge,ic,icplus,icmoins);
      if (sharp.Value(ic)) {
	dist1.SetValue(ic, 0);
	dist2.SetValue(ic, 0);
      }
      else {        
	jfp = 3 - jf.Value(ic);       
	Calcul_P2dOnSurf(CD.Value(ic),jfp,i.Value(ic,icmoins),p.Value(ic,icmoins),p2);
	indice=SurfIndex(CD, ic, i.Value(ic,icmoins), ChFiSURFACE);
	DStr.Surface(indice).Surface()->D0(p2.X(),p2.Y(),pic);
	dist1.SetValue(ic, sommet.Distance(pic));
	if (dist1.Value(ic) > distance ) distance= dist1.Value(ic);

	Calcul_P2dOnSurf(CD.Value(ic),jf.Value(ic),i.Value(ic,icplus),p.Value(ic,icplus),p2);
	indice=SurfIndex(CD, ic, i.Value(ic,icplus), ChFiSURFACE);
	DStr.Surface(indice).Surface()->D0(p2.X(),p2.Y(),pic);
	dist2.SetValue(ic, sommet.Distance(pic));
	if( dist2.Value(ic) > distance  )  
	  distance= dist2.Value(ic);
      }
    }

//  offset of parameters and removal of intersection points 
//  too close to the top 

    Standard_Real ec, dist; 
    if (!deuxconges && !deuxcgnontg)
    for (ic=0;ic<nedge;ic++) {
      Indices(nedge,ic,icplus,icmoins);
      if (sharp.Value(ic) ) {
        BRepAdaptor_Curve C(TopoDS::Edge(Evive.Value(ic)));
        // to pass from 3D distance to a parametric distance
	if (!tangentregul(ic))
	  ec = distance*100*C.Resolution(0.01);
        else ec=0.0;
	if (TopExp::FirstVertex(TopoDS::Edge(Evive.Value(ic))).IsSame(V1)) {
          para=p.Value(ic,icmoins) + ec;
	  p.SetValue(ic,icmoins, para);
        }
	else {
          para=p.Value(ic,icmoins) - ec;
	  p.SetValue(ic,icmoins,para);
        }
// it is necessary to be on to remain on the edge
	p.SetValue(ic,icplus, p.Value(ic,icmoins));
      }
      else if (!distmini) {
	dist = dist1.Value(ic);
	if ((!oksea.Value(icmoins))||(oksea.Value(icmoins)&&(distance>1.3*dist))) {
	  ec= distance-dist;
	  if (oksea.Value(icmoins)) {
	    oksea.SetValue(icmoins,Standard_False);
	    inters=Standard_False;
	  }
	  if (sens.Value(ic)==1) {
            para=p.Value(ic,icmoins) + ec;
            p.SetValue(ic,icmoins, para);
          }
	  else{
             para=p.Value(ic,icmoins) - ec;
             p.SetValue(ic,icmoins,para);
          }
	}
	dist = dist2.Value(ic);
	if ((!oksea.Value(ic))||(oksea.Value(ic)&&(distance>1.3*dist))) {
	  if(oksea.Value(ic)) { 
	    oksea.SetValue(ic,Standard_False);
	    inters=Standard_False;
	  }
	  if (nconges!=1) {
	    Standard_Real parold,parnew;
	    parold=p.Value(ic,icplus);
	    parnew=p.Value(ic,icmoins);
	    if (sens.Value(ic)==1) {
	      if (parnew> parold) p.SetValue(ic,icplus, p.Value(ic,icmoins));
	    }
	    else {
	      if (parnew<parold) p.SetValue(ic,icplus, p.Value(ic,icmoins));
	    }
	  }  
	}
      }
    }
  }

// it is attempted to limit the edge by a commonpoint
//
 
  Standard_Real tolcp=0;
  gp_Pnt PE, sommet=BRep_Tool::Pnt(V1);
  if (!deuxconges)  
  for (ic=0;ic<nedge;ic++) {
    if (sharp.Value(ic)) {
      Indices(nedge,ic,icplus,icmoins);
      BRepAdaptor_Curve C(TopoDS::Edge(Evive.Value(ic)));
      PE = C.Value(p.Value(ic,icplus));
      Standard_Real d1=0., d2=0., dS = PE.Distance(sommet);
      ChFiDS_CommonPoint cp1, cp2;
      if (!sharp.Value(icplus)) {
	isfirst=(sens.Value(icplus)==1);
	jfp = 3 - jf.Value(icplus);
	cp1 = CD.Value(icplus)->SetOfSurfData()->Value(i.Value(icplus,ic))->
	  ChangeVertex (isfirst,jfp);
	d1 = cp1.Point().Distance(sommet);
      }
      if (!sharp.Value(icmoins)) {
	isfirst=(sens.Value(icmoins)==1);
	cp2 = CD.Value(icmoins)->SetOfSurfData()->Value(i.Value(icmoins,ic))->
	  ChangeVertex (isfirst,jf.Value(icmoins));
	d2 = cp2.Point().Distance(sommet);
      }
      Standard_Boolean samecompoint=Standard_False;
      if (!sharp.Value(icmoins) &&  !sharp.Value(icplus))
	samecompoint=cp1.Point().Distance(cp2.Point())<tolapp;
      if ((dS<d1 || dS<d2)&& !samecompoint) {
// step back till Common Points
// without leaving the Edge ??
	if (d2<d1 &&cp1.IsOnArc() ) {
// cp1 is chosen
	  p.SetValue(ic,icmoins, cp1.ParameterOnArc());
	  p.SetValue(ic,icplus, p.Value(ic,icmoins));
	  isfirst=(sens.Value(icplus)==1);
	  jfp = 3 - jf.Value(icplus);
	  Calcul_Param(CD.Value(icplus),jfp,i.Value(icplus,ic),isfirst,para);
          p.SetValue(icplus,ic,para);
          if (cp1.Tolerance()>tolcp &&cp1.Tolerance()<1 ) tolcp=cp1.Tolerance();
	}
	else if( cp2.IsOnArc()){
// cp2 is chosen
	  p.SetValue(ic,icmoins, cp2.ParameterOnArc());
	  p.SetValue(ic,icplus, p.Value(ic,icmoins));
	  isfirst=(sens.Value(icmoins)==1);
	  Calcul_Param(CD.Value(icmoins),jf.Value(icmoins),i.Value(icmoins,ic),isfirst, para);
          p.SetValue(icmoins,ic,para);
           if (cp2.Tolerance()>tolcp&&cp2.Tolerance()<1) tolcp=cp2.Tolerance();
	}
      }
      else {
// step back till Common Point only if it is very close
	if (!sharp.Value(icplus)) {
	  if ((cp1.Point().Distance(PE)<cp1.Tolerance() || 
               samecompoint || nconges==1) && cp1.IsOnArc()) {
// it is very close to cp1
	    p.SetValue(ic,icmoins, cp1.ParameterOnArc());
            ponctuel.SetValue(ic,Standard_True);
	    p.SetValue(ic,icplus, p.Value(ic,icmoins));
	    isfirst=(sens.Value(icplus)==1);
	    jfp = 3 - jf.Value(icplus);
	    Calcul_Param(CD.Value(icplus),jfp,i.Value(icplus,ic),isfirst,para);
            p.SetValue(icplus,ic,para);
            if (cp1.Tolerance()>tolcp &&cp1.Tolerance()<1) tolcp=cp1.Tolerance();
	  }
	}
	 if (!sharp.Value(icmoins)){
	  if ((cp2.Point().Distance(PE)<cp2.Tolerance() || 
	       samecompoint || nconges==1) && cp2.IsOnArc()) {
// it is very close to cp2
            ponctuel.SetValue(icmoins,Standard_True);
	    p.SetValue(ic,icmoins, cp2.ParameterOnArc());
	    p.SetValue(ic,icplus,p.Value(ic,icmoins));
	    isfirst=(sens.Value(icmoins)==1);
	    Calcul_Param(CD.Value(icmoins),jf.Value(icmoins),i.Value(icmoins,ic),isfirst,para);
            p.SetValue(icmoins,ic,para);
            if (cp2.Tolerance()>tolcp&&cp2.Tolerance()<1 ) tolcp=cp2.Tolerance();
	  }
	}
      }
    }
  }

// in case of a free border the parameter corresponding 
// to the common point on the free edge is chosen. 

  for (ic=0;ic<nedge;ic++) {
    if (TopoDS::Edge(Evive.Value(ic)).IsSame(edgelibre1) || 
	TopoDS::Edge(Evive.Value(ic)).IsSame(edgelibre2)) {
      Standard_Integer indic;
      ChFiDS_CommonPoint CP1;
      Indices(nedge,ic,icplus,icmoins);
      if (libre.Value(ic))indic=icmoins;
      else indic=icplus;
      if (!sharp(indic)) {
	isfirst=sens.Value(indic)==1;         
	CP1 = CD.Value(indic)->SetOfSurfData()->Value(Index.Value(indic))->ChangeVertex(isfirst,1);
	/*Standard_Boolean*/ trouve=Standard_False;
	if (CP1.IsOnArc()) {
	  if(CP1.Arc().IsSame(TopoDS::Edge(Evive.Value(ic)))) {
	    p.SetValue(ic,icmoins,CP1.ParameterOnArc());
            p.SetValue(ic,icplus,CP1.ParameterOnArc());
            trouve=Standard_True;
	  }  
	}
	if (!trouve) {
	  CP1 = CD.Value(indic)->SetOfSurfData()->Value(Index.Value(indic))->ChangeVertex(isfirst,2);
	  if (CP1.IsOnArc()) {
	    if(CP1.Arc().IsSame(TopoDS::Edge(Evive.Value(ic)))) {
	      p.SetValue(ic,icmoins,CP1.ParameterOnArc());
              p.SetValue(ic,icplus,CP1.ParameterOnArc());
	    }  
	  }
	}
      }
    }   
  }

// if ic is a regular edge, one finds edge indfin which is not 
// a regular edge, and construtc a curve 3d 
// between edges (or stripes ) icmoins and indfin. 
// Then this courbe3d is projected on all faces (nbface) that
// separate icmoins and indfin
  Standard_Integer nbface = 0;
  Standard_Real  error = 0.;
  TColGeom2d_Array1OfCurve proj2d1(0,size);
  TColGeom2d_Array1OfCurve proj2d2(0,size);
  TColGeom_Array1OfCurve cproj1(0,size);
  TColGeom_Array1OfCurve cproj2(0,size);
  if (!deuxconges) 
  for (ic=0;ic<nedge;ic++) {
    Standard_Integer ilin;
    TColGeom_SequenceOfCurve cr;
    TColGeom2d_SequenceOfCurve pr;
    TopTools_SequenceOfShape Lface;
    TopTools_SequenceOfShape Ledge;
    Lface.Clear();
    if (regul.Value(ic)){
      Indices(nedge,ic,icplus,icmoins);
      Indices(nedge,icplus,icplus2,ic);
      Standard_Integer indfin,indfinmoins,indfinplus;
      indfin=icplus;
      trouve=Standard_False;
      ii=icplus;
      while (!trouve) { 
        if (!regul.Value(ii)) { 
	  indfin=ii;
	  trouve=Standard_True;
        }
        if (ii==nedge-1) ii=0;
        else ii++;
      } 
      Indices(nedge,indfin,indfinplus,indfinmoins);
      if (!sharp.Value(icmoins)){
	if( jf.Value(icmoins)==1)
          ilin= SurfIndex(CD, icmoins, i.Value(icmoins,ic), FACE1);
	else 
          ilin= SurfIndex(CD, icmoins, i.Value(icmoins,ic), FACE2);
	Lface.Append(TopoDS::Face(DStr.Shape(ilin)));
      }
      else Lface.Append( Fvive(ic,icmoins));
      if (indfin>icmoins) 
	nbface=indfin-icmoins;
      else nbface =nedge-(icmoins-indfin);
      TopTools_SequenceOfShape Epj;
      TColStd_SequenceOfReal  seqpr;
      ii=ic;
      for (Standard_Integer nf=1;nf<=nbface-1;nf++) { 
        Standard_Integer iimoins,iiplus;
        Indices(nedge,ii,iiplus,iimoins); 
        Ledge.Append(TopoDS::Edge(Evive.Value(ii)));
        seqpr.Append(p.Value(ii,iiplus));
        if (nf!=nbface-1) Lface.Append( Fvive(ii,iiplus));
        if (ii==nedge-1) ii=0;
        else ii++;
      }
      if (!sharp.Value(indfin) ){
	jfp=3-jf.Value(indfin);   
	if (jfp==1) 
	  ilin= SurfIndex(CD, indfin, i.Value(indfin,indfinmoins), FACE1);
	else  ilin=SurfIndex(CD, indfin, i.Value(indfin,indfinmoins), FACE2);
	Lface.Append(TopoDS::Face(DStr.Shape(ilin)));
      }
      else  Lface.Append(Fvive(indfin,indfinmoins));
      CurveHermite(DStr,CD.Value(icmoins),jf.Value(icmoins),i.Value(icmoins,ic),
		   p.Value(icmoins,ic),sens.Value(icmoins),sharp.Value(icmoins),
		   TopoDS::Edge(Evive.Value(icmoins)),CD.Value(indfin),jf.Value(indfin),
		   i.Value(indfin,indfinmoins),p.Value(indfin,indfinmoins),sens.Value(indfin),
		   sharp.Value(indfin),TopoDS::Edge(Evive.Value(indfin)),nbface,Ledge,
		   Lface,pr,cr,Epj,seqpr,error);
      ii=ic;
      for (ind=1;ind<=nbface-1;ind++) {
        Standard_Integer iimoins,iiplus;
        Indices(nedge,ii,iiplus,iimoins);
	p.SetValue(ii,iiplus,seqpr.Value(ind));
	p.SetValue(ii,iimoins,seqpr.Value(ind));
	proj2d1.SetValue(ii,pr.Value(ind));
	proj2d2.SetValue(ii,pr.Value(ind+1));
	cproj1.SetValue(ii,cr.Value(ind));
	cproj2.SetValue(ii,cr.Value(ind+1));
        if (ii==nedge-1) ii=0;
        else ii++;
      }
      if (!sharp.Value(icmoins)&&!sharp.Value(indfin)) {   
        ii=icmoins;
        while (ii!=indfin) {
         isG1.SetValue(ii,Standard_True);
         if (ii==nedge-1) ii=0;
         else ii++;
        }
      }
      ic=ic+nbface-1;
    }       
  }

 // case when the conncting curve between ic and icplus crosses many faces
  
  TopTools_SequenceOfShape Ecom;
  TopTools_SequenceOfShape Eproj;
  TColStd_SequenceOfReal parcom; 
  if (!deuxconges) 
  for (ic=0;ic<nedge;ic++) {
    Standard_Integer iface1,iface2;
    TopoDS_Face face1,face2;
    TopoDS_Edge edge;
    TColGeom_SequenceOfCurve cr;
    TColGeom2d_SequenceOfCurve pr;
    Indices(nedge,ic,icplus,icmoins);
    if (!oksea.Value(ic)){
      iface1=numfa.Value(ic,icplus);
      iface2=numfa.Value(icplus,ic);
       if (!sharp.Value(ic)) {
        if (jf.Value(ic)==1)
	  iface1 =SurfIndex(CD, ic, i.Value(ic,icplus), FACE1);
        else   iface1=SurfIndex(CD, ic, i.Value(ic,icplus), FACE2);
      }
      face1=TopoDS::Face(myDS->Shape(iface1));
      
      if (!sharp.Value(icplus)) {
	if (jf.Value(icplus)==1)
	  iface2 =SurfIndex(CD, icplus, i.Value(icplus,ic), FACE2);
	else   iface2=SurfIndex(CD, icplus, i.Value(icplus,ic), FACE1);
      }
      face2=TopoDS::Face(myDS->Shape(iface2));
      if (!face1.IsSame(face2)) {
	if (Fproj.Length()==0) {
	  Fproj.Append(face1);
	  Fproj.Append(face2); 
	}
	moresurf.SetValue(ic,Standard_True);	
	nbface=Fproj.Length();
	if (!TopoDS::Face(Fproj.Value(nbface)).IsSame(face2)) {
	  Fproj.Remove(nbface); 
	  Fproj.Append(face2);   
	}
	if (!TopoDS::Face(Fproj.Value(1)).IsSame(face1)) {
	  Fproj.Remove(1); 
	  Fproj.Prepend(face1);   
	}
	for (nb=1;nb<=nbface-1; nb++) {
          cherche_edge1 ( TopoDS::Face(Fproj.Value(nb)), TopoDS::Face(Fproj.Value(nb+1)),edge);
          Ecom.Append(edge); 
	  para=BRep_Tool::Parameter(TopExp::FirstVertex(edge),edge);
	  parcom.Append(para);   
	}      
	CurveHermite (DStr,CD.Value(ic),jf.Value(ic),i.Value(ic,icplus),
		    p.Value(ic,icplus),sens.Value(ic),sharp.Value(ic),
                    TopoDS::Edge(Evive.Value(ic)),
	            CD.Value(icplus),jf.Value(icplus),i.Value(icplus,ic),
                    p.Value(icplus,ic),sens.Value(icplus),sharp.Value(icplus),
                    TopoDS::Edge(Evive.Value(icplus)),nbface,Ecom,Fproj, pr,cr,Eproj,parcom,error);
	Ecom.Append(Ecom.Value(nbface-1)); 
	parcom.Append(parcom.Value(nbface-1));
      }
    }
  } 

// case when two fillets have the same commonpoints 
// one continues then by intersection 
// it is checked if the extremities of the intersection coincide with commonpoints

  Standard_Boolean intersection=Standard_False, introuve;
  if (nconges==2 && !deuxconges) { 
    gp_Pnt P1,P2,P3,P4;
    Standard_Integer ic1 = 0,ic2 = 0;
    trouve=Standard_False;
    for (ic=0;ic<nedge&&!trouve;ic++) {
      if (!sharp.Value(ic)){ 
	ic1=ic;
	trouve=Standard_True;
      }
    }
    for (ic=0;ic<nedge;ic++) {
      if (!sharp.Value(ic)&& ic!=ic1) ic2=ic;   
    }
    jfp = 3 - jf.Value(ic1);
    Indices(nedge,ic1,icplus,icmoins);   
    Calcul_P2dOnSurf(CD.Value(ic1),jfp,i.Value(ic1,icmoins),p.Value(ic1,icmoins),p2);
    indice=SurfIndex(CD, ic1, i.Value(ic1,icmoins), ChFiSURFACE);
    DStr.Surface(indice).Surface()->D0(p2.X(),p2.Y(),P1);
    
    Calcul_P2dOnSurf(CD.Value(ic1),jf.Value(ic1),i.Value(ic1,icplus),p.Value(ic1,icplus),p2);
    indice=SurfIndex(CD, ic1, i.Value(ic1,icplus), ChFiSURFACE);
    DStr.Surface(indice).Surface()->D0(p2.X(),p2.Y(),P2);
    
    jfp = 3 - jf.Value(ic2);    
    Indices(nedge,ic2,icplus,icmoins);   
    Calcul_P2dOnSurf(CD.Value(ic2),jfp,i.Value(ic2,icmoins),p.Value(ic2,icmoins),p2);
    indice=SurfIndex(CD, ic2, i.Value(ic2,icmoins), ChFiSURFACE);
    DStr.Surface(indice).Surface()->D0(p2.X(),p2.Y(),P3);
    
    Calcul_P2dOnSurf(CD.Value(ic2),jf.Value(ic2),i.Value(ic2,icplus),p.Value(ic2,icplus),p2);
    indice=SurfIndex(CD, ic2, i.Value(ic2,icplus), ChFiSURFACE);
    DStr.Surface(indice).Surface()->D0(p2.X(),p2.Y(),P4);
    intersection=(P1.Distance(P4)<=1.e-7 ||  P1.Distance(P3)<=1.e-7) &&
      (P2.Distance(P4)<=1.e-7 ||  P2.Distance(P3)<=1.e-7);
    if (intersection) { 
      PerformTwoCornerSameExt(DStr,CD.Value(ic1),Index.Value(ic1),sens.Value(ic1),
			      CD.Value(ic2),Index.Value(ic2),sens.Value(ic2),introuve);      
      if (introuve) return;
    }
  } 

// declaration for plate 
  //GeomPlate_BuildPlateSurface PSurf(3,10,3,tol2d,tolesp,angular);
  //
  //Sence of Plate parameters and their preferable values :
  // degree is total order of ordinary or mixed derivatives:
  // dS/dU, dS/dV have degree 1, d2S/dU2, d2S/dV2, d2S/(dUdV) have degree 2
  // nbiter - number of iterations, when surface from previous iteration uses as initial surface for next one
  // practically this process does not converge, using "bad" initial surface leads to much more "bad" solution.
  // constr is order of constraint: 0 - G0, 1 - G1 ...
  // Using constraint order > 0 very often causes  unpredicable undulations of solution
  Standard_Integer degree = 3, nbcurvpnt = 10, nbiter = 1;
  Standard_Integer constr = 1; //G1
  GeomPlate_BuildPlateSurface PSurf(degree, nbcurvpnt, nbiter, tol2d, tolapp3d, angular);
// calculation of curves on surface for each stripe 
  for (ic=0;ic<nedge;ic++) {
    gp_Pnt2d p2d1, p2d2;
    if (!sharp.Value(ic)) {
      n3d++;
      Indices(nedge,ic,icplus,icmoins);
      jfp = 3 - jf.Value(ic);
      Calcul_P2dOnSurf(CD.Value(ic),jfp,i.Value(ic,icmoins),p.Value(ic,icmoins),p2d1);
      Calcul_P2dOnSurf(CD.Value(ic),jf.Value(ic),i.Value(ic,icplus),p.Value(ic,icplus),p2d2);
//      if (i[ic][icplus]!=  i[ic][icmoins]) std::cout<<"probleme surface"<<std::endl;
      indice= SurfIndex(CD, ic, i.Value(ic,icplus), ChFiSURFACE);
      Handle (GeomAdaptor_Surface) Asurf =
	new GeomAdaptor_Surface(DStr.Surface(indice).Surface());
      // calculation of curve 2d  
      xdir= p2d2.X()-p2d1.X();  
      ydir= p2d2.Y()-p2d1.Y();
      Standard_Real l0 = sqrt(xdir*xdir+ ydir*ydir );
      gp_Dir2d dir (xdir, ydir);
      Handle(Geom2d_Line) l= new Geom2d_Line (p2d1 ,dir);
      Handle (Geom2d_Curve) pcurve = new  Geom2d_TrimmedCurve(l,0,l0); 
      Handle (Geom2dAdaptor_Curve) Acurv = new Geom2dAdaptor_Curve(pcurve);
      Adaptor3d_CurveOnSurface  CurvOnS (Acurv,Asurf);
      Handle(Adaptor3d_CurveOnSurface) HCons =
	new Adaptor3d_CurveOnSurface(CurvOnS);
      //Order.SetValue(ic,1);
      Order.SetValue(ic, constr);
      Handle(GeomPlate_CurveConstraint) Cont =
	new GeomPlate_CurveConstraint(HCons,Order.Value(ic),nbcurvpnt,tolapp3d,angular,0.1);
      PSurf.Add(Cont);
      
      // calculate indexes of points and of the curve for the DS         
      isfirst=(sens.Value(ic)==1);
      GeomLib::BuildCurve3d(tolapp,CurvOnS,CurvOnS.FirstParameter(),
			    CurvOnS.LastParameter(),Curv3d,maxapp,avedev);
      TopOpeBRepDS_Curve tcurv3d( Curv3d,maxapp);
      indcurve3d.SetValue(n3d,DStr.AddCurve(tcurv3d));
      gp_Pnt point1,point2; 
      point1=  CurvOnS.Value(CurvOnS.FirstParameter());
      point2 =CurvOnS.Value(CurvOnS.LastParameter());
      
      TopOpeBRepDS_Point tpoint1 (point1,maxapp);
      TopOpeBRepDS_Point tpoint2 (point2,maxapp);
      errapp.SetValue(ic,maxapp);
      if (ic==0) {
// it is necessary to create two points
	indpoint.SetValue(ic,0,DStr.AddPoint(tpoint1));
	indpoint.SetValue(ic,1,DStr.AddPoint(tpoint2));
      }
      else {
// probably the points are already on the fillet 
// (previous intersection...)
	trouve = Standard_False;
	for (ii=0;ii<ic&&(!trouve);ii++) {
	  if (!sharp.Value(ii)) {
	    TopOpeBRepDS_Point & tpt= DStr.ChangePoint(indpoint.Value(ii,1));
	    if (point1.Distance(tpt.Point())<1.e-4)
	      trouve = Standard_True;
	  }
	}
	if (trouve)
	  indpoint.SetValue(ic,0,indpoint.Value(ii-1,1));
	else
	  indpoint.SetValue(ic,0,DStr.AddPoint(tpoint1));

	trouve = Standard_False;
	for (ii=0;ii<ic&&(!trouve);ii++) {
	  if (!sharp.Value(ii)) {
	    TopOpeBRepDS_Point & tpt= DStr.ChangePoint(indpoint.Value(ii,0));
	    if (point2.Distance(tpt.Point())<1.e-4)
	      trouve = Standard_True;
	  }
	}
	if (trouve)
	  indpoint.SetValue(ic,1,indpoint.Value(ii-1,0));
	else
	  indpoint.SetValue(ic,1,DStr.AddPoint(tpoint2));
      }
      
      //   update of the stripe 
      isurf1=3-jf.Value(ic); isurf2=jf.Value(ic);
      if (isurf1==2)  CD.Value(ic)->SetOrientation(TopAbs_REVERSED,isfirst);
      CD.Value(ic)->SetCurve(indcurve3d.Value(n3d),isfirst);
      CD.Value(ic)->SetIndexPoint(indpoint.Value(ic,0),isfirst,isurf1); 
      CD.Value(ic)->SetIndexPoint(indpoint.Value(ic,1),isfirst,isurf2);
      CD.Value(ic)->SetParameters(isfirst,pcurve->FirstParameter(),pcurve->LastParameter());     
      ChFiDS_CommonPoint cp1;
      ChFiDS_CommonPoint cp2;
      cp1.SetPoint (point1);
      cp2.SetPoint( point2);
      CD.Value(ic)->SetOfSurfData()->Value(i.Value(ic,icmoins))->
	ChangeVertex (isfirst,isurf1)=cp1;
      CD.Value(ic)->SetOfSurfData()->Value(i.Value(ic,icmoins))->
	ChangeVertex (isfirst,isurf2)=cp2; 
      CD.Value(ic)->SetOfSurfData()->Value(i.Value(ic,icmoins))->
	ChangeInterference(isurf1).SetParameter(p.Value(ic,icmoins),isfirst);
      CD.Value(ic)->SetOfSurfData()->Value(i.Value(ic,icmoins))->
	ChangeInterference(isurf2).SetParameter(p.Value(ic,icplus),isfirst);
      CD.Value(ic)-> ChangePCurve(isfirst)= pcurve;
    }
  }
      
// calculate the indices of points for living edges    
  for (ic=0;ic<nedge;ic++) {
    if (sharp.Value(ic)) {
      Indices(nedge,ic,icplus,icmoins);
      BRepAdaptor_Curve C(TopoDS::Edge(Evive.Value(ic)));
      /*gp_Pnt*/ PE = C.Value(p.Value(ic,icplus));
      TopOpeBRepDS_Point TPE(PE,BRep_Tool::Tolerance(TopoDS::Edge(Evive.Value(ic))));
      ChFiDS_CommonPoint cp;
      if (deuxconges ) {
        IVtx = DStr.AddShape(V1);
        indpoint.SetValue(ic,0, IVtx );
        indpoint.SetValue(ic,1, IVtx );
      }
      if (!sharp.Value(icplus)) {
	isfirst=(sens.Value(icplus)==1);
	jfp = 3 - jf.Value(icplus);
	cp = CD.Value(icplus)->SetOfSurfData()->Value(i.Value(icplus,ic))->
	  ChangeVertex (isfirst,jfp);
	if ( cp.Point().Distance(PE) <= Max(1.e-4,tolcp)) {
// edge was limited by the 1st CommonPoint of CD[icplus]
	  indpoint.SetValue(ic,0,indpoint.Value(icplus,0));
	  indpoint.SetValue(ic,1,indpoint.Value(icplus,0));
	}
      }
      if (!sharp.Value(icmoins)) {
	isfirst=(sens.Value(icmoins)==1);
	cp = CD.Value(icmoins)->SetOfSurfData()->Value(i.Value(icmoins,ic))->
	  ChangeVertex (isfirst,jf.Value(icmoins));
	if ( cp.Point().Distance(PE) <= Max(1.e-4,tolcp)) {
// edge was limited by the 2nd CommonPoint of CD[icmoins]
	 if (indpoint.Value(ic,0)==0) { 
          indpoint.SetValue(ic,0, indpoint.Value(icmoins,1));
	  indpoint.SetValue(ic,1, indpoint.Value(icmoins,1));
         }
	}
      }
      if (indpoint.Value(ic,0)==0) { 
         indpoint.SetValue(ic,0,DStr.AddPoint(TPE));
         indpoint.SetValue(ic,1, indpoint.Value(ic,0));
      }
    }
  }

// calculation of intermediary curves connecting two stripes in case if  
// there is no intersection. The curve is a straight line, projection or batten 
  
  Standard_Boolean raccordbatten;
  if (!inters) {

    for (ic=0;ic<nedge;ic++) {
       
      if (!oksea.Value(ic)&& !moresurf.Value(ic) && !libre.Value(ic) ) {
	Indices(nedge,ic,icplus,icmoins);
        raccordbatten=Standard_False;
        if (!regul.Value(ic)) {
          raccordbatten=Standard_True;
          if (regul.Value(icplus))
          raccordbatten=Standard_False;
        }
	n3d++;
	gp_Pnt2d p2d1, p2d2;
	Handle(Geom2d_Curve) curv2d1,curv2d2;
	Handle (Geom2d_Curve) pcurve;
        Handle (Geom_Curve) curveint;
	Handle (GeomAdaptor_Surface) Asurf;
	Standard_Real u1bid,u2bid;
	
	// return the 1st curve 2d 
	// and the 1st connection point 
	if (sharp.Value(ic))
	  curv2d1 = BRep_Tool::CurveOnSurface(TopoDS::Edge(Evive.Value(ic)),TopoDS::Face(Fvive.Value(ic,icplus)),
                                              u1bid,u2bid);
	else
	  Calcul_C2dOnFace(CD.Value(ic),jf.Value(ic),i.Value(ic,icplus),curv2d1);

        if (curv2d1.IsNull()) 
          throw Standard_ConstructionError ("Failed to get p-curve of edge");
	p2d1 = curv2d1 ->Value(p.Value(ic,icplus));
	
	// recuperation de la deuxieme courbe 2d
	// et du deuxieme point de raccordement
	if (sharp.Value(icplus))
	  curv2d2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(Evive.Value(icplus)),
                                              TopoDS::Face(Fvive.Value(ic,icplus)),u1bid,u2bid);
	else {
	  jfp = 3 - jf.Value(icplus);
	  Calcul_C2dOnFace(CD.Value(icplus),jfp,i.Value(icplus,ic),curv2d2);
	}
        if (curv2d2.IsNull()) 
          throw Standard_ConstructionError ("Failed to get p-curve of edge");
	p2d2 = curv2d2 ->Value(p.Value(icplus,ic));

	Asurf = new GeomAdaptor_Surface(BRep_Tool::Surface(TopoDS::Face(Fvive.Value(ic,icplus))));
	Standard_Real tolu,tolv,ratio; 
	tolu=Asurf->UResolution(1.e-3);
	tolv=Asurf->VResolution(1.e-3);
	if (tolu>tolv) ratio=tolu/tolv;
	else ratio=tolv/tolu;
        
        // in case of a sewing edge the parameters are reframed 
        if (couture) {
	  Standard_Boolean PI1=Standard_False, PI2=Standard_False;
	  Standard_Real xx;
	  PI1=0<=p2d1.X() && p2d1.X() <=M_PI;
	  PI2=0<=p2d2.X() && p2d2.X() <=M_PI;
	  
	  if (Evive.Value(ic).IsSame(edgecouture)){
	    xx=p2d1.X();
	    if (PI2&&!PI1) xx=xx-2*M_PI;
	    if (!PI2&&PI1) xx=xx+2*M_PI;
	    p2d1.SetX(xx);
              
	  }
	  if (Evive.Value(icplus).IsSame(edgecouture)){
	    xx=p2d2.X();
	    if (PI2&&!PI1) xx=xx+2*M_PI;
	    if (!PI2&&PI1) xx=xx-2*M_PI;
	    p2d2.SetX(xx); 
	  }
        }
        xdir= p2d2.X()-p2d1.X();
	ydir= p2d2.Y()-p2d1.Y();

	Standard_Real l0 = sqrt(xdir*xdir+ ydir*ydir );
	if (l0<1.e-7|| ponctuel.Value(ic)) {
// unused connection
	  n3d--;
          ponctuel.SetValue(ic,Standard_True);
          if (!deuxconges) {
	    if ( sharp.Value(icplus) && indpoint.Value(icplus,0) == 0 ) {
	      indpoint.SetValue(icplus,0, indpoint.Value(ic,1));
	      indpoint.SetValue(icplus,1, indpoint.Value(ic,1));
	    }
	    if ( sharp.Value(ic) && indpoint.Value(ic,0) == 0 ) {
	      indpoint.SetValue(ic,0,indpoint.Value(icmoins,1));
	      indpoint.SetValue(ic,1,indpoint.Value(icmoins,1));
	   }
          }
	}
	else {  // the connection is a straight line, projection or batten 
         if (ratio>10 && nconges==1) raccordbatten=Standard_True; 
         if (ratio>10 && raccordbatten) {
	    CalculDroite(p2d1,xdir,ydir,pcurve);
            raccordbatten=Standard_False;
          }
          else  if (!raccordbatten){  // the projected curves are returned 
	    if (regul.Value(ic)) {
               if (cproj2.Value(ic).IsNull()){ 
                   raccordbatten=Standard_True;
               }
               else {
                pcurve=proj2d2.Value(ic);
                curveint=cproj2.Value(ic);
                maxapp1=1.e-6;
               }
               
            }
	    else  {
              if (cproj1.Value(ic+1).IsNull()) {
                  raccordbatten=Standard_True; 
              }
              else {
                pcurve=proj2d1.Value(ic+1);
                curveint=cproj1.Value(ic+1); 
                maxapp1=1.e-6;
              }
            }
          }
          Standard_Boolean contraint1=Standard_True,
                            contraint2=Standard_True;
          if (raccordbatten) {
#ifdef OCCT_DEBUG
	    ChFi3d_InitChron(ch);// initial performances for  battens  
#endif  
            Standard_Boolean inverseic,inverseicplus;
            if (sharp.Value(ic)) {
                 inverseic=TopExp::FirstVertex(TopoDS::Edge(Evive.Value(ic))).
                         IsSame(V1);   
            }
            else {
              inverseic=sens.Value(ic)==1;
            }
            if (sharp.Value(icplus)){
              inverseicplus=TopExp::FirstVertex(TopoDS::Edge(Evive.Value(icplus))).
                         IsSame(V1);
            }
            else {
              inverseicplus=sens.Value(icplus)==1;
            } 
            if (TopoDS::Edge(Evive.Value(ic)).IsSame(edgelibre1) ||
                TopoDS::Edge(Evive.Value(ic)).IsSame(edgelibre2)) 
                contraint1=Standard_False;
            if (TopoDS::Edge(Evive.Value(icplus)).IsSame(edgelibre1) ||
                TopoDS::Edge(Evive.Value(icplus)).IsSame(edgelibre2))
            contraint2=Standard_False;
	    CalculBatten(Asurf,TopoDS::Face(Fvive(ic,icplus)),xdir,ydir,p2d1,p2d2,contraint1,contraint2,curv2d1,curv2d2,p.Value(ic,icplus),
			 p.Value(icplus,ic),inverseic,inverseicplus,pcurve);
#ifdef OCCT_DEBUG
	    ChFi3d_ResultChron( ch,t_batten);  // resulting performances for battens 
#endif 
          }

         // construction of borders for Plate 
         Handle (Geom2dAdaptor_Curve)  Acurv=new Geom2dAdaptor_Curve(pcurve);
         Adaptor3d_CurveOnSurface  CurvOnS (Acurv,Asurf);
         Handle(Adaptor3d_CurveOnSurface) HCons =
           new Adaptor3d_CurveOnSurface(CurvOnS);

         // constraints G1 are set if edges ic and icplus are not both alive 


         Order.SetValue(n3d,0);
         if (!sharp.Value(ic)&& !sharp.Value(icplus))
           Order.SetValue(n3d,1);
         if (!contraint1 && !sharp.Value(icplus))
           Order.SetValue(n3d,1);
         if (!contraint2 && !sharp.Value(ic))
           Order.SetValue(n3d,1);
         if (tangentregul(ic) || tangentregul(icplus) )
           Order.SetValue(n3d,1);
         if (isG1.Value(ic)) 
           Order.SetValue(n3d,1);
         Handle(GeomPlate_CurveConstraint) Cont =
           new GeomPlate_CurveConstraint(HCons,Order.Value(n3d),10,tolapp3d,angular,0.1);
         PSurf.Add(Cont);

         //calculation of curve 3d if it is not a projection 
         if (curveint.IsNull()) {
           GeomLib::BuildCurve3d(tolapp,CurvOnS,CurvOnS.FirstParameter(),
                                 CurvOnS.LastParameter(),Curv3d,maxapp1,avedev);
           pardeb=CurvOnS.FirstParameter();
           parfin= CurvOnS.LastParameter();
           curveint= new Geom_TrimmedCurve(Curv3d,pardeb,parfin);
         }

         //storage in the DS  
         TopOpeBRepDS_Curve tcurv3d( curveint,maxapp1);
         indcurve3d.SetValue(n3d, DStr.AddCurve(tcurv3d));
         pardeb=curveint->FirstParameter();
         parfin=curveint->LastParameter();
         if ( sharp.Value(icplus) && indpoint.Value(icplus,0) == 0) {
           // it is necessary to initialize indpoint[icplus][0] and indpoint[icplus][1]
           gp_Pnt point2; 
           point2 =curveint->Value(parfin);
           TopOpeBRepDS_Point tpoint2 (point2,maxapp); 
           indpoint.SetValue(icplus,0,DStr.AddPoint(tpoint2));
           indpoint.SetValue(icplus,1,indpoint.Value(icplus,0));
         }
         Standard_Boolean IsVt1=Standard_False;
         Standard_Boolean IsVt2=Standard_False;
         if(deuxconges) {
           IsVt1=sharp.Value(ic);
           IsVt2=sharp.Value(icplus);
          }
	  Interfp1=ChFi3d_FilPointInDS(TopAbs_FORWARD,indcurve3d.Value(n3d),
				       indpoint.Value(ic,1),pardeb,IsVt1);
	  Interfp2=ChFi3d_FilPointInDS(TopAbs_REVERSED,indcurve3d.Value(n3d),
				       indpoint(icplus,0),parfin,IsVt2);
	  DStr.ChangeCurveInterferences(indcurve3d.Value(n3d)).Append(Interfp1);
	  DStr.ChangeCurveInterferences(indcurve3d.Value(n3d)).Append(Interfp2);
	  if (!IsVt1) {
	    TopOpeBRepDS_Point & tpt1= DStr.ChangePoint(indpoint(ic,1));
            tpt1.Tolerance (tpt1.Tolerance()+maxapp1);
          }	  
          if (!IsVt2) {
            TopOpeBRepDS_Point &tpt2= DStr.ChangePoint(indpoint(icplus,0));
	    tpt2.Tolerance (tpt2.Tolerance()+maxapp1);     
	  }

	// calculate orientation of the curve  
	  TopAbs_Orientation orinterf; 
	  if (!sharp.Value(ic)) {
              OrientationIcNonVive(CD.Value(ic),jf.Value(ic),i.Value(ic,icplus),sens.Value(ic),orinterf);
	  }
	  else if (!sharp.Value(icplus)) {
	      OrientationIcplusNonVive(CD.Value(icplus),jf.Value(icplus),i.Value(icplus,ic),sens.Value(icplus),orinterf);
	    }
	  else {
                OrientationAreteViveConsecutive (Fvive.Value(ic,icplus) ,Evive.Value(ic),V1,orinterf);                                      
	  } 
	  Interfc=ChFi3d_FilCurveInDS(indcurve3d.Value(n3d),numfa.Value(ic,icplus),pcurve,orinterf);	  
	  DStr.ChangeShapeInterferences(numfa.Value(ic,icplus)).Append(Interfc);
	}
       } // end of processing by edge 
    } // end of the loop on edges 
  }  // end of processing for intermediary curves 
        
//  storage in the DS of curves projected on several faces 
  for (ic=0;ic<nedge;ic++) {
    if (moresurf.Value(ic) ){
      TopoDS_Vertex Vf,Vl;
      gp_Pnt Pf,Pl,P1,P2,Pcom;
      ind = 0; //must be initialized because of possible use, see L2249
      Standard_Real up1,up2;
      TopAbs_Orientation orvt;
      TopAbs_Orientation oredge = TopAbs_FORWARD;
      Standard_Integer indpoint1,indpoint2;
      Indices(nedge,ic,icplus,icmoins);
      Handle(Geom2d_Curve) proj,proj2d;
      Handle(Geom_Curve) projc,cproj;
      TopOpeBRepDS_Point& tpt1= DStr.ChangePoint(indpoint(ic,1));
      TopOpeBRepDS_Point& tpt2= DStr.ChangePoint(indpoint(icplus,0));
      tpt1.Tolerance (tpt1.Tolerance()+error);
      tpt2.Tolerance (tpt1.Tolerance()+error);
      for(nb=1;nb<=nbface;nb++) {
	orvt=TopAbs_REVERSED;
	Vf=TopExp::FirstVertex(TopoDS::Edge(Ecom.Value(nb)));
	Vl=TopExp::LastVertex (TopoDS::Edge(Ecom.Value(nb)));
	Pf=BRep_Tool::Pnt(Vf);
	Pl=BRep_Tool::Pnt(Vl);
	para=parcom.Value(nb);
	Pcom=BRep_Tool::Curve(TopoDS::Edge(Ecom.Value(nb)),up1,up2)->Value(para);
	if (Pf.Distance(BRep_Tool::Pnt(V1))< Pl.Distance(BRep_Tool::Pnt(V1)))
	  orvt=TopAbs_FORWARD;
	if (!Eproj.Value(nb).IsNull())  {
	  n3d++;
	  proj=BRep_Tool::CurveOnSurface(TopoDS::Edge(Eproj.Value(nb)),
					 TopoDS::Face(Fproj.Value(nb)),up1,up2);
          if (proj.IsNull()) 
            throw Standard_ConstructionError ("Failed to get p-curve of edge");
	  proj2d=new Geom2d_TrimmedCurve(proj,up1,up2);
	  projc=BRep_Tool::Curve(TopoDS::Edge(Eproj.Value(nb)),up1,up2);
          if (projc.IsNull()) 
            throw Standard_ConstructionError ("Failed to get 3D curve of edge");
	  cproj=new Geom_TrimmedCurve(projc,up1,up2);
	  pardeb=cproj->FirstParameter();
	  parfin=cproj->LastParameter();
	  P1=cproj->Value(pardeb);
	  P2=cproj->Value(parfin);
	  if (P1.Distance(tpt1.Point())<1.e-3) 
	    indpoint1=indpoint(ic,1); 
	  else  indpoint1=ind;
	  if (P2.Distance(tpt2.Point())<1.e-3) 
	    indpoint2=indpoint(icplus,0); 
	  else  {
	    TopOpeBRepDS_Point tpoint2 (P2,error);
	    indpoint2= DStr.AddPoint(tpoint2);
	    ind=indpoint2;    
	  }
	  Handle (GeomAdaptor_Surface) Asurf;
	  Asurf = new GeomAdaptor_Surface(BRep_Tool::Surface
					   (TopoDS::Face(Fproj.Value(nb))));
	  Handle (Geom2dAdaptor_Curve)  Acurv=new Geom2dAdaptor_Curve(proj2d);
	  Adaptor3d_CurveOnSurface  CurvOnS (Acurv,Asurf);
	  Handle(Adaptor3d_CurveOnSurface) HCons =new Adaptor3d_CurveOnSurface(CurvOnS);
	  Order.SetValue(n3d,1);
	  Handle(GeomPlate_CurveConstraint) Cont =
	    new GeomPlate_CurveConstraint(HCons,Order.Value(n3d),10,tolapp3d,angular,0.1);
	  PSurf.Add(Cont);
	  TopOpeBRepDS_Curve tcurv3d( cproj,error);
	  indcurve3d.SetValue(n3d, DStr.AddCurve(tcurv3d));
	  Interfp1=ChFi3d_FilPointInDS(TopAbs_FORWARD,indcurve3d.Value(n3d),
				       indpoint1,pardeb);
	  Interfp2=ChFi3d_FilPointInDS(TopAbs_REVERSED,indcurve3d.Value(n3d),
				       indpoint2,parfin);
	  DStr.ChangeCurveInterferences(indcurve3d.Value(n3d)).Append(Interfp1);
	  DStr.ChangeCurveInterferences(indcurve3d.Value(n3d)).Append(Interfp2);
	  num=DStr.AddShape(Fproj.Value(nb));
	  TopExp_Explorer ex;
	  for(ex.Init(Fproj.Value(nb).Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
	      ex.More(); ex.Next()){
	    if(Ecom.Value(nb).IsSame(ex.Current())) {
	      oredge = ex.Current().Orientation();
	      break;
	    }
	  }

	  //calculation of the orientation 	  
	  TopAbs_Orientation orinterf;
	  if (P1.Distance(Pcom)>1.e-4) {
	    if (orvt==TopAbs_FORWARD) {
	      orinterf=oredge;
	    }
	    else {
	      orinterf=TopAbs::Reverse(oredge);
	    }
	  }
	  else {
	    if (orvt==TopAbs_FORWARD) {
	      orinterf=TopAbs::Reverse(oredge); 
	    }
	    else {
	      orinterf=oredge;
	    }
	  }
	  Interfc=ChFi3d_FilCurveInDS(indcurve3d.Value(n3d),num,proj2d,orinterf);	  
	  DStr.ChangeShapeInterferences(num).Append(Interfc);
	}
	indice=ind;
	if (nb!=nbface) {    
	  if (Eproj.Value(nb).IsNull())  indice=indpoint(ic,1);
	  if (Eproj.Value(nb+1).IsNull()) indice=indpoint(icplus,0); 
	  Indice.SetValue(n3d,indice);
	  Standard_Integer Iarc1=DStr.AddShape(TopoDS::Edge(Ecom.Value(nb)));
	  Interfp1=ChFi3d_FilPointInDS(orvt,Iarc1,indice,parcom.Value(nb));
	  DStr.ChangeShapeInterferences(Iarc1).Append(Interfp1);
	}
      }
    }                     
  }
            
// case when two free borders are tangent
  if (droit)      
    for (ic=0;ic<nedge;ic++) {
      Handle(Geom_Curve) curve,ctrim,rcurve;
      Handle(Geom2d_Curve) curve2d,ctrim2d,rcurve2d;
      Standard_Real ufirst,ulast;  
      Indices(nedge,ic,icplus,icmoins);
      Standard_Integer indpoint1,indpoint2;
      Standard_Boolean isvt1=Standard_False,isvt2=Standard_False;
      TopoDS_Edge ecur =TopoDS::Edge(Evive.Value(ic));
      if (ecur.IsSame(edgelibre1)|| ecur.IsSame(edgelibre2)) {
	n3d++;
	curve2d=BRep_Tool::CurveOnSurface(TopoDS::Edge(Evive.Value(ic)),
					  TopoDS::Face(Fvive.Value(ic,icplus)),ufirst,ulast);
	curve=BRep_Tool::Curve(TopoDS::Edge(Evive.Value(ic)),ufirst,ulast);
	if (TopExp::FirstVertex((TopoDS::Edge(Evive.Value(ic)))).IsSame (V1)) { 
	  ctrim=new Geom_TrimmedCurve(curve,ufirst,p.Value(ic,icmoins));
	  ctrim2d=new Geom2d_TrimmedCurve(curve2d,ufirst,p.Value(ic,icmoins)); 
	  indpoint1=DStr.AddShape(V1);
	  isvt1=1;
	  indpoint2=indpoint(ic,1);
	}
	else { 
	  ctrim=new Geom_TrimmedCurve(curve, p.Value(ic,icmoins),ulast);
	  ctrim2d=new Geom2d_TrimmedCurve(curve2d,p.Value(ic,icmoins),ulast);
	  indpoint2=DStr.AddShape(V1);
	  isvt2=1;
	  indpoint1=indpoint(ic,1);
	}
	if (libre.Value(ic)){
	  if (TopExp::FirstVertex((TopoDS::Edge(Evive.Value(ic)))).IsSame(V1)) { 
	    ctrim->Reverse();
	    ctrim2d->Reverse();
	    indpoint2=DStr.AddShape(V1);
	    isvt2=1;
	    isvt1=0;
	    indpoint1=indpoint(ic,1);
	  }
	}
	else {
	  if (TopExp::LastVertex((TopoDS::Edge(Evive.Value(ic)))).IsSame(V1)) {
	    ctrim->Reverse();
	    ctrim2d->Reverse();
	    indpoint1=DStr.AddShape(V1);
	    isvt1=1;
	    isvt2=0;
	    indpoint2=indpoint(ic,1);  
	  } 
	}       
	ufirst=ctrim->FirstParameter();
	ulast=ctrim->LastParameter();
	Handle (GeomAdaptor_Surface) Asurf;
	Asurf = new GeomAdaptor_Surface(BRep_Tool::Surface
					 (TopoDS::Face(Fvive.Value(ic,icplus))));
	Handle (Geom2dAdaptor_Curve)  Acurv=new Geom2dAdaptor_Curve(ctrim2d);
	Adaptor3d_CurveOnSurface  CurvOnS (Acurv,Asurf);
	Handle(Adaptor3d_CurveOnSurface) HCons =new Adaptor3d_CurveOnSurface(CurvOnS);
	Order.SetValue(n3d,0);
	Handle(GeomPlate_CurveConstraint) Cont =
	  new GeomPlate_CurveConstraint(HCons,Order.Value(n3d),10,tolapp3d,angular,0.1);
	PSurf.Add(Cont);
	TopOpeBRepDS_Curve tcurv3d( ctrim,1.e-4);
	indcurve3d.SetValue(n3d, DStr.AddCurve(tcurv3d));
	Interfp1=ChFi3d_FilPointInDS(TopAbs_FORWARD,indcurve3d.Value(n3d),
				     indpoint1,ufirst,isvt1);
	Interfp2=ChFi3d_FilPointInDS(TopAbs_REVERSED,indcurve3d.Value(n3d),
				     indpoint2,ulast,isvt2);
	DStr.ChangeCurveInterferences(indcurve3d.Value(n3d)).Append(Interfp1);
	DStr.ChangeCurveInterferences(indcurve3d.Value(n3d)).Append(Interfp2);
      }
  } 
 
#ifdef OCCT_DEBUG
  ChFi3d_InitChron(ch); // init performances for plate 
#endif

  PSurf.Perform();

#ifdef OCCT_DEBUG
  ChFi3d_ResultChron(ch, t_plate); //result performances for plate 
#endif 

  // call of approx  
 
#ifdef OCCT_DEBUG
  ChFi3d_InitChron(ch);  // init performances for approxplate
#endif
  if (PSurf.IsDone()) {
    Standard_Integer nbcarreau=9;
    Standard_Integer degmax=8;
    Standard_Real seuil;
    Handle(GeomPlate_Surface) gpPlate = PSurf.Surface();

    TColgp_SequenceOfXY S2d;
    TColgp_SequenceOfXYZ S3d;
    S2d.Clear();
    S3d.Clear();
    PSurf.Disc2dContour(4,S2d);
    PSurf.Disc3dContour(4,0,S3d);
    seuil = Max(tolapp,10*PSurf.G0Error());
    GeomPlate_PlateG0Criterion critere (S2d,S3d,seuil);
    GeomPlate_MakeApprox Mapp(gpPlate,critere,tolapp,nbcarreau,degmax);
    Handle (Geom_Surface) Surf (Mapp.Surface());
    Standard_Real coef = 1.1 ,apperror;
    apperror=Mapp.CriterionError()*coef;

#ifdef OCCT_DEBUG
  ChFi3d_ResultChron(ch, t_approxplate); // result performances for approxplate
#endif
  
//  Storage of the surface plate and corresponding curves in the DS 

    TopAbs_Orientation orplate,orsurfdata,orpcurve,orien;
#ifdef OCCT_DEBUG
//    Standard_Real ang1=PSurf.G1Error();
#endif
//     gp_Vec n1,n2,du,dv,du1,dv1;
//     gp_Pnt pp,pp1;
//     Standard_Real tpar;
//     gp_Pnt2d uv; 
//     Standard_Real scal;
    
    TopOpeBRepDS_Surface Tsurf(Surf,Mapp.ApproxError());
    Standard_Integer Isurf=DStr.AddSurface(Tsurf);
    //lbo : historique QDF.
    if(!myEVIMap.IsBound(V1)){
      TColStd_ListOfInteger li;
      myEVIMap.Bind(V1,li);
    }
    myEVIMap.ChangeFind(V1).Append(Isurf);
  
    Standard_Integer SolInd = CD.Value(0)->SolidIndex();
    TopOpeBRepDS_ListOfInterference& SolidInterfs = 
      DStr.ChangeShapeInterferences(SolInd);
 
// in case when one rereads at top, it is necessary that 
// alive edges that arrive at the top should be removed from the DS. 
// For this they are stored in the DS with their inverted orientation 
    Standard_Integer nbedge;
    TopExp_Explorer ex;
    if (deuxconges)
      for (ic=0;ic<nedge;ic++) {
	if (!sharp.Value(ic)){
	  nbedge = CD.Value(ic)->Spine()->NbEdges();
	  TopoDS_Edge Arcspine; 
	  if (sens.Value(ic) ==1) 
	    Arcspine=CD.Value(ic) ->Spine()->Edges(1);
	  else  
	    Arcspine= CD.Value(ic)->Spine()->Edges(nbedge);
	  Standard_Integer IArcspine = DStr.AddShape(Arcspine);
	  TopAbs_Orientation OVtx = TopAbs_FORWARD;
	  for(ex.Init(Arcspine.Oriented(TopAbs_FORWARD),TopAbs_VERTEX); 
	      ex.More(); ex.Next()){
	    if(V1.IsSame(ex.Current())) {
	      OVtx = ex.Current().Orientation();
	      break;
	    }
	  }
	  OVtx = TopAbs::Reverse(OVtx);
	  Standard_Real parVtx = BRep_Tool::Parameter(V1,Arcspine);
	  Handle(TopOpeBRepDS_CurvePointInterference) 
	    interfv = ChFi3d_FilVertexInDS(OVtx,IArcspine,IVtx,parVtx);
	  DStr.ChangeShapeInterferences(IArcspine).Append(interfv);
	}
      }
    
    // calculate orientation of Plate orplate corresponding to surfdata 
    // calculation corresponding to the first stripe 
    Indices(nedge,0,icplus,icmoins);
    isfirst=(sens.Value(0)==1);
    const Handle(ChFiDS_SurfData)& Fd = 
      CD.Value(0)->SetOfSurfData()->Value(i.Value(0,icmoins));
    indice= Fd->Surf();
//    Handle (Geom_Surface) surfdata  = DStr.Surface(indice).Surface();
//     tpar= (CD.Value(0)->PCurve(isfirst)->FirstParameter()+
// 	 CD.Value(0)->PCurve(isfirst)->LastParameter())/2 ;
//     CD.Value(0)->PCurve(isfirst)->D0(tpar,uv);
//     surfdata->D1(uv.X(),uv.Y(),pp,du,dv);
//     tpar=(PSurf.Curves2d()->Value(1)->FirstParameter()+
// 	  PSurf.Curves2d()->Value(1)->LastParameter())/2;
//     (PSurf.Curves2d())->Value(1)->D0(tpar,uv);
//     Surf-> D1(uv.X(),uv.Y(),pp1,du1,dv1);
//     n1=du.Crossed(dv);
//     n2=du1.Crossed(dv1);  
//     scal= n1.Dot(n2);
    orsurfdata=Fd->Orientation();
//     if (scal>0) orplate=orsurfdata;
//     else  orplate=TopAbs::Reverse(orsurfdata);  
    orplate = PlateOrientation(Surf,PSurf.Curves2d(),SumFaceNormalAtV1);
    
    //  creation of solidinterderence for Plate 
    Handle(TopOpeBRepDS_SolidSurfaceInterference) SSI = 
      new TopOpeBRepDS_SolidSurfaceInterference(TopOpeBRepDS_Transition(orplate),
					      TopOpeBRepDS_SOLID,
					      SolInd,
					      TopOpeBRepDS_SURFACE,
					      Isurf);
    SolidInterfs.Append(SSI);
  
  // calculate orientation orien of pcurves of Plate
  // the curves from ic to icplus the pcurves of Plate 
  // all have the same orientation  
    Standard_Integer Ishape1,Ishape2; 
    TopAbs_Orientation trafil1 = TopAbs_FORWARD, trafil2 = TopAbs_FORWARD;
    Ishape1 = Fd->IndexOfS1();
    Ishape2 = Fd->IndexOfS2();
    const ChFiDS_FaceInterference& Fi1 = Fd->InterferenceOnS1();
    const ChFiDS_FaceInterference& Fi2 = Fd->InterferenceOnS2();     
    if (Ishape1 != 0) {
      if (Ishape1 > 0) {
	trafil1 = DStr.Shape(Ishape1).Orientation();
      }
      trafil1 = TopAbs::Compose(trafil1,Fd->Orientation());
      trafil1 = TopAbs::Compose(TopAbs::Reverse(Fi1.Transition()),trafil1);
      trafil2 = TopAbs::Reverse(trafil1);
    }
    else {
      if (Ishape2 > 0) {
	trafil2 = DStr.Shape(Ishape2).Orientation();
      }
      trafil2 = TopAbs::Compose(trafil2,Fd->Orientation());
      trafil2 = TopAbs::Compose(TopAbs::Reverse(Fi2.Transition()),trafil2);
      trafil1 = TopAbs::Reverse(trafil2);
    }
    if (isfirst) {
      orpcurve=TopAbs::Reverse(trafil1);
      orpcurve= TopAbs::Compose(orpcurve,CD.Value(0)->FirstPCurveOrientation ()); }
    else {
      orpcurve=trafil1;
      orpcurve= TopAbs::Compose(orpcurve,CD.Value(0)->LastPCurveOrientation ());
    }
    if (orsurfdata==orplate) 
      orien =TopAbs::Reverse(orpcurve);
    else  orien=orpcurve; 
    
    
    if (!droit)
      for (ic=0;ic<=nedge;ic++) {
	if (libre.Value(ic)) {
	  Standard_Integer icplus21;
	  Indices(nedge,ic,icplus,icmoins);
	  Indices(nedge,icplus,icplus21,ic);
	  gp_Pnt2d UV1,UV2;
	  Handle (Geom_Curve) C3d;
	  Handle (Geom2d_Curve) C2d,curv2d;
	  gp_Pnt ptic,pticplus;
	  BRepAdaptor_Curve BCurv1(TopoDS::Edge(Evive.Value(ic)));
	  BRepAdaptor_Curve BCurv2(TopoDS::Edge(Evive.Value(icplus)));
	  Standard_Real par1=p.Value(ic,icplus);
	  Standard_Real par2=p.Value(icplus,ic);
	  BCurv1.D0(par1,ptic);
	  BCurv2.D0(par2,pticplus);
	  ParametrePlate(n3d,PSurf,Surf,ptic,apperror,UV1);
	  ParametrePlate(n3d,PSurf,Surf,pticplus,apperror,UV2);
	  Standard_Real to3d=1.e-3,to2d=1.e-6,tolreached;
	  ChFiDS_CommonPoint CP1,CP2;
	  CP1.SetArc(1.e-3, TopoDS::Edge(Evive.Value(ic)),par1,TopAbs_FORWARD);
	  CP1.SetPoint(ptic);
	  CP2.SetArc(1.e-3, TopoDS::Edge(Evive.Value(icplus)),par2,TopAbs_FORWARD);
	  CP2.SetPoint(pticplus);
	  Standard_Real param1,param2;
	  ChFi3d_ComputeArete( CP1,UV1,CP2,UV2,Surf,C3d,C2d,param1,param2, 
			      to3d,to2d,tolreached,0);
	  TopOpeBRepDS_Curve tcurv3d( C3d,tolreached);
	  Standard_Integer ind1,ind2;
	  ind1=indpoint(ic,0);
	  ind2=indpoint(icplus,0);
	  Standard_Integer indcurv=DStr.AddCurve(tcurv3d);
	  Interfp1=ChFi3d_FilPointInDS(TopAbs_FORWARD,indcurv,ind1,param1);
	  Interfp2=ChFi3d_FilPointInDS(TopAbs_REVERSED,indcurv,ind2,param2);
	  DStr.ChangeCurveInterferences(indcurv).Append(Interfp1);
	  DStr.ChangeCurveInterferences(indcurv).Append(Interfp2);
	  Interfc=ChFi3d_FilCurveInDS(indcurv,Isurf,C2d,orien);
	  DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc);
	}
  }
    
    //  stockage des courbes relatives aux stripes  
    n3d = 0;
    for (ic=0; ic<nedge ;ic++) {
      if (!sharp.Value(ic)) {
	n3d++;
	Indices(nedge,ic,icplus,icmoins);
	
	isfirst=(sens.Value(ic)==1);
      //   calculate curves interference relative to stripes
      
	apperror=Mapp.CriterionError()*coef;
	pardeb=CD.Value(ic)->PCurve(isfirst)->FirstParameter();
	parfin=CD.Value(ic)->PCurve(isfirst)->LastParameter();
      
	Interfp1=ChFi3d_FilPointInDS(TopAbs_FORWARD,indcurve3d.Value(n3d),
				     indpoint.Value(ic,0),pardeb);
	Interfp2=ChFi3d_FilPointInDS(TopAbs_REVERSED,indcurve3d.Value(n3d),
				     indpoint.Value(ic,1),parfin);
	DStr.ChangeCurveInterferences(indcurve3d.Value(n3d)).Append( Interfp1);
	DStr.ChangeCurveInterferences(indcurve3d.Value(n3d)).Append( Interfp2);
	TopOpeBRepDS_Curve& tcourb = DStr.ChangeCurve(indcurve3d.Value(n3d));
	
	tcourb.Tolerance(errapp.Value(ic)+apperror);
	TopOpeBRepDS_Point& tpt1= DStr.ChangePoint(indpoint(ic,0));
	TopOpeBRepDS_Point& tpt2= DStr.ChangePoint(indpoint(ic,1));
	tpt1.Tolerance (tpt1.Tolerance()+apperror);
	tpt2.Tolerance (tpt2.Tolerance()+apperror ); 
	
      // calculate surfaceinterference
	Interfc=ChFi3d_FilCurveInDS(indcurve3d.Value(n3d),Isurf,
				  PSurf.Curves2d()->Value(n3d),orien);     
	DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc);
	regular.SetCurve(indcurve3d.Value(n3d));
	regular.SetS1(Isurf,Standard_False);
	indice=CD.Value(ic)->SetOfSurfData()->Value( i.Value(ic,icmoins))->Surf();
	regular.SetS2(indice,Standard_False);
	myRegul.Append(regular);
      }
    }

  // storage of connection curves 

    for (ic=0; ic<nedge;ic++) {
      Indices(nedge,ic,icplus,icmoins);
      if (!oksea.Value(ic)) {
	if (sharp.Value(ic) &&!deuxconges) {
	  // limitation of the alive edge 
	  TopAbs_Orientation ori;
	  gp_Pnt Pf,Pl,sommet1;
	  TopoDS_Vertex Vd = TopExp::FirstVertex(TopoDS::Edge(Evive.Value(ic)));
	  TopoDS_Vertex Vf = TopExp::LastVertex(TopoDS::Edge(Evive.Value(ic)));
	  Pf=BRep_Tool::Pnt(Vd);
	  Pl=BRep_Tool::Pnt(Vf);
	  sommet1=BRep_Tool::Pnt(V1);
	  if (Pf.Distance(sommet1)<Pl.Distance(sommet1))
	    ori = TopAbs_FORWARD;
	  else
	    ori = TopAbs_REVERSED;
	  Standard_Integer Iarc1=DStr.AddShape(TopoDS::Edge(Evive.Value(ic)));
	  Interfp1=ChFi3d_FilPointInDS(ori,Iarc1,indpoint(ic,1),p.Value(ic,icplus));
	  DStr.ChangeShapeInterferences(TopoDS::Edge(Evive.Value(ic))).Append(Interfp1);
	}
	
	if (!ponctuel.Value(ic) && !libre.Value(ic)) {
	  // actual connection
	  if (!moresurf.Value(ic)){
	    n3d++;
	    TopOpeBRepDS_Curve& tcourb1 = DStr.ChangeCurve(indcurve3d.Value(n3d));
	    tcourb1.Tolerance(tcourb1.Tolerance()+apperror);
	    if (!deuxconges) {
	      TopOpeBRepDS_Point& tpt11= DStr.ChangePoint(indpoint(ic,1));
	      TopOpeBRepDS_Point& tpt21= DStr.ChangePoint(indpoint(icplus,0));
	      tpt11.Tolerance (tpt11.Tolerance()+apperror);
	      tpt21.Tolerance (tpt21.Tolerance()+apperror ); 
	    }
	    Interfc=ChFi3d_FilCurveInDS(indcurve3d.Value(n3d),Isurf,
					PSurf.Curves2d()->Value(n3d),orien);
	    DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc);
	    if( Order.Value(n3d)==1) {
	      regular.SetCurve(indcurve3d.Value(n3d));
	      regular.SetS1(Isurf,Standard_False);
	      regular.SetS2(numfa.Value(ic,icplus));
	      myRegul.Append(regular);
	    }
	  }
	}
      }
    }

  //storage of curves projected on several faces 
    for (ic=0; ic<nedge;ic++) {
      Indices(nedge,ic,icplus,icmoins);
      if (moresurf(ic))
	for (nb=1;nb<=nbface;nb++){ 
	  if (!Eproj.Value(nb).IsNull()) {
	    n3d++;
	    TopOpeBRepDS_Curve& tcourb1 = DStr.ChangeCurve(indcurve3d.Value(n3d));
	    tcourb1.Tolerance(tcourb1.Tolerance()+apperror);
	    if(Indice.Value(n3d)!=0) {
	      TopOpeBRepDS_Point& tpt11= DStr.ChangePoint(Indice.Value(n3d));
	      tpt11.Tolerance (tpt11.Tolerance()+apperror);
	    }
	    Interfc=ChFi3d_FilCurveInDS(indcurve3d.Value(n3d),Isurf,
					PSurf.Curves2d()->Value(n3d),orien);
	    DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc);
	    if( Order.Value(n3d)==1) {
	      regular.SetCurve(indcurve3d.Value(n3d));
	      regular.SetS1(Isurf,Standard_False);
	      regular.SetS2(DStr.AddShape(TopoDS::Face(Fproj.Value(nb))));
	      myRegul.Append(regular);
	    }  
	  }
	} 
    }

  // storage of curves in case of tangent free borders 
    if (droit)
      for (ic=0; ic<nedge;ic++) {
	Indices(nedge,ic,icplus,icmoins);  
	TopoDS_Edge ecom;
	ecom=TopoDS::Edge(Evive.Value(ic));
	if (ecom.IsSame(edgelibre1)||ecom.IsSame(edgelibre2)) {
	  n3d++;
	  TopOpeBRepDS_Curve& tcourb1 = DStr.ChangeCurve(indcurve3d.Value(n3d));
	  tcourb1.Tolerance(tcourb1.Tolerance()+apperror);
	  Interfc=ChFi3d_FilCurveInDS(indcurve3d.Value(n3d),Isurf,
				    PSurf.Curves2d()->Value(n3d),orien);
	  DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc);
	}	  
      } 
  }
  else { // there is only one partial result 
    done=Standard_False;
    hasresult=Standard_True;
    for (ic=0; ic<nedge;ic++) {
      Indices(nedge,ic,icplus,icmoins);
      if (!oksea.Value(ic)) {
	if (sharp.Value(ic) &&!deuxconges) {
	  // limitation of the alive edge
	  TopAbs_Orientation ori;
	  gp_Pnt Pf,Pl,sommet1;
	  TopoDS_Vertex Vd = TopExp::FirstVertex(TopoDS::Edge(Evive.Value(ic)));
	  TopoDS_Vertex Vf = TopExp::LastVertex(TopoDS::Edge(Evive.Value(ic)));
	  Pf=BRep_Tool::Pnt(Vd);
	  Pl=BRep_Tool::Pnt(Vf);
	  sommet1=BRep_Tool::Pnt(V1);
	  if (Pf.Distance(sommet1)<Pl.Distance(sommet1))
	    ori = TopAbs_FORWARD;
	  else
	    ori = TopAbs_REVERSED;
	  Standard_Integer Iarc1=DStr.AddShape(TopoDS::Edge(Evive.Value(ic)));
	  Interfp1=ChFi3d_FilPointInDS(ori,Iarc1,indpoint(ic,1),p.Value(ic,icplus));
	  DStr.ChangeShapeInterferences(TopoDS::Edge(Evive.Value(ic))).Append(Interfp1);
	}
      }
    }
  }
}
