// File:	BRepFill_Sweep.cxx
// Created:	Wed Jan  7 13:39:37 1998
// Author:	Philippe MANGIN
//		<pmn@sgi29>

#include <stdio.h>

#include <BRepFill_Sweep.ixx>

#include <BRepFill_SectionLaw.hxx>
//#include <BRepFill_TrimCorner.hxx>
#include <BRepFill_CurveConstraint.hxx>

#include <GeomFill_SectionLaw.hxx>
#include <GeomFill_LocationLaw.hxx>
#include <GeomFill_Sweep.hxx>

// modified by NIZHNY-MKK  Wed Oct 22 12:25:45 2003
#include <BRepFill_TrimShellCorner.hxx>

//#include <GeomPlate_BuildPlateSurface.hxx>
//#include <GeomPlate_Surface.hxx>
//#include <GeomPlate_PointConstraint.hxx>

#include <gp_Pnt2d.hxx>
#include <gp_Vec2d.hxx>
#include <Bnd_Box.hxx>

#include <Geom_Surface.hxx>
#include <Geom_SurfaceOfRevolution.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_Plane.hxx>
#include <Geom_Curve.hxx>
#include <Geom_BezierCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GeomLib.hxx>
#include <GeomLib_IsPlanarSurface.hxx>
#include <BRepLib_FindSurface.hxx>
#include <GeomConvert_ApproxSurface.hxx>

#include <BRepAdaptor_HCurve.hxx>
#include <BRepAdaptor_HCurve2d.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <Adaptor3d_HCurveOnSurface.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomAdaptor_HCurve.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <Approx_CurveOnSurface.hxx>
#include <Approx_SameParameter.hxx>
#include <GCPnts_AbscissaPoint.hxx>

#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
#include <BRep_TEdge.hxx>
#include <BRep_TVertex.hxx>
#include <BRep_CurveRepresentation.hxx>
#include <BRep_GCurve.hxx>

#include <BRepLib.hxx>
#include <BRepLib_MakeEdge.hxx>
#include <BRepLib_MakeFace.hxx>
#include <BRepLib_FaceError.hxx>

#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Shell.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopAbs_Orientation.hxx>

#include <TColStd_HArray1OfInteger.hxx>
#include <TColStd_Array2OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array2OfReal.hxx>
#include <TColGeom_Array2OfSurface.hxx>
#include <TColgp_Array1OfPnt.hxx>

#include <TopTools_Array1OfShape.hxx>
#include <TopTools_Array2OfShape.hxx>
#include <TopTools_HArray2OfShape.hxx>
#include <TopTools_HArray1OfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx> 
#include <TopTools_ListOfShape.hxx> 
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <BRepTools_WireExplorer.hxx>

#include <Standard_ConstructionError.hxx>
#include <Precision.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>

#include <BRepTools_Substitution.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
#include <TopoDS_Iterator.hxx>

//OCC500(apo)
#include <BRepCheck_Edge.hxx>  

#ifdef DRAW
#include <Draw.hxx>
#include <DrawTrSurf.hxx>
#include <DBRep.hxx>
static Standard_Boolean Affich = 0;
#endif

//=======================================================================
//function : NumberOfPoles
//purpose  : 
//=======================================================================
static Standard_Integer NumberOfPoles(const TopoDS_Wire& W)
{
  Standard_Integer NbPoints = 0;

  TopoDS_Iterator iter(W);
  for (; iter.More(); iter.Next()) 
  {
    BRepAdaptor_Curve c(TopoDS::Edge(iter.Value()));

    Standard_Real dfUf = c.FirstParameter();
    Standard_Real dfUl = c.LastParameter();
    if (IsEqual(dfUf,dfUl))
      // Degenerate
      continue;

    switch (c.GetType()) 
    {
    case GeomAbs_BezierCurve:
      {
	// Put all poles for bezier
	Handle(Geom_BezierCurve) GC = c.Bezier();
	Standard_Integer iNbPol = GC->NbPoles();
	if ( iNbPol >= 2)
	  NbPoints += iNbPol;
	break;
      }
    case GeomAbs_BSplineCurve:
      {
	// Put all poles for bspline
	Handle(Geom_BSplineCurve) GC = c.BSpline();
	Standard_Integer iNbPol = GC->NbPoles();
	if ( iNbPol >= 2)
	  NbPoints += iNbPol;
	break;
      }
    case GeomAbs_Line:
      {
	NbPoints += 2;
	break;
      }
    case GeomAbs_Circle:
    case GeomAbs_Ellipse:
    case GeomAbs_Hyperbola:
    case GeomAbs_Parabola:
      {
	NbPoints += 4;
	break;
      }
    default:
      NbPoints += 15 + c.NbIntervals(GeomAbs_C3);
    } // switch (c.GetType()) ...
  } // for (; iter.More(); iter.Next())

  return NbPoints;
}

//=======================================================================
//function : HasPCurves
//purpose  : 
//=======================================================================
static Standard_Boolean HasPCurves(const TopoDS_Edge& E)
{
  Standard_Boolean haspcurves = Standard_False;

  BRep_ListIteratorOfListOfCurveRepresentation itcr
    ((*((Handle(BRep_TEdge)*)&E.TShape()))->Curves());
  for (; itcr.More(); itcr.Next())
    {
      const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
      if (cr->IsCurveOnSurface())
	{
	  haspcurves = Standard_True;
	  break;
	}
    }
  return haspcurves;
}

//=======================================================================
//function : Translate
//purpose  : Copy une colonne d'un tableau dans un autre. 
//=======================================================================
static void Translate(const Handle(TopTools_HArray2OfShape)& ArrayIn,
		      const Standard_Integer In,
		      Handle(TopTools_HArray2OfShape)& ArrayOut,
		      const Standard_Integer Out)
{
  Standard_Integer ii, Nb;
  Nb =  ArrayOut->ColLength();
  for (ii=1; ii<=Nb; ii++) {
     ArrayOut->SetValue(ii, Out,  ArrayIn->Value(ii, In));
  } 
}


//=======================================================================
//function : Box
//purpose  : Boite d'encombrement d'une section.
//=======================================================================
static void Box(Handle(GeomFill_SectionLaw)& Sec,
		const Standard_Real U,
		Bnd_Box& Box)

{
  Standard_Integer NbPoles, bid;
  Box.SetVoid();
  Sec->SectionShape(NbPoles, bid, bid);
  TColgp_Array1OfPnt Poles(1, NbPoles);
  TColStd_Array1OfReal W(1, NbPoles);
  Sec->D0(U, Poles, W);
  for (Standard_Integer ii=1; ii<=NbPoles; ii++) {
      Box.Add(Poles(ii));
    }  
}

//=======================================================================
//function : Couture
//purpose  : Controle si E est une arete de couture sur S
//           et rend la representation HadHoc
//=======================================================================
static Handle(Geom2d_Curve) Couture(const TopoDS_Edge& E, 
				    const Handle(Geom_Surface)& S,
				    const TopLoc_Location& L)
{
  TopLoc_Location l = L.Predivided(E.Location());
  Standard_Boolean Eisreversed = (E.Orientation() == TopAbs_REVERSED);

  // find the representation
  BRep_ListIteratorOfListOfCurveRepresentation itcr
    ((*((Handle(BRep_TEdge)*)&E.TShape()))->ChangeCurves());

  while (itcr.More()) {
    Handle(BRep_CurveRepresentation)& cr = itcr.Value();
    if (cr->IsCurveOnSurface(S,l)) {
      Handle(BRep_GCurve)& GC = *((Handle(BRep_GCurve)*)&cr);
      if (GC->IsCurveOnClosedSurface() && Eisreversed) 
	return  GC->PCurve2();
      else
	return GC->PCurve();
    }
    itcr.Next();
  }
  Handle(Geom2d_Curve) pc;
  pc.Nullify();
  return pc;
}

//=======================================================================
//function : CheckSameParameter
//purpose  : Controle a posteriori que sameparameter a bien fait son boulot
//=======================================================================

static Standard_Boolean CheckSameParameter 
(const Handle(Adaptor3d_HCurve)&   C3d,
 Handle(Geom2d_Curve)&           Pcurv,
 const Handle(Adaptor3d_HSurface)& S,
 const Standard_Real             tol3d,
 Standard_Real&                  tolreached)
{
  tolreached = 0.;
  Standard_Real f = C3d->FirstParameter();
  Standard_Real l = C3d->LastParameter();
  Standard_Integer nbp = 45;
  Standard_Real step = 1./(nbp -1);
  for(Standard_Integer i = 0; i < nbp; i++){
    Standard_Real t,u,v;
    t = step * i;
    t = (1-t) * f + t * l;
    Pcurv->Value(t).Coord(u,v);
    gp_Pnt pS = S->Value(u,v);
    gp_Pnt pC = C3d->Value(t);
    Standard_Real d2 = pS.SquareDistance(pC);
    tolreached = Max(tolreached,d2);
  }
  tolreached = sqrt(tolreached);
  if(tolreached > tol3d){
    tolreached *= 2.;
    return Standard_False;
  }
  tolreached *= 2.;
  tolreached = Max(tolreached,Precision::Confusion());
  return Standard_True;
}

//=======================================================================
//function : SameParameter
//purpose  : Encapsulation de Sameparameter
// Le boolean dit si l'on a calcule la pcurve ou non...
// La tolerance est toujours Ok.
//=======================================================================

static Standard_Boolean SameParameter(TopoDS_Edge&    E,
				      Handle(Geom2d_Curve)&        Pcurv,
				      const Handle(Geom_Surface)&  Surf,
				      const Standard_Real          tol3d,
				      Standard_Real&               tolreached)
{
  //Handle(BRepAdaptor_HCurve) C3d = new (BRepAdaptor_HCurve)(E);
  Standard_Real f, l;
  Handle(Geom_Curve) C3d = BRep_Tool::Curve( E, f, l );
  GeomAdaptor_Curve GAC3d( C3d, f, l );
  Handle(GeomAdaptor_HCurve) HC3d = new GeomAdaptor_HCurve( GAC3d );

  Handle(GeomAdaptor_HSurface) S = new (GeomAdaptor_HSurface)(Surf);
  Standard_Real ResTol;

  if(CheckSameParameter( HC3d, Pcurv, S, tol3d, tolreached )) 
    return Standard_True;

  if (!HasPCurves(E))
    {
      Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( Pcurv );
      Approx_CurveOnSurface AppCurve(HC2d, S, HC2d->FirstParameter(), HC2d->LastParameter(),
				     Precision::Confusion(), GeomAbs_C1, 10, 10, Standard_True);
      if (AppCurve.IsDone() && AppCurve.HasResult())
	{
	  C3d = AppCurve.Curve3d();
	  tolreached = AppCurve.MaxError3d();
	  BRep_Builder B;
	  B.UpdateEdge( E, C3d, tolreached );
	  return Standard_True;
	}
    }

  Approx_SameParameter sp( HC3d, Pcurv, S, tol3d );
  if(sp.IsDone() && !sp.IsSameParameter()) Pcurv = sp.Curve2d();
  else if(!sp.IsDone() && !sp.IsSameParameter()){
#ifdef DEB
    cout<<"echec SameParameter"<<endl;
#endif  
    return Standard_False;
  }

  ResTol = sp.TolReached();
  if(ResTol > tolreached ){
#ifdef DEB
    cout<<"SameParameter : Tol non atteinte!!!"<<endl;
    cout<<"tol visee : "<<tol3d<<" tol obtenue : "<<ResTol<<endl;
#endif  
    return Standard_False;
  }
  else {
    tolreached = 1.1*ResTol;
    if(sp.IsDone() && !sp.IsSameParameter()) Pcurv = sp.Curve2d();
  }
  return Standard_True;
}

//=======================================================================
//Objet : Oriente une arete de restriction naturelle
//      : Cas generale
//=======================================================================
static void Oriente(const Handle(Geom_Surface)& S,
		    TopoDS_Edge& E)
{
  gp_Pnt2d P;
  gp_Vec2d D, URef(1, 0), VRef(0, 1);
  Standard_Boolean isuiso, isfirst, isopposite;
  Standard_Real UFirst, ULast, VFirst, VLast, f, l;
  S->Bounds(UFirst, ULast, VFirst, VLast);
  Handle(Geom2d_Curve) C;
  TopLoc_Location bid;

  C = BRep_Tool::CurveOnSurface(E, S, bid, f, l);
  C->D1((f+l)/2, P, D);

  isuiso = D.IsParallel(VRef, 0.1);
  
  if ( isuiso ) {
    isfirst = (Abs (P.X()-UFirst) < Precision::Confusion());
    isopposite = D.IsOpposite(VRef, 0.1);
    E.Orientation(TopAbs_REVERSED);
  }
  else {
    isfirst = (Abs (P.Y()-VFirst) < Precision::Confusion());
    isopposite = D.IsOpposite(URef, 0.1);
    E.Orientation(TopAbs_FORWARD);
  }

  if (!isfirst)   E.Reverse();
  if (isopposite) E.Reverse();
}
//OCC500(apo)->
static void UpdateEdgeOnPlane(const TopoDS_Face& F, const TopoDS_Edge& E,
			      const BRep_Builder& BB)
{
  Standard_Real f, l;
  Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E,F,f,l);
  Handle(Geom_Surface) S = BRep_Tool::Surface(F);
  TopLoc_Location Loc;
  Standard_Real Tol = BRep_Tool::Tolerance(E);
  BB.UpdateEdge(E, C2d, S, Loc, Tol);
  BRepCheck_Edge Check(E);
  Tol = Max(Tol,Check.Tolerance());
  BB.UpdateEdge(E, Tol);
  TopoDS_Vertex V; 
  Tol *= 1.01;
  V = TopExp::FirstVertex(E);
  if(BRep_Tool::Tolerance(V) < Tol) BB.UpdateVertex(V, Tol);
  V = TopExp::LastVertex(E);
  if(BRep_Tool::Tolerance(V) < Tol) BB.UpdateVertex(V, Tol);
}
//<-OCC500(apo)
//=======================================================================
//Function : BuildFace
//Objet : Construire une Face via, une surface et 4 Edge( Bords naturels)
//      : Seule Hypothese : les iso u et v sont alternee :
//        Edge1/3 sont des iso u (recp v)
//        Edge2/4 sont des iso v (recp u)
//=======================================================================
static void BuildFace(const Handle(Geom_Surface)& S,
		      const TopoDS_Edge& E1,
		      const TopoDS_Edge& E2,
		      const TopoDS_Edge& E3,
		      const TopoDS_Edge& E4,
		      TopTools_DataMapOfShapeShape& EEmap,
		      const Standard_Boolean ExchUV,
		      const Standard_Boolean UReverse,
		      TopoDS_Face& F)
{
  Standard_Real Tol;
// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
  TopoDS_Edge e1, e2, E;
  TopoDS_Wire WW;
  BRep_Builder BB;
  BRepBuilderAPI_MakeWire B;
  TopoDS_Iterator Iter;
  //gp_Pnt2d P;

  //La surface est elle plane ?
  Standard_Real Tol1, Tol2, Tol3, Tol4;
  Tol1 = BRep_Tool::Tolerance( E1 );
  Tol2 = BRep_Tool::Tolerance( E2 );
  Tol3 = BRep_Tool::Tolerance( E3 );
  Tol4 = BRep_Tool::Tolerance( E4 );
//  Tol = Min( BT.Tolerance(E1), BT.Tolerance(E2));
  Tol = Min( Tol1, Tol2 );
//  Tol = Min(Tol, Min(BT.Tolerance(E3),BT.Tolerance(E4)));
  Tol = Min( Tol, Min( Tol3, Tol4 ) );
  Standard_Boolean IsPlan = Standard_False;
  Handle(Geom_Plane) thePlane;

  if (!E1.IsSame(E3) && !E2.IsSame(E4)) //exclude cases with seam edges: they are not planar
    {
      GeomLib_IsPlanarSurface IsP(S, Tol);
      if (IsP.IsPlanar())
	{
	  IsPlan = Standard_True;
	  thePlane = new Geom_Plane( IsP.Plan() );
	}
      else
	{
	  Handle(BRep_TEdge)& TE1 = *((Handle(BRep_TEdge)*)&E1.TShape());
	  Handle(BRep_TEdge)& TE2 = *((Handle(BRep_TEdge)*)&E2.TShape());
	  Handle(BRep_TEdge)& TE3 = *((Handle(BRep_TEdge)*)&E3.TShape());
	  Handle(BRep_TEdge)& TE4 = *((Handle(BRep_TEdge)*)&E4.TShape());
	  TE1->Tolerance( Precision::Confusion() );
	  TE2->Tolerance( Precision::Confusion() );
	  TE3->Tolerance( Precision::Confusion() );
	  TE4->Tolerance( Precision::Confusion() );
	  
	  TopoDS_Wire theWire = BRepLib_MakeWire( E1, E2, E3, E4 );
	  Standard_Integer NbPoints = NumberOfPoles( theWire );
	  if (NbPoints <= 100) //limitation for CPU
	    {
	      BRepLib_FindSurface FS( theWire, -1, Standard_True );
	      if (FS.Found())
		{
		  IsPlan = Standard_True;
		  thePlane = Handle(Geom_Plane)::DownCast(FS.Surface());
		}
	    }
	  BB.UpdateEdge( E1, Tol1 );
	  BB.UpdateEdge( E2, Tol2 );
	  BB.UpdateEdge( E3, Tol3 );
	  BB.UpdateEdge( E4, Tol4 );
	}
    }

  // Construction du wire
//  B.MakeWire(WW);
  e1 = E1;
  Oriente(S, e1);
//  if (!IsPlan || !BT.Degenerated(e1)) 
  if (!IsPlan || !BRep_Tool::Degenerated(e1)) 
    B.Add(e1);

  e2 = E2;
  Oriente(S, e2);  
//  if (!IsPlan || !BT.Degenerated(e2)) 
  if (!IsPlan || !BRep_Tool::Degenerated(e2))
    {
      B.Add(e2);
      if (!BRep_Tool::Degenerated(e2))
	{
	  WW = B.Wire();
	  TopoDS_Shape NewEdge;
	  //take the last edge added to WW
	  for (Iter.Initialize( WW ); Iter.More(); Iter.Next())
	    NewEdge = Iter.Value();
	  if (! e2.IsSame(NewEdge))
	    EEmap.Bind( e2, NewEdge );
	}
    }

  if (E3.IsSame(E1)) {
    E = e1;
    E.Reverse();
  }
  else {
    E = E3;
    Oriente(S, E);
  }
//  if (!IsPlan || !BT.Degenerated(E))   
  if (!IsPlan || !BRep_Tool::Degenerated(E))
    {
      B.Add(E);
      if (!BRep_Tool::Degenerated(E))
	{
	  WW = B.Wire();
	  TopoDS_Shape NewEdge;
	  //take the last edge added to WW
	  for (Iter.Initialize( WW ); Iter.More(); Iter.Next())
	    NewEdge = Iter.Value();
	  if (! E.IsSame(NewEdge))
	    EEmap.Bind( E, NewEdge );
	}
    }

  if (E4.IsSame(E2)) {
    E = e2;
    E.Reverse();
  }
  else {
    E = E4;
    Oriente(S, E);
  }
//  if (!IsPlan || !BT.Degenerated(E))  
  if (!IsPlan || !BRep_Tool::Degenerated(E)) 
    {
      B.Add(E);
      if (!BRep_Tool::Degenerated(E))
	{
	  WW = B.Wire();
	  TopoDS_Shape NewEdge;
	  //take the last edge added to WW
	  for (Iter.Initialize( WW ); Iter.More(); Iter.Next())
	    NewEdge = Iter.Value();
	  if (! E.IsSame(NewEdge))
	    EEmap.Bind( E, NewEdge );
	}
    }

  WW = B.Wire();
#if DRAW
  if (Affich) {
    char* name;
    sprintf(name,"wire-on-face");
    DBRep::Set(name, WW);
  }
#endif
  
// Construction de la face.
  if (IsPlan) { // On vire les representation 2d 
    // et on constuit une face Plane

    //BRepLib_MakeFace MkF(IsP.Plan(), WW);
    gp_Pnt aPnt;
    gp_Vec DU, DV, NS, NP;
    Standard_Real Ufirst, Ulast, Vfirst, Vlast;
    S->Bounds( Ufirst, Ulast, Vfirst, Vlast );
    S->D1( (Ufirst+Ulast)/2., (Vfirst+Vlast)/2., aPnt, DU, DV );
    NS = DU ^ DV;
    NP = thePlane->Pln().Axis().Direction();
    if (NS.Dot(NP) < 0.)
      thePlane->UReverse();
    BRepLib_MakeFace MkF( thePlane, WW );
    if (MkF.Error() != BRepLib_FaceDone) {
#if DEB
      BRepLib_FaceError Err = MkF.Error();
      cout << "Planar Face Error :" <<   Err << endl;
#endif
    }
    else {
      Handle(Geom2d_Curve) NullC2d;
      TopLoc_Location Loc;
      BB.UpdateEdge( E1, NullC2d, S, Loc, Tol1 );
      BB.UpdateEdge( E2, NullC2d, S, Loc, Tol2 );
      BB.UpdateEdge( E3, NullC2d, S, Loc, Tol3 );
      BB.UpdateEdge( E4, NullC2d, S, Loc, Tol4 );

      F =  MkF.Face();
      UpdateEdgeOnPlane(F,E1,BB);
      UpdateEdgeOnPlane(F,E2,BB);
      UpdateEdgeOnPlane(F,E3,BB);
      UpdateEdgeOnPlane(F,E4,BB);
/*OCC500(apo)->
      TopLoc_Location Loc;
      Handle(Geom2d_Curve) NC;
      NC.Nullify();
//      B.UpdateEdge(E1, NC, S, Loc, BT.Tolerance(E1));
      BB.UpdateEdge(E1, NC, S, Loc, BRep_Tool::Tolerance(E1));
//      B.UpdateEdge(E2, NC, S, Loc, BT.Tolerance(E2));
      BB.UpdateEdge(E2, NC, S, Loc, BRep_Tool::Tolerance(E2));
//      B.UpdateEdge(E3, NC, S, Loc, BT.Tolerance(E3));
      BB.UpdateEdge(E3, NC, S, Loc, BRep_Tool::Tolerance(E3));
//      B.UpdateEdge(E4, NC, S, Loc, BT.Tolerance(E4));
      BB.UpdateEdge(E4, NC, S, Loc, BRep_Tool::Tolerance(E4));
<-OCC500(apo)*/
    }  
  }

  if (!IsPlan) {// Cas Standard : Ajout
    BB.MakeFace(F, S, Precision::Confusion());
    BB.Add(F, WW);
  }

  // Reorientation
  if (ExchUV) F.Reverse();
  if (UReverse) F.Reverse();
}


//=======================================================================
//Fonction : BuildEdge
//Objet : Construit une Edge non fermee
//=======================================================================
static TopoDS_Edge BuildEdge(Handle(Geom_Curve)& C3d,
			     Handle(Geom2d_Curve)& C2d,
			     Handle(Geom_Surface)& S,
			     const TopoDS_Vertex& VF,
			     const TopoDS_Vertex& VL,
			     const Standard_Real f, 
			     const Standard_Real l,
			     const Standard_Real Tol3d)
{
  gp_Pnt P1, P2, P;
  Standard_Real Tol1, Tol2, Tol, d;
// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
  BRep_Builder B;
  TopoDS_Edge E;

//  P1  = BT.Pnt(VF);
  P1  = BRep_Tool::Pnt(VF);
//  Tol1 = BT.Tolerance(VF);
  Tol1 = BRep_Tool::Tolerance(VF);
//  P2  = BT.Pnt(VL);
  P2  = BRep_Tool::Pnt(VL);
//  Tol2 = BT.Tolerance(VF);
  Tol2 = BRep_Tool::Tolerance(VF);
  Tol = Max(Tol1, Tol2);

  if (VF.IsSame(VL) || 
      (P1.Distance(P2) < Tol ) ) { 
    // Cas degenere
    gp_Pnt2d P2d;
    C2d->D0(f, P2d);
    S->D0(P2d.X(), P2d.Y(), P);
    d = P1.Distance(P);
    if (d > Tol) Tol = d;
    C2d->D0(l, P2d);
    S->D0(P2d.X(), P2d.Y(), P);
    d = P2.Distance(P);
    if (d > Tol) Tol = d;

    B.UpdateVertex(VF, Tol);
    B.UpdateVertex(VL, Tol);

    B.MakeEdge(E);
    B.UpdateEdge(E,C2d,S,TopLoc_Location(), Tol);
    B.Add(E,VF);
    B.Add(E,VL);
    B.Range(E,f,l);
    B.Degenerated(E, Standard_True);

    return E;
  }

  C3d->D0(f, P);
  d = P1.Distance(P);
  if (d > Tol1)
      B.UpdateVertex(VF, d);

//  P1 = BT.Pnt(VL);
  P1 = BRep_Tool::Pnt(VL);
  C3d->D0(l, P);
  d = P2.Distance(P);
  if (d > Tol2)
      B.UpdateVertex(VL, d); 

  BRepLib_MakeEdge MkE (C3d, VF, VL, f, l);
  if (!MkE.IsDone()) { // Erreur de construction !!     
#ifdef DRAW    
    char name[100];
    sprintf(name,"firstvertex_error");
    DBRep::Set(name, VF);
    sprintf(name,"lastvertex_error");
    DBRep::Set(name, VL);
    sprintf(name,"curve3d_error");
    char* Temp = name ;
    DrawTrSurf::Set(Temp, C3d);
//    DrawTrSurf::Set(name, C3d);
    Standard_ConstructionError::Raise("BRepFill_Sweep::BuildEdge");
#endif
  }

  E = MkE.Edge();
  TopLoc_Location Loc;
  B.UpdateEdge(E, C2d, S, Loc, Tol3d);

  return E;
}

	
//=======================================================================
//Fonction : Filling
//Objet : Construit les faces de remplisage
//=======================================================================
static Standard_Boolean Filling(const TopoDS_Shape& EF,
				const TopoDS_Shape& F1,
				const TopoDS_Shape& EL,
				const TopoDS_Shape& F2,
				TopTools_DataMapOfShapeShape& EEmap,
				const Standard_Real Tol,
				const  gp_Ax2& Axe,
				const  gp_Vec& TangentOnPart1,
				TopoDS_Edge& Aux1,
				TopoDS_Edge& Aux2,
				TopoDS_Face& Result)
{
  BRep_Builder B;
// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
//  Standard_Integer NbInt =0;
//  Standard_Real Tol3d = Tol;
  Standard_Boolean WithE3, WithE4;

// Recuperation des contraintes
  TopoDS_Vertex V1, V2, Vf, Vl;
  TopoDS_Edge E1, E2, E3, E4;
  E1 = TopoDS::Edge(EF);
  E2 = TopoDS::Edge(EL);
  
  TopExp::Vertices(E1, Vf, Vl);
  Vf.Orientation(TopAbs_FORWARD);
  Vl.Orientation(TopAbs_FORWARD);

  TopExp::Vertices(E2, V1, V2);
  V1.Orientation(TopAbs_REVERSED);
  V2.Orientation(TopAbs_REVERSED);  
  
  B.MakeEdge(E3);
  B.MakeEdge(E4);

  WithE3 = WithE4 = Standard_False;

  if ((!Aux1.IsNull()) && (!Vf.IsSame(V1))) {
    E3 = Aux1;
//    E3 = TopoDS::Edge(Aux1);
    WithE3 = Standard_True;
  }

  if (Vf.IsSame(Vl)) {
    E4 = E3;
    E4.Reverse();
    WithE4 = WithE3;
  }
  else if (!Aux2.IsNull() && (!Vl.IsSame(V2))) {
    E4 = Aux2;
//    E4 = TopoDS::Edge(Aux2);
    WithE4 = Standard_True;
  }

#if DRAW
  if (Affich) {
    DBRep::Set("Fill_Edge1", E1);
    DBRep::Set("Fill_Edge2", E2);
    if (!E3.IsNull())
      DBRep::Set("Fill_Edge3", E3);
    if (!E4.IsNull())
      DBRep::Set("Fill_Edge4", E4);
  }
#endif

// Construction d'une surface de revolution
  Handle(Geom_Curve) Prof1, Prof2;
  //Standard_Integer ii, jj;//, Nb;
  Standard_Real f1, f2, l1, l2,/*d1, d2,*/ Angle;//, Eps = 1.e-9;
//  Prof1 = BT.Curve(E1, f1, l1);
  Prof1 = BRep_Tool::Curve(E1, f1, l1);
//  Prof2 = BT.Curve(E2, f2, l2);
  Prof2 = BRep_Tool::Curve(E2, f2, l2);
  gp_Pnt P1, P2, P;
  gp_Pnt2d p1, p2;
  gp_Trsf Tf;
  Tf.SetTransformation(Axe);

// Choix d'un angle d'ouverture
  P1 = Prof1->Value((f1+l1)/2);
  P2 = Prof2->Value((f2+l2)/2);
  P1.Transform(Tf);
  P2.Transform(Tf);
  p1.SetCoord(P1.Z(), P1.X());
  p2.SetCoord(P2.Z(), P2.X());
  gp_Vec2d v1(gp::Origin2d(), p1);
  gp_Vec2d v2(gp::Origin2d(), p2);
  if (v1.Magnitude() <= gp::Resolution() ||
      v2.Magnitude() <= gp::Resolution())
    return Standard_False;
  Angle = v1.Angle(v2);

  gp_Ax1 axe(Axe.Location(), Axe.YDirection());

  if (Angle < 0) {
    Angle = -Angle;
    axe.Reverse();
  }

  Handle(Geom_SurfaceOfRevolution) Rev = 
    new (Geom_SurfaceOfRevolution) (Prof1, axe);
  
  Handle(Geom_Surface) Surf = 
    new (Geom_RectangularTrimmedSurface) (Rev, 0, Angle, f1, l1);

  // Controle le sens de la rotation
  Standard_Boolean ToReverseResult = Standard_False;
  gp_Vec d1u;
  d1u = Surf->DN(0, (f1+l1)/2, 1, 0);
  if (d1u.Angle(TangentOnPart1) > PI/2) { //On inverse tout
    ToReverseResult = Standard_True;
    /*
    axe.Reverse();
    Angle = 2*PI - Angle;
    Rev = new (Geom_SurfaceOfRevolution) (Prof1, axe);
    Surf = new (Geom_RectangularTrimmedSurface) 
           (Rev, 0, Angle, f1, l1);
    */
  }

#if DRAW
  if (Affich) { 
      char* Temp = "Surf_Init" ;
      DrawTrSurf::Set(Temp, Surf);
    }
#endif

  Handle(Geom2d_Curve) C1, C2, C3, C4;
/*
// Deformation de la surface de revolution.
  GeomPlate_BuildPlateSurface BPS;

  Handle(BRepAdaptor_HSurface) AS;
  Handle(BRepAdaptor_HCurve2d) AC2d;
  Handle(Adaptor3d_HCurveOnSurface) HConS;
*/
  Handle(Geom2d_Line) L;
  gp_Pnt2d P2d(0.,0.);

  L = new (Geom2d_Line) (P2d, gp::DY2d());
  C1 = new (Geom2d_TrimmedCurve) (L, f1, l1);

  P2d.SetCoord(Angle,0.);
  L = new (Geom2d_Line) (P2d, gp::DY2d());
  C2 = new (Geom2d_TrimmedCurve) (L, f1, l1);
 
  // Ici il faut controler le sens et le range.
  C2->D0(f1, P2d);
  Surf->D0(P2d.X(), P2d.Y(), P1);
  C2->D0(l1, P2d);
  Surf->D0(P2d.X(), P2d.Y(), P2);
//  P = BT.Pnt(V1);
  P = BRep_Tool::Pnt(V1);
  if (P.Distance(P2)+Tol < P.Distance(P1)) {
    // E2 est (sans doute!) parcourue dans le sens inverse de E1
    C2->Reverse();
    TopoDS_Vertex aux;
    aux = V2;
    V2 = V1;
    V1 = aux;
  }
  GeomLib::SameRange(Precision::PConfusion(), C2, 
		     C2->FirstParameter(),
		     C2->LastParameter(),
		     f2, l2, C3);
  C2 = C3;

  Standard_Boolean pointu_f,  pointu_l;
//  P1 = BT.Pnt(Vf);
  P1 = BRep_Tool::Pnt(Vf);
//  P2 = BT.Pnt(V1);
  P2 = BRep_Tool::Pnt(V1);
//  pointu_f = Vf.IsSame(V1) || (P1.Distance(P2) < BT.Tolerance(Vf));
  pointu_f = Vf.IsSame(V1) || (P1.Distance(P2) < BRep_Tool::Tolerance(Vf));
//  P1 = BT.Pnt(Vl);
  P1 = BRep_Tool::Pnt(Vl);
//  P2 = BT.Pnt(V2);
  P2 = BRep_Tool::Pnt(V2);
//  pointu_l = Vl.IsSame(V2) || (P1.Distance(P2) < BT.Tolerance(Vl));
  pointu_l = Vl.IsSame(V2) || (P1.Distance(P2) < BRep_Tool::Tolerance(Vl));


  P2d.SetCoord(0.,f1);
  L = new (Geom2d_Line) (P2d, gp::DX2d());
  C3 = new (Geom2d_TrimmedCurve) (L, 0, Angle);


  P2d.SetCoord(0.,l1);
  L = new (Geom2d_Line) (P2d, gp::DX2d());   
  C4 = new (Geom2d_TrimmedCurve) (L, 0, Angle);
/*
  // Determination des contraintes et 
  // de leur localisation parametrique.
  if (!E1.IsNull()) {
     AS = new BRepAdaptor_HSurface(TopoDS::Face(F1));
     AC2d = new BRepAdaptor_HCurve2d();
     AC2d->ChangeCurve2d().Initialize(E1,TopoDS::Face(F1));
     HConS = new (Adaptor3d_HCurveOnSurface)();
     HConS->ChangeCurve().Load(AC2d);
     HConS->ChangeCurve().Load(AS);

     Handle(BRepFill_CurveConstraint) Cont
      = new BRepFill_CurveConstraint(HConS, 1, 15);
     Cont->SetCurve2dOnSurf(C1);

     BPS.Add(Cont);
     NbInt = HConS->NbIntervals(GeomAbs_CN);
   }

  if (!E2.IsNull()) {
    AS = new BRepAdaptor_HSurface(TopoDS::Face(F2));
    AC2d = new BRepAdaptor_HCurve2d();
    AC2d->ChangeCurve2d().Initialize(E2,TopoDS::Face(F2));
    HConS = new (Adaptor3d_HCurveOnSurface);

    HConS->ChangeCurve().Load(AC2d);
    HConS->ChangeCurve().Load(AS);

    Handle(BRepFill_CurveConstraint) Cont
      = new BRepFill_CurveConstraint(HConS, 1, 15);
    Cont->SetCurve2dOnSurf(C2);
    BPS.Add(Cont);
  }

  if (WithE3) {
    Handle(BRepAdaptor_HCurve) AC = new (BRepAdaptor_HCurve) (E3);
    Handle(BRepFill_CurveConstraint) Cont
      = new BRepFill_CurveConstraint(AC, 0);
    Cont->SetCurve2dOnSurf(C3);
    BPS.Add(Cont);
  } 
  else if (pointu_f) {
    Standard_Real delta = Angle / 11;
//    P = BT.Pnt(Vf);
    P = BRep_Tool::Pnt(Vf);
    Handle(GeomPlate_PointConstraint) PC;
    for (ii=1; ii<=10; ii++) {
      C3->D0(ii*delta, P2d);
      PC = new (GeomPlate_PointConstraint) (P, 0); 
      PC->SetPnt2dOnSurf(P2d);
      BPS.Add(PC);
    }
  }


  if (WithE4) {
    Handle(BRepAdaptor_HCurve) AC = new (BRepAdaptor_HCurve) (E4);
    Handle(BRepFill_CurveConstraint) Cont
      = new BRepFill_CurveConstraint(AC, 0);
    Cont->SetCurve2dOnSurf(C4);
    BPS.Add(Cont);
  }
  else if (pointu_l) {
    Standard_Real delta = Angle / 11;
//    P = BT.Pnt(Vl);
    P = BRep_Tool::Pnt(Vl);
    Handle(GeomPlate_PointConstraint) PC;
    for (ii=1; ii<=10; ii++) {
      C4->D0(ii*delta, P2d);
      PC = new (GeomPlate_PointConstraint) (P, 0); 
      PC->SetPnt2dOnSurf(P2d);
      BPS.Add(PC);
    }
  }

  BPS.LoadInitSurface(Surf);
  BPS.Perform();

  // Controle s'il y a une deformation effective
  Handle(GeomPlate_Surface) plate;
  plate = BPS.Surface();
  plate->SetBounds(0, Angle, f1, l1);
  Standard_Boolean Ok=Standard_True;
  Standard_Real u, v;
  d1 = (l1-f1)/5;
  d2 = Angle/5;
  for (ii=0; ii<=5 && Ok; ii++) {
    u = f1 + ii*d1;
    for (jj=0; jj<=5 && Ok; jj++) {
      v = jj*d2;
      plate->D0(u, v, P1);
      Surf->D0(u, v, P2);
      Ok = (P2.IsEqual(P1, Tol)); 
    }
  }


  if (!Ok) {
    // Approx de la plate surface
    // Bords naturelles => pas besoin de criteres.
    GeomConvert_ApproxSurface App(BPS.Surface(), 
				  Tol3d,
				  GeomAbs_C1, GeomAbs_C1,
				  8, 8, 2*NbInt, 0);
    if (!App.HasResult()) {
#if DEB
      cout << "Filling_Approx : Pas de resultat" << endl;
#endif      
      return Standard_False;
    }
#if DEB
    cout <<  "Filling_Approx Error 3d = " << 
      App.MaxError() << endl;
#endif
    Surf = App.Surface();
    Tol3d = App.MaxError();  
  }
*/

// Update des Edges
  TopLoc_Location Loc;
  Handle(Geom_Curve) C3d;
  B.UpdateEdge(E1, C1, Surf, Loc, /*Tol3d*/Precision::Confusion());
  B.UpdateEdge(E2, C2, Surf, Loc, /*Tol3d*/Precision::Confusion());
 
  if (E3.IsSame(E4)) {
    if (!WithE3)
      {
	C3d = Surf->VIso(f1);
	E3 = BuildEdge(C3d, C3, Surf, Vf, V1, 0, Angle, /*Tol3d*/Precision::Confusion());
      }
    else
      {
	BRepAdaptor_Curve aCurve(E3);
	Standard_Real AngleOld = aCurve.LastParameter();
	if (Angle > AngleOld)
	  {
	    B.Range( E3, 0, Angle );
	    TopoDS_Vertex V (TopExp::LastVertex(E3));
	    Handle(BRep_TVertex)& TVlast = *((Handle(BRep_TVertex)*) &V.TShape());
	    TVlast->Tolerance( Precision::Confusion() );
	  }
      }

    B.UpdateEdge(E3, C3, C4, Surf, Loc, /*Tol3d*/Precision::Confusion());
    E4 = E3;
    E4.Reverse();
  }
  else {
    if (!WithE3)
      {
	C3d = Surf->VIso(f1);
	E3 = BuildEdge(C3d, C3, Surf, Vf, V1, 0, Angle, /*Tol3d*/Precision::Confusion());
      }
    else
      {
	BRepAdaptor_Curve aCurve(E3);
	Standard_Real AngleOld = aCurve.LastParameter();
	if (Angle > AngleOld)
	  {
	    B.Range( E3, 0, Angle );
	    TopoDS_Vertex V(TopExp::LastVertex(E3));
	    Handle(BRep_TVertex)& TVlast = *((Handle(BRep_TVertex)*) &V.TShape());
	    TVlast->Tolerance( Precision::Confusion() );
	  }

	B.UpdateEdge(E3, C3, Surf, Loc, /*Tol3d*/Precision::Confusion());
      }
    
    if (!WithE4)
      {
	C3d = Surf->VIso(l1);
	E4 = BuildEdge(C3d, C4, Surf, Vl, V2, 0, Angle, /*Tol3d*/Precision::Confusion());
      }
    else
      {
	BRepAdaptor_Curve aCurve(E4);
	Standard_Real AngleOld = aCurve.LastParameter();
	if (Angle > AngleOld)
	  {
	    B.Range( E4, 0, Angle );
	    TopoDS_Vertex V (TopExp::LastVertex(E4));
	    Handle(BRep_TVertex)& TVlast = *((Handle(BRep_TVertex)*)&V.TShape());
	    TVlast->Tolerance( Precision::Confusion() );
	  }

	B.UpdateEdge(E4, C4, Surf, Loc, /*Tol3d*/Precision::Confusion());
      }
  }

//Construction de la face
  BuildFace(Surf,E1, E3, E2, E4, EEmap,
	    Standard_False, Standard_False, 
	    Result);

// Set Les continuites.
  B.Continuity(E1, TopoDS::Face(F1), Result, GeomAbs_G1);
  B.Continuity(E2, TopoDS::Face(F2), Result, GeomAbs_G1);

// Rend les bords calcules.
//  if (!BT.Degenerated(E3))
  if (!BRep_Tool::Degenerated(E3))
    Aux1 = E3;
  else
    B.MakeEdge(Aux1); //Nullify

//  if (!BT.Degenerated(E4))
  if (!BRep_Tool::Degenerated(E4))
    Aux2 = E4;
  else
    B.MakeEdge(Aux2);

  // Set de l'orientation
  gp_Vec D1U, D1V, N1, N2;
  C1->D0( (f1+l1)/2, P2d);
  Surf->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
  N1 = D1U^D1V;
  
//  C1 = BT.CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
  C1 = BRep_Tool::CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
  C1->D0( (f1+l1)/2, P2d);
  Handle(BRepAdaptor_HSurface) AS = new BRepAdaptor_HSurface(TopoDS::Face(F1));
  AS->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
  N2 = D1U^D1V;
  
  if ( (F1.Orientation() == TopAbs_REVERSED) ^ (N1.Angle(N2)>PI/2) )
    Result.Orientation(TopAbs_REVERSED);
  else  Result.Orientation(TopAbs_FORWARD);

  if (ToReverseResult)
    Result.Reverse();

#if DRAW
  if (Affich) DBRep::Set("BoucheTrou", Result);
#endif

  return Standard_True;
}

//=======================================================================
//function : Substitute
//purpose  :
//=======================================================================
static void Substitute(BRepTools_Substitution& aSubstitute,
		       const TopoDS_Edge& Old,
		       const TopoDS_Edge& New) 
{
  TopTools_ListOfShape listShape;

  TopoDS_Vertex OldV1, OldV2, NewV1, NewV2;
  TopExp::Vertices( Old, OldV1, OldV2 );
  TopExp::Vertices( New, NewV1, NewV2 );

  if (!aSubstitute.IsCopied( OldV1 ))
    {
      listShape.Append( NewV1.Oriented(TopAbs_FORWARD) );
      aSubstitute.Substitute( OldV1, listShape );
      listShape.Clear();
    }
  if (!aSubstitute.IsCopied( OldV2 ))
    {
      listShape.Append( NewV2.Oriented(TopAbs_FORWARD) );
      aSubstitute.Substitute( OldV2, listShape );
      listShape.Clear();
    }
  if (!aSubstitute.IsCopied( Old ))
    {
      listShape.Append( New.Oriented(TopAbs_FORWARD) );
      aSubstitute.Substitute( Old, listShape );
    }
}

//=======================================================================
//Function : SetCommonEdgeInFace
//Purpose  : Replace an edge of the face by correspondent edge from
//           myUEdges
//=======================================================================
/*
static void SetCommonEdgeInFace(BRepTools_Substitution& aSubstitute,
				const TopoDS_Shape& Face,
				const TopoDS_Shape& Edge)
{
  if (Edge.IsNull())
    return;

  Standard_Boolean done = Standard_False;
// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
  Standard_Real f, l;
  TopExp_Explorer Exp(Face, TopAbs_EDGE);
  Handle(Geom_Curve) Cref, C;
  TopLoc_Location Lref, L;
//  Cref = BT.Curve(TopoDS::Edge(Edge), Lref, f, l); 
  const TopoDS_Edge& NewEdge = TopoDS::Edge(Edge);
  Cref = BRep_Tool::Curve( NewEdge, Lref, f, l ); 

  for ( ; Exp.More() && !done; Exp.Next()) {
//    C = BT.Curve(TopoDS::Edge(Exp.Current()), L, f, l);
    const TopoDS_Edge& OldEdge = TopoDS::Edge(Exp.Current());
    C = BRep_Tool::Curve(OldEdge, L, f, l);
    if ((Cref==C) && (Lref == L)) {
      done = Standard_True;
      Substitute( aSubstitute, OldEdge, NewEdge );
    }
  }
#if DEB
  if (!done) cout << "Substitution of Edge failed" << endl;
#endif  
}
*/

//=======================================================================
//Fonction : KeepEdge
//Objet : Recheche les edges de la face supporte par la meme Courbe.
//=======================================================================
static void KeepEdge(const TopoDS_Shape& Face,
		     const TopoDS_Shape& Edge,
		     TopTools_ListOfShape& List)
{
  List.Clear();
// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
  Standard_Real f, l;
  TopExp_Explorer Exp(Face, TopAbs_EDGE);
  Handle(Geom_Curve) Cref, C;
  TopLoc_Location Lref, L;
//  Cref = BT.Curve(TopoDS::Edge(Edge), Lref, f, l); 
  Cref = BRep_Tool::Curve(TopoDS::Edge(Edge), Lref, f, l); 

  for ( ; Exp.More(); Exp.Next()) {
//    C = BT.Curve(TopoDS::Edge(Exp.Current()), L, f, l);
    C = BRep_Tool::Curve(TopoDS::Edge(Exp.Current()), L, f, l);
    if ((Cref==C) && (Lref == L)) { 
      List.Append(Exp.Current());
    }
  }
}

//=======================================================================
//Function : 
//Objet : Construire un vertex via, une iso
//=======================================================================
static void BuildVertex(const Handle(Geom_Curve)& Iso,
			const Standard_Boolean isfirst,
			const Standard_Real First,
			const Standard_Real Last,
			TopoDS_Shape& Vertex)
{
  BRep_Builder B;
  Standard_Real val;

  if (isfirst) val = First;
  else val = Last;
  B.MakeVertex(TopoDS::Vertex(Vertex),
	       Iso->Value(val),
	       Precision::Confusion());
}

//=======================================================================
//Function : 
//Objet : Construire une arete vide
//=======================================================================
static TopoDS_Edge NullEdge(TopoDS_Shape& Vertex)
{
  TopoDS_Edge E;
  BRep_Builder B;
  B.MakeEdge(E);
  Vertex.Orientation(TopAbs_FORWARD);
  B.Add(E, Vertex);
  B.Add(E, Vertex.Reversed());
  B.Degenerated(E, Standard_True);
  return E;

}
	
//=======================================================================
//Function : 
//Objet : Construire une arete via, une iso
//=======================================================================
static TopoDS_Edge BuildEdge(const Handle(Geom_Surface)& S,
			     const Standard_Boolean isUiso,
			     const Standard_Real ValIso,
			     const TopoDS_Shape&  VFirst,
			     const TopoDS_Shape&  VLast,
			     const Standard_Real  Tol)
{
  TopoDS_Edge E;
  BRep_Builder B;
  Handle(Geom_Curve) Iso;
  Standard_Boolean sing = Standard_False;
  if (isUiso) {
    Iso = S->UIso(ValIso);
  }
  else {      
    Iso = S->VIso(ValIso);
  }

  if (VFirst.IsSame(VLast)) { // Cas Singulier ?
    gp_Pnt P; 
// Class BRep_Tool without fields and without Constructor :
//    BRep_Tool BT;
    const TopoDS_Vertex& V = TopoDS::Vertex(VFirst);
//    Standard_Real tol = BT.Tolerance(V);
    Standard_Real tol = BRep_Tool::Tolerance(V);
    if (Tol > tol) tol = Tol; 
    Iso->D0((Iso->FirstParameter()+Iso->LastParameter())/2, P);
//    if (P.Distance(BT.Pnt(V)) < tol) {
    if (P.Distance(BRep_Tool::Pnt(V)) < tol) {
      GeomAdaptor_Curve AC(Iso);
      sing = GCPnts_AbscissaPoint::Length(AC, tol/4) < tol;
    }
  }


  if (sing) { // Cas Singulier
    TopoDS_Shape V;
    V = VFirst;
    E = NullEdge(V);
//    Iso.Nullify();
//    B.UpdateEdge(E, Iso, Precision::Confusion());
    B.Degenerated(E, Standard_True);
  }
  
  else {
    // Construction Via le 3d
//    if (isUiso) {
//      Iso = S->UIso(ValIso);
    gp_Pnt P1,P2;
    Standard_Real p1, p2, p11, p12, p21, p22;
    Standard_Boolean fwd = Standard_False;
    p1 = Iso->FirstParameter();
    p2 = Iso->LastParameter();
    P1 = Iso->Value(p1);
    P2 = Iso->Value(p2);

    Standard_Real t1 = BRep_Tool::Tolerance(TopoDS::Vertex(VFirst));
    Standard_Real t2 = BRep_Tool::Tolerance(TopoDS::Vertex(VLast));

    BRep_Builder BB;

    p11 = P1.Distance(BRep_Tool::Pnt(TopoDS::Vertex(VFirst)));
    p22 = P2.Distance(BRep_Tool::Pnt(TopoDS::Vertex(VLast)));
    p12 = P1.Distance(BRep_Tool::Pnt(TopoDS::Vertex(VLast)));
    p21 = P2.Distance(BRep_Tool::Pnt(TopoDS::Vertex(VFirst)));
    
    if(p11 < p12 && p22 < p21) fwd = Standard_True;

    if(fwd) { //OCC500(apo)
      if (p11 >= t1) BB.UpdateVertex(TopoDS::Vertex(VFirst), 1.01*p11);
      if (p22 >= t2) BB.UpdateVertex(TopoDS::Vertex(VLast), 1.01*p22);
    }
    else {      
//      Iso = S->VIso(ValIso);
      if (p12 >= t2) BB.UpdateVertex(TopoDS::Vertex(VLast), 1.01*p12);
      if (p21 >= t1) BB.UpdateVertex(TopoDS::Vertex(VFirst), 1.01*p21);
    }

    BRepLib_MakeEdge MkE;

//    MkE.Init(Iso, 
//	     TopoDS::Vertex(VFirst), 
//	     TopoDS::Vertex(VLast), 
//	     Iso->FirstParameter(),
//	     Iso->LastParameter());
    if(fwd)
      MkE.Init(Iso, 
	       TopoDS::Vertex(VFirst), 
	       TopoDS::Vertex(VLast), 
	       Iso->FirstParameter(),
	       Iso->LastParameter());
    else
      MkE.Init(Iso,
	       TopoDS::Vertex(VLast),
	       TopoDS::Vertex(VFirst), 
	       Iso->FirstParameter(),
	       Iso->LastParameter());

//    if (!MkE.IsDone()) { // Il faut peut etre permuter les Vertex
//      MkE.Init(Iso,
//	       TopoDS::Vertex(VLast),
//	       TopoDS::Vertex(VFirst), 
//	       Iso->FirstParameter(),
//	       Iso->LastParameter());
//    }

    if (!MkE.IsDone()) { // Erreur de construction !!     
#ifdef DRAW
      char name[100];
      sprintf(name,"firstvertex_error");
      DBRep::Set(name, VFirst);
      sprintf(name,"lastvertex_error");
      DBRep::Set(name, VLast);
      sprintf(name,"curve3d_error");
      char* Temp = name ;
      DrawTrSurf::Set(Temp,Iso);
//      DrawTrSurf::Set(name,Iso);
#endif
      Standard_ConstructionError::Raise("BRepFill_Sweep::BuildEdge");
    }

    E = MkE.Edge();
  }

  // On associe le 2d
  Handle(Geom2d_Line) L;
  TopLoc_Location Loc;
  if (isUiso) {
    gp_Pnt2d P(ValIso, 0);
    gp_Vec2d V(0., 1.);
    L = new (Geom2d_Line) (P, V);
  }
  else {
    gp_Pnt2d P(0., ValIso);
    gp_Vec2d V(1., 0.);
    L = new (Geom2d_Line) (P, V);
  }

  B.UpdateEdge(E, L, S, Loc, Precision::Confusion());
  if (sing) B.Range(E, S, Loc, 
		    Iso->FirstParameter(), 
		    Iso->LastParameter());

  return E;
}

//=======================================================================
//Function : 
//Objet : Completer une arete via, une iso
//=======================================================================
static void UpdateEdge(TopoDS_Edge& E,
		       const Handle(Geom_Surface)& S,
		       const Standard_Boolean isUiso,
		       const Standard_Real ValIso)
{
  BRep_Builder B;
  Handle(Geom2d_Line) L;
  Handle(Geom2d_Curve) PCurve, CL;
  TopLoc_Location Loc;
  Standard_Real UFirst, ULast, VFirst, VLast, F2d, L2d;
  S->Bounds( UFirst, ULast, VFirst, VLast);

  Standard_Boolean sing = Standard_False;
  Handle(Geom_Curve) Iso;
  if (isUiso) {
    Iso = S->UIso(ValIso);
  }
  else {      
    Iso = S->VIso(ValIso);
  }

  TopoDS_Vertex Vf, Vl;
  TopExp::Vertices(E, Vf, Vl);
  if (Vf.IsSame(Vl)) { // Cas Singulier ?
    gp_Pnt Pmid; 
    Standard_Real tol = BRep_Tool::Tolerance(Vf);
    Iso->D0((Iso->FirstParameter()+Iso->LastParameter())/2, Pmid);
    if (Pmid.Distance(BRep_Tool::Pnt(Vf)) < tol) {
      GeomAdaptor_Curve AC(Iso);
      sing = GCPnts_AbscissaPoint::Length(AC, tol/4) < tol;
    }
  }

  if (isUiso) {
    gp_Pnt2d P(ValIso, 0);
    gp_Vec2d V(0., 1.);
    L = new (Geom2d_Line) (P, V);
    F2d = VFirst;
    L2d = VLast;
  }
  else {
    gp_Pnt2d P(0., ValIso);
    gp_Vec2d V(1., 0.);
    L = new (Geom2d_Line) (P, V);
    F2d = UFirst;
    L2d = ULast;
  }
  CL = new (Geom2d_TrimmedCurve) (L, F2d, L2d);

  // Controle sens & Range
  Standard_Real R, First, Last, Tol=1.e-4;
  Standard_Boolean reverse = Standard_False;;
  

// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
  gp_Pnt POnS;
  gp_Pnt2d P2d;
//  BT.Range(E, First, Last);
  BRep_Tool::Range(E, First, Last);

  if (!Vf.IsSame(Vl)) {
    // On test les distance entre le "FirstPoint et les Vertex"
    P2d = CL->Value(F2d);
    POnS = S->Value(P2d.X(), P2d.Y());
//    reverse = POnS.Distance(BT.Pnt(Vl)) < POnS.Distance(BT.Pnt(Vf));
    reverse = POnS.Distance(BRep_Tool::Pnt(Vl)) < POnS.Distance(BRep_Tool::Pnt(Vf));
  }
  else if (!sing) {
    // On test l'angle entre les "First Tangente"
    gp_Vec2d V2d;
    gp_Vec V3d, du, dv, dC3d;
    BRepAdaptor_Curve C3d(E);

    C3d.D1(First, POnS,  dC3d);
    CL->D1(F2d, P2d, V2d);
    S->D1(P2d.X(), P2d.Y(), POnS, du, dv);
    V3d.SetLinearForm(V2d.X(), du, V2d.Y(), dv);
    reverse = ( dC3d.Angle(V3d) > Tol);
  }
  if (reverse ) { // On retourne la courbe 2d
    CL = new (Geom2d_TrimmedCurve)(L, F2d, L2d);
    CL->Reverse();  
    F2d = CL->FirstParameter();
    L2d = CL->LastParameter();
  }

  if (sing)
    {
      Handle(Geom_Curve) NullCurve;
      B.UpdateEdge(E, NullCurve, 0.);
      B.Degenerated(E, Standard_True);
      B.Range(E, F2d, L2d);
      First = F2d;
      Last  = L2d;
    }

  if (First != F2d || Last != L2d) {
    Handle(Geom2d_Curve) C2d;
    GeomLib::SameRange(Precision::PConfusion(), CL, 
		       F2d, L2d, First, Last,
		       C2d);
    CL = new (Geom2d_TrimmedCurve)(C2d, First, Last);
  }

  // Update des Vertex

  TopoDS_Vertex V;

  P2d = CL->Value(First);
  POnS = S->Value(P2d.X(), P2d.Y());
  V = TopExp::FirstVertex(E); 
//  R = POnS.Distance(BT.Pnt(V));
  R = POnS.Distance(BRep_Tool::Pnt(V));
  B.UpdateVertex(V, R);

  P2d = CL->Value(Last);
  POnS = S->Value(P2d.X(), P2d.Y());
  V = TopExp::LastVertex(E);
//  R = POnS.Distance(BT.Pnt(V));
  R = POnS.Distance(BRep_Tool::Pnt(V));
  B.UpdateVertex(V, R);

  // Update de l'Edge
  if (!sing && SameParameter(E, CL, S, Tol, R)) {
    B.UpdateEdge(E, R);
  }

  PCurve = Couture(E, S, Loc);
  if (PCurve.IsNull())
    B.UpdateEdge(E, CL, S, Loc, Precision::Confusion());
  else { // Arete de couture
    TopoDS_Edge e = E;
    Oriente(S, e);
    if (e.Orientation() == TopAbs_REVERSED)
      B.UpdateEdge(E, CL, PCurve, S, Loc, Precision::Confusion());
    else         
      B.UpdateEdge(E, PCurve, CL, S, Loc, Precision::Confusion());
  }

  // Attention au cas non SameRange sur ces shapes (PRO13551)
//  if (!BT.SameRange(E)) B.Range(E, S, Loc, First, Last);
  if (!BRep_Tool::SameRange(E)) B.Range(E, S, Loc, First, Last);
}

//=======================================================================
//Objet : Voir si une surface est degenere
//=======================================================================
static Standard_Boolean IsDegen(const Handle(Geom_Surface)& S,
				const Standard_Real Tol)
{
  Standard_Integer Nb = 5;
  Standard_Boolean B = Standard_True;
  Standard_Real Umax, Umin, Vmax, Vmin, t, dt, l;
  Standard_Integer ii;
  Handle(Geom_Curve) Iso;
  gp_Pnt P1,P2,P3;
  GCPnts_AbscissaPoint GC;

  S->Bounds(Umin, Umax, Vmin, Vmax);

  // Controle la longeur des Iso-U
  t = (Umin + Umax)/2;
  S->D0(t, Vmin, P1);
  S->D0(t, (Vmin+Vmax)/2, P2);
  S->D0(t, Vmax, P3);
  B = ((P1.Distance(P2) + P2.Distance(P3)) < Tol);
  
  for (ii=1, dt = (Umax-Umin)/(Nb+1); B && (ii<=Nb); ii++) {
    t =  Umin + ii*dt;
    Iso = S->UIso(t);
    GeomAdaptor_Curve AC(Iso);
    l = GC.Length(AC, Tol/4);
    B = (l <= Tol);
  }
 
  if (B) return Standard_True;

  // Controle la longeur des Iso-V
  t = (Vmin + Vmax)/2;
  S->D0(Umin, t, P1);
  S->D0((Umin+Umax)/2, t, P2);
  S->D0(Umax, t, P3);
  B = ((P1.Distance(P2) + P2.Distance(P3)) < Tol); 
 
 
  for (ii=1, dt = (Vmax-Vmin)/(Nb+1); B && (ii<=Nb); ii++) {
    t =  Vmin + ii*dt;
    Iso = S->VIso(t);
    GeomAdaptor_Curve AC(Iso);
    l = GC.Length(AC, Tol/4);
    B = (l <= Tol);
  }  
    
  return B;
}

//=======================================================================
//function : Constructeur
//purpose  : 
//======================================================================
BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
			       const Handle(BRepFill_LocationLaw)& Location,
			       const Standard_Boolean WithKPart) : 
			       isDone(Standard_False),
			       KPart(WithKPart)


{
 mySec = Section;
 myLoc = Location;
 
 SetTolerance(1.e-4);
 SetAngularControl();
 myAuxShape.Clear();
}

//=======================================================================
//function : SetBounds
//purpose  : Definit les shapes de debut et fin
//======================================================================
 void BRepFill_Sweep::SetBounds(const TopoDS_Wire& First,
				const TopoDS_Wire& Last)
{ 
  FirstShape = First;
  LastShape  = Last; 

  // Il faut verifier le SameRange sur ces shapes (PRO13551)
  Standard_Boolean issame = Standard_True;
  BRep_Builder B;
  BRepTools_WireExplorer wexp;
  if (!FirstShape.IsNull()) {
    for (wexp.Init(FirstShape); wexp.More(); wexp.Next()) {
      if (!BRepLib::CheckSameRange(wexp.Current())) {
	B.SameRange(wexp.Current(), Standard_False);
	B.SameParameter(wexp.Current(), Standard_False);
	issame = Standard_False;
      }
    }
  }
  
  if (!LastShape.IsNull()) {
    for (wexp.Init(LastShape); wexp.More(); wexp.Next()) {
      if (!BRepLib::CheckSameRange(wexp.Current())) {
	B.SameRange(wexp.Current(), Standard_False); 
	B.SameParameter(wexp.Current(), Standard_False);
	issame = Standard_False;
      }
    }
  }

#if DEB
  if (!issame) 
    cout<<"Sweep Warning : Edge non SameRange dans les bornes"<<endl;
#endif
}

//=======================================================================
//function : SetTolerance
//purpose  :
//======================================================================
 void BRepFill_Sweep::SetTolerance(const Standard_Real Tol3d,
				   const Standard_Real BoundTol,
				   const Standard_Real Tol2d, 
				   const Standard_Real TolAngular) 
{
  myTol3d = Tol3d;
  myBoundTol = BoundTol;
  myTol2d =Tol2d;
  myTolAngular = TolAngular;
}
//=======================================================================
//function : SetAngularControl
//purpose  :
//======================================================================
 void BRepFill_Sweep::SetAngularControl(const Standard_Real MinAngle,
				   const Standard_Real MaxAngle)
{
  myAngMin = Max (MinAngle, Precision::Angular());
  myAngMax = Min (MaxAngle, 6.28);
}

//=======================================================================
//function : BuildWire
//purpose  : Construit un wire par balayage
//======================================================================
 Standard_Boolean 
 BRepFill_Sweep::BuildWire(const BRepFill_TransitionStyle Transition,
			   const GeomFill_ApproxStyle Approx,
			   const GeomAbs_Shape Continuity,
			   const Standard_Integer Degmax,
			   const Standard_Integer Segmax) 
{
  Standard_Integer ipath, isec = 1;
  gp_Pnt P1;//, P2;

  BRep_Builder B;
// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
  Standard_Integer NbPath = myLoc->NbLaw();
  Standard_Boolean vclose;
  vclose = (myLoc->IsClosed() && (myLoc->IsG1(0, myTol3d)>= 0));
  Error = 0.;
  Handle(Geom_Surface) S;
  Handle(Geom_Curve) Iso;
  Standard_Real val, bid, First, Last, Tol;

 TopoDS_Wire wire;
 TopoDS_Edge E;
 B.MakeWire(wire);

 // (1) Construction de toutes les courbes

 // (1.1) Construction des Tables
 myFaces = new (TopTools_HArray2OfShape) (1, 1, 1, NbPath);
 myUEdges = new (TopTools_HArray2OfShape) (1, 2, 1, NbPath);
 myVEdges = new (TopTools_HArray2OfShape) (1, 1, 1, NbPath+1);

 // (1.2) Calcul des courbes / vertex / edge
  for (ipath=1; ipath <=NbPath; ipath++) { 
    // Courbe par iso valeur
    GeomFill_Sweep Sweep(myLoc->Law(ipath), KPart);
    Sweep.SetTolerance(myTol3d, myBoundTol, myTol2d, myTolAngular);
    Sweep.Build(mySec->Law(isec), Approx, Continuity, Degmax, Segmax);
    if (!Sweep.IsDone())  
      return Standard_False;
    S = Sweep.Surface();
    if (Sweep.ExchangeUV()) {
      if  (Sweep.UReversed()) S->Bounds(First, Last, bid, val);
      else S->Bounds(First, Last, val, bid);
      Iso = S->VIso(val); 
    }
    else {
      if (Sweep.UReversed()) S->Bounds(bid,  val, First, Last);
      else  S->Bounds(val, bid, First, Last);
      Iso = S->UIso(val); 
    }
    // Vertex par positionement
    if (ipath < NbPath) 
      BuildVertex(Iso, Standard_False, First, Last, 
		  myVEdges->ChangeValue(1, ipath+1));
    else {
      if (vclose) { 
	TopoDS_Vertex& V = TopoDS::Vertex(myVEdges->ChangeValue(1, 1));
	myVEdges->SetValue(1, ipath+1, V);
	Iso->D0(Last, P1);
//	Tol = P1.Distance(BT.Pnt(V));
	Tol = P1.Distance(BRep_Tool::Pnt(V));
	B.UpdateVertex(V, Tol);
      }
      else {
	if (!LastShape.IsNull()) myVEdges->SetValue(1, NbPath, FirstShape);
	else BuildVertex(Iso, Standard_False, First, Last, 
			 myVEdges->ChangeValue(1, NbPath+1));
      }
    }
  
    if (ipath > 1) {
      Iso->D0(First, P1);
      TopoDS_Vertex& V = TopoDS::Vertex(myVEdges->ChangeValue(1, ipath));
//      Tol = P1.Distance(BT.Pnt(V));
      Tol = P1.Distance(BRep_Tool::Pnt(V));
      B.UpdateVertex(V, Tol);
    }
    if (ipath == 1) {
      if (!FirstShape.IsNull()) myVEdges->SetValue(1,1, FirstShape);
      else BuildVertex(Iso, Standard_True, First, Last, 
		       myVEdges->ChangeValue(1, 1));
    }

    // Construction de l'arete
    BRepLib_MakeEdge MkE;
    MkE.Init(Iso, 
	     TopoDS::Vertex(myVEdges->Value(1, ipath)), 
	     TopoDS::Vertex(myVEdges->Value(1, ipath+1)), 
	     Iso->FirstParameter(),
	     Iso->LastParameter());
    if (!MkE.IsDone()) { // Erreur de construction !!     
#ifdef DRAW
      char name[100];
      sprintf(name,"firstvertex_error");
      DBRep::Set(name, myVEdges->Value(1, ipath));
      sprintf(name,"lastvertex_error");
      DBRep::Set(name, myVEdges->Value(1, ipath+1));
      sprintf(name,"curve3d_error");
      char* Temp = name ;
      DrawTrSurf::Set(Temp,Iso);
//       DrawTrSurf::Set(name,Iso);
      Standard_ConstructionError::Raise("BRepFill_Sweep::BuildEdge");
#endif
       return Standard_False;  
     }
    E = MkE.Edge();
#if DRAW
    if (Affich) {
      sprintf(name,"Surf_%d", ipath);
      char* Temp = name;
      DrawTrSurf::Set(Temp, S);
//      DrawTrSurf::Set(name, S);
      sprintf(name,"Edge_%d", ipath);
      DBRep::Set(name, E);
    }
#endif
    B.UpdateEdge(E, Sweep.ErrorOnSurface());
    B.Add(wire, E);
    myFaces->SetValue(1, ipath, E);
  }  
  myShape = wire;
  return Standard_True;
}

//=======================================================================
//function : BuildShell
//purpose  : Construit une Shell par balayage
//======================================================================
 Standard_Boolean BRepFill_Sweep::
 BuildShell(const BRepFill_TransitionStyle Transition,
	    const Standard_Integer IFirst,
	    const Standard_Integer ILast,
	    const GeomFill_ApproxStyle Approx,
	    const GeomAbs_Shape Continuity,
	    const Standard_Integer Degmax,
	    const Standard_Integer Segmax,
	    const Standard_Real ExtendFirst,
	    const Standard_Real ExtendLast) 
{
  Standard_Integer ipath, isec, IPath;
#ifdef DRAW
  char name[100];
#endif
  BRep_Builder B;
  Standard_Integer NbPath = ILast - IFirst;
  Standard_Integer NbLaw =  mySec->NbLaw();
  Standard_Boolean uclose, vclose,  constSection, hasdegen = Standard_False;
  constSection = mySec->IsConstant();
  uclose = mySec->IsUClosed();
  vclose = (mySec->IsVClosed() && myLoc->IsClosed()) && 
           (NbPath == myLoc->NbLaw()) && (myLoc->IsG1(0, myTol3d)>= 0);
  Error = 0.;

  // (1) Construction de toutes les surfaces

  // (1.1) Construction des Tables

  TColStd_Array2OfInteger ExchUV(1, NbLaw, 1, NbPath);
  TColStd_Array2OfInteger UReverse(1, NbLaw, 1, NbPath);
  TColStd_Array2OfInteger Degenerated(1, NbLaw, 1, NbPath);
  Degenerated.Init(0);
  // Pas de VReverse pour le moment...
  TColStd_Array2OfReal TabErr(1, NbLaw   , 1, NbPath);
  TColGeom_Array2OfSurface TabS(1, NbLaw , 1, NbPath);
  
  TopTools_Array2OfShape UEdge(1, NbLaw+1, 1, NbPath);
  TopTools_Array2OfShape VEdge(1, NbLaw  , 1, NbPath+1);
  TopTools_Array2OfShape Vertex(1,NbLaw+1, 1, NbPath+1);

  TopoDS_Vertex VNULL;
  VNULL.Nullify();
  Vertex.Init(VNULL);

  TopTools_Array1OfShape SecVertex(1, NbLaw+1);
  TColStd_Array1OfReal VError(1, NbLaw+1);
  TColStd_Array1OfReal Vi(1, NbPath+1);

//Initialisation de la gestion des intervalles parametrique 
//(Cas des sections evolutive)
  Standard_Real Length, SecDom, SecDeb;
  myLoc->CurvilinearBounds(myLoc->NbLaw(), SecDom, Length);
  mySec->Law(1)->GetDomain(SecDeb, SecDom);
  SecDom -= SecDeb;
  if (IFirst > 1) {
    Standard_Real Lf, Ll;
    myLoc->CurvilinearBounds(IFirst-1, Lf, Ll);
    Vi(1) = SecDeb + (Ll/Length)*SecDom;
  }
  else 
    Vi(1) = SecDeb;

  // Erreur a priori sur les vertex
  if (constSection) {
    for (isec=1; isec<=NbLaw+1; isec++) {
      VError(isec) = mySec->VertexTol(isec-1, 0.);
      SecVertex(isec) = mySec->Vertex(isec, 0.);
    }
  }
 

  // (1.2) Calcul des surfaces
  for (ipath=1, IPath=IFirst; ipath <=NbPath; ipath++, IPath++) {

    GeomFill_Sweep Sweep(myLoc->Law(IPath), KPart);
    Sweep.SetTolerance(myTol3d, myBoundTol, myTol2d, myTolAngular);

    // Cas des section evolutive, definition de la correspondance parametrique
    if (!constSection) {
      Standard_Real lf, ll, Lf, Ll;
      myLoc->Law(IPath)->GetDomain(lf, ll);
      myLoc->CurvilinearBounds(IPath, Lf, Ll);
      Vi(ipath+1) = SecDeb + (Ll/Length)*SecDom;
      Sweep.SetDomain(lf, ll, Vi(ipath), Vi(ipath+1));
    }
    
    for(isec=1; isec<=NbLaw; isec++) {
      Sweep.Build(mySec->Law(isec), Approx, Continuity, Degmax, Segmax);
      if (!Sweep.IsDone()) 
	return Standard_False;
      TabS(isec,ipath) = Sweep.Surface();
      TabErr(isec,ipath) = Sweep.ErrorOnSurface();
      ExchUV(isec, ipath) =  Sweep.ExchangeUV();
      UReverse(isec, ipath) =  Sweep.UReversed();
      if (Sweep.ErrorOnSurface()>Error) Error = Sweep.ErrorOnSurface();

      if ((ipath==1)&&(ExtendFirst>0)) {
	Handle(Geom_BoundedSurface) BndS;
	BndS = Handle(Geom_BoundedSurface)::DownCast(TabS(isec,ipath));
	GeomLib::ExtendSurfByLength(BndS, ExtendFirst, 1, 
				    Sweep.ExchangeUV(), Standard_False);
	TabS(isec,ipath) = BndS;
      }
      if ((ipath==NbPath)&&(ExtendLast>0)){
	Handle(Geom_BoundedSurface) BndS;
	BndS = Handle(Geom_BoundedSurface)::DownCast(TabS(isec,ipath));
	GeomLib::ExtendSurfByLength(BndS, ExtendLast, 1, 
				    Sweep.ExchangeUV(), Standard_True);
	TabS(isec,ipath) = BndS;
      }

#ifdef DRAW
      if (Affich) {
	sprintf(name,"Surf_%d_%d", isec, IPath);
	char* Temp = name ;
	DrawTrSurf::Set(Temp, TabS(isec,ipath));
      }
#endif
    }
  }

  // (2) Construction des Edges
  Standard_Real UFirst, ULast, VFirst, VLast;
  Standard_Boolean exuv, singu, singv;
  Handle(Geom_Surface) S;

  if (! vclose) {
    // (2.0) recuperation des Edges et vertex prexistant
    TopoDS_Edge E;
    if (! FirstShape.IsNull() && (IFirst==1)) {
      mySec->Init(FirstShape);
      for (isec=1; isec<=NbLaw; isec++) {
	E = mySec->CurrentEdge();
	VEdge(isec, 1) = E;
	 if (E.Orientation() == TopAbs_REVERSED)
	   Vertex(isec+1, 1) = TopExp::FirstVertex(E);
	 else 
	   Vertex(isec+1, 1) =  TopExp::LastVertex(E);
	UpdateVertex(IFirst-1, isec+1, 
		     TabErr(isec, 1), Vi(1),  Vertex(isec+1, 1));
       }
      if (VEdge(1, 1).Orientation() == TopAbs_REVERSED)
	Vertex(1, 1) =  TopExp::LastVertex(TopoDS::Edge(VEdge(1, 1)));
      else
	Vertex(1, 1) = TopExp::FirstVertex(TopoDS::Edge(VEdge(1, 1)));
      UpdateVertex(IFirst-1, 1, 
		   TabErr(1, 1), Vi(1),  Vertex(1, 1));
    }
    else { // Sinon on construit quand meme les vertex
      Standard_Real u, v, aux;
      Standard_Boolean ureverse;
      for (isec=1; isec<=NbLaw+1; isec++) {
	// Recuperation des donne
	if (isec >NbLaw) {
	  S = TabS(NbLaw, 1);
	  ureverse = UReverse(NbLaw, 1);
	  exuv = ExchUV(NbLaw, 1);
	}
	else  {
	  S = TabS(isec, 1);
	  ureverse = UReverse(isec, 1);
	  exuv = ExchUV(isec, 1);
	}
	S->Bounds(UFirst, ULast, VFirst, VLast);

	// Choix des parametres
	if (ureverse) {
	  if (exuv) {
	    aux = VFirst; VFirst = VLast; VLast = aux;	  
	  }
	  else {
	    aux = UFirst; UFirst = ULast; ULast = aux;
	  }
	}
	if (isec!= NbLaw+1) {
	  u = UFirst;
	  v = VFirst;
	}
	else {
	  if (exuv) {
	    u = UFirst;
	    v = VLast;
	  }
	  else {
	    u = ULast;
	    v = VFirst;
	  }
	}

	// construction du vertex
	B.MakeVertex(TopoDS::Vertex(Vertex(isec, 1)), 
		     S->Value(u,v), 
		     mySec->VertexTol(isec-1,Vi(1)));
      }
   }

    if (! LastShape.IsNull() && (ILast==myLoc->NbLaw()+1) ) {
      mySec->Init(LastShape);
      for (isec=1; isec<=NbLaw; isec++) {
	E = mySec->CurrentEdge();
	VEdge(isec, NbPath+1) = E;
	if (E.Orientation() == TopAbs_REVERSED)
	   Vertex(isec+1, NbPath+1) = TopExp::FirstVertex(E);
	else 
	  Vertex(isec+1, NbPath+1) = TopExp::LastVertex(E);
	UpdateVertex(ILast-1, isec+1, TabErr(isec, NbPath), 
		     Vi(NbPath+1),  Vertex(isec+1, NbPath+1));
      }
      if (VEdge(1,  NbPath+1).Orientation() == TopAbs_REVERSED)
	Vertex(1,  NbPath+1) =  
	  TopExp::LastVertex(TopoDS::Edge(VEdge(1,  NbPath+1)));
      else
	Vertex(1,  NbPath+1) = 
	  TopExp::FirstVertex(TopoDS::Edge(VEdge(1, NbPath+1)));
      UpdateVertex(ILast-1, 1, 
		   TabErr(1, NbPath), Vi(NbPath+1),  Vertex(1, NbPath+1 ));
    }    
    else {
      Standard_Real u, v, aux;
      Standard_Boolean ureverse;
      for (isec=1; isec<=NbLaw+1; isec++) {
	// Recuperation des donne
	if (isec >NbLaw) {
	  S = TabS(NbLaw, NbPath);
	  ureverse = UReverse(NbLaw, NbPath);
	  exuv = ExchUV(NbLaw, NbPath);
	}
	else  {
	  S = TabS(isec, NbPath);
	  ureverse = UReverse(isec, NbPath);
	  exuv = ExchUV(isec, NbPath);
	}
	S->Bounds(UFirst, ULast, VFirst, VLast);

	// Choix des parametres
	if (ureverse) {
	  if (exuv) {
	    aux = VFirst; VFirst = VLast; VLast = aux;	  
	  }
	  else {
	    aux = UFirst; UFirst = ULast; ULast = aux;
	  }
	}
	if (isec == NbLaw+1) {
	  u = ULast;
	  v = VLast;
	}
	else {
	  if (exuv) {
	    u = ULast;
	    v = VFirst;
	  }
	  else {
	    u = UFirst;
	    v = VLast;
	  }
	}

	// construction du vertex
	B.MakeVertex(TopoDS::Vertex(Vertex(isec, NbPath+1)), 
		     S->Value(u,v), 
		     mySec->VertexTol(isec-1, Vi(NbPath+1)));
      }
    }
  }

 
  // ---------- Creation de Vertex et edge ------------
  for (ipath=1, IPath=IFirst; ipath<=NbPath; 
       ipath++, IPath++) {
    for (isec=1; isec <=NbLaw; isec++) {
      S = TabS(isec, ipath);
      exuv = ExchUV(isec, ipath);
      S->Bounds(UFirst, ULast, VFirst, VLast);
      if (UReverse(isec, ipath)) {
	Standard_Real aux;
	if (exuv) {
	  aux = VFirst; VFirst = VLast; VLast = aux;	  
	}
	else {
	  aux = UFirst; UFirst = ULast; ULast = aux;
	}
      }

      // (2.1) Construction des nouveaux vertex
      if (isec == 1) {
	if (ipath == 1 && Vertex(1, 1).IsNull()) {
	  // Le tout premier
	  if (constSection)
	    myLoc->PerformVertex(IPath-1, 
				 TopoDS::Vertex(SecVertex(1)), 
				 VError(1),
				 TopoDS::Vertex(Vertex(1, 1)));
	  else
	    myLoc->PerformVertex(IPath-1, 
				 mySec->Vertex(1,Vi(1)), 
				 mySec->VertexTol(0,Vi(1)),
				 TopoDS::Vertex(Vertex(1, 1)));
	}
	// le premier de la colonne suivante
	if (vclose &&(ipath == NbPath) ) {
	  Vertex(1, ipath+1) =  Vertex(1, 1);
	}
	else if (Vertex(1, ipath+1).IsNull()) {
	  if (constSection)
	    myLoc->PerformVertex(IPath, 
				 TopoDS::Vertex(SecVertex(1)),
				 TabErr(1,ipath)+VError(1),
				 TopoDS::Vertex(Vertex(1, ipath+1)) );
	  else
	    myLoc->PerformVertex(IPath, 
				 mySec->Vertex(1,Vi(ipath+1)), 
				 TabErr(1,ipath) +
				 mySec->VertexTol(0,Vi(ipath+1)),
				 TopoDS::Vertex(Vertex(1, ipath+1)));

	  if (MergeVertex(Vertex(1,ipath), Vertex(1,ipath+1))) {
	    UEdge(1, ipath) = NullEdge(Vertex(1,ipath));
	  }
	 }
       }

      if (ipath == 1)
	if (uclose && (isec == NbLaw)) {
	  Vertex(isec+1, 1) =  Vertex(1, 1);
	}  
	else if (Vertex(isec+1, 1).IsNull()) {
	  if (constSection)
	    myLoc->PerformVertex(IPath-1, 
				 TopoDS::Vertex(SecVertex(isec+1)),
				 TabErr(isec,1)+VError(isec+1),
				 TopoDS::Vertex(Vertex(isec+1, 1)) );
	  else
	    myLoc->PerformVertex(IPath-1, 
				 mySec->Vertex(isec+1,Vi(1)), 
				 TabErr(isec,1) +
				 mySec->VertexTol(isec,Vi(1)),
				 TopoDS::Vertex(Vertex(isec+1, 1)) );
	  if (MergeVertex(Vertex(isec,1), Vertex(isec+1,1))) {
	    VEdge(isec, 1) = NullEdge(Vertex(isec, 1)); 
	  }
	}

      if (uclose && (isec == NbLaw)) {
	Vertex(isec+1, ipath+1) = Vertex(1, ipath+1);
      }
      else if (vclose && (ipath == NbPath)) {
	Vertex(isec+1, ipath+1) =  Vertex(isec+1, 1);
      }
      else if (Vertex(isec+1, ipath+1).IsNull()) {
	if (constSection)
	  myLoc->PerformVertex(IPath, 
			       TopoDS::Vertex(SecVertex(isec+1)),
			       TabErr(isec, ipath)+ VError(isec+1),
			       TopoDS::Vertex(Vertex(isec+1, ipath+1)) );
	else
	 myLoc->PerformVertex(IPath, 
			      mySec->Vertex(isec+1,Vi(ipath+1)),
			      TabErr(isec, ipath) + 
			      mySec->VertexTol(isec, Vi(ipath+1)),
			      TopoDS::Vertex(Vertex(isec+1, ipath+1)) ); 
      }

      // Cas Singuliers
      singv = MergeVertex(Vertex(isec,ipath+1), Vertex(isec+1,ipath+1));
      singu = MergeVertex(Vertex(isec+1,ipath), Vertex(isec+1,ipath+1));

      

      if (singu || singv) {
	Degenerated(isec, ipath) = IsDegen(TabS(isec,ipath), 
					   Max(myTol3d, TabErr(isec,ipath)));
      }
      if (Degenerated(isec, ipath)) { 
#if DEB
	cout << "Sweep : Cas degenere" << endl;
#endif
	hasdegen = Standard_True;
        // Construction particuliere des edge
	if (UEdge(isec+1, ipath).IsNull()) {
	  if (singu) {
	    // Edge degenere
	    UEdge(isec+1, ipath) = NullEdge(Vertex(isec+1,ipath));
	  }
	  else { // Copie de l'edge precedente
	    UEdge(isec+1, ipath) = UEdge(isec, ipath);
	  }
	}
	if (VEdge(isec, ipath+1).IsNull()) {
	  if (singv) {
	    // Edge degenere
	    VEdge(isec, ipath+1) = NullEdge(Vertex(isec,ipath+1));
	  }
	  else { // Copie de l'edge precedente
	    VEdge(isec, ipath+1) = VEdge(isec, ipath);
	  }
	}
      }
      else { // Construction des edges par les isos
	if (exuv) {
	  Standard_Real UV;
	  UV = UFirst; UFirst = VFirst; VFirst = UV;
	  UV = ULast ; ULast = VLast  ; VLast = UV;
	}
  
	// (2.2) Iso-u
	if (isec == 1) {
	  if (!Vertex(1,ipath).IsSame(Vertex(1,ipath+1))) {
	    gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(Vertex(1,ipath)));
	    gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(Vertex(1,ipath+1)));
	    if (P1.Distance(P2) <= myTol3d)
	      Vertex(1,ipath+1) = Vertex(1,ipath);
	  }
	  UEdge(1, ipath) = BuildEdge(S, !exuv, UFirst, 
				      Vertex(1,ipath), 
				      Vertex(1,ipath+1),
				      myTol3d);
	}
 	else UpdateEdge(TopoDS::Edge(UEdge(isec, ipath)), 
			S, !exuv, UFirst);
     
	if (uclose && (isec==NbLaw)) {
	  UpdateEdge(TopoDS::Edge(UEdge(1, ipath)), 
		     S, !exuv, ULast);
	  UEdge(isec+1, ipath) = UEdge(1, ipath);
	}
	else {
	  UEdge(isec+1, ipath) = BuildEdge(S, !exuv, ULast, 
					   Vertex(isec+1, ipath), 
					   Vertex(isec+1, ipath+1),
					   myTol3d);
	}

	// (2.3) Iso-v 
	if (ipath == 1 && VEdge(isec, ipath).IsNull())
	  VEdge(isec, ipath) = BuildEdge(S, exuv, VFirst, 
					 Vertex(isec  , 1), 
					 Vertex(isec+1, 1),
					 myTol3d);
	
	else UpdateEdge(TopoDS::Edge(VEdge(isec, ipath)), 
			S, exuv, VFirst);
	
	if (vclose && (ipath == NbPath)) {
	  UpdateEdge(TopoDS::Edge(VEdge(isec, 1)), 
		     S, exuv, VLast);
	  VEdge(isec, ipath+1) = VEdge(isec, 1);
	}
	else if (VEdge(isec, ipath+1).IsNull())
	  VEdge(isec, ipath+1) = BuildEdge(S, exuv, VLast, 
					   Vertex(isec  , ipath+1), 
					   Vertex(isec+1, ipath+1),
					   myTol3d);
	else UpdateEdge(TopoDS::Edge(VEdge(isec, ipath+1)), 
			S, exuv, VLast);
	  
      }
    }//Fin de contruction des edges
  }

  // (3) Construction des Faces
  TopoDS_Face face;

#ifdef DRAW
  if (Affich) {
    for (ipath=1, IPath=IFirst; ipath<=NbPath; ipath++, IPath++) {
      for (isec=1; isec <=NbLaw+1; isec++){
	sprintf(name,"uedge_%d_%d", isec, IPath);
	DBRep::Set(name,UEdge(isec, ipath));
      }
    }

    for (ipath=1, IPath=IFirst; ipath<=NbPath+1; ipath++, IPath++) {
      for (isec=1; isec <=NbLaw; isec++){
	sprintf(name,"vedge_%d_%d", isec, IPath);
	DBRep::Set(name,VEdge(isec, ipath));
      }

      for (isec=1; isec <=NbLaw+1; isec++){
	sprintf(name,"vertex_%d_%d", isec, IPath);
	DBRep::Set(name,Vertex(isec, ipath));
      }
    }
  }
#endif 

  for (ipath=1, IPath=IFirst; ipath<=NbPath; ipath++, IPath++) {
    for (isec=1; isec <=NbLaw; isec++) {
      if (Degenerated(isec, ipath)) {
	if (UEdge(isec, ipath).IsSame(UEdge(isec+1, ipath))) 
	  myFaces->SetValue(isec, IPath, UEdge(isec, ipath));
	else  
	  myFaces->SetValue(isec, IPath, VEdge(isec, ipath));
      }
      else {
	BuildFace(TabS(isec,ipath), 
		  TopoDS::Edge(UEdge(isec, ipath)),
		  TopoDS::Edge(VEdge(isec, ipath)),
		  TopoDS::Edge(UEdge(isec+1, ipath)),
		  TopoDS::Edge(VEdge(isec, ipath+1)),
		  myVEdgesModified,
		  ExchUV(isec, ipath),
		  UReverse(isec, ipath),
		  face);
	myFaces->SetValue(isec, IPath, face);
      }
    }
  }


  // (4) Historique et Continuity 

  if (hasdegen) {
  //(4.1) // Cas degenere => Marteau Pilon
    TopoDS_Compound Comp;
    B.MakeCompound(Comp);
    for (isec=1; isec <=  NbLaw+1; isec++) 
      for (ipath=1, IPath=IFirst; ipath<=  NbPath+1; ipath++, IPath++) {
      if (ipath <= NbPath) myUEdges->SetValue(isec, IPath, UEdge(isec, ipath));
      if (isec <= NbLaw) myVEdges->SetValue(isec, IPath, VEdge(isec, ipath)); 
      if ((ipath <= NbPath) && (isec <= NbLaw) && 
	  (myFaces->Value(isec, IPath).ShapeType() == TopAbs_FACE))
	B.Add(Comp, myFaces->Value(isec, IPath));
    }
    BRepLib::EncodeRegularity(Comp, myTolAngular);
  }
  else {
    //(4.2) // Cas generale => Pince a epiler 
    Standard_Boolean isG1;
    TopoDS_Face FF;
    TopoDS_Edge E;
 
    for (isec=1; isec <=  NbLaw+1; isec++) {
      if (isec>1) isG1 = 
	(mySec->Continuity(isec-1, myTolAngular) >= GeomAbs_G1);
      else isG1 = Standard_False;
      for (ipath=1, IPath=IFirst; ipath<=  NbPath; ipath++, IPath++) {
	myUEdges->SetValue(isec, IPath, UEdge(isec, ipath));
	if (isG1) {
	  if (isec == NbLaw+1) FF = TopoDS::Face(myFaces->Value(1, IPath));
	  else  FF = TopoDS::Face(myFaces->Value(isec, IPath));
	  B.Continuity(TopoDS::Edge(myUEdges->Value(isec, IPath)),
		       TopoDS::Face(myFaces->Value(isec-1, IPath)), 
		       FF, GeomAbs_G1);
	}
      }
    }

    Standard_Integer nbpath = NbPath;
    if (vclose) nbpath++; //Un test G1 en plus
    for (ipath=1, IPath=IFirst; ipath<=  NbPath+1; ipath++, IPath++) {
      if ((ipath > 1) && (ipath <=nbpath)) 
	isG1 = (myLoc->IsG1(IPath-1, myTol3d, myTolAngular) >= 0);
      else isG1 = Standard_False;
      for (isec=1; isec <=  NbLaw; isec++) {
	myVEdges->SetValue(isec, IPath, VEdge(isec, ipath));
	if (isG1) { 
	  if (ipath==NbPath+1) FF = TopoDS::Face(myFaces->Value(isec, 1));
	  else  FF = TopoDS::Face(myFaces->Value(isec, IPath));
	  E = TopoDS::Edge(myVEdges->Value(isec, IPath));
	  BRepLib::EncodeRegularity(E, FF,
				    TopoDS::Face(myFaces->Value(isec, IPath-1)),
				    myTolAngular);
	}
      } 
    }
  }
  return Standard_True;
}

//=======================================================================
//function : Build
//purpose  : Construit le resultat d'un balayage
//======================================================================
 void BRepFill_Sweep::Build(const BRepFill_TransitionStyle Transition,
			    const GeomFill_ApproxStyle Approx,
			    const GeomAbs_Shape Continuity,
			    const Standard_Integer Degmax,
			    const Standard_Integer Segmax) 
{
  // Wire
  if (mySec->IsVertex()) isDone = BuildWire(Transition, Approx, Continuity, 
					    Degmax, Segmax);   
  else { // Shell   
    Standard_Integer NbTrous = myLoc->NbHoles(myTol3d),
                     NbPath   = myLoc->NbLaw(),
                     NbLaw    = mySec->NbLaw(), ii, jj, NbPart=1;
    Standard_Integer ipath, isec;
    BRep_Builder B;
    myUEdges = new (TopTools_HArray2OfShape) (1, NbLaw+1, 1, NbPath);
    myVEdges = new (TopTools_HArray2OfShape) (1, NbLaw, 1, NbPath+1); 
    myFaces = new (TopTools_HArray2OfShape) (1, NbLaw, 1, NbPath);
    Handle (TopTools_HArray2OfShape) Bounds =  
      new (TopTools_HArray2OfShape) (1, NbLaw, 1, 2);
 
    Handle(TColStd_HArray1OfInteger) Trous;
 
    if (NbTrous>0) { // Combien de sous parties ?
      Trous = new (TColStd_HArray1OfInteger) (1, NbTrous);
      myLoc->Holes(Trous->ChangeArray1());
      NbPart += NbTrous;
      if (Trous->Value(NbTrous) == NbPath+1) NbPart--;  
    }
    if (NbPart == 1)  { // On le fait en un coup
      Standard_Real Extend = 0.0;
      if (NbTrous==1)  Extend = EvalExtrapol(1, Transition);
      isDone = BuildShell(Transition, 
			  1, NbPath+1,
			  Approx, Continuity, 
			  Degmax, Segmax, Extend, Extend);
    }
    else { //  On le fait bout par bout
      Standard_Integer IFirst = 1, ILast;
      for (ii=1, isDone=Standard_True; 
	   ii<=NbPart && isDone; ii++) {
	if (ii > NbTrous) ILast =  NbPath+1;
	else ILast = Trous->Value(ii);
	isDone = BuildShell(Transition, 
			    IFirst, ILast,
			    Approx, Continuity, 
			    Degmax, Segmax,
			    EvalExtrapol(IFirst, Transition),
			    EvalExtrapol(ILast,  Transition));
	if (IFirst>1) {
	  Translate(myVEdges, IFirst, Bounds, 2);
	  PerformCorner(IFirst, 
			Transition, Bounds);
	}
	IFirst = ILast;
	Translate(myVEdges, IFirst, Bounds, 1);
      }
    }
    // Gestion des terminaisons bouclantes
    if ( (NbTrous>0) && (myLoc->IsClosed()) &&
	 (Trous->Value(NbTrous) == NbPath+1) ) {
      Translate(myVEdges,  NbPath+1, Bounds, 1);
      Translate(myVEdges,  1, Bounds, 2);
      PerformCorner(1, Transition, Bounds); 
    }

    // Construction de la shell
    TopoDS_Shell shell;
    B.MakeShell(shell);
    for (ipath=1; ipath<=NbPath; ipath++) 
      for (isec=1; isec <=NbLaw; isec++) {
      const TopoDS_Shape& face = myFaces->Value(isec, ipath);
	if (!face.IsNull() && 
	    (face.ShapeType() == TopAbs_FACE) ) B.Add(shell, face);
      }

    TopTools_ListIteratorOfListOfShape It(myAuxShape);
    for (; It.More(); It.Next()) {
       const TopoDS_Shape& face = It.Value();
       if (!face.IsNull() && 
	    (face.ShapeType() == TopAbs_FACE) ) B.Add(shell, face);
    }
    //Set common Uedges to faces
    BRepTools_Substitution aSubstitute;
    /*
    for (ii = 1; ii <= NbLaw; ii++)
      for (jj = 1; jj <= NbPath; jj++)
	{
	  SetCommonEdgeInFace(aSubstitute,
			      myFaces->Value(ii, jj),
			      myUEdges->Value(ii, jj));
	  SetCommonEdgeInFace(aSubstitute,
			      myFaces->Value(ii, jj),
			      myUEdges->Value(ii+1, jj));
	}
    if (mySec->IsUClosed())
      for (jj = 1; jj <= NbPath; jj++)
	SetCommonEdgeInFace(aSubstitute,
			    myFaces->Value( 1, jj ),
			    myUEdges->Value( NbLaw+1, jj));
    */
    TopTools_DataMapIteratorOfDataMapOfShapeShape mapit( myVEdgesModified );
    for (; mapit.More(); mapit.Next())
      {
	const TopoDS_Edge& OldEdge = TopoDS::Edge(mapit.Key());
	const TopoDS_Edge& NewEdge = TopoDS::Edge(mapit.Value());
	Substitute( aSubstitute, OldEdge, NewEdge );
      }
    aSubstitute.Build( shell );
    if (aSubstitute.IsCopied( shell )) {
      const TopTools_ListOfShape& listSh = aSubstitute.Copy( shell );
      shell = TopoDS::Shell( listSh.First() );
    }

    for (ii = myFaces->LowerRow(); ii <= myFaces->UpperRow(); ii++) {
      for (jj = myFaces->LowerCol(); jj <= myFaces->UpperCol(); jj++) {
	const TopoDS_Shape& aLocalShape = myFaces->Value(ii, jj);

	if(!aLocalShape.IsNull() && aSubstitute.IsCopied(aLocalShape)) {
	  const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);

	  if(!aList.IsEmpty())
	    myFaces->ChangeValue(ii, jj) = aList.First();
	}
      }
    }

    for (ii = myVEdges->LowerRow(); ii <= myVEdges->UpperRow(); ii++) {
      for (jj = myVEdges->LowerCol(); jj <= myVEdges->UpperCol(); jj++) {
	const TopoDS_Shape& aLocalShape = myVEdges->Value(ii, jj);

	if(!aLocalShape.IsNull() && aSubstitute.IsCopied(aLocalShape)) {
	  const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);

	  if(!aList.IsEmpty())
	    myVEdges->ChangeValue(ii, jj) = aList.First();
	}
      }
    }

    for (ii = myUEdges->LowerRow(); ii <= myUEdges->UpperRow(); ii++) {
      for (jj = myUEdges->LowerCol(); jj <= myUEdges->UpperCol(); jj++) {
	const TopoDS_Shape& aLocalShape = myUEdges->Value(ii, jj);

	if(!aLocalShape.IsNull() && aSubstitute.IsCopied(aLocalShape)) {
	  const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);

	  if(!aList.IsEmpty())
	    myUEdges->ChangeValue(ii, jj) = aList.First();
	}
      }
    }

    // Est ce Ferme ?
    if (myLoc->IsClosed() && mySec->IsUClosed()) {
      //On verifie
      Standard_Boolean closed = Standard_True;
      Standard_Integer iedge;
      TopTools_IndexedDataMapOfShapeListOfShape EFmap;
      TopExp::MapShapesAndAncestors(shell, TopAbs_EDGE, 
				    TopAbs_FACE, EFmap);
      
      for (iedge = 1; iedge <=EFmap.Extent() && closed; iedge++) {
        const TopoDS_Edge& theEdge = TopoDS::Edge(EFmap.FindKey(iedge));
	if (BRep_Tool::Degenerated(theEdge)) continue;
	closed = (  EFmap(iedge).Extent() > 1);
      }
      shell.Closed(closed);
    }
    myShape = shell;
  }
}


//=======================================================================
//function : IsDone
//purpose  : 
//=======================================================================
 Standard_Boolean BRepFill_Sweep::IsDone() const
{
  return isDone;
}

//=======================================================================
//function : Shape
//purpose  : 
//=======================================================================
 TopoDS_Shape BRepFill_Sweep::Shape() const
{
  return myShape;
}

//=======================================================================
//function : ErrorOnSurface
//purpose  : 
//=======================================================================
 Standard_Real BRepFill_Sweep::ErrorOnSurface() const
{
  return Error;
}

//=======================================================================
//function : SubShape
//purpose  : Les faces obtenues par balayage
//=======================================================================
 Handle(TopTools_HArray2OfShape) BRepFill_Sweep::SubShape() const
{
  return myFaces;
}

//=======================================================================
//function : InterFaces
//purpose  : les Edges  obtenues par balayage
//=======================================================================
 Handle(TopTools_HArray2OfShape) BRepFill_Sweep::InterFaces() const
{
  return myUEdges;
}

//=======================================================================
//function : Sections
//purpose  : Les Edges ou Face (ou compound des 2) Transition entre 2 balayages.
//=======================================================================
 Handle(TopTools_HArray2OfShape) BRepFill_Sweep::Sections() const
{
  return myVEdges;
}

//=======================================================================
//function : PerformCorner
//purpose  : Trim et/ou bouche un coin
//======================================================================
 void  BRepFill_Sweep::PerformCorner(const Standard_Integer Index,
				     const BRepFill_TransitionStyle Transition,
				     const Handle(TopTools_HArray2OfShape)& Bounds)
{

  if (Transition == BRepFill_Modified) return; // On ne fait rien.

  BRepFill_TransitionStyle TheTransition = Transition;
  Standard_Boolean isTangent=Standard_False;
  Standard_Real F, L;
  Standard_Integer I1, I2, ii; //, jj;
  gp_Pnt P1,P2;
  gp_Vec T1, T2, Tang, Sortant;
//  gp_Mat M;
  //Handle(TopTools_HArray1OfShape) TheShape = 
    //new TopTools_HArray1OfShape( 1, mySec->NbLaw() );
//  TopTools_ListIteratorOfListOfShape Iterator;

  if (Index > 1) { 
    I1 = Index-1;
    I2 = Index;
  }
  else {
    I1 = myLoc->NbLaw();
    I2 = 1;
  }

  // On Construit un axe supporte par la bissectrice
  myLoc->Law(I1)->GetDomain(F, L);
  myLoc->Law(I1)->GetCurve()->D1(L, P1, T1);
  T1.Normalize();

  myLoc->Law(I2)->GetDomain(F, L);  
  myLoc->Law(I2)->GetCurve()->D1(F, P2, T2);
  T2.Normalize();

  if (T1.Angle(T2) <  myAngMin) {
    isTangent = Standard_True;
    gp_Vec t1, t2, V;
    gp_Mat M;
    myLoc->Law(I1)->GetDomain(F, L);
    myLoc->Law(I1)->D0(L, M, V);
    t1 = M.Column(3);
    myLoc->Law(I2)->GetDomain(F, L);
    myLoc->Law(I2)->D0(L, M, V);
    t2 = M.Column(3);

    if (t1.Angle(t2) < myAngMin) {
#if DEB
      cout << "BRepFill_Sweep::PerformCorner : Ce n'est pas un coin !" << endl;
#endif
      return;
    }
    Sortant = t2 - t1;
  }

  if ((TheTransition == BRepFill_Right) 
      && (T1.Angle(T2) >  myAngMax) ) {
    TheTransition =  BRepFill_Round;
  }

  Tang = T1 + T2; //Direction moyenne
  gp_Dir NormalOfBisPlane = Tang;

  if (isTangent) {
    Sortant -= Tang.Dot(Tang)*Tang;
  }
  else {
    Sortant = T2-T1; //Direction rentrente
    Sortant *= -1; //   "   "   sortante
    Tang -= (Tang.Dot(T2))*T2;
  }

  P1.BaryCenter(0.5, P2, 0.5);
  gp_Dir N(Sortant);
  gp_Dir Dx(Tang);
    
  gp_Ax2 Axe (P1, N, Dx);
  gp_Ax2 AxeOfBisPlane( P1, NormalOfBisPlane );

  // On construit les 2 Shell a intersecter
  Handle (TopTools_HArray2OfShape) UEdges =
    new TopTools_HArray2OfShape( 1, mySec->NbLaw()+1, 1, myLoc->NbLaw() );
  UEdges->ChangeArray2() = myUEdges->Array2();

// modified by NIZHNY-MKK  Wed Oct 29 18:31:47 2003.BEGIN
  Handle (TopTools_HArray2OfShape) aFaces =
    new TopTools_HArray2OfShape(myFaces->LowerRow(), myFaces->UpperRow(), 1, 2);
  Translate(myFaces, I1, aFaces, 1);
  Translate(myFaces, I2, aFaces, 2);

  Handle (TopTools_HArray2OfShape) aUEdges =
    new TopTools_HArray2OfShape(myUEdges->LowerRow(), myUEdges->UpperRow(), 1, 2);
  Translate(myUEdges, I1, aUEdges, 1);
  Translate(myUEdges, I2, aUEdges, 2);

  gp_Vec aNormal = T2 + T1;
  TopoDS_Face aPlaneF;

  if(aNormal.Magnitude() > gp::Resolution()) {
    gp_Pln pl(P1, gp_Dir(aNormal));
    BRepLib_MakeFace aFMaker(pl);

    if(aFMaker.Error() == BRepLib_FaceDone) {
      aPlaneF = aFMaker.Face();
      BRep_Builder aBB;
      aBB.UpdateFace(aPlaneF, Precision::Confusion() * 10.);
    }
  }

  BRepFill_TrimShellCorner aTrim(aFaces, AxeOfBisPlane, aPlaneF);
  aTrim.AddBounds(Bounds);
  aTrim.AddUEdges(aUEdges);
  aTrim.Perform();

  if (aTrim.IsDone()) {
    TopTools_ListOfShape listmodif;
    Standard_Integer iit = 0;

    for(iit = 0; iit < 2; iit++) {
      Standard_Integer II = (iit == 0) ? I1 : I2;

      for (ii = 1; ii <= mySec->NbLaw(); ii++) {
	aTrim.Modified(myFaces->Value(ii, II), listmodif);

	if(!listmodif.IsEmpty()) {
	  myFaces->SetValue(ii, II, listmodif.First());
	}
      }

      for (ii = myUEdges->LowerRow(); ii <= myUEdges->UpperRow(); ii++) {
	aTrim.Modified(myUEdges->Value(ii, II), listmodif);

	if(!listmodif.IsEmpty()) {
	  myUEdges->SetValue(ii, II, listmodif.First());
	}
      }
    }
  }
  else if ((TheTransition == BRepFill_Right) ||
	   aTrim.HasSection() ) { 
#if DEB
    cout << "Echec de TrimCorner" << endl;
#endif
    return; // On ne touche a rien
  }

  if (mySec->IsUClosed())
    {
      myUEdges->SetValue( 1, I1, myUEdges->Value(mySec->NbLaw()+1, I1) );
      myUEdges->SetValue( 1, I2, myUEdges->Value(mySec->NbLaw()+1, I2) );
    }

  if (TheTransition == BRepFill_Round) {
  // Remplissage
    TopTools_ListOfShape list1, list2;
    TopoDS_Edge Bord1, Bord2, BordFirst;
    BordFirst.Nullify();
    Bord1.Nullify();
    Bord2.Nullify();
    Standard_Boolean HasFilling = Standard_False;
    TopoDS_Face FF;
    for (ii=1; ii<=mySec->NbLaw(); ii++) {
      KeepEdge(myFaces->Value(ii, I1), Bounds->Value(ii, 1), list1);
      KeepEdge(myFaces->Value(ii, I2), Bounds->Value(ii, 2), list2);
      if (list1.Extent() == list2.Extent()) {
	TopTools_ListIteratorOfListOfShape It1(list1);
	TopTools_ListIteratorOfListOfShape It2(list2);
	Standard_Boolean B;
	for (; It1.More(); It1.Next(), It2.Next()) {
	  if (HasFilling) { // Choix des contraintes transversale
	    TopoDS_Vertex VF, VL, VC;
	    TopoDS_Edge E = TopoDS::Edge(It1.Value());
	    TopoDS_Edge E1, E2;
	    E1.Nullify();
	    E2.Nullify();
	    TopExp::Vertices(E, VF, VL);
	    if (!Bord1.IsNull() && 
		TopExp::CommonVertex(E, Bord1, VC)) {
	      if (VC.IsSame(VF)) E1 = Bord1;
	      else               E2 = Bord1;
	    }
	    if (!Bord2.IsNull() && 
		TopExp::CommonVertex(E, Bord2, VC)) {
	      if (VC.IsSame(VF)) E1 = Bord2;
	      else               E2 = Bord2;
	    }
	    if (!BordFirst.IsNull() && 
		TopExp::CommonVertex(E, BordFirst, VC)) {
	      if (VC.IsSame(VF)) E1 = BordFirst;
	      else               E2 = BordFirst;
	    }
	    Bord1 = E1;
	    Bord2 = E2;
	  }
	  
	  // Remplissage
	  B = Filling(It1.Value(), myFaces->Value(ii, I1),
		      It2.Value(), myFaces->Value(ii, I2),
		      myVEdgesModified, myTol3d, Axe, T1, Bord1, Bord2, FF);
	  
	  if (B) {
	    myAuxShape.Append(FF);
	    myVEdges->ChangeValue(ii, I2) = FF;
	    HasFilling = Standard_True;
	  }
	  if (ii==1) BordFirst = Bord1;
	}
      }
#if DEB
      else cout << "PerformCorner : Disymetrie de bord libre" << endl;
#endif
    }
  }

/*  
#if DRAW
  if (Affich) {
    Standard_Integer jj;
    char name[100];
    DBRep::Set("TrimmedShell", TheShape);
    for (jj=1; jj <=myFaces->ColLength(); jj++){
      sprintf(name,"Tfaces_%d_%d", jj, I1);
      DBRep::Set(name, myFaces->Value(jj, I1));
      sprintf(name,"Tfaces_%d_%d", jj, I2);
      DBRep::Set(name, myFaces->Value(jj, I2));
    }
  }
#endif
*/
}

//=======================================================================
//function : EvalExtrapol
//purpose  : 
//======================================================================
Standard_Real BRepFill_Sweep::
  EvalExtrapol(const Standard_Integer Index,
	       const BRepFill_TransitionStyle Transition) const
{
  Standard_Real Extrap = 0.0;
  if (Transition == BRepFill_Right) {
    Standard_Integer I1, I2;
    if ((Index == 1) || (Index ==myLoc->NbLaw()+1) ) {
      if (!myLoc->IsClosed() || !mySec->IsVClosed()) return Extrap;
      I1 = myLoc->NbLaw();
      I2 = 1;
    }
    else {
      I1 = Index-1;
      I2 = Index;
    }

    gp_Vec V1, V2, T1, T2;
    gp_Mat M1, M2;
    Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax, R, f, l;

    myLoc->Law(I1)->GetDomain(f, l);
    myLoc->Law(I1)->D0(l, M1, V1);
    T1.SetXYZ(M1.Column(3));
    myLoc->Law(I2)->GetDomain(f, l);
    myLoc->Law(I2)->D0(f, M2, V2);
    T2.SetXYZ(M2.Column(3));
     
    Standard_Real alpha = T1.Angle(T2);
    if ((alpha >  myAngMax) || (alpha <  myAngMin)) {
      //Angle trop grand => Pas de raccord "droit"
      //Angle trop petit => Pas de raccord
      return Extrap; // = 0.0
    }   

    Handle(GeomFill_SectionLaw) Sec;
    Sec = mySec->ConcatenedLaw();

    //Calculating parameter U
    Standard_Real U, Length, SecFirst, SecLen, Lf, Ll;
    myLoc->CurvilinearBounds( myLoc->NbLaw(), Lf, Length );
    mySec->Law(1)->GetDomain( SecFirst, SecLen );
    SecLen -= SecFirst;
    myLoc->CurvilinearBounds( I1, Lf, Ll );
    U = SecFirst + (Ll/Length)*SecLen;

    Bnd_Box box;
    //Box(Sec, 0., box);
    Box(Sec, U, box);
    box.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
    
    R =  Max(Max(Abs(Xmin), Abs(Xmax)),Max(Abs(Ymin), Abs(Ymax)));
    //R *= 1.1;
    // modified by NIZHNY-MKK  Fri Oct 31 18:57:51 2003
    //     Standard_Real coef = 1.2;
    Standard_Real coef = 2.;
    R *= coef;
    Extrap = Max(Abs(Zmin), Abs(Zmax)) + 100*myTol3d; 
    Extrap += R*Tan(alpha/2);
  }
  return Extrap;
}

//=======================================================================
//function : MergeVertex
//purpose  : Fait V2 = V1 si V2 est trop proche de V1
//======================================================================
Standard_Boolean BRepFill_Sweep::MergeVertex(const TopoDS_Shape& V1,
					           TopoDS_Shape& V2) const
{
// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
  const TopoDS_Vertex& v1 = TopoDS::Vertex(V1);
  const TopoDS_Vertex& v2 = TopoDS::Vertex(V2);  
  Standard_Real tol;
//  tol = Max(BT.Tolerance(v1), BT.Tolerance(v2));
  tol = Max(BRep_Tool::Tolerance(v1), BRep_Tool::Tolerance(v2));
  if (tol < myTol3d) tol = myTol3d;
//  if (BT.Pnt(v1).Distance(BT.Pnt(v2)) <= tol ){
  if (BRep_Tool::Pnt(v1).Distance(BRep_Tool::Pnt(v2)) <= tol ){
    V2 = V1;
    return Standard_True;
  }				 
  return Standard_False;
}

	
//=======================================================================
//function : UpdateVertex
//purpose  : Update la Tolerance des Vertexs en Fonction des Lois.
//======================================================================
void BRepFill_Sweep::UpdateVertex(const Standard_Integer ipath,
				  const Standard_Integer isec,
				  const Standard_Real ErrApp,
				  const Standard_Real Param,
				  TopoDS_Shape& V) const
{
  TopoDS_Vertex vv, TheV;
  TheV = TopoDS::Vertex(V);
  myLoc->PerformVertex(ipath, 
		       mySec->Vertex(isec, Param), 
		       ErrApp+mySec->VertexTol(isec-1, Param),
		       vv);
// Class BRep_Tool without fields and without Constructor :
//  BRep_Tool BT;
  gp_Pnt P1, P2;
//  P1 = BT.Pnt(vv);
  P1 = BRep_Tool::Pnt(vv);
//  P2 = BT.Pnt(TheV);
  P2 = BRep_Tool::Pnt(TheV);

//  Standard_Real Tol = BT.Tolerance(vv);
  Standard_Real Tol = BRep_Tool::Tolerance(vv);
  Tol += P1.Distance(P2);
  
//  if (Tol >  BT.Tolerance(TheV)) {
  if (Tol >  BRep_Tool::Tolerance(TheV)) {
    BRep_Builder B;
    B.UpdateVertex(TheV, Tol);
  }
}
