Logo Search packages:      
Sourcecode: opencascade version File versions  Download package

BRepOffset_Inter2d.cxx

// File:    BRepOffset_Inter2d.cxx
// Created: Tue Sep  3 16:37:35 1996
// Author:  Yves FRICAUD
//          <yfr@claquox.paris1.matra-dtv.fr>

//  Modified by skv - Wed Dec 24 18:08:39 2003 OCC4455

#include <stdio.h>

#include <BRepOffset_Inter2d.ixx>
#include <BRepAlgo_AsDes.hxx>
#include <BRepOffset_Offset.hxx>
#include <BRepOffset_Tool.hxx>

#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepLib_MakeVertex.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Iterator.hxx>

#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
#include <gp_Pnt.hxx>
#include <BRep_TEdge.hxx>
#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
#include <BRep_CurveRepresentation.hxx>
#include <BRep_GCurve.hxx>

#ifdef DRAW 
#include <DBRep.hxx>
#endif
#ifdef DEB
#ifndef WNT
extern Standard_Integer AffichInt2d;
#else
Standard_IMPORT Standard_Boolean AffichInt2d;
#endif
static Standard_Integer NbF2d = 0;
static Standard_Integer NbE2d = 0;
static Standard_Integer NbNewVertices  = 0;
#endif

#include <Geom_Line.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <GeomConvert_CompCurveToBSplineCurve.hxx>
#include <Precision.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2d_BezierCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>

#include <BRepLib.hxx>
#include <BRepAdaptor_Curve2d.hxx>
#include <Adaptor3d_HSurface.hxx>
#include <Adaptor3d_CurveOnSurface.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Adaptor2d_HCurve2d.hxx>
#include <TColGeom2d_SequenceOfCurve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <IntRes2d_IntersectionPoint.hxx>
#include <IntRes2d_IntersectionSegment.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomLib.hxx>
#include <GeomProjLib.hxx>
#include <TColgp_SequenceOfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <Bnd_Box.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <BRepTools.hxx>


//=======================================================================
//function : CommonVertex
//purpose  : 
//=======================================================================

static TopoDS_Vertex CommonVertex(TopoDS_Edge& E1,
                          TopoDS_Edge& E2)
{
  TopoDS_Vertex V1[2],V2[2],V;
  //  Modified by skv - Wed Dec 24 18:08:39 2003 OCC4455 Begin
//  TopExp::Vertices(E1,V1[0],V1[1]);
//  TopExp::Vertices(E2,V2[0],V2[1]);

  TopExp::Vertices(E1,V1[0],V1[1], Standard_True);
  TopExp::Vertices(E2,V2[0],V2[1], Standard_True);
  // The first edge is the current one, the second edge is the next one.
  // We check last vertex of the first edge first.
//  if (V1[0].IsSame(V2[0]) || V1[0].IsSame(V2[1])) return V1[0];
//  if (V1[1].IsSame(V2[0]) || V1[1].IsSame(V2[1])) return V1[1];
  if (V1[1].IsSame(V2[0]) || V1[1].IsSame(V2[1])) return V1[1];
  if (V1[0].IsSame(V2[0]) || V1[0].IsSame(V2[1])) return V1[0];
  //  Modified by skv - Wed Dec 24 18:08:40 2003 OCC4455 End
  return V;
}

//=======================================================================
//function : Store
//purpose  : 
//=======================================================================

static void  Store (const TopoDS_Edge&       E1,
                const TopoDS_Edge&       E2,
                TopTools_ListOfShape&    LV1,
                TopTools_ListOfShape&    LV2,
                Handle(BRepAlgo_AsDes)   AsDes,
                Standard_Real            Tol)
{
  //-------------------------------------------------------------
  // Test si les points d intersection correspondent a des vertex
  // existants.Sinon  ajout dans les descendants des edges.
  // Remarque a ce stade seulement les vertex d intersection sont
  // dans les descendants.
  //-------------------------------------------------------------
  const TopTools_ListOfShape& VOnE1 = AsDes->Descendant(E1);
  const TopTools_ListOfShape& VOnE2 = AsDes->Descendant(E2);
  TopTools_ListOfShape        NewVOnE1;   
  TopTools_ListOfShape        NewVOnE2; 
  gp_Pnt                      P,P1,P2;
  TopoDS_Vertex               V1,V2;
  TopTools_ListIteratorOfListOfShape it, itLV1, itLV2;
  BRep_Builder                       B;
  TopAbs_Orientation                 O1,O2;
  Standard_Real                      U1,U2;
  Standard_Boolean                   OnE1,OnE2;

  for (itLV1.Initialize(LV1),itLV2.Initialize(LV2); 
       itLV1.More(); 
       itLV1.Next()  ,itLV2.Next()) {

    TopoDS_Vertex V    = TopoDS::Vertex(itLV1.Value());

    U1 = BRep_Tool::Parameter(V,E1);
    U2 = BRep_Tool::Parameter(V,E2);
    O1 = V.Orientation();
    O2 = itLV2.Value().Orientation();
    P  = BRep_Tool::Pnt(V);
    OnE1 = OnE2 = Standard_False;
    
    if (!VOnE1.IsEmpty()) {
      //-----------------------------------------------------------------
      // Recherche si le point d intersection correspond a un vertex de E1.
      //-----------------------------------------------------------------
      for (it.Initialize(VOnE1); it.More(); it.Next()) {
      P1 = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
      if (P.IsEqual(P1,Tol)) {
        V    = TopoDS::Vertex(it.Value());
        V1   = V;
        OnE1 = Standard_True;
        break;
      }
      }
    }
    if (!VOnE2.IsEmpty()) {
      if (OnE1) {
      //-----------------------------------------------------------------
      // Recherche si le vertex trouve sur E1 n est pas deja sur E2.
      //-----------------------------------------------------------------
      for (it.Initialize(VOnE2); it.More(); it.Next()) {
        if (it.Value().IsSame(V)) {
          OnE2 = Standard_True;
          V2   = V;
          break;
        }
      }
      }
      for (it.Initialize(VOnE2); it.More(); it.Next()) {
      //-----------------------------------------------------------------
      // Recherche si le point d intersection correspond a un vertex de E2.
      //-----------------------------------------------------------------
      P2 = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
      if (P.IsEqual(P2,Tol)) {
        V  = TopoDS::Vertex(it.Value());
        V2 = V;
        OnE2 = Standard_True;
        break;
      }
      }      
    }  
    if (OnE1 && OnE2) {
      if (!V1.IsSame(V2)) {
      //---------------------------------------------------------------
      // Les deux vertex sont en fait les memes.
      // on va remplacer V2 par V1. 
      // mis a jour des parametres des vertex sur les edges.
      //---------------------------------------------------------------
      Standard_Real UV2;
      TopoDS_Edge   EWE2;
      const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);

      for (it.Initialize(EdgeWithV2); it.More(); it.Next()) {
        EWE2  = TopoDS::Edge(it.Value());
        TopoDS_Shape aLocalShape =V2.Oriented(TopAbs_INTERNAL);
        UV2   = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
//      UV2   = 
//        BRep_Tool::Parameter(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),EWE2);
        aLocalShape = V1.Oriented(TopAbs_INTERNAL);
        B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
//      B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
//                 UV2,EWE2,Tol);
      }
      AsDes->Replace(V2,V1);
      }
    }
    if (!OnE1) {
      if (OnE2) {
      TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
      B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol);
//    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
//                 U1,E1,Tol);
      }
      NewVOnE1.Append(V.Oriented(O1));
    }
    if (!OnE2) {
      if (OnE1) {
      TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
      B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol);
//    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
//                 U2,E2,Tol);
      }
      NewVOnE2.Append(V.Oriented(O2));
    }
    
#ifdef DRAW
   if (AffichInt2d) {     
     if (!OnE1 && !OnE2) {
       //POP pour NT
       char* name = new char[100];
       sprintf(name,"VV_%d",NbNewVertices++);   
       DBRep::Set(name,V);
     }
   }  
#endif    
  }
  if (!NewVOnE1.IsEmpty()) AsDes->Add(E1,NewVOnE1);
  if (!NewVOnE2.IsEmpty()) AsDes->Add(E2,NewVOnE2);
}


//=======================================================================
//function : EdgeInter
//purpose  : 
//=======================================================================

static void EdgeInter(const TopoDS_Face&              F,
                  const TopoDS_Edge&              E1,
                  const TopoDS_Edge&              E2,
                  const Handle(BRepAlgo_AsDes)&   AsDes,
                  Standard_Real                   Tol,
                  Standard_Boolean                WithOri)
{
#ifdef DRAW
  if (AffichInt2d) {
    //POP pour NT
    char* name = new char[100];
    sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
    DBRep::Set(name,E1);
    sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
    DBRep::Set(name,E2);
  }
#endif

  if (E1.IsSame(E2))
    return;

  Standard_Real f[3],l[3];
  Standard_Real MilTol2 = 1000*Tol*Tol;
  Standard_Real TolDub = 1.e-7;  // Faire un calcul plus malin !!! NYI
  Standard_Integer i;

  BRep_Tool::Range(E1, f[1], l[1]);
  BRep_Tool::Range(E2, f[2], l[2]);

  BRepAdaptor_Curve CE1(E1,F);
  BRepAdaptor_Curve CE2(E2,F);

  TopoDS_Edge                 EI[3]; EI[1] = E1; EI[2] = E2;
  TopTools_ListOfShape        LV1;   
  TopTools_ListOfShape        LV2; 
  BRep_Builder                B;

  TopoDS_Vertex CV;
  if (!TopExp::CommonVertex( E1, E2, CV ))
    {
      BRepLib::BuildCurve3d(E1);
      BRepLib::BuildCurve3d(E2);
      
      Standard_Real TolSum = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
      TolSum = Max( TolSum, 1.e-5 );

      TColgp_SequenceOfPnt   ResPoints;
      TColStd_SequenceOfReal ResParamsOnE1, ResParamsOnE2;
      gp_Pnt DegPoint;
      Standard_Boolean WithDegen = BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2);
      
      if (WithDegen)
      {
        Standard_Integer ideg = (BRep_Tool::Degenerated(E1))? 1 : 2;
        TopoDS_Iterator iter( EI[ideg] );
        if (iter.More())
          {
            const TopoDS_Vertex& vdeg = TopoDS::Vertex(iter.Value());
            DegPoint = BRep_Tool::Pnt(vdeg);
          }
        else
          {
            BRepAdaptor_Curve CEdeg( EI[ideg], F );
            DegPoint = CEdeg.Value( CEdeg.FirstParameter() );
          }
      }
      BRepAdaptor_Surface BAsurf(F);
      Handle(Geom2d_Curve) pcurve1 = BRep_Tool::CurveOnSurface(E1, F, f[1], l[1]);
      Handle(Geom2d_Curve) pcurve2 = BRep_Tool::CurveOnSurface(E2, F, f[2], l[2]);
      Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]);
      Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]);
      Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub );
      for (i = 1; i <= Inter2d.NbPoints(); i++)
      {
        gp_Pnt P3d;
        if (WithDegen)
          P3d = DegPoint;
        else
          {
            gp_Pnt2d P2d = Inter2d.Point(i).Value();
            P3d = BAsurf.Value( P2d.X(), P2d.Y() );
          }
        ResPoints.Append( P3d );
        ResParamsOnE1.Append( Inter2d.Point(i).ParamOnFirst() );
        ResParamsOnE2.Append( Inter2d.Point(i).ParamOnSecond() );
      }

      for (i = 1; i <= ResPoints.Length(); i++)
      {
        Standard_Real aT1 = ResParamsOnE1(i); //ponc1.Parameter();
        Standard_Real aT2 = ResParamsOnE2(i); //ponc2.Parameter();
        if (Precision::IsInfinite(aT1) || Precision::IsInfinite(aT2))
          {
#ifdef DEB
            cout << "Inter2d : Solution rejected due to infinite parameter"<<endl;
#endif
            continue;
          }
        
        gp_Pnt P = ResPoints(i); //ponc1.Value();
        TopoDS_Vertex aNewVertex = BRepLib_MakeVertex(P);
        B.UpdateVertex( aNewVertex, aT1, E1, Tol );
        B.UpdateVertex( aNewVertex, aT2, E2, Tol );
        gp_Pnt P1 = CE1.Value(aT1);
        gp_Pnt P2 = CE2.Value(aT2);
        Standard_Real dist1, dist2, dist3;
        dist1 = P1.Distance(P);
        dist2 = P2.Distance(P);
        dist3 = P1.Distance(P2);
        dist1 = Max( dist1, dist2 );
        dist1 = Max( dist1, dist3 );
        B.UpdateVertex( aNewVertex, dist1 );
        
#ifdef DEB
        if (aT1 < f[1]-Tol  || aT1 > l[1]+Tol)
          {
            cout << "hors borne"<<endl;
            cout<<"aT1 = "<<aT1<<", f[1] = "<<f[1]<<", l[1] = "<<l[1]<<endl;
          }
        if (aT2 < f[2]-Tol  || aT2 > l[2]+Tol)
          {
            cout << "hors borne"<<endl;
            cout<<"aT2 = "<<aT2<<", f[2] = "<<f[2]<<", l[2] = "<<l[2]<<endl;
          }
        if (P1.SquareDistance(P) >  MilTol2 || P2.SquareDistance(P) > MilTol2 || P1.Distance(P2) > 2.*Tol)
          {
            cout << "Inter2d : Solution rejete "<<endl;
            cout<<"P  = "<<P.X()<<" "<<P.Y()<<" "<<P.Z()<<endl;
            cout<<"P1 = "<<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<endl;
            cout<<"P2 = "<<P2.X()<<" "<<P2.Y()<<" "<<P2.Z()<<endl;
            cout<<"MaxDist = "<<dist1<<endl;
          }
#endif
        //define the orientation of a new vertex
        TopAbs_Orientation OO1 = TopAbs_REVERSED;
        TopAbs_Orientation OO2 = TopAbs_REVERSED;
        if (WithOri)
          {
            BRepAdaptor_Curve2d PCE1( E1, F );
            BRepAdaptor_Curve2d PCE2( E2, F );
            gp_Pnt2d P2d1, P2d2;
            gp_Vec2d V1, V2, V1or, V2or;
            PCE1.D1( aT1, P2d1, V1 );
            PCE2.D1( aT2, P2d2, V2 );
            V1or = V1; V2or = V2;
            if (E1.Orientation() == TopAbs_REVERSED) V1or.Reverse();
            if (E2.Orientation() == TopAbs_REVERSED) V2or.Reverse();
            Standard_Real CrossProd = V2or ^ V1;
#ifdef DEB
            if (Abs(CrossProd) <= gp::Resolution())
            cout<<endl<<"CrossProd = "<<CrossProd<<endl;
#endif
            if (CrossProd > 0.)
            OO1 = TopAbs_FORWARD;
            CrossProd = V1or ^ V2;
            if (CrossProd > 0.)
            OO2 = TopAbs_FORWARD;
          }
        LV1.Append( aNewVertex.Oriented(OO1) );
        LV2.Append( aNewVertex.Oriented(OO2) );
      }
    }
  
  //----------------------------------
  // Test en bout.
  //---------------------------------
  Standard_Real U1,U2;
  Standard_Real TolConf = Tol;
  TopoDS_Vertex V1[2],V2[2];
  TopExp::Vertices(E1,V1[0],V1[1]);
  TopExp::Vertices(E2,V2[0],V2[1]);

  Standard_Integer j;
  for (j = 0; j < 2; j++) {
    if (V1[j].IsNull()) continue;
    for (Standard_Integer k = 0; k < 2; k++) {
      if (V2[k].IsNull()) continue;
      gp_Pnt P1 = BRep_Tool::Pnt(V1[j]);
      gp_Pnt P2 = BRep_Tool::Pnt(V2[k]);
      Standard_Real Dist = P1.Distance(P2); 
      if (Dist < TolConf) {
      TopoDS_Vertex V = BRepLib_MakeVertex(P1);
      U1 = (j == 0) ? f[1] : l[1];
      U2 = (k == 0) ? f[2] : l[2];
      TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
//  Modified by skv - Thu Jan 22 18:16:01 2004 OCC4455 Begin
      Standard_Real aTol = BRep_Tool::Tolerance(V1[j]);

      if (!V1[j].IsSame(V2[k])) {
        Standard_Real aTol2 = BRep_Tool::Tolerance(V2[k]);

        aTol = Max(aTol, aTol2);
      }

      B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,aTol);
      B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,aTol);
//    B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol);
//    B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol);
//    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
//                 U1,E1,Tol);
//    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
//                 U2,E2,Tol);
//  Modified by skv - Thu Jan 22 18:16:01 2004 OCC4455 End
      LV1.Prepend(V.Oriented(V1[j].Orientation()));
      LV2.Prepend(V.Oriented(V2[k].Orientation()));
      }
    }
  }

  Standard_Boolean AffichPurge = Standard_False;

  if ( !LV1.IsEmpty()) {
    //----------------------------------
    // Purge de l ensemble des vertex.
    // il peut y avoir des doublons
    //----------------------------------
    TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1;
    gp_Pnt P1,P2;
    Standard_Boolean Purge = Standard_True;

    while (Purge) {
      i = 1;
      Purge = Standard_False;
      for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); 
         it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
      j = 1;
      it2LV1.Initialize(LV1);
      while (j < i) {      
        P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
        P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2LV1.Value()));
//  Modified by skv - Thu Jan 22 18:19:04 2004 OCC4455 Begin
//      if (P1.IsEqual(P2,10*Tol)) {
        Standard_Real aTol;

        aTol = Max(BRep_Tool::Tolerance(TopoDS::Vertex(it1LV1.Value())),
                 BRep_Tool::Tolerance(TopoDS::Vertex(it2LV1.Value())));
        if (P1.IsEqual(P2,aTol)) {
//  Modified by skv - Thu Jan 22 18:19:05 2004 OCC4455 End
          LV1.Remove(it1LV1);
          LV2.Remove(it1LV2);
          if (AffichPurge) cout <<"Doublons purges dans EdgeInter."<<endl;
          Purge = Standard_True;
          break;
        }
        j++;
        it2LV1.Next();
      }
      if (Purge) break;
      i++;
      }
    }
    //---------------------------------
    // Stockage vertex en SD.
    //---------------------------------
//  Modified by skv - Tue Jan 13 15:14:30 2004 Begin
    Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);

    TolStore = Max(TolStore, 10.*Tol);

    Store (E1,E2,LV1,LV2,AsDes,TolStore);
//    Store (E1,E2,LV1,LV2,AsDes,10.*Tol);
//    Store (E1,E2,LV1,LV2,AsDes,Tol);
//  Modified by skv - Tue Jan 13 15:14:30 2004 End
  }
}
//=======================================================================
//function : EdgeInter
//purpose  : 
//=======================================================================

static void RefEdgeInter(const TopoDS_Face&              F,
                   const TopoDS_Edge&              E1,
                   const TopoDS_Edge&              E2,
                   const Handle(BRepAlgo_AsDes)&   AsDes,
                   Standard_Real                   Tol,
                   Standard_Boolean                WithOri,
                   gp_Pnt&                         Pref)
{
#ifdef DRAW
  if (AffichInt2d) {
    //POP pour NT
    char* name = new char[100];
    sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
    DBRep::Set(name,E1);
    sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
    DBRep::Set(name,E2);
  }
#endif

  if (E1.IsSame(E2))
    return;

  Standard_Real f[3],l[3];
  Standard_Real MilTol2 = 1000*Tol*Tol;
  Standard_Real TolDub = 1.e-7;  // Faire un calcul plus malin !!! NYI
  Standard_Integer i;

  //BRep_Tool::Range(E1, f[1], l[1]);
  //BRep_Tool::Range(E2, f[2], l[2]);

  BRepAdaptor_Curve CE1(E1,F);
  BRepAdaptor_Curve CE2(E2,F);

  TopoDS_Edge                 EI[3]; EI[1] = E1; EI[2] = E2;
  TopTools_ListOfShape        LV1;   
  TopTools_ListOfShape        LV2; 
  BRep_Builder                B;

  BRepLib::BuildCurve3d(E1);
  BRepLib::BuildCurve3d(E2);

  Standard_Real TolSum = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
  TolSum = Max( TolSum, 1.e-5 );

  TColgp_SequenceOfPnt   ResPoints;
  TColStd_SequenceOfReal ResParamsOnE1, ResParamsOnE2;
  gp_Pnt DegPoint;
  Standard_Boolean WithDegen = BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2);
  
  if (WithDegen)
    {
      Standard_Integer ideg = (BRep_Tool::Degenerated(E1))? 1 : 2;
      TopoDS_Iterator iter( EI[ideg] );
      if (iter.More())
      {
        const TopoDS_Vertex& vdeg = TopoDS::Vertex(iter.Value());
        DegPoint = BRep_Tool::Pnt(vdeg);
      }
      else
      {
        BRepAdaptor_Curve CEdeg( EI[ideg], F );
        DegPoint = CEdeg.Value( CEdeg.FirstParameter() );
      }
    }
  BRepAdaptor_Surface BAsurf(F);
  Handle(Geom2d_Curve) pcurve1 = BRep_Tool::CurveOnSurface(E1, F, f[1], l[1]);
  Handle(Geom2d_Curve) pcurve2 = BRep_Tool::CurveOnSurface(E2, F, f[2], l[2]);
  Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]);
  Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]);
  Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub );
  for (i = 1; i <= Inter2d.NbPoints(); i++)
    {
      gp_Pnt P3d;
      if (WithDegen)
      P3d = DegPoint;
      else
      {
        gp_Pnt2d P2d = Inter2d.Point(i).Value();
        P3d = BAsurf.Value( P2d.X(), P2d.Y() );
      }
      ResPoints.Append( P3d );
      ResParamsOnE1.Append( Inter2d.Point(i).ParamOnFirst() );
      ResParamsOnE2.Append( Inter2d.Point(i).ParamOnSecond() );
    }
  
  for (i = 1; i <= ResPoints.Length(); i++)
    {
      Standard_Real aT1 = ResParamsOnE1(i); //ponc1.Parameter();
      Standard_Real aT2 = ResParamsOnE2(i); //ponc2.Parameter();
      if (Precision::IsInfinite(aT1) || Precision::IsInfinite(aT2))
      {
#ifdef DEB
        cout << "Inter2d : Solution rejected due to infinite parameter"<<endl;
#endif
        continue;
      }
      
      gp_Pnt P = ResPoints(i); //ponc1.Value();
      TopoDS_Vertex aNewVertex = BRepLib_MakeVertex(P);
      B.UpdateVertex( aNewVertex, aT1, E1, Tol );
      B.UpdateVertex( aNewVertex, aT2, E2, Tol );
      gp_Pnt P1 = CE1.Value(aT1);
      gp_Pnt P2 = CE2.Value(aT2);
      Standard_Real dist1, dist2, dist3;
      dist1 = P1.Distance(P);
      dist2 = P2.Distance(P);
      dist3 = P1.Distance(P2);
      dist1 = Max( dist1, dist2 );
      dist1 = Max( dist1, dist3 );
      B.UpdateVertex( aNewVertex, dist1 );
      
#ifdef DEB
      if (aT1 < f[1]-Tol  || aT1 > l[1]+Tol)
      {
        cout << "hors borne"<<endl;
        cout<<"aT1 = "<<aT1<<", f[1] = "<<f[1]<<", l[1] = "<<l[1]<<endl;
      }
      if (aT2 < f[2]-Tol  || aT2 > l[2]+Tol)
      {
        cout << "hors borne"<<endl;
        cout<<"aT2 = "<<aT2<<", f[2] = "<<f[2]<<", l[2] = "<<l[2]<<endl;
      }
      if (P1.SquareDistance(P) >  MilTol2 || P2.SquareDistance(P) > MilTol2 || P1.Distance(P2) > 2.*Tol)
      {
        cout << "Inter2d : Solution rejete "<<endl;
        cout<<"P  = "<<P.X()<<" "<<P.Y()<<" "<<P.Z()<<endl;
        cout<<"P1 = "<<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<endl;
        cout<<"P2 = "<<P2.X()<<" "<<P2.Y()<<" "<<P2.Z()<<endl;
        cout<<"MaxDist = "<<dist1<<endl;
      }
#endif
      //define the orientation of a new vertex
      TopAbs_Orientation OO1 = TopAbs_REVERSED;
      TopAbs_Orientation OO2 = TopAbs_REVERSED;
      if (WithOri)
      {
        BRepAdaptor_Curve2d PCE1( E1, F );
        BRepAdaptor_Curve2d PCE2( E2, F );
        gp_Pnt2d P2d1, P2d2;
        gp_Vec2d V1, V2, V1or, V2or;
        PCE1.D1( aT1, P2d1, V1 );
        PCE2.D1( aT2, P2d2, V2 );
        V1or = V1; V2or = V2;
        if (E1.Orientation() == TopAbs_REVERSED) V1or.Reverse();
        if (E2.Orientation() == TopAbs_REVERSED) V2or.Reverse();
        Standard_Real CrossProd = V2or ^ V1;
#ifdef DEB
        if (Abs(CrossProd) <= gp::Resolution())
          cout<<endl<<"CrossProd = "<<CrossProd<<endl;
#endif
        if (CrossProd > 0.)
          OO1 = TopAbs_FORWARD;
        CrossProd = V1or ^ V2;
        if (CrossProd > 0.)
          OO2 = TopAbs_FORWARD;
      }
      LV1.Append( aNewVertex.Oriented(OO1) );
      LV2.Append( aNewVertex.Oriented(OO2) );
    }
  
  //----------------------------------
  // Test en bout.
  //---------------------------------
  Standard_Real U1,U2;
  Standard_Real TolConf = Tol;
  TopoDS_Vertex V1[2],V2[2];
  TopExp::Vertices(E1,V1[0],V1[1]);
  TopExp::Vertices(E2,V2[0],V2[1]);

  Standard_Integer j;
  for (j = 0; j < 2; j++) {
    if (V1[j].IsNull()) continue;
    for (Standard_Integer k = 0; k < 2; k++) {
      if (V2[k].IsNull()) continue;
      gp_Pnt P1 = BRep_Tool::Pnt(V1[j]);
      gp_Pnt P2 = BRep_Tool::Pnt(V2[k]);
      Standard_Real Dist = P1.Distance(P2); 
      if (Dist < TolConf) {
      TopoDS_Vertex V = BRepLib_MakeVertex(P1);
      U1 = (j == 0) ? f[1] : l[1];
      U2 = (k == 0) ? f[2] : l[2];
      TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
      B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol);
      B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol);
//    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
//                 U1,E1,Tol);
//    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
//                 U2,E2,Tol);
      LV1.Prepend(V.Oriented(V1[j].Orientation()));
      LV2.Prepend(V.Oriented(V2[k].Orientation()));
      }
    }
  }

  Standard_Boolean AffichPurge = Standard_False;

  if ( !LV1.IsEmpty()) {
    //----------------------------------
    // Purge de l ensemble des vertex.
    // il peut y avoir des doublons
    //----------------------------------
    TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1;
    gp_Pnt P1,P2;
    Standard_Boolean Purge = Standard_True;

    while (Purge) {
      i = 1;
      Purge = Standard_False;
      for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); 
         it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
      j = 1;
      it2LV1.Initialize(LV1);
      while (j < i) {      
        P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
        P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2LV1.Value()));
        if (P1.IsEqual(P2,10*Tol)) {
          LV1.Remove(it1LV1);
          LV2.Remove(it1LV2);
          if (AffichPurge) cout <<"Doublons purges dans EdgeInter."<<endl;
          Purge = Standard_True;
          break;
        }
        j++;
        it2LV1.Next();
      }
      if (Purge) break;
      i++;
      }
    }
    //---------------------------------
    // Stockage vertex en SD.
    //---------------------------------
////-----------------------------------------------------
    if(LV1.Extent() > 1) {
      //cout << "IFV - RefEdgeInter: remove vertex" << endl;
      Standard_Real dmin = RealLast();
      TopoDS_Vertex Vmin;
      for (it1LV1.Initialize(LV1); it1LV1.More(); it1LV1.Next()) {
      gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
      Standard_Real d = P.SquareDistance(Pref);
      if(d < dmin) {
        dmin = d;
        Vmin = TopoDS::Vertex(it1LV1.Value());
      }
      }
      for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); 
         it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
      if(!Vmin.IsSame(it1LV1.Value())) {
        LV1.Remove(it1LV1);
        LV2.Remove(it1LV2);
        if(!it1LV1.More()) break;
      }
      }
    }
      
////-----------------------------------------------------

//  Modified by skv - Tue Jan 13 15:14:30 2004 Begin
    Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);

    TolStore = Max(TolStore, 10.*Tol);

    Store (E1,E2,LV1,LV2,AsDes,TolStore);
//    Store (E1,E2,LV1,LV2,AsDes,10.*Tol);
//    Store (E1,E2,LV1,LV2,AsDes,Tol);
//  Modified by skv - Tue Jan 13 15:14:30 2004 End
  }
}


//======================================================================
//function : EvaluateMaxSegment
//purpose  : return MaxSegment to pass in approximation
//======================================================================

static Standard_Integer evaluateMaxSegment(const Adaptor3d_CurveOnSurface& aCurveOnSurface)
{
  Handle(Adaptor3d_HSurface) aSurf   = aCurveOnSurface.GetSurface();
  Handle(Adaptor2d_HCurve2d) aCurv2d = aCurveOnSurface.GetCurve();

  Standard_Real aNbSKnots = 0, aNbC2dKnots = 0;
  
  if (aSurf->GetType() == GeomAbs_BSplineSurface) {
    Handle(Geom_BSplineSurface) aBSpline = aSurf->BSpline();
    aNbSKnots = Max(aBSpline->NbUKnots(), aBSpline->NbVKnots());
  }
  if (aCurv2d->GetType() == GeomAbs_BSplineCurve) {
    aNbC2dKnots = aCurv2d->NbKnots();
  }
  Standard_Integer aReturn = (Standard_Integer) (  30 + Max(aNbSKnots, aNbC2dKnots) ) ;
  return aReturn;
}


//=======================================================================
//function : ExtendPCurve
//purpose  : 
//=======================================================================

static Standard_Boolean ExtendPCurve(const Handle(Geom2d_Curve)& aPCurve,
                             const Standard_Real anEf,
                             const Standard_Real anEl,
                             const Standard_Real a2Offset,
                             Handle(Geom2d_Curve)& NewPCurve)
{
  NewPCurve = aPCurve;
  if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve)))
    NewPCurve = (*((Handle(Geom2d_TrimmedCurve)*)&NewPCurve))->BasisCurve();
  
  Standard_Real FirstPar = NewPCurve->FirstParameter();
  Standard_Real LastPar  = NewPCurve->LastParameter();

  if (NewPCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) &&
      (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset))
    {
      if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BezierCurve)))
      {
        Handle(Geom2d_BezierCurve) aBezier = *((Handle(Geom2d_BezierCurve)*)&NewPCurve);
        if (aBezier->NbPoles() == 2)
          {
            TColgp_Array1OfPnt2d thePoles(1,2);
            aBezier->Poles(thePoles);
            gp_Vec2d aVec(thePoles(1), thePoles(2));
            NewPCurve = new Geom2d_Line(thePoles(1), aVec);
            return Standard_True;
          }
      }
      else if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BSplineCurve)))
      {
        Handle(Geom2d_BSplineCurve) aBSpline = *((Handle(Geom2d_BSplineCurve)*)&NewPCurve);
        if (aBSpline->NbKnots() == 2 && aBSpline->NbPoles() == 2)
          {
            TColgp_Array1OfPnt2d thePoles(1,2);
            aBSpline->Poles(thePoles);
            gp_Vec2d aVec(thePoles(1), thePoles(2));
            NewPCurve = new Geom2d_Line(thePoles(1), aVec);
            return Standard_True;
          }
      }
    }

  FirstPar = aPCurve->FirstParameter();
  LastPar  = aPCurve->LastParameter();
  Handle(Geom2d_TrimmedCurve) aTrCurve = 
    new Geom2d_TrimmedCurve(aPCurve, FirstPar, LastPar);
  
  // The curve is not prolonged on begin or end.
  // Trying to prolong it adding a segment to its bound.
  gp_Pnt2d                              aPBnd;
  gp_Vec2d                              aVBnd;
  gp_Pnt2d                              aPBeg;
  gp_Dir2d                              aDBnd;
  Handle(Geom2d_Line)                   aLin;
  Handle(Geom2d_TrimmedCurve)           aSegment;
  Geom2dConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1);
  Standard_Real                         aTol = Precision::Confusion();
  Standard_Real                         aDelta = Max(a2Offset, 1.);
  
  if (FirstPar > anEf - a2Offset) {
    aPCurve->D1(FirstPar, aPBnd, aVBnd);
    aDBnd.SetXY(aVBnd.XY());
    aPBeg    = aPBnd.Translated(gp_Vec2d(-aDelta*aDBnd.XY()));
    aLin     = new Geom2d_Line(aPBeg, aDBnd);
    aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta);
    
    if (!aCompCurve.Add(aSegment, aTol))
      return Standard_False;
  }
  
  if (LastPar < anEl + a2Offset) {
    aPCurve->D1(LastPar, aPBeg, aVBnd);
    aDBnd.SetXY(aVBnd.XY());
    aLin     = new Geom2d_Line(aPBeg, aDBnd);
    aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta);
    
    if (!aCompCurve.Add(aSegment, aTol))
      return Standard_False;
  }
  
  NewPCurve  = aCompCurve.BSplineCurve();
  return Standard_True;
}

//=======================================================================
//function : ExtentEdge
//purpose  : 
//=======================================================================

//  Modified by skv - Fri Dec 26 17:00:55 2003 OCC4455 Begin
//static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE) 
static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE, const Standard_Real theOffset)
{
  //BRepLib::BuildCurve3d(E);

  TopoDS_Shape  aLocalShape = E.EmptyCopied();
  Standard_Real anEf;
  Standard_Real anEl;
  Standard_Real a2Offset = 2.*Abs(theOffset);
  BRep_Builder BB;
  Standard_Integer i, j;

  BRep_Tool::Range(E, anEf, anEl);
  NE = TopoDS::Edge(aLocalShape); 
//  NE = TopoDS::Edge(E.EmptyCopied()); 
  // Suffit pour les edges analytiques, pour le cas general reconstruire la
  // la geometrie de l edge en recalculant l intersection des surfaces.

  //BRepLib::BuildCurve3d(E);

  Standard_Integer NbPCurves = 0;
  Standard_Real FirstParOnPC = RealFirst(), LastParOnPC = RealLast();
  Handle(Geom2d_Curve) MinPC;
  Handle(Geom_Surface) MinSurf;
  TopLoc_Location      MinLoc;

  BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves() );
  for (; itr.More(); itr.Next())
    {
      Handle( BRep_CurveRepresentation ) CurveRep = itr.Value();
      Standard_Real FirstPar, LastPar;
      if (CurveRep->IsCurveOnSurface())
      {
        NbPCurves++;
        Handle(Geom2d_Curve) theCurve = CurveRep->PCurve();
        FirstPar = theCurve->FirstParameter();
        LastPar  = theCurve->LastParameter();

        if (theCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) &&
            (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset))
          {
            Handle(Geom2d_Curve) NewPCurve;
            if (ExtendPCurve(theCurve, anEf, anEl, a2Offset, NewPCurve))
            {
              CurveRep->PCurve(NewPCurve);
              FirstPar = NewPCurve->FirstParameter();
              LastPar  = NewPCurve->LastParameter();
              if (CurveRep->IsCurveOnClosedSurface())
                {
                  Handle(Geom2d_Curve) PCurve2 = CurveRep->PCurve2();
                  if (ExtendPCurve(PCurve2, anEf, anEl, a2Offset, NewPCurve))
                  CurveRep->PCurve2(NewPCurve);
                }
            }
          }
        else if (theCurve->IsPeriodic())
          {
            Standard_Real delta = (theCurve->Period() - (anEl - anEf))*0.5;
            delta *= 0.95;
            FirstPar = anEf - delta;
            LastPar  = anEl + delta;
          }
        else if (theCurve->IsClosed())
          LastPar -= 0.05*(LastPar - FirstPar);

        //check FirstPar and LastPar: the pcurve should be in its surface
        theCurve = CurveRep->PCurve();
        Handle(Geom_Surface) theSurf = CurveRep->Surface();
        Standard_Real Umin, Umax, Vmin, Vmax;
        theSurf->Bounds(Umin, Umax, Vmin, Vmax);
        TColGeom2d_SequenceOfCurve BoundLines;
        if (!Precision::IsInfinite(Vmin))
          {
            Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmin ),
                                            gp_Dir2d( 1., 0. ));
            BoundLines.Append(aLine);
          }
        if (!Precision::IsInfinite(Umin))
          {
            Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umin, 0. ),
                                            gp_Dir2d( 0., 1. ));
            BoundLines.Append(aLine);
          }
        if (!Precision::IsInfinite(Vmax))
          {
            Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmax ),
                                            gp_Dir2d( 1., 0. ));
            BoundLines.Append(aLine);
          }
        if (!Precision::IsInfinite(Umax))
          {
            Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umax, 0. ),
                                            gp_Dir2d( 0., 1. ));
            BoundLines.Append(aLine);
          }

        TColStd_SequenceOfReal params;
        Geom2dInt_GInter IntCC;
        Geom2dAdaptor_Curve GAcurve(theCurve);
        for (i = 1; i <= BoundLines.Length(); i++)
          {
            Geom2dAdaptor_Curve GAline( BoundLines(i) );
            IntCC.Perform( GAcurve, GAline, Precision::PConfusion(), Precision::PConfusion());
            if (IntCC.IsDone())
            {
              for (j = 1; j <= IntCC.NbPoints(); j++)
                {
                  const IntRes2d_IntersectionPoint& ip = IntCC.Point(j);
                  gp_Pnt2d aPoint = ip.Value();
                  if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
                    aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
                  params.Append( ip.ParamOnFirst() );
                }
              for (j = 1; j <= IntCC.NbSegments(); j++)
                {
                  const IntRes2d_IntersectionSegment& is = IntCC.Segment(j);
                  if (is.HasFirstPoint())
                  {
                    const IntRes2d_IntersectionPoint& ip = is.FirstPoint();
                    gp_Pnt2d aPoint = ip.Value();
                    if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
                        aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
                      params.Append( ip.ParamOnFirst() );
                  }
                  if (is.HasLastPoint())
                  {
                    const IntRes2d_IntersectionPoint& ip = is.LastPoint();
                    gp_Pnt2d aPoint = ip.Value();
                    if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
                        aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
                      params.Append( ip.ParamOnFirst() );
                  }
                }
            }
          }
        if (!params.IsEmpty())
          {
            if (params.Length() == 1)
            {
              gp_Pnt2d PntFirst = theCurve->Value(FirstPar);
              if (PntFirst.X() >= Umin && PntFirst.X() <= Umax &&
                  PntFirst.Y() >= Vmin && PntFirst.Y() <= Vmax)
                {
                  if (LastPar > params(1))
                  LastPar = params(1);
                }
              else if (FirstPar < params(1))
                FirstPar = params(1);
            }
            else
            {
              Standard_Real fpar = RealLast(), lpar = RealFirst();
              for (i = 1; i <= params.Length(); i++)
                {
                  if (params(i) < fpar)
                  fpar = params(i);
                  if (params(i) > lpar)
                  lpar = params(i);
                }
              if (FirstPar < fpar)
                FirstPar = fpar;
              if (LastPar > lpar)
                LastPar = lpar;
            }
          }
        //// end of check ////
        (Handle(BRep_GCurve)::DownCast(CurveRep))->SetRange( FirstPar, LastPar );
        //gp_Pnt2d Pfirst = theCurve->Value(FirstPar);
        //gp_Pnt2d Plast  = theCurve->Value(LastPar);
        //(Handle(BRep_CurveOnSurface)::DownCast(CurveRep))->SetUVPoints( Pfirst, Plast );

        //update FirstParOnPC and LastParOnPC
        if (FirstPar > FirstParOnPC)
          {
            FirstParOnPC = FirstPar;
            MinPC   = theCurve;
            MinSurf = theSurf;
            MinLoc  = CurveRep->Location();
          }
        if (LastPar  < LastParOnPC)
          {
            LastParOnPC  = LastPar;
            MinPC   = theCurve;
            MinSurf = theSurf;
            MinLoc  = CurveRep->Location();
          }
      }
    }

  Standard_Real f, l;
  Handle(Geom_Curve) C3d = BRep_Tool::Curve( NE, f, l );
  if (NbPCurves)
    {
      MinLoc = E.Location() * MinLoc;
      if (!C3d.IsNull())
      {
        Standard_Real FirstPar = C3d->FirstParameter();
        Standard_Real LastPar  = C3d->LastParameter();
        if (MinPC->IsClosed())
          {
            f = FirstParOnPC;
            l = LastParOnPC;
          }
        else if (C3d->IsPeriodic())
          {
            Standard_Real delta = (C3d->Period() - (l - f))*0.5;
            delta *= 0.95;
            f -= delta;
            l += delta;
          }
        else if (C3d->IsClosed())
          l -= 0.05*(l - f);
        else
          {
            f = FirstParOnPC;
            l = LastParOnPC;
            GeomAPI_ProjectPointOnCurve Projector;
            if (!Precision::IsInfinite(FirstParOnPC))
            {
              gp_Pnt2d P2d1 = MinPC->Value(FirstParOnPC);
              gp_Pnt P1 = MinSurf->Value( P2d1.X(), P2d1.Y() );
              P1.Transform(MinLoc.Transformation());
              Projector.Init( P1, C3d );
              if (Projector.NbPoints() > 0)
                f = Projector.LowerDistanceParameter();
#ifdef DEB
              else
                cout<<"ProjectPointOnCurve not done"<<endl;
#endif
            }
            if (!Precision::IsInfinite(LastParOnPC))
            {
              gp_Pnt2d P2d2 = MinPC->Value(LastParOnPC);
              gp_Pnt P2 = MinSurf->Value( P2d2.X(), P2d2.Y() );
              P2.Transform(MinLoc.Transformation());
              Projector.Init( P2, C3d );
              if (Projector.NbPoints() > 0)
                l = Projector.LowerDistanceParameter();
#ifdef DEB
              else
                cout<<"ProjectPointOnCurve not done"<<endl;
#endif
            }
          }
        BB.Range( NE, f, l );
        if (!Precision::IsInfinite(f) && !Precision::IsInfinite(l))
          BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
      }
      else //no 3d curve
      {
        MinSurf = Handle(Geom_Surface)::DownCast
          (MinSurf->Transformed(MinLoc.Transformation()));
        Standard_Real max_deviation = 0.;
        if (Precision::IsInfinite(FirstParOnPC) || Precision::IsInfinite(LastParOnPC))
          {
            if (MinPC->IsInstance(STANDARD_TYPE(Geom2d_Line)))
            {
              Standard_Boolean IsLine = Standard_False;
              if (MinSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
                IsLine = Standard_True;
              else if (MinSurf->IsInstance(STANDARD_TYPE(Geom_CylindricalSurface)) ||
                     MinSurf->IsInstance(STANDARD_TYPE(Geom_ConicalSurface)))
                {
                  Handle(Geom2d_Line) theLine = *((Handle(Geom2d_Line)*)&MinPC);
                  gp_Dir2d LineDir = theLine->Direction();
                  if (LineDir.IsParallel( gp::DY2d(), Precision::Angular() ))
                  IsLine = Standard_True;
                }
              if (IsLine)
                {
                  gp_Pnt2d P2d1 = MinPC->Value(0.), P2d2 = MinPC->Value(1.);
                  gp_Pnt P1 = MinSurf->Value(P2d1.X(), P2d1.Y());
                  gp_Pnt P2 = MinSurf->Value(P2d2.X(), P2d2.Y());
                  gp_Vec aVec(P1, P2);
                  C3d = new Geom_Line( P1, aVec );
                }
            }
          }
        else
          {
            Geom2dAdaptor_Curve AC2d( MinPC, FirstParOnPC, LastParOnPC );
            GeomAdaptor_Surface GAsurf( MinSurf );
            Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
            Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
            Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
            Standard_Real /*max_deviation,*/ average_deviation;
            GeomAbs_Shape Continuity = GeomAbs_C1;
            Standard_Integer MaxDegree = 14;
            Standard_Integer MaxSegment = evaluateMaxSegment(ConS);
            GeomLib::BuildCurve3d(Precision::Confusion(),
                            ConS, FirstParOnPC, LastParOnPC,
                            C3d, max_deviation, average_deviation,
                            Continuity, MaxDegree, MaxSegment);
          }
        BB.UpdateEdge( NE, C3d, max_deviation );
        //BB.Range( NE, FirstParOnPC, LastParOnPC );
        Standard_Boolean ProjectionSuccess = Standard_True;
        if (NbPCurves > 1)
          //BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
          for (itr.Initialize((Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves());
             itr.More();
             itr.Next())
            {
            Handle( BRep_CurveRepresentation ) CurveRep = itr.Value();
            Standard_Real FirstPar, LastPar;
            if (CurveRep->IsCurveOnSurface())
              {
                Handle(Geom2d_Curve) theCurve = CurveRep->PCurve();
                Handle(Geom_Surface) theSurf  = CurveRep->Surface();
                TopLoc_Location      theLoc   = CurveRep->Location();
                if (theCurve == MinPC && theSurf == MinSurf && theLoc == MinLoc)
                  continue;
                FirstPar = (Handle(BRep_GCurve)::DownCast(CurveRep))->First();
                LastPar  = (Handle(BRep_GCurve)::DownCast(CurveRep))->Last();
                if (Abs(FirstPar - FirstParOnPC) > Precision::PConfusion() ||
                  Abs(LastPar  - LastParOnPC)  > Precision::PConfusion())
                  {
                  theLoc = E.Location() * theLoc;
                  theSurf = Handle(Geom_Surface)::DownCast
                    (theSurf->Transformed(theLoc.Transformation()));

                  if (theCurve->IsInstance(STANDARD_TYPE(Geom2d_Line)) &&
                      theSurf->IsKind(STANDARD_TYPE(Geom_BoundedSurface)))
                    {
                      gp_Dir2d theDir = (*((Handle(Geom2d_Line)*)&theCurve))->Direction();
                      if (theDir.IsParallel(gp::DX2d(), Precision::Angular()) ||
                        theDir.IsParallel(gp::DY2d(), Precision::Angular()))
                        {
                        Standard_Real U1, U2, V1, V2;
                        theSurf->Bounds(U1, U2, V1, V2);
                        gp_Pnt2d Origin = (*((Handle(Geom2d_Line)*)&theCurve))->Location();
                        if (Abs(Origin.X()-U1) <= Precision::Confusion() ||
                            Abs(Origin.X()-U2) <= Precision::Confusion() ||
                            Abs(Origin.Y()-V1) <= Precision::Confusion() ||
                            Abs(Origin.Y()-V2) <= Precision::Confusion())
                          {
                            BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
                            break;
                          }
                        }
                    }

                  Handle(Geom2d_Curve) ProjPCurve =
                    GeomProjLib::Curve2d( C3d, FirstParOnPC, LastParOnPC, theSurf );
                  if (ProjPCurve.IsNull())
                    ProjectionSuccess = Standard_False;
                  else
                    CurveRep->PCurve( ProjPCurve );
                  }
              }
            }
        if (ProjectionSuccess)
          BB.Range( NE, FirstParOnPC, LastParOnPC );
        else
          {
            BB.Range( NE, FirstParOnPC, LastParOnPC, Standard_True );
            BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
          }
      }
    }
  else //no pcurves
    {
      Standard_Real FirstPar = C3d->FirstParameter();
      Standard_Real LastPar  = C3d->LastParameter();
      
      if (C3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) &&
        FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset)
      {
        Handle(Geom_TrimmedCurve) aTrCurve = 
          new Geom_TrimmedCurve(C3d, FirstPar, LastPar);
        
        // The curve is not prolonged on begin or end.
        // Trying to prolong it adding a segment to its bound.
        gp_Pnt                              aPBnd;
        gp_Vec                              aVBnd;
        gp_Pnt                              aPBeg;
        gp_Dir                              aDBnd;
        Handle(Geom_Line)                   aLin;
        Handle(Geom_TrimmedCurve)           aSegment;
        GeomConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1);
        Standard_Real                       aTol = Precision::Confusion();
        Standard_Real                       aDelta = Max(a2Offset, 1.);
        
        if (FirstPar > anEf - a2Offset) {
          C3d->D1(FirstPar, aPBnd, aVBnd);
          aDBnd.SetXYZ(aVBnd.XYZ());
          aPBeg    = aPBnd.Translated(gp_Vec(-aDelta*aDBnd.XYZ()));
          aLin     = new Geom_Line(aPBeg, aDBnd);
          aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta);
          
          if (!aCompCurve.Add(aSegment, aTol))
            return;
        }
        
        if (LastPar < anEl + a2Offset) {
          C3d->D1(LastPar, aPBeg, aVBnd);
          aDBnd.SetXYZ(aVBnd.XYZ());
          aLin     = new Geom_Line(aPBeg, aDBnd);
          aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta);
          
          if (!aCompCurve.Add(aSegment, aTol))
            return;
        }
        
        C3d = aCompCurve.BSplineCurve();
        FirstPar = C3d->FirstParameter();
        LastPar  = C3d->LastParameter();
        BB.UpdateEdge(NE, C3d, Precision::Confusion());
      }
      else if (C3d->IsPeriodic())
      {
        Standard_Real delta = (C3d->Period() - (anEl - anEf))*0.5;
        delta *= 0.95;
        FirstPar = anEf - delta;
        LastPar  = anEl + delta;
      }
      else if (C3d->IsClosed())
      LastPar -= 0.05*(LastPar - FirstPar);
      
      BB.Range( NE, FirstPar, LastPar );
    }
}
//  Modified by skv - Fri Dec 26 17:00:57 2003 OCC4455 End


//=======================================================================
//function : UpdateVertex
//purpose  : 
//=======================================================================

static Standard_Boolean  UpdateVertex(TopoDS_Vertex V,
                              TopoDS_Edge&  OE,
                              TopoDS_Edge&  NE,
                              Standard_Real TolConf)
{
  BRepAdaptor_Curve OC(OE);
  BRepAdaptor_Curve NC(NE);
  Standard_Real Of = OC.FirstParameter(); Standard_Real Ol = OC.LastParameter();
  Standard_Real Nf = NC.FirstParameter(); Standard_Real Nl = NC.LastParameter();
#ifndef DEB
  Standard_Real U = 0.;
#else
  Standard_Real U;
#endif
  Standard_Real ParTol = Precision::PConfusion();
  gp_Pnt           P  = BRep_Tool::Pnt(V);
  Standard_Boolean OK = Standard_False;

  if (P.Distance(OC.Value(Of)) < TolConf) {
    if (Of >= Nf + ParTol && Of <= Nl + ParTol  && P.Distance(NC.Value(Of)) < TolConf) {
      OK = Standard_True;
      U    = Of;
    }
  }
  if (P.Distance(OC.Value(Ol)) < TolConf) {
    if (Ol >= Nf + ParTol && Ol <= Nl + ParTol  && P.Distance(NC.Value(Ol)) < TolConf) {
      OK = Standard_True;
      U    = Ol;
    }
  }
  if (OK) {
    BRep_Builder B;
    TopoDS_Shape aLocalShape = NE.Oriented(TopAbs_FORWARD);
    TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
//    TopoDS_Edge EE = TopoDS::Edge(NE.Oriented(TopAbs_FORWARD));
    aLocalShape = V.Oriented(TopAbs_INTERNAL);
    B.UpdateVertex(TopoDS::Vertex(aLocalShape),
               U,NE,BRep_Tool::Tolerance(NE));
//    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
//             U,NE,BRep_Tool::Tolerance(NE));
  }
  return OK;  
}

//=======================================================================
//function : Compute
//purpose  : 
//=======================================================================

01398 void BRepOffset_Inter2d::Compute (const Handle(BRepAlgo_AsDes)&   AsDes,
                          const TopoDS_Face&              F,
                          const TopTools_MapOfShape&      NewEdges,
                          const Standard_Real             Tol)
{
#ifdef DEB
  NbF2d++;
  NbE2d = 0;
#endif 

  //Do not intersect the edges of face
  TopTools_MapOfShape EdgesOfFace;
  TopExp_Explorer Explo( F, TopAbs_EDGE );
  for (; Explo.More(); Explo.Next())
    EdgesOfFace.Add( Explo.Current() );

  //-----------------------------------------------------------
  // calcul des intersections2d sur les faces touchees par les 
  // intersection3d
  //---------------------------------------------------------
  TopTools_ListIteratorOfListOfShape it1LE ;    
  TopTools_ListIteratorOfListOfShape it2LE ;  

  //-----------------------------------------------
  // Intersection des edges 2 a 2.
  //-----------------------------------------------
  const TopTools_ListOfShape&        LE = AsDes->Descendant(F);
  TopoDS_Vertex                      V1,V2;
  Standard_Integer                   j, i = 1;

  for ( it1LE.Initialize(LE) ; it1LE.More(); it1LE.Next()) {
    const TopoDS_Edge& E1 = TopoDS::Edge(it1LE.Value());    
    j = 1;
    it2LE.Initialize(LE);
    
    while (j < i && it2LE.More()) {
      const TopoDS_Edge& E2 = TopoDS::Edge(it2LE.Value());
      //--------------------------------------------------------------
      // Intersectionns des Nouvelles edges obtenues par intersection
      // entre elles et avec les edges de restictions
      //------------------------------------------------------
      if ( (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) &&
         (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) {
      TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
      EdgeInter(TopoDS::Face(aLocalShape),E1,E2,AsDes,Tol,Standard_True);
//      EdgeInter(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),E1,E2,AsDes,Tol,Standard_True);
      }
      it2LE.Next();
      j++;
    }
    i++;
  }
}

//=======================================================================
//function : ConnexIntByInt
//purpose  : 
//=======================================================================

//  Modified by skv - Fri Dec 26 16:53:16 2003 OCC4455 Begin
//  Add another parameter: offset value.
void BRepOffset_Inter2d::ConnexIntByInt
(const TopoDS_Face&            FI,
 BRepOffset_Offset&            OFI,
 TopTools_DataMapOfShapeShape& MES,
 const TopTools_DataMapOfShapeShape& Build,
 const Handle(BRepAlgo_AsDes)&     AsDes,
 const Standard_Real           Offset,
 const Standard_Real           Tol)
//  Modified by skv - Fri Dec 26 16:53:18 2003 OCC4455 End
{  

  TopTools_DataMapOfShapeListOfShape MVE;
  BRepOffset_Tool::MapVertexEdges(FI,MVE);

  //---------------------
  // Extension des edges.
  //---------------------
  TopoDS_Edge  NE;
  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it(MVE);
  for  ( ; it.More(); it.Next()) {
    const TopTools_ListOfShape&  L = it.Value();
    Standard_Boolean   YaBuild = 0;
    TopTools_ListIteratorOfListOfShape itL(L);
    for (; itL.More(); itL.Next()) {
      YaBuild = Build.IsBound(itL.Value());
      if (YaBuild) break;
    }
    if (YaBuild) {
      for (itL.Initialize(L); itL.More(); itL.Next()) {
      const TopoDS_Edge& EI = TopoDS::Edge(itL.Value());
      TopoDS_Shape aLocalShape = OFI.Generated(EI);
      const TopoDS_Edge& OE = TopoDS::Edge(aLocalShape);
//    const TopoDS_Edge& OE = TopoDS::Edge(OFI.Generated(EI));
      if (!MES.IsBound(OE) && !Build.IsBound(EI)) {
//  Modified by skv - Fri Dec 26 16:59:52 2003 OCC4455 Begin
//      ExtentEdge(OE,NE);
        ExtentEdge(OE,NE, Offset);
//  Modified by skv - Fri Dec 26 16:59:54 2003 OCC4455 End
        MES.Bind  (OE,NE);
      }
      }
    } 
  }
  
  TopoDS_Face           FIO = TopoDS::Face(OFI.Face());
  if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO));

  TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
  for (; exp.More(); exp.Next()) {
    const TopoDS_Wire&     W = TopoDS::Wire(exp.Current());
    BRepTools_WireExplorer wexp;
    Standard_Boolean       end = Standard_False ;
    TopoDS_Edge            FirstE,CurE,NextE;

    TopoDS_Shape aLocalWire = W .Oriented(TopAbs_FORWARD);
    TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD);
    wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
//    wexp.Init(TopoDS::Wire(W .Oriented(TopAbs_FORWARD)),
//          TopoDS::Face(FI.Oriented(TopAbs_FORWARD)));
    CurE = FirstE  = wexp.Current(); 
    while (!end) {
      wexp.Next();
      if (wexp.More()) {
      NextE = wexp.Current();
      } 
      else {
      NextE = FirstE; end = Standard_True;
      }
      if (CurE.IsSame(NextE)) continue;

      //IFV------------
      TopoDS_Vertex Vref = CommonVertex(CurE, NextE); 
      gp_Pnt Pref = BRep_Tool::Pnt(Vref);
      //IFV------------

      TopoDS_Shape aLocalShape = OFI.Generated(CurE);
      TopoDS_Edge CEO = TopoDS::Edge(aLocalShape);
      aLocalShape = OFI.Generated(NextE);
      TopoDS_Edge NEO = TopoDS::Edge(aLocalShape);
//      TopoDS_Edge CEO = TopoDS::Edge(OFI.Generated(CurE));
//      TopoDS_Edge NEO = TopoDS::Edge(OFI.Generated(NextE));
      //------------------------------------------
      //traitement Inter des images de CurE NextE.
      //------------------------------------------
      TopTools_ListOfShape LV1,LV2;
      Standard_Boolean     DoInter = 1;
      TopoDS_Shape         NE1,NE2;
      
      if (Build.IsBound(CurE) && Build.IsBound(NextE)) {
      NE1 = Build(CurE );
      NE2 = Build(NextE);
      }
      else if (Build.IsBound(CurE) && MES.IsBound(NEO)) {
      NE1 = Build(CurE);
      NE2 = MES  (NEO);
      }
      else if (Build.IsBound(NextE) && MES.IsBound(CEO)) {
      NE1 = Build(NextE);
      NE2 = MES(CEO);
      }
      else {
      DoInter = 0;
      }
      if (DoInter) {
      //------------------------------------
      // NE1,NE2 can be a compound of Edges.
      //------------------------------------
      TopExp_Explorer Exp1,Exp2;
      for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) {
        for (Exp2.Init(NE2,TopAbs_EDGE) ; Exp2.More(); Exp2.Next()) {
          RefEdgeInter(FIO,TopoDS::Edge(Exp1.Current()),TopoDS::Edge(Exp2.Current()),
                  AsDes,Tol,Standard_True/*Standard_False*/, Pref);
        }
      }
      }
      else {
      if (MES.IsBound(CEO)) {
        TopoDS_Vertex  V = CommonVertex(CEO,NEO); 
        UpdateVertex  (V,CEO,TopoDS::Edge(MES(CEO)),Tol);
        AsDes->Add     (MES(CEO),V);
      }
      else if (MES.IsBound(NEO)) {
        TopoDS_Vertex V = CommonVertex(CEO,NEO); 
        UpdateVertex (V,NEO,TopoDS::Edge(MES(NEO)),Tol);
        AsDes->Add    (MES(NEO),V);
      }
      }
      CurE = NextE;
    }
  }
}




Generated by  Doxygen 1.6.0   Back to index