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

Draft_Modification_1.cxx

// File:    Draft_Modification_1.cxx
// Created: Fri Dec  2 17:11:53 1994
// Author:  Jacques GOUSSARD

#include <Draft_Modification.jxx>

#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>

#include <BRepLib_MakeFace.hxx>

#include <TopLoc_Location.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>

#include <Draft_DataMapIteratorOfDataMapOfFaceFaceInfo.hxx>
#include <Draft_DataMapIteratorOfDataMapOfEdgeEdgeInfo.hxx>
#include <Draft_DataMapIteratorOfDataMapOfVertexVertexInfo.hxx>
#include <Draft_FaceInfo.hxx>
#include <Draft_EdgeInfo.hxx>
#include <Draft_VertexInfo.hxx>
#include <BRep_Tool.hxx>
#include <BRep_Tool.hxx>

#include <Geom_Surface.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>


#include <Geom2d_Line.hxx>
#include <Geom_Plane.hxx>
#include <Geom_SurfaceOfLinearExtrusion.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_Parabola.hxx>
#include <Geom_Hyperbola.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <Adaptor3d_SurfaceOfLinearExtrusion.hxx>

#include <gp_Vec.hxx>
#include <gp_Lin.hxx>
#include <gp_Pln.hxx>
#include <gp_Circ.hxx>
#include <gp_Elips.hxx>
#include <gp_Parab.hxx>
#include <gp_Hypr.hxx>

#include <IntCurveSurface_HInter.hxx>
#include <GeomInt_IntSS.hxx>
#include <IntCurveSurface_IntersectionPoint.hxx>
#include <IntAna_QuadQuadGeo.hxx>
#include <IntAna_IntConicQuad.hxx>

#include <Extrema_ExtPC.hxx>
#include <BRepExtrema_ExtPC.hxx>
#include <BRepExtrema_ExtCF.hxx>

#include <Standard_DomainError.hxx>
#include <Standard_Failure.hxx>
#include <Standard_NotImplemented.hxx>

#include <TopTools_MapOfShape.hxx>
#include <TopTools_MapIteratorOfMapOfShape.hxx>

#include <gp.hxx>
#include <Precision.hxx>
#include <ElCLib.hxx>
#include <ElSLib.hxx>
#include <BRepTools.hxx>
#include <TopoDS.hxx>
#include <TopExp.hxx>

#include <GeomAdaptor_HCurve.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>

#include <GeomAPI_ProjectPointOnCurve.hxx>

#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2dConvert.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <Adaptor3d_CurveOnSurface.hxx>

#include <GeomProjLib.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <Geom2d_BezierCurve.hxx>
#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>

#include <Adaptor3d_HCurveOnSurface.hxx>
#include <ProjLib_CompProjectedCurve.hxx>
#include <ProjLib_HCompProjectedCurve.hxx>
#include <Approx_CurveOnSurface.hxx>

#include <GeomConvert_CompCurveToBSplineCurve.hxx>


static Standard_Boolean Choose(const Draft_DataMapOfFaceFaceInfo&,
                         Draft_DataMapOfEdgeEdgeInfo&,
                         const TopoDS_Vertex&,
                         Draft_VertexInfo&,
                         GeomAdaptor_Curve&,
                         GeomAdaptor_Surface&);

static Standard_Real Parameter(const Handle(Geom_Curve)&,
                         const gp_Pnt&,
                         Standard_Integer&);

static Standard_Real SmartParameter(Draft_EdgeInfo&,
                            const Standard_Real EdgeTol,
                            const gp_Pnt&,
                            const Standard_Integer,
                            const Handle(Geom_Surface)&,
                            const Handle(Geom_Surface)&);

static TopAbs_Orientation Orientation(const TopoDS_Shape&,
                              const TopoDS_Face&);

static Standard_Boolean FindRotation(const gp_Pln&,
                             const TopAbs_Orientation,
                             const gp_Dir&,
                             const Standard_Real,
                             const gp_Pln&,
                             gp_Ax1&,
                             Standard_Real&);


//=======================================================================
//function : InternalAdd
//purpose  : 
//=======================================================================

Standard_Boolean Draft_Modification::InternalAdd(const TopoDS_Face& F,
                                     const gp_Dir& Direction,
                                     const Standard_Real Angle,
                                     const gp_Pln& NeutralPlane,
                                     const Standard_Boolean Flag)
{

  if (myFMap.IsBound(F)) {
    return (badShape.IsNull());
  }

  TopAbs_Orientation oris = Orientation(myShape,F);
  TopLoc_Location Lo;
  //gp_Dir NewDirection = Direction;
  //Standard_Real NewAngle = Angle;
  Handle(Geom_Surface) S = BRep_Tool::Surface(F,Lo);
  S = Handle(Geom_Surface)::DownCast(S->Transformed(Lo.Transformation()));
  if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
    S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
  }
  Handle(Geom_Surface) NewS;
  Handle(Geom_Circle) theCircle;

  Standard_Boolean postponed = (Flag == Standard_False);
  if (postponed) {
    Handle(Standard_Type) typS = S->DynamicType();
    if (typS == STANDARD_TYPE(Geom_CylindricalSurface) ||
      typS == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
      gp_Circ Cir;
      if (typS == STANDARD_TYPE(Geom_CylindricalSurface)) {
      gp_Cylinder cyl = 
        Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();
      gp_Ax1 axcyl = cyl.Axis();
      Cir = ElSLib::CylinderVIso( cyl.Position(), cyl.Radius(), 0.);
      gp_Vec VV(cyl.Location(),NeutralPlane.Location());
      Cir.Translate(VV.Dot(axcyl.Direction())*axcyl.Direction());
      }
      else {
      Handle(Geom_Curve) Cbas = 
        Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S)->BasisCurve();
      gp_Dir theDirextr = 
        Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S)->Direction();

      if (Cbas->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
        Cbas = Handle(Geom_TrimmedCurve)::DownCast(Cbas)->BasisCurve();
      }
      if (Cbas->IsKind(STANDARD_TYPE(Geom_Circle))) {
        Cir = Handle(Geom_Circle)::DownCast(Cbas)->Circ();
        gp_Dir dircir = Cir.Axis().Direction();
        if (!Direction.IsParallel(dircir,Precision::Angular())) {
          badShape = F;
          errStat = Draft_FaceRecomputation;
          return Standard_False;
        }
      }
      else {
        badShape = F;
        errStat = Draft_FaceRecomputation;
        return Standard_False;
      }

      gp_Ax3 Axis = NeutralPlane.Position();
      Standard_Real L =
        gp_Vec(Cir.Location(),Axis.Location()).
          Dot(Axis.Direction());
      Standard_Real Cos = theDirextr.Dot(Axis.Direction());
      gp_Vec VV = ( L / Cos) * theDirextr;
      Cir.Translate(VV);
      }

      theCircle = new Geom_Circle(Cir);

    }
    else {
      postponed = Standard_False;
    }
  }


  if (!postponed) {
    NewS = NewSurface(S,oris,Direction,Angle,NeutralPlane); 
    if (NewS.IsNull()) {
      badShape = F;
      errStat = Draft_FaceRecomputation;
      return Standard_False;
    }
    // Pour eviter certains pbs sur restrictions infinies
    const Handle(Standard_Type)& typs = NewS->DynamicType();
    if (typs == STANDARD_TYPE(Geom_CylindricalSurface) ||
      typs == STANDARD_TYPE(Geom_ConicalSurface)) {
      Standard_Real umin,umax,vmin,vmax;
      BRepTools::UVBounds(F,umin,umax,vmin,vmax);
      if (!Precision::IsNegativeInfinite(vmin) &&
        !Precision::IsPositiveInfinite(vmax)) {
      Standard_Real deltav = 10.*(vmax-vmin);
      if(typs == STANDARD_TYPE(Geom_CylindricalSurface)) {
        vmin = vmin - deltav;
        vmax = vmax + deltav;
      }
      else {
        gp_Cone Co = Handle(Geom_ConicalSurface)::DownCast(NewS)->Cone();
        Standard_Real Vapex = - Co.RefRadius()/Sin(Co.SemiAngle());
        if (vmin < Vapex) { // vmax ne doit pas exceder Vapex
          if (vmax + deltav > Vapex) {
            vmax = Vapex;
            vmin = vmin - 10.*(vmax - vmin);
            // JAG debug pour eviter apex
            vmax = vmax-Precision::Confusion();
          }
          else {
            vmin = vmin - deltav;
            vmax = vmax + deltav;
          }
        }
        else { // on a Vapex <= vmin < vmax
          if (vmin - deltav < Vapex) {
            vmin = Vapex;
            vmax = vmax + 10.*(vmax - vmin);
            // JAG debug pour eviter apex
            vmin = vmin+Precision::Confusion();
          }
          else {
            vmin = vmin - deltav;
            vmax = vmax + deltav;
          }
        }
      }
      NewS = new Geom_RectangularTrimmedSurface(NewS,0.,2.*PI,vmin,vmax);
      }
    }
  }

  if (postponed || S != NewS) {
    Draft_FaceInfo FI(NewS,Standard_True);
    FI.RootFace(curFace);
    myFMap.Bind(F,FI);
    if (postponed) {
      myFMap(F).ChangeCurve() = theCircle;
    }
  }    

  TopExp_Explorer expl(F,TopAbs_EDGE);
  TopTools_MapOfShape MapOfE;
  while (expl.More() && badShape.IsNull()) {
    const TopoDS_Edge& edg = TopoDS::Edge(expl.Current());
    if (!myEMap.IsBound(edg)) {
      Standard_Boolean addedg  = Standard_False;
      Standard_Boolean addface = Standard_False;
      TopoDS_Face OtherF;
      //    if (BRep_Tool::IsClosed(edg,F)) {
      if (BRepTools::IsReallyClosed(edg,F)) {
      addedg = Standard_True;
      addface = Standard_False;
      }
      else {
      // Chercher l autre face contenant l edge.
      TopTools_ListIteratorOfListOfShape it;
      it.Initialize(myEFMap.FindFromKey(edg));
      Standard_Integer nbother = 0;
      while (it.More()) {
        if (!it.Value().IsSame(F)) {
          if (OtherF.IsNull()) {
            OtherF = TopoDS::Face(it.Value());
          }
          nbother++;
        }
        it.Next();
      }       
      if (nbother >=2) {
        badShape = edg;
        errStat = Draft_EdgeRecomputation;
      }
      else if (! OtherF.IsNull() && 
             BRep_Tool::Continuity(edg,F,OtherF) >= GeomAbs_G1) {
        addface= Standard_True;
        addedg = Standard_True;
      }
      else if (nbother == 0) { // jag : ajout du 8 Novembre 95 : bord libre
        //      badShape = F;
      }
      }
      if (addedg) {
      if (postponed) {
        myFMap(F).Add(OtherF);
      }
      Standard_Real f,l;
      TopLoc_Location L;
      Handle(Geom_Curve) C = BRep_Tool::Curve(edg,L,f,l);
      C = Handle(Geom_Curve)::DownCast(C->Transformed(L));
      if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
        C = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
      }
        Handle(Geom_Curve) NewC;
      Draft_EdgeInfo EInf(Standard_True); 
        if(postponed) {
        EInf.Add(F);
        EInf.Add(OtherF);

        // recherche du point fixe
        Handle(Geom_Line) aLocalGeom = Handle(Geom_Line)::DownCast(C);
        if (aLocalGeom.IsNull()) {
          badShape = edg;
          errStat = Draft_EdgeRecomputation;
        }
        else {
          gp_Lin lin = aLocalGeom->Lin();
          IntAna_IntConicQuad ilipl(lin,NeutralPlane,Precision::Angular());
          if (ilipl.IsDone() && ilipl.NbPoints() != 0){
            EInf.Tangent(ilipl.Point(1));
          }
          else {
            badShape = edg;
            errStat = Draft_EdgeRecomputation;
          }
        }
      }
        else {
        NewC = NewCurve(C,S,oris,Direction,Angle,NeutralPlane, Flag);
        if (NewC.IsNull()) {
          badShape = edg;
          errStat = Draft_EdgeRecomputation;
        }
      }

      Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(NewC);
      if (!T.IsNull()) NewC = T->BasisCurve();
      EInf.ChangeGeometry() = NewC;

      EInf.RootFace(curFace);
      myEMap.Bind(edg,EInf);
      MapOfE.Add(edg);
      if (addface) {
        Standard_Boolean Fl = Flag;
        Handle(Geom_Surface) alocalSurface = BRep_Tool::Surface(OtherF,Lo);
        if (alocalSurface->DynamicType() == 
            STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
          alocalSurface = Handle(Geom_RectangularTrimmedSurface)::
            DownCast(alocalSurface)->BasisSurface();
        }
        Handle(Standard_Type) typS = alocalSurface->DynamicType();
        if (typS == STANDARD_TYPE(Geom_CylindricalSurface) || 
            typS == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
          if ( myFMap.IsBound(F)) {
            if ( Flag == Standard_False && !postponed) {
            myFMap.UnBind(F);
            TopTools_MapIteratorOfMapOfShape itm(MapOfE);
            for ( ; itm.More(); itm.Next())
              myEMap.UnBind(TopoDS::Edge(itm.Key()));
            }
          }
        } 
        InternalAdd(OtherF,Direction,Angle,NeutralPlane, Fl);
      }
      }
    }
    expl.Next();
  }
  return (badShape.IsNull());
}
    

//=======================================================================
//function : Propagate
//purpose  : 
//=======================================================================

Standard_Boolean Draft_Modification::Propagate ()
{

  if (!badShape.IsNull()) return Standard_False;

  Draft_DataMapIteratorOfDataMapOfFaceFaceInfo itf(myFMap);

  // On met tous les edges et les vertex des faces modifiees
  TopoDS_Face F;
  TopoDS_Edge E;
  TopoDS_Vertex V;
  TopExp_Explorer editer;
  TopExp_Explorer vtiter;

  while (itf.More()) {
    const TopoDS_Face& Fc = itf.Key();

    // Exploration of the edges of the face
    editer.Init(Fc,TopAbs_EDGE);
    while (editer.More()) {
      E = TopoDS::Edge(editer.Current());

      if (!myEMap.IsBound(E)) {
      Draft_EdgeInfo EInf(Standard_True); 
      myEMap.Bind(E,EInf);
      }
      myEMap(E).Add(Fc);

      // Exploration of the vertices of the edge
      vtiter.Init(E,TopAbs_VERTEX);
      while (vtiter.More()) {
      V = TopoDS::Vertex(vtiter.Current());
      if (!myVMap.IsBound(V)) {
        Draft_VertexInfo VInf;
        myVMap.Bind(V,VInf);
      }

      myVMap(V).Add(E);
      myVMap(V).ChangeParameter(E) = BRep_Tool::Parameter(V, E);
      vtiter.Next();
      }
      editer.Next();
    }
    itf.Next();
  }


  TopExp_Explorer anc;
  Standard_Boolean found;

  // On met les edges contenant les vertex modifies.

  Draft_DataMapIteratorOfDataMapOfVertexVertexInfo itv(myVMap);

  while (itv.More()) {
    const TopoDS_Vertex& Vt = itv.Key();

    // Exploration of the ancestors of the vertex
    anc.Init(myShape,TopAbs_EDGE);

    while (anc.More()) {
      E = TopoDS::Edge(anc.Current());
      vtiter.Init(E,TopAbs_VERTEX);
      found = Standard_False;
      while (vtiter.More()) {
      if (Vt.IsSame(TopoDS::Vertex(vtiter.Current()))) {
        found = Standard_True;
        break;
      }
      vtiter.Next();
      }
      if (found) {
      if (!myEMap.IsBound(E)) {
        Draft_EdgeInfo EInf(Standard_False);
        myEMap.Bind(E,EInf);
      }
      myVMap(Vt).Add(E);
      myVMap(Vt).ChangeParameter(E) = BRep_Tool::Parameter(Vt, E);
      }
      anc.Next();
    }
    itv.Next();
  }


  // On met les faces contenant des edges modifiees

  Draft_DataMapIteratorOfDataMapOfEdgeEdgeInfo ite(myEMap);

  while (ite.More()) {
    const TopoDS_Edge& Ed = ite.Key();
    TopTools_ListIteratorOfListOfShape it;
    for (it.Initialize(myEFMap.FindFromKey(Ed)); it.More(); it.Next()) {
      F = TopoDS::Face(it.Value());
      if (!myFMap.IsBound(F)) {
      TopLoc_Location L;
      Handle(Geom_Surface) S = BRep_Tool::Surface(F,L);
      Handle(Geom_Surface) NewS = 
        Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
      
      const Handle(Standard_Type)& typs = S->DynamicType();
      if (typs == STANDARD_TYPE(Geom_CylindricalSurface) ||
          typs == STANDARD_TYPE(Geom_ConicalSurface)) {
        Standard_Real umin,umax,vmin,vmax;
        BRepTools::UVBounds(F,umin,umax,vmin,vmax);
        if (!Precision::IsNegativeInfinite(vmin) &&
            !Precision::IsPositiveInfinite(vmax)) {
          Standard_Real deltav = 10.*(vmax-vmin);
          vmin = vmin - deltav;
          vmax = vmax + deltav;
          NewS = 
            new Geom_RectangularTrimmedSurface(NewS,0.,2.*PI,vmin,vmax);
        }
      }
      
      Draft_FaceInfo FInf(NewS,Standard_False);
      myFMap.Bind(F,FInf);
      }
      myEMap(Ed).Add(F);
    }
    ite.Next();
  }

  // JAG. On essaie de rajouter des faces pour les bords libres...
  // JAG 09.11.95
  ite.Initialize(myEMap);
  for (; ite.More(); ite.Next()) {
    Draft_EdgeInfo& Einf = myEMap(ite.Key());
    if (Einf.NewGeometry() && Einf.Geometry().IsNull() && 
      Einf.SecondFace().IsNull()) {
      
      TopLoc_Location Loc;
      Handle(Geom_Surface) S1 = BRep_Tool::Surface(Einf.FirstFace(),Loc);
      S1 = Handle(Geom_Surface)::
        DownCast(S1->Transformed(Loc.Transformation()));
      Handle(Geom_Surface) S2;
      
      Standard_Real f,l;
      Handle(Geom_Curve) C = BRep_Tool::Curve(ite.Key(),Loc,f,l);
      C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
      if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
      C = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
      }
      if (!S1->IsKind(STANDARD_TYPE(Geom_Plane))) {
      if (C->IsKind(STANDARD_TYPE(Geom_Conic))) {
        gp_Ax3 thePl(Handle(Geom_Conic)::DownCast(C)->Position());
        S2 = new Geom_Plane(thePl);
      }
      else if (C->DynamicType() == STANDARD_TYPE(Geom_Line)) {
        gp_Ax1 axis;
        if (S1->DynamicType()== STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
          axis = Handle(Geom_ElementarySurface)::DownCast
            (Handle(Geom_RectangularTrimmedSurface)::DownCast(S1)->
             BasisSurface())->Axis();
        }
        else {
          axis = Handle(Geom_ElementarySurface)::DownCast(S1)->Axis();
        }
        gp_Vec they(axis.Location(), C->Value(0.));
        gp_Dir axz(axis.Direction().Crossed(they));
        S2=new Geom_Plane(gp_Ax3(axis.Location(),axz,axis.Direction()));

      }
      else {
        badShape = TopoDS::Edge(ite.Key());
        errStat = Draft_EdgeRecomputation;
        break; // on sort du for
      }
      }
      else { // on est sur un plan
      Draft_DataMapIteratorOfDataMapOfVertexVertexInfo anewitv(myVMap);
      while (anewitv.More()) {
        Draft_VertexInfo& Vinf = myVMap(anewitv.Key());
        for (Vinf.InitEdgeIterator();Vinf.MoreEdge();Vinf.NextEdge()) {
          if (Vinf.Edge().IsSame(ite.Key())) {
            break;
          }
        }
        if (Vinf.MoreEdge()) {
          for (Vinf.InitEdgeIterator();Vinf.MoreEdge();Vinf.NextEdge()) {
            const TopoDS_Edge& edg = Vinf.Edge();
            if (!edg.IsSame(ite.Key())) {
            if (!myEMap(edg).FirstFace().IsSame(Einf.FirstFace()) &&
                (myEMap(edg).SecondFace().IsNull() || 
                 !myEMap(edg).SecondFace().IsSame(Einf.FirstFace()))) {
              break;
            }
            }
          }
          if (Vinf.MoreEdge()) {
            Handle(Geom_Curve) C2 = BRep_Tool::Curve(Vinf.Edge(), Loc,f,l);
            Handle(GeomAdaptor_HCurve) HCur;
            gp_Vec Direc;
            C2 = Handle(Geom_Curve)::DownCast
            (C2->Transformed(Loc.Transformation()));
            if (C2->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
            C2 = Handle(Geom_TrimmedCurve)::DownCast(C2)->BasisCurve();
            }
            if (C->DynamicType() == STANDARD_TYPE(Geom_Line)) {
            Direc = Handle(Geom_Line)::DownCast(C)->Lin().Direction();
            HCur = new GeomAdaptor_HCurve(C2);

            }
            else if (C2->DynamicType() == STANDARD_TYPE(Geom_Line)) {
            Direc = Handle(Geom_Line)::DownCast(C2)->Lin().Direction();
            HCur = new GeomAdaptor_HCurve(C);
            }
            else {
            badShape = TopoDS::Edge(ite.Key());
            errStat = Draft_EdgeRecomputation;
            break; // on sort de while
            }
            Adaptor3d_SurfaceOfLinearExtrusion SLE(HCur,Direc);
            switch(SLE.GetType()){

            case GeomAbs_Plane :
            {
              S2 = new Geom_Plane(SLE.Plane());
            }
            break;
            case GeomAbs_Cylinder :
            {
              S2 =   new Geom_CylindricalSurface(SLE.Cylinder());
            }
            break;
            default :
            {
              S2 = new Geom_SurfaceOfLinearExtrusion(HCur->ChangeCurve().
                                           Curve(),
                                           Direc);
            }
            break;
            }
            
          }
          else {
            badShape = TopoDS::Edge(ite.Key());
            errStat = Draft_EdgeRecomputation;
            break; // on sort du while
          }
          break;
        }
        anewitv.Next();
      }
      }

      if (badShape.IsNull()) {
      BRep_Builder B;
      TopoDS_Face TheNewFace;
      B.MakeFace(TheNewFace,S2,Precision::Confusion());
      Einf.Add(TheNewFace);
      Draft_FaceInfo FI(S2,Standard_False);
      myFMap.Bind(TheNewFace,FI);
      }
      else {
      break; // on sort du for
      }
      // Fin JAG 09.11.95
    }
  }
  return (badShape.IsNull());
}




//=======================================================================
//function : Perform
//purpose  : 
//=======================================================================

void Draft_Modification::Perform ()
{
  if (!badShape.IsNull())  Standard_ConstructionError::Raise();

  if (!myComp) {
    myComp = Standard_True;
    if (!Propagate()) {
      return;
    }

    // On calcule les faces eventuelles

    Draft_DataMapIteratorOfDataMapOfFaceFaceInfo itf(myFMap);
    while (itf.More()) {
      Draft_FaceInfo& Finf = myFMap(itf.Key());
      if (Finf.NewGeometry() && Finf.Geometry().IsNull()) {
      const TopoDS_Face& F1 = Finf.FirstFace();
      const TopoDS_Face& F2 = Finf.SecondFace();

      if (F1.IsNull() || F2.IsNull()) {
        errStat = Draft_FaceRecomputation;
        badShape = TopoDS::Face(itf.Key());
        return;
      }
      Handle(Geom_Surface) S1 = myFMap(F1).Geometry();
      Handle(Geom_Surface) S2 = myFMap(F2).Geometry();
      if (S1.IsNull() || S2.IsNull()) {
        errStat = Draft_FaceRecomputation;
        badShape = TopoDS::Face(itf.Key());
        return;
      }
      if (S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
        S1 = Handle(Geom_RectangularTrimmedSurface)::
          DownCast(S1)->BasisSurface();
      }
      if (S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
        S2 = Handle(Geom_RectangularTrimmedSurface)::
          DownCast(S2)->BasisSurface();
      }
      Handle(Geom_Plane) P1 = Handle(Geom_Plane)::DownCast(S1);
      Handle(Geom_Plane) P2 = Handle(Geom_Plane)::DownCast(S2);
      if (P1.IsNull() || P2.IsNull()) {
        errStat = Draft_FaceRecomputation;
        badShape = TopoDS::Face(itf.Key());
        return;
      }
      gp_Pln pp1 = P1->Pln();
      gp_Pln pp2 = P2->Pln();
      IntAna_QuadQuadGeo i2p(pp1,pp2,
                         Precision::Angular(),Precision::Confusion());
      if (!i2p.IsDone() || i2p.TypeInter() != IntAna_Line) {
        errStat = Draft_FaceRecomputation;
        badShape = TopoDS::Face(itf.Key());
        return;
      }

      gp_Dir extrdir = i2p.Line(1).Direction();

      // On garde le meme sens que la face de base
      Handle(Geom_Surface) RefSurf = 
        BRep_Tool::Surface(TopoDS::Face(itf.Key()));
      if (RefSurf->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
        RefSurf = 
          Handle(Geom_RectangularTrimmedSurface)::DownCast(RefSurf)
            ->BasisSurface();
      }
      gp_Dir DirRef;

      if ( RefSurf->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
        gp_Ax3 AxeRef = 
          Handle(Geom_CylindricalSurface)::DownCast(RefSurf)
            ->Cylinder().Position();
        DirRef = AxeRef.Direction();
      }
      else if (RefSurf->DynamicType() == 
             STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
        DirRef = 
          Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(RefSurf)
            ->Direction();
      }
      
      if (extrdir.Dot(DirRef) < 0.) extrdir.Reverse();

      // on peut ameliorer la rapidite en stockant l`info lors de
      // InternalAdd --> modif de FaceInfo pour garder le cercle

      Handle(Geom_Circle) CCir = 
        Handle(Geom_Circle)::DownCast(Finf.Curve());
      Handle(Geom_Surface) NewS = 
        new Geom_SurfaceOfLinearExtrusion(CCir, extrdir);    

      Standard_Real umin, umax, vmin, vmax;
      BRepTools::UVBounds(TopoDS::Face(itf.Key()),umin,umax,vmin,vmax);
      if (!Precision::IsNegativeInfinite(vmin) &&
          !Precision::IsPositiveInfinite(vmax)) {
        Standard_Real deltav = 2.*(vmax-vmin);
        vmin = vmin - deltav;
        vmax = vmax + deltav;
      }

      // tres temporaire
      else {
        vmax = 300;
        vmin = -300;
      }

      NewS = new Geom_RectangularTrimmedSurface(NewS,0.,1.9*PI,vmin,vmax);
      Finf.ChangeGeometry() = NewS;
      }
      itf.Next();
    }
    
    // On calcule les nouveaux edges.

    Handle(Geom_Surface) S1,S2;
    Handle(Geom_Curve) C, newC;
    Standard_Real f,l;
    TopLoc_Location L;
    Draft_DataMapIteratorOfDataMapOfEdgeEdgeInfo ite(myEMap);

    while (ite.More()) {
      Draft_EdgeInfo& Einf = myEMap(ite.Key());

      const TopoDS_Edge& theEdge = TopoDS::Edge(ite.Key());

      C = BRep_Tool::Curve(theEdge,L,f,l);
      C = Handle(Geom_Curve)::DownCast(C->Transformed(L.Transformation()));

      if (Einf.NewGeometry() && Einf.Geometry().IsNull()) {
      gp_Pnt ptfixe;
      if (!Einf.IsTangent(ptfixe)) {
        const TopoDS_Face& FirstFace = Einf.FirstFace();
        const TopoDS_Face& SecondFace = Einf.SecondFace();

        S1 = myFMap(FirstFace).Geometry();
        S2 = myFMap(SecondFace).Geometry();

        Standard_Integer detrompeur = 0;

        // On recupere le FirstVertex et la tangente en ce point.
        TopoDS_Vertex FV = TopExp::FirstVertex(theEdge);
        TopoDS_Vertex LV = TopExp::LastVertex(theEdge);
        Standard_Real pmin = 0.;
        Standard_Real prmfv = BRep_Tool::Parameter(FV,ite.Key());
        Standard_Real prmlv = BRep_Tool::Parameter(LV,ite.Key());
        gp_Pnt pfv, plv;
        gp_Vec d1fv,d1lv, newd1;
        C->D1(prmfv,pfv,d1fv);
        C->D1(prmlv,plv,d1lv);

        Standard_Real TolF1 = BRep_Tool::Tolerance (FirstFace);
        Standard_Real TolF2 = BRep_Tool::Tolerance (SecondFace);

        //On passe la tolerance de la face pour projeter
        GeomAPI_ProjectPointOnSurf proj1 (pfv, S1, TolF1);
        GeomAPI_ProjectPointOnSurf proj2 (plv, S1, TolF1);
        GeomAPI_ProjectPointOnSurf proj3 (pfv, S2, TolF2);
        GeomAPI_ProjectPointOnSurf proj4 (plv, S2, TolF2);

        if (proj1.IsDone () && proj2.IsDone ()) {
          if(proj1.LowerDistance()<= Precision::Confusion() &&
             proj2.LowerDistance()<= Precision::Confusion())  {
            detrompeur = 1;
          }
        }

        if (proj3.IsDone () && proj4.IsDone ()) {
          if(proj3.LowerDistance() <= Precision::Confusion() &&
             proj4.LowerDistance() <= Precision::Confusion())  {
            detrompeur = 2;
          }
        }
        
        gp_Dir TheDirExtr;
        gp_Ax3 Axis;
        Handle(Geom_Curve) TheNewCurve;
        Standard_Boolean KPart = Standard_False;

        if ( S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
          S1 = Handle(Geom_RectangularTrimmedSurface)::
            DownCast(S1)->BasisSurface();
        }
        if ( S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
          S2 = Handle(Geom_RectangularTrimmedSurface)::
            DownCast(S2)->BasisSurface();
        }

        Standard_Boolean PC1 = Standard_True; // KPart sur S1
        if (S1->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) &&
            S2->DynamicType() == STANDARD_TYPE(Geom_Plane) ) {
          KPart = Standard_True;
          Axis = Handle(Geom_Plane)::DownCast(S2)->Position();
          TheNewCurve = Handle(Geom_SurfaceOfLinearExtrusion)::
            DownCast(S1)->BasisCurve();
          TheDirExtr = Handle(Geom_SurfaceOfLinearExtrusion)::
            DownCast(S1)->Direction();
        }
        else if (S2->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) &&
               S1->DynamicType() == STANDARD_TYPE(Geom_Plane) ) {
          KPart = Standard_True;
          PC1 = Standard_False;
          Axis = Handle(Geom_Plane)::DownCast(S1)->Position();
          TheNewCurve = Handle(Geom_SurfaceOfLinearExtrusion)::
            DownCast(S2)->BasisCurve();
          TheDirExtr = Handle(Geom_SurfaceOfLinearExtrusion)::
            DownCast(S2)->Direction();
        }
        Handle(Geom_Circle) aCirc ;
        if ( KPart) {  // TRES Provisoire sur les cercles !!!
          aCirc = Handle(Geom_Circle)::DownCast(TheNewCurve);
          if (aCirc.IsNull())
            KPart = Standard_False;
          else
            {
            gp_Dir AxofCirc = aCirc->Position().Direction();
            if (AxofCirc.IsParallel(Axis.Direction(),Precision::Angular()))
              KPart = Standard_True;
            else
              KPart = Standard_False;
            }
        }

        Standard_Integer imin;
        GeomInt_IntSS i2s;
        if ( KPart) {
          //calcul direct de NewC
          Standard_Real aLocalReal =
            gp_Vec(aCirc->Circ().Location(),Axis.Location()).
            Dot(Axis.Direction());
          Standard_Real Cos = TheDirExtr.Dot(Axis.Direction());
          gp_Vec VV = ( aLocalReal / Cos) * TheDirExtr;
          newC = Handle(Geom_Curve)::DownCast(TheNewCurve->Translated(VV));
          // on sait calculer la PCurve
          Handle(Geom2d_Line) L2d 
            = new Geom2d_Line(gp_Pnt2d(0.,aLocalReal/Cos),
                        gp::DX2d());

          if ( PC1) 
            Einf.ChangeFirstPC() = L2d;
          else
            Einf.ChangeSecondPC() = L2d;
        }
        else {
          S1 = myFMap(Einf.FirstFace()).Geometry();
          S2 = myFMap(Einf.SecondFace()).Geometry();

          // rem : dub 16/09/97
          // On ne calcule plus les PCurves tout de suite et pour 2 raisons:
          // 1 - Si ProjLib doit faire une Approx, c'est idiot d'approximer 
          //     toute la courbe d'intersection.
          // 2 - De plus, si YaRev, on risque de ne plus etre SameRange.
          i2s.Perform(S1,S2,Precision::Confusion(),
                  Standard_True,Standard_False,Standard_False);
          
          if (!i2s.IsDone() || i2s.NbLines() <= 0) {
            errStat = Draft_EdgeRecomputation;
            badShape = TopoDS::Edge(ite.Key());
            return;
          }
          
          Standard_Real Dist, DistMin = 0., GlobMin = RealLast();
          GeomAdaptor_Curve TheCurve;
          
          Standard_Integer i,j; //,jmin;
          
          if (i2s.Line(1)->DynamicType() != STANDARD_TYPE(Geom_BSplineCurve))
            {
            imin = 0;
            for (i=1; i<= i2s.NbLines(); i++) {
              TheCurve.Load(i2s.Line(i));
              Extrema_ExtPC myExtPC(pfv,TheCurve);
              
              Standard_Real locpmin = 0.;
              if (myExtPC.IsDone()) {
                if(myExtPC.NbExt() >= 1) {
                  DistMin = myExtPC.Value(1);
                  locpmin = myExtPC.Point(1).Parameter();
                }
                if(myExtPC.NbExt() == 2 && DistMin > Precision::Confusion()) {  
                  //pour ne pas se tromper dans le choix d'image 
                  //du premier vertex de l'edge initial
                  Standard_Real d1 = myExtPC.Value(1);
                  Standard_Real d2 = myExtPC.Value(2);
                  if(d1 > 1.1*d2) {
                  DistMin = myExtPC.Value(2);
                  locpmin = myExtPC.Point(2).Parameter();
                  }
                  else if(d2 > 1.1*d1) {
                  DistMin = myExtPC.Value(1);
                  locpmin = myExtPC.Point(1).Parameter();
                  }
                  else {
                  Standard_Real pfvpar = myExtPC.Point(1).Parameter();
                  Standard_Real plvpar = myExtPC.Point(2).Parameter();
                  newC = i2s.Line(i);
                  
                  gp_Pnt pfvprim, plvprim;
                  
                  newC->D0(pfvpar,pfvprim);
                  newC->D0(plvpar,plvprim);
                  
                  Handle(Geom_Surface) theSurf;
                  if(detrompeur == 1) {
                    if(S1->DynamicType() == 
                       STANDARD_TYPE(Geom_RectangularTrimmedSurface))  
                      S1 = Handle(Geom_RectangularTrimmedSurface)::
                        DownCast(S1)->BasisSurface();
                    theSurf = S1;
                    
                  }
                  else if(detrompeur == 2) {
                    if(S2->DynamicType() == 
                       STANDARD_TYPE(Geom_RectangularTrimmedSurface)) 
                      S2 = Handle(Geom_RectangularTrimmedSurface)::
                        DownCast(S2)->BasisSurface();
                    theSurf = S2;             
                  }
                  if(detrompeur != 0 && detrompeur != 4) {
                    Standard_Real ul, vl, uf, vf;
                    Standard_Real ufprim, ulprim, vfprim, vlprim;
                    
                    if(theSurf->DynamicType() == STANDARD_TYPE(Geom_Plane)) { 
                      gp_Pln pl = Handle(Geom_Plane)::DownCast(S2)->Pln();
                      ElSLib::Parameters(pl, plv, ul, vl);
                      ElSLib::Parameters(pl, pfv, uf, vf);
                      ElSLib::Parameters(pl, plvprim, ulprim, vlprim);
                      ElSLib::Parameters(pl, pfvprim, ufprim, vfprim);
                    }
                    else if(theSurf->DynamicType() == 
                          STANDARD_TYPE(Geom_CylindricalSurface)) {
                      gp_Cylinder cy = Handle(Geom_CylindricalSurface)
                        ::DownCast(S2)->Cylinder();
                      ElSLib::Parameters(cy, plv, ul, vl);
                      ElSLib::Parameters(cy, pfv, uf, vf);
                      ElSLib::Parameters(cy, plvprim, ulprim, vlprim);
                      ElSLib::Parameters(cy, pfvprim, ufprim, vfprim);
                    }
                    else detrompeur = 4;
                    
                    if(detrompeur == 1 || detrompeur == 2) {
                      gp_Vec2d v1((ul-ufprim), (vl-vfprim));
                      gp_Vec2d norm((vf-vfprim), (ufprim-uf)); 
                      gp_Vec2d v2((ulprim-ufprim), (vlprim-vfprim));
                      if( (v1.Dot(norm))*(v2.Dot(norm)) < 0) {
                        DistMin = myExtPC.Value(2);
                        locpmin = myExtPC.Point(2).Parameter();
                      }
                    }
                  }
                  }
                }
                if (myExtPC.NbExt() == 1 || myExtPC.NbExt() > 2 || detrompeur ==4) {
                  DistMin = myExtPC.Value(1);
                  locpmin = myExtPC.Point(1).Parameter();
                  for (j=2; j<=myExtPC.NbExt(); j++) {
                  Dist = myExtPC.Value(j);
                  if (Dist < DistMin) {
                    DistMin = Dist;
                    locpmin = myExtPC.Point(j).Parameter();
                  }
                  }
                }
                else if(myExtPC.NbExt() < 1){
                  Standard_Real dist1,dist2;
                  gp_Pnt p1b,p2b;
                  myExtPC.TrimmedDistances(dist1,dist2,p1b,p2b);
                  if (dist1 < dist2) {
                  DistMin = dist1;
                  locpmin = TheCurve.FirstParameter();
                  }
                  else {
                  DistMin = dist2;
                  locpmin = TheCurve.LastParameter();
                  }
                }
                
                if (DistMin  < GlobMin) {
                  GlobMin = DistMin;
                  imin = i;
                  pmin = locpmin;
                }
              }
            }
            if (imin == 0) {
              errStat = Draft_EdgeRecomputation;
              badShape = TopoDS::Edge(ite.Key());
              return;
            }
            
            newC = i2s.Line(imin);
            
            newC->D1(pmin,pfv,newd1);
            Standard_Boolean YaRev = d1fv.Dot(newd1) <0.; 
            
            if (YaRev)
              newC->Reverse();
            
            if (i2s.HasLineOnS1(imin)) {
              Einf.ChangeFirstPC() = i2s.LineOnS1(imin);
              if ( YaRev) 
                Einf.ChangeFirstPC()->Reverse();
            }
            
            if (i2s.HasLineOnS2(imin)) {
              Einf.ChangeSecondPC() = i2s.LineOnS2(imin);
              if ( YaRev) 
                Einf.ChangeSecondPC()->Reverse();
            }
            } // if (i2s.Line(1)->DynamicType() != STANDARD_TYPE(Geom_BSplineCurve))
          else // i2s.Line(1) is BSplineCurve
            {
            //Find the first curve to glue
            TColGeom_SequenceOfCurve Candidates;
            if (S1->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface) ||
                S1->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface)) 
              {
                for (i = 1; i <= i2s.NbLines(); i++)
                  {
                  Handle( Geom_Curve ) aCurve = i2s.Line(i);
                  gp_Pnt Pnt = aCurve->Value( aCurve->FirstParameter() );
                  GeomAPI_ProjectPointOnSurf projector( Pnt, S1, Precision::Confusion() );
                  Standard_Real U, V;
                  projector.LowerDistanceParameters( U, V );
                  if (Abs(U) <= Precision::Confusion() || Abs(U-2.*PI) <= Precision::Confusion())
                    Candidates.Append( aCurve );
                  else
                    {
                      Pnt = aCurve->Value( aCurve->LastParameter() );
                      projector.Init( Pnt, S1, Precision::Confusion() );
                      projector.LowerDistanceParameters( U, V );
                      if (Abs(U) <= Precision::Confusion() || Abs(U-2.*PI) <= Precision::Confusion())
                        {
                        aCurve->Reverse();
                        Candidates.Append( aCurve );
                        }
                    }
                  }

                if(Candidates.Length() == 0) 
                  {
//                errStat = Draft_EdgeRecomputation;
//                badShape = TopoDS::Edge(ite.Key());
//                return;
                  for (i = 1; i <= i2s.NbLines(); i++)
                    Candidates.Append( i2s.Line(i) );
                  }
              }
            else 
              {
                for (i = 1; i <= i2s.NbLines(); i++)
                  Candidates.Append( i2s.Line(i) );
              }
            
            Handle( Geom_Curve ) FirstCurve;
            if (Candidates.Length() > 1)
              {
                DistMin = RealLast();
                for (i = 1; i <= Candidates.Length(); i++)
                  {
                  Handle( Geom_Curve ) aCurve = Candidates(i);
                  gp_Pnt Pnt = aCurve->Value( aCurve->FirstParameter() );
                  Dist = Pnt.Distance( pfv );
                  if (Dist < DistMin)
                    {
                      DistMin = Dist;
                      FirstCurve = aCurve;
                    }
                  }
              }
            else
              FirstCurve = Candidates(1);

            //Glueing
            TColGeom_SequenceOfCurve Curves;
            for (i = 1; i <= i2s.NbLines(); i++)
              if (FirstCurve != i2s.Line(i))
                Curves.Append( i2s.Line(i) );

            TColGeom_SequenceOfCurve ToGlue;
            gp_Pnt EndPoint = FirstCurve->Value( FirstCurve->LastParameter() );
            Standard_Boolean added = Standard_True;
            while (added)
              {
                added = Standard_False;
                for (i = 1; i <= Curves.Length(); i++)
                  {
                  Handle( Geom_Curve ) aCurve = Curves(i);
                  gp_Pnt pfirst, plast;
                  pfirst = aCurve->Value( aCurve->FirstParameter() );
                  plast = aCurve->Value( aCurve->LastParameter() );
                  if (pfirst.Distance( EndPoint ) <= Precision::Confusion())
                    {
                      ToGlue.Append( aCurve );
                      EndPoint = plast;
                      Curves.Remove(i);
                      added = Standard_True;
                      break;
                    }
                  if (plast.Distance( EndPoint ) <= Precision::Confusion())
                    {
                      aCurve->Reverse();
                      ToGlue.Append( aCurve );
                      EndPoint = pfirst;
                      Curves.Remove(i);
                      added = Standard_True;
                      break;
                    }
                  }
              }

            if (FirstCurve.IsNull()) {
              errStat = Draft_EdgeRecomputation;
              badShape = TopoDS::Edge(ite.Key());
              return;
            }
            
            GeomConvert_CompCurveToBSplineCurve Concat( Handle(Geom_BSplineCurve)::DownCast(FirstCurve) );
            for (i = 1; i <= ToGlue.Length(); i++)
              Concat.Add( Handle(Geom_BSplineCurve)::DownCast(ToGlue(i)), Precision::Confusion(), Standard_True );

            newC = Concat.BSplineCurve();
            
            TheCurve.Load( newC );
            Extrema_ExtPC myExtPC( pfv, TheCurve );
            DistMin = RealLast();
            for (i = 1; i <= myExtPC.NbExt(); i++)
              {
                Dist = myExtPC.Value(i);
                if (Dist < DistMin)
                  {
                  DistMin = Dist;
                  pmin = myExtPC.Point(i).Parameter();
                  }
              }

            newC->D1(pmin,pfv,newd1);
            Standard_Boolean YaRev = d1fv.Dot(newd1) < 0.; 
            
            if (YaRev)
              newC->Reverse();
            /*
            if (i2s.HasLineOnS1(imin)) {
              Einf.ChangeFirstPC() = i2s.LineOnS1(imin);
              if ( YaRev) 
                Einf.ChangeFirstPC()->Reverse();
            }
            
            if (i2s.HasLineOnS2(imin)) {
              Einf.ChangeSecondPC() = i2s.LineOnS2(imin);
              if ( YaRev) 
                Einf.ChangeSecondPC()->Reverse();
            }
            */
            } // else: i2s.NbLines() > 2 && S1 is Cylinder or Cone
          
          Einf.Tolerance(Max(Einf.Tolerance(), i2s.TolReached3d()));
        }  // Fin pas KPart
      }
      else { // cas de tangence
        const TopoDS_Face& F1 = Einf.FirstFace();
        const TopoDS_Face& F2 = Einf.SecondFace();

        Handle(Geom_Surface) aLocalS1 = myFMap(F1).Geometry();
        Handle(Geom_Surface) aLocalS2 = myFMap(F2).Geometry();
        if (aLocalS1.IsNull() || aLocalS2.IsNull()) {
          errStat = Draft_EdgeRecomputation;
          badShape = TopoDS::Edge(ite.Key());
          return;
        }
        if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
          aLocalS1 = Handle(Geom_RectangularTrimmedSurface)::
          DownCast(aLocalS1)->BasisSurface();
        }
        if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
          aLocalS2 = Handle(Geom_RectangularTrimmedSurface)::
          DownCast(aLocalS2)->BasisSurface();
        }

        gp_Dir dirextr;
        //Standard_Boolean dirfound = Standard_False;
        if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
          gp_Cylinder cyl = 
            Handle(Geom_CylindricalSurface)::DownCast(aLocalS1)->Cylinder();
          dirextr = cyl.Axis().Direction();
          //dirfound = Standard_True;
          // voir sens...

        }
        else if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
          dirextr = Handle(Geom_SurfaceOfLinearExtrusion)::
            DownCast(aLocalS1)->Direction();
          //dirfound = Standard_True;
          // voir sens...

          // Ici on sait calculer la PCurve.
          Handle(Geom_SurfaceOfLinearExtrusion) SEL = 
            Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aLocalS1);
          Handle(Geom_Circle) GCir = 
            Handle(Geom_Circle)::DownCast(SEL->BasisCurve());
          if ( !GCir.IsNull()) {
            Standard_Real U = ElCLib::Parameter(GCir->Circ(),ptfixe);
            Handle(Geom2d_Line) PC1 = 
            new Geom2d_Line(gp_Pnt2d(U,0.),gp::DY2d());
            Einf.ChangeFirstPC() = PC1;
          }
        }

        else if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
          gp_Cylinder cyl = 
            Handle(Geom_CylindricalSurface)::DownCast(aLocalS2)->Cylinder();
          dirextr = cyl.Axis().Direction();
          //dirfound = Standard_True;
          // voir sens...

        }
        else if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
          dirextr = Handle(Geom_SurfaceOfLinearExtrusion)::
            DownCast(aLocalS2)->Direction();
          //dirfound = Standard_True;
          // voir sens...

          // Ici on sait calculer la PCurve.
          Handle(Geom_SurfaceOfLinearExtrusion) SEL = 
            Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aLocalS2);
          Handle(Geom_Circle) GCir = 
            Handle(Geom_Circle)::DownCast(SEL->BasisCurve());
          if ( !GCir.IsNull()) {
            Standard_Real U = ElCLib::Parameter(GCir->Circ(),ptfixe);
            Handle(Geom2d_Line) PC2 = 
            new Geom2d_Line(gp_Pnt2d(U,0.),gp::DY2d());
            Einf.ChangeSecondPC() = PC2;
          }
        }
        newC = new Geom_Line(ptfixe,dirextr);

        gp_Pnt pfv;
        gp_Vec d1fv,newd1;
        C->D1(0.,pfv,d1fv);
        newC->D1(0.,pfv,newd1);
        Standard_Boolean YaRev = d1fv.Dot(newd1) <0.; 
        if (YaRev) {
          newC->Reverse();
          if(!Einf.FirstPC().IsNull()) {
            Einf.ChangeFirstPC()->Reverse();
          }
          if(!Einf.SecondPC().IsNull()) {
            Einf.ChangeSecondPC()->Reverse();
          }
        }
      }

      Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(newC);
      if (!T.IsNull()) newC = T->BasisCurve();
      Einf.ChangeGeometry() = newC;
      }
      else if (!Einf.NewGeometry()){
      // on met la courbe 3d existante
      Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(C);
      if (!T.IsNull()) C = T->BasisCurve();
      Einf.ChangeGeometry() = C;
      }
      ite.Next();
    }

    // On calcule les nouveaux vertex.

    Draft_DataMapIteratorOfDataMapOfVertexVertexInfo itv(myVMap);

    Handle(GeomAdaptor_HCurve)   HAC = new GeomAdaptor_HCurve;
    Handle(GeomAdaptor_HSurface) HAS = new GeomAdaptor_HSurface;
    
    while (itv.More()) {
      GeomAdaptor_Curve    AC;
      GeomAdaptor_Surface  AS;

      Draft_VertexInfo& Vinf = myVMap(itv.Key());
      if (!Choose(myFMap,myEMap,itv.Key(),Vinf,AC,AS)) {

// pas d'edge concourante => alignement de deux edges consecutives.
      gp_Pnt pvt;
      Vinf.ChangeGeometry() = pvt;
      Vinf.InitEdgeIterator();
      if (Vinf.MoreEdge()) {
        const TopoDS_Edge& Edg1 = Vinf.Edge();
        //const Draft_EdgeInfo& Einf1 = myEMap(Edg1);
        Draft_EdgeInfo& Einf1 = myEMap(Edg1);
        gp_Pnt vtori = BRep_Tool::Pnt(itv.Key());
        //Einf1.Geometry()->D0(Vinf.Parameter(Edg1), pvt);
        GeomAPI_ProjectPointOnCurve Projector( vtori, Einf1.Geometry() ); //patch
        pvt = Projector.NearestPoint();

#ifdef DEB
        static Standard_Integer VertexRecomp = 1;
        if (VertexRecomp!=0) {
          cout << "pori :" << vtori.X() << " " << vtori.Y() << " " << vtori.Z() << endl;
          cout << "  Edg 1 :" << Vinf.Parameter(Edg1) << endl;
          cout << "pvt :" << pvt.X() << " " << pvt.Y() << " " << pvt.Z() << endl;
        }
#endif

        Standard_Real dion=pvt.SquareDistance(vtori);
        Vinf.NextEdge();
        if (Vinf.MoreEdge()) {
          const TopoDS_Edge& Edg2 = Vinf.Edge();
          //const Draft_EdgeInfo& Einf2 = myEMap(Edg2);
          Draft_EdgeInfo& Einf2 = myEMap(Edg2);
//        Standard_Real f;
          gp_Pnt opvt;
          Einf2.Geometry()->D0(Vinf.Parameter(Edg2), opvt);

#ifdef DEB
        if (VertexRecomp!=0) {
          cout << "  Edg 2 :" << Vinf.Parameter(Vinf.Edge()) << endl;
          cout << "opvt " << opvt.X() << " " << opvt.Y() << " " << opvt.Z() << endl;
        }
#endif

          if (opvt.SquareDistance(vtori) < dion) {
            pvt = opvt;
          }
          //Vinf.ChangeParameter(Edg2) = Parameter(Einf2.Geometry(), pvt);
          Standard_Integer done;
          Standard_Real param = Parameter(Einf2.Geometry(), pvt, done);
          if (done != 0)
            {
            S1 = myFMap(Einf2.FirstFace()).Geometry();
            S2 = myFMap(Einf2.SecondFace()).Geometry();
            Vinf.ChangeParameter(Edg2) = SmartParameter( Einf2, BRep_Tool::Tolerance(Edg2), pvt, done, S1, S2 );
            }
          else
            Vinf.ChangeParameter(Edg2) = param;
        }

        Vinf.ChangeGeometry() = pvt;
        //Vinf.ChangeParameter(Edg1) = Parameter(Einf1.Geometry(), pvt);
        Standard_Integer done;
        Standard_Real param = Parameter(Einf1.Geometry(), pvt, done);
        if (done != 0)
          {
            S1 = myFMap(Einf1.FirstFace()).Geometry();
            S2 = myFMap(Einf1.SecondFace()).Geometry();
            Vinf.ChangeParameter(Edg1) = SmartParameter( Einf1, BRep_Tool::Tolerance(Edg1), pvt, done, S1, S2 );
          }
        else
          Vinf.ChangeParameter(Edg1) = param;
        itv.Next();
        continue;
      }


      errStat = Draft_VertexRecomputation;
      badShape = TopoDS::Vertex(itv.Key());
      return;
      }

      IntCurveSurface_HInter myintcs;
      HAC->Set(AC);
      HAS->Set(AS);
      myintcs.Perform(HAC,HAS);

      if (!myintcs.IsDone()) {
      errStat = Draft_VertexRecomputation;
      badShape = TopoDS::Vertex(itv.Key());
      return;
      }

      gp_Pnt vtori = BRep_Tool::Pnt(itv.Key());
      gp_Pnt pvt;

      Standard_Integer nbsol = myintcs.NbPoints();
      if (nbsol <= 0)
      {
        Extrema_ExtCS extr( AC, AS, Precision::PConfusion(), Precision::PConfusion() );

        if(!extr.IsDone() || extr.NbExt() == 0) {
          errStat = Draft_VertexRecomputation;
          badShape = TopoDS::Vertex(itv.Key());
          return;
        }
          

        Standard_Real disref = RealLast();
        Standard_Integer iref = 0;
        Extrema_POnCurv Pc;
        Extrema_POnSurf Ps;
        for (Standard_Integer i = 1; i <= extr.NbExt(); i++)
          {
            extr.Points( i, Pc, Ps );
            Standard_Real distemp = Pc.Value().SquareDistance(vtori);
            if ( distemp < disref)
            {
              disref = distemp;
              iref = i;
            }
          } 
        extr.Points( iref, Pc, Ps );
        pvt = Pc.Value();
      }
      else
      {
        Standard_Real disref = RealLast();
        Standard_Integer iref = 0;
        for (Standard_Integer i = 1; i <= nbsol; i++)
          {
            Standard_Real distemp = myintcs.Point(i).Pnt().SquareDistance(vtori);
            if ( distemp < disref)
            {
              disref = distemp;
              iref = i;
            }
          } 
        pvt = myintcs.Point(iref).Pnt();
      }
        
      Vinf.ChangeGeometry() = pvt;

      for (Vinf.InitEdgeIterator();Vinf.MoreEdge(); Vinf.NextEdge()) {
      const TopoDS_Edge& Edg = Vinf.Edge();
      //const Draft_EdgeInfo& Einf = myEMap(Edg);
      Draft_EdgeInfo& Einf = myEMap(Edg);
      //Vinf.ChangeParameter(Edg) = Parameter(Einf.Geometry(),pvt);
      Standard_Integer done;
      Standard_Real param = Parameter(Einf.Geometry(), pvt, done);
      if (done != 0)
        {
          S1 = myFMap(Einf.FirstFace()).Geometry();
          S2 = myFMap(Einf.SecondFace()).Geometry();
          Vinf.ChangeParameter(Edg) = SmartParameter( Einf, BRep_Tool::Tolerance(Edg), pvt, done, S1, S2 );
        }
      else
        Vinf.ChangeParameter(Edg) = param;
      }
      itv.Next();
    }
  }

  // petite boucle de validation/protection

  for (Draft_DataMapIteratorOfDataMapOfEdgeEdgeInfo ite(myEMap);
       ite.More(); ite.Next()) {
    const TopoDS_Edge& edg = TopoDS::Edge(ite.Key());

    TopoDS_Vertex Vf,Vl;
    TopExp::Vertices(edg,Vf,Vl);
    if (edg.Orientation() == TopAbs_REVERSED) {
      Vf.Reverse();
      Vl.Reverse();
    }
    Standard_Real pf,pl,tolerance;
    if (!NewParameter(Vf,edg,pf,tolerance)) {
      pf = BRep_Tool::Parameter(Vf,edg);
    }
    if (!NewParameter(Vl,edg,pl,tolerance)) {
      pl = BRep_Tool::Parameter(Vl,edg);
    }
    if (pl <= pf) {
//      const Handle(Geom_Curve) gc=ite.Value().Geometry();
//      if (!gc.IsNull()) {
//    pl = gc->LastParameter();
//    pf = gc->FirstParameter();
//      }
      Handle( Geom_Curve ) theCurve = myEMap(edg).Geometry();
      if (theCurve->IsClosed())
      {
        // pf >= pl
        Standard_Real FirstPar = theCurve->FirstParameter(), LastPar = theCurve->LastParameter();
        Standard_Real pconf = Precision::PConfusion();
        if (Abs( pf - LastPar ) <= pconf)
          pf = FirstPar;
        else if (Abs( pl - FirstPar ) <= pconf)
          pl = LastPar;

        if(pl <= pf) {
          pl += (LastPar-FirstPar);
        }

      }
      if (pl <= pf) {
      errStat = Draft_EdgeRecomputation;
      badShape = TopoDS::Edge(ite.Key());
      return;
      }
    }
    if (myVMap.IsBound( Vf ))
      myVMap(Vf).ChangeParameter(edg) = pf;
    if (myVMap.IsBound( Vl ))
      myVMap(Vl).ChangeParameter(edg) = pl;
  }
}



//=======================================================================
//function : NewSurface
//purpose  : 
//=======================================================================

Handle(Geom_Surface) Draft_Modification::NewSurface
  (const Handle(Geom_Surface)& S,
   const TopAbs_Orientation Oris,
   const gp_Dir& Direction,
   const Standard_Real Angle,
   const gp_Pln& NeutralPlane) 
{
  Handle(Geom_Surface) NewS;

  Handle(Standard_Type) TypeS = S->DynamicType();

  if (TypeS == STANDARD_TYPE(Geom_Plane)) {
    gp_Pln Pl = Handle(Geom_Plane)::DownCast(S)->Pln();
    gp_Ax1 Axe;
    Standard_Real Theta;
    if (FindRotation(Pl,Oris,Direction,Angle,NeutralPlane,Axe,Theta)) {
      if ( Abs(Theta) > Precision::Angular()) {
      NewS = Handle(Geom_Surface)::DownCast(S->Rotated(Axe,Theta));
      }
      else {
      NewS = S;
      }
    }
  }
  else if (TypeS == STANDARD_TYPE(Geom_CylindricalSurface)) {
    Standard_Real testdir = Direction.Dot(NeutralPlane.Axis().Direction());
    if (Abs(testdir) <= 1.-Precision::Angular()) {    
#ifdef DEB
    cout << "NewSurfaceCyl:Draft_Direction_and_Neutral_Perpendicular" << endl;
#endif
      return NewS;      
    }   
    gp_Cylinder Cy = Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();     
    testdir = Direction.Dot(Cy.Axis().Direction());
    if (Abs(testdir) <= 1.-Precision::Angular()) {
#ifdef DEB
    cout << "NewSurfaceCyl:Draft_Direction_and_Cylinder_Perpendicular" << endl;
#endif
      return NewS;
    }
    if (Abs(Angle) > Precision::Angular()) {
      IntAna_QuadQuadGeo i2s;
      i2s.Perform(NeutralPlane,Cy,Precision::Angular(),Precision::Confusion());
      if (!i2s.IsDone() || i2s.TypeInter() != IntAna_Circle) {
#ifdef DEB
    cout << "NewSurfaceCyl:Draft_Intersection_Neutral_Cylinder_NotDone" << endl;
#endif
      return NewS;
      } 
      gp_Ax3 axcone = Cy.Position();
      // Pb : Ou est la matiere???
      Standard_Real alpha = Angle;
      Standard_Boolean direct(axcone.Direct());
      if ((direct && Oris == TopAbs_REVERSED) ||
        (!direct && Oris == TopAbs_FORWARD)) {
      alpha = -alpha;
      }
      
      gp_Pnt Center = i2s.Circle(1).Location();
      if (testdir <0.) {
      alpha = -alpha;
      }
      Standard_Real Z = ElCLib::LineParameter(Cy.Axis(),Center);
      Standard_Real Rad = Cy.Radius()+Z*Tan(alpha);
      if (Rad < 0.) {
      Rad = -Rad;
      }
      else {
      alpha = -alpha;
      }
      gp_Cone co(axcone,alpha,Rad);
      NewS = new Geom_ConicalSurface(co);
    }
    else {
      NewS = S;
    }
  }
  else if (TypeS == STANDARD_TYPE(Geom_ConicalSurface)) {
    
    Standard_Real testdir = Direction.Dot(NeutralPlane.Axis().Direction());
    if (Abs(testdir) <= 1.-Precision::Angular()) {    
#ifdef DEB
    cout << "NewSurfaceCone:Draft_Direction_and_Neutral_Perpendicular" << endl;
#endif
      return NewS;      
    } 
    
    gp_Cone Co1 = Handle(Geom_ConicalSurface)::DownCast(S)->Cone();
    
    testdir = Direction.Dot(Co1.Axis().Direction());
    if (Abs(testdir) <= 1.-Precision::Angular()) {
#ifdef DEB
    cout << "NewSurfaceCone:Draft_Direction_and_Cone_Perpendicular" << endl;
#endif
      return NewS;
    }


    IntAna_QuadQuadGeo i2s;
    i2s.Perform(NeutralPlane,Co1,Precision::Angular(),Precision::Confusion());
    if (!i2s.IsDone() || i2s.TypeInter() != IntAna_Circle) {
#ifdef DEB
    cout << "NewSurfaceCone:Draft_Intersection_Neutral_Conical_NotDone" << endl;
#endif
      return NewS;
    }
    gp_Ax3 axcone = Co1.Position();
    // Pb : Ou est la matiere???
    Standard_Real alpha = Angle;
    Standard_Boolean direct(axcone.Direct());
    if ((direct && Oris == TopAbs_REVERSED) ||
      (!direct && Oris == TopAbs_FORWARD)) {
      alpha = -alpha;
    }

    gp_Pnt Center = i2s.Circle(1).Location();
    if (Abs(Angle) > Precision::Angular()) {
      if (testdir <0.) {
        alpha = -alpha;
      }
      Standard_Real Z = ElCLib::LineParameter(Co1.Axis(),Center);
      Standard_Real Rad = i2s.Circle(1).Radius()+Z*Tan(alpha);
      if (Rad < 0.) {
        Rad = -Rad;
      }
      else {
        alpha = -alpha;
      }
      if (Abs(alpha-Co1.SemiAngle()) < Precision::Angular()) {
        NewS = S;
      }
      else {
        gp_Cone co(axcone,alpha,Rad);
        NewS = new Geom_ConicalSurface(co);
      }
    }
    else {
      NewS = new
      Geom_CylindricalSurface(gp_Cylinder(axcone,i2s.Circle(1).Radius()));
    }
  }
  else {
#ifdef DEB
    cout << "NewSurface:Draft_SurfNotYetImplemented" << endl;
#endif
  }
  return NewS;
} 


//=======================================================================
//function : NewCurve
//purpose  : 
//=======================================================================

Handle(Geom_Curve) Draft_Modification::NewCurve
  (const Handle(Geom_Curve)& C,
   const Handle(Geom_Surface)& S,
   const TopAbs_Orientation Oris,
   const gp_Dir& Direction,
   const Standard_Real Angle,
   const gp_Pln& NeutralPlane,
   const Standard_Boolean )

{
  Handle(Geom_Curve) NewC;

  Handle(Standard_Type) TypeS = S->DynamicType();

  if (TypeS == STANDARD_TYPE(Geom_Plane)) {
    gp_Pln Pl = Handle(Geom_Plane)::DownCast(S)->Pln();
    gp_Ax1 Axe;
    Standard_Real Theta;
    if (FindRotation(Pl,Oris,Direction,Angle,NeutralPlane,Axe,Theta)) {
      if ( Abs(Theta) > Precision::Angular()) {
      NewC = Handle(Geom_Curve)::DownCast(C->Rotated(Axe,Theta));
      }
      else {
      NewC = C;
      }
    }
    return NewC;
  }


  if (C->DynamicType() != STANDARD_TYPE(Geom_Line)) {
    return NewC;
  }


  gp_Lin lin = Handle(Geom_Line)::DownCast(C)->Lin();
//  Standard_Real testdir = Direction.Dot(lin.Direction());
//  if (Abs(testdir) <= 1.-Precision::Angular()) {
//    return NewC;
//  }
  gp_Dir Norm;
  if (TypeS == STANDARD_TYPE(Geom_CylindricalSurface)) {
    Standard_Real U,V;
    gp_Vec d1u,d1v;
    gp_Pnt pbid;
    gp_Cylinder Cy = Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();
    ElSLib::Parameters(Cy,lin.Location(),U,V);
    ElSLib::D1(U,V,Cy,pbid,d1u,d1v);
    Norm = d1u.Crossed(d1v);
  }
  else if (TypeS == STANDARD_TYPE(Geom_ConicalSurface)) {
    Standard_Real U,V;
    gp_Vec d1u,d1v;
    gp_Pnt pbid;
    gp_Cone Co = Handle(Geom_ConicalSurface)::DownCast(S)->Cone();
    ElSLib::Parameters(Co,lin.Location(),U,V);
    ElSLib::D1(U,V,Co,pbid,d1u,d1v);
    Norm = d1u.Crossed(d1v);
  }

  IntAna_IntConicQuad ilipl(lin,NeutralPlane,Precision::Angular());
  if (ilipl.IsDone() && ilipl.NbPoints() != 0){
    if (Oris == TopAbs_REVERSED) {
      Norm.Reverse();
    }
    gp_Ax1 axrot(ilipl.Point(1), Norm.Crossed(Direction));
    gp_Lin lires = gp_Lin(gp_Ax1(ilipl.Point(1),Direction)).
      Rotated(axrot,Angle);
    if (lires.Direction().Dot(lin.Direction()) < 0.) {
      lires.Reverse();
    }
    NewC = new Geom_Line(lires);
  }
  return NewC;
}


//=======================================================================
//function : Choose
//purpose  : 
//=======================================================================

static Standard_Boolean Choose(const Draft_DataMapOfFaceFaceInfo& theFMap,
                         Draft_DataMapOfEdgeEdgeInfo& theEMap,
                         const TopoDS_Vertex& Vtx,
                         Draft_VertexInfo& Vinf,
                         GeomAdaptor_Curve& AC,
                         GeomAdaptor_Surface& AS)
{
  gp_Vec tgref; 
  Vinf.InitEdgeIterator();

  // On cherche un edge de regularite ou dont SecondFace est nulle
  while (Vinf.MoreEdge()) {
    const TopoDS_Edge& E1 = Vinf.Edge();
    const Draft_EdgeInfo& Einf1 = theEMap(E1);
    if (Einf1.SecondFace().IsNull()) {
      break;
    }
    else {
      GeomAbs_Shape te = BRep_Tool::Continuity(E1,Einf1.FirstFace(),
                                        Einf1.SecondFace());
      if (te >= GeomAbs_G1) {
      break;
      }
    }
    Vinf.NextEdge();
  }
  if (!Vinf.MoreEdge()) { // on prend le premier edge
    Vinf.InitEdgeIterator();
  }

  const TopoDS_Edge& Eref = Vinf.Edge();
  //const Draft_EdgeInfo& Einf = theEMap(Eref);
  Draft_EdgeInfo& Einf = theEMap(Eref);

  AC.Load(Einf.Geometry());

  Standard_Real f,l,prm;
  TopLoc_Location Loc;
  Handle(Geom_Curve) C = BRep_Tool::Curve(Eref,Loc,f,l);
  C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
  gp_Pnt ptbid;
  //prm = Parameter(C,BRep_Tool::Pnt(Vtx));
  Standard_Integer done;
  Standard_Real param = Parameter( C, BRep_Tool::Pnt(Vtx), done );
  if (done != 0)
    {
      Handle( Geom_Surface ) S1 = theFMap(Einf.FirstFace()).Geometry();
      Handle( Geom_Surface ) S2 = theFMap(Einf.SecondFace()).Geometry();
      prm = SmartParameter( Einf, BRep_Tool::Tolerance(Eref), BRep_Tool::Pnt(Vtx), done, S1, S2 );
    }
  else
    prm = param;
  C->D1(prm,ptbid,tgref);


  Vinf.InitEdgeIterator();
  while (Vinf.MoreEdge()) {
    // On cherche un edge non tangent
    const TopoDS_Edge& Edg = Vinf.Edge();
    if (!Edg.IsSame(Eref)) {
      //const Draft_EdgeInfo& Einfo = theEMap(Edg);
      Draft_EdgeInfo& Einfo = theEMap(Edg);
      if (!Einfo.SecondFace().IsNull() &&
        BRep_Tool::Continuity(Edg,Einfo.FirstFace(),Einfo.SecondFace()) 
        <= GeomAbs_C0) {
      C = BRep_Tool::Curve(Edg,Loc,f,l);
      C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
      //prm = Parameter(C,BRep_Tool::Pnt(Vtx));
      Standard_Integer anewdone;
      Standard_Real anewparam = Parameter( C, BRep_Tool::Pnt(Vtx), anewdone );
      if (anewdone != 0)
        {
          Handle( Geom_Surface ) S1 = theFMap(Einfo.FirstFace()).Geometry();
          Handle( Geom_Surface ) S2 = theFMap(Einfo.SecondFace()).Geometry();
          prm = SmartParameter( Einfo, BRep_Tool::Tolerance(Edg), BRep_Tool::Pnt(Vtx), anewdone, S1, S2 );
        }
      else
        prm = anewparam;
      gp_Vec tg;
      C->D1(prm,ptbid,tg);
      if (tg.CrossMagnitude(tgref) > Precision::Confusion()) {
        break;
      }
      }
    }
    Vinf.NextEdge();
  }
  if (!Vinf.MoreEdge()) {
    return Standard_False;
  }

  const Draft_EdgeInfo& Einf2 = theEMap(Vinf.Edge());
  if (!Einf.SecondFace().IsNull()) {

    if (Einf2.FirstFace().IsSame(Einf.FirstFace()) ||
      Einf2.FirstFace().IsSame(Einf.SecondFace())) {
      AS.Load(theFMap(Einf2.SecondFace()).Geometry());
    }
    else {
      AS.Load(theFMap(Einf2.FirstFace()).Geometry());
    }
  }
  else {
    if (Einf2.FirstFace().IsSame(Einf.FirstFace())) {
      AS.Load(theFMap(Einf2.SecondFace()).Geometry());
    }
    else {
      AS.Load(theFMap(Einf2.FirstFace()).Geometry());
    }
  }
  return Standard_True;
}


//=======================================================================
//function : Parameter
//purpose  : 
//=======================================================================

static Standard_Real Parameter(const Handle(Geom_Curve)& C,
                         const gp_Pnt& P,
                         Standard_Integer& done)
{
  done = 0;
  Handle(Geom_Curve) cbase = C;
  Handle(Standard_Type) ctyp = C->DynamicType();
  if (ctyp == STANDARD_TYPE(Geom_TrimmedCurve)) {
    cbase = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
    ctyp = cbase->DynamicType();
  }
  Standard_Real param;
  if (ctyp == STANDARD_TYPE(Geom_Line)) {
    param = ElCLib::Parameter(Handle(Geom_Line)::DownCast(cbase)->Lin(),P);
  }
  else if (ctyp == STANDARD_TYPE(Geom_Circle)) {
    param = ElCLib::Parameter(Handle(Geom_Circle)::DownCast(cbase)->Circ(),P);
    if (Abs(2.*PI-param) <=Epsilon(2.*PI)) {
      param = 0.;
    }
  }
  else if (ctyp == STANDARD_TYPE(Geom_Ellipse)) {
    param = ElCLib::Parameter(Handle(Geom_Ellipse)::DownCast(cbase)->Elips(),P);
    if (Abs(2.*PI-param) <=Epsilon(2.*PI)) {
      param = 0.;
    }
  }
  else if (ctyp == STANDARD_TYPE(Geom_Parabola)) {
    param = ElCLib::Parameter(Handle(Geom_Parabola)::DownCast(cbase)->Parab(),P);
  }
  else if (ctyp == STANDARD_TYPE(Geom_Hyperbola)) {
    param = ElCLib::Parameter(Handle(Geom_Hyperbola)::DownCast(cbase)->Hypr(),P);
  }
  else {
    GeomAdaptor_Curve TheCurve(C);
    Extrema_ExtPC myExtPC(P,TheCurve);
    if (!myExtPC.IsDone()) {
      Standard_Failure::Raise();
    }
    if (myExtPC.NbExt() >= 1) {
      Standard_Real Dist, DistMin = myExtPC.Value(1);
      Standard_Integer j, jmin = 1;
      for (j = 2; j <= myExtPC.NbExt(); j++) {
        Dist = myExtPC.Value(j);
        if (Dist < DistMin) {
          DistMin = Dist;
          jmin = j;
        }
      }
      param = myExtPC.Point(jmin).Parameter();
    }
    else {
      Standard_Real dist1,dist2;
      gp_Pnt p1b,p2b;
      myExtPC.TrimmedDistances(dist1,dist2,p1b,p2b);
      if (dist1 < dist2) {
      done = -1;
        param = TheCurve.FirstParameter();
      }
      else {
      done = 1;
        param = TheCurve.LastParameter();
      }
    }

    if (cbase->IsPeriodic()) {
      Standard_Real Per  = cbase->Period();
      Standard_Real Tolp = Precision::Parametric(Precision::Confusion());  
      if (Abs(Per-param) <= Tolp) {
      param = 0.;
      }
    }
  }
  return param;
}

//=======================================================================
//function : SmartParameter
//purpose  : 
//=======================================================================

static Standard_Real SmartParameter(Draft_EdgeInfo& Einf,
                            const Standard_Real EdgeTol,
                            const gp_Pnt& Pnt,
                            const Standard_Integer sign,
                            const Handle(Geom_Surface)& S1,
                            const Handle(Geom_Surface)& S2)
{
  Handle( Geom2d_Curve ) NewC2d;
  Standard_Real Tol = Precision::Confusion();
  Standard_Real Etol = EdgeTol;

  Handle( Geom2d_Curve ) pcu1 = Einf.FirstPC();
  Handle( Geom2d_Curve ) pcu2 = Einf.SecondPC();

  if (pcu1.IsNull())
    {
      Handle( Geom_Curve ) theCurve = Einf.Geometry();
      pcu1 = GeomProjLib::Curve2d( theCurve, theCurve->FirstParameter(), theCurve->LastParameter(), S1, Etol );
      Einf.ChangeFirstPC() = pcu1;
    }
  if (pcu2.IsNull())
    {
      Handle( Geom_Curve ) theCurve = Einf.Geometry();
      pcu2 = GeomProjLib::Curve2d( theCurve, theCurve->FirstParameter(), theCurve->LastParameter(), S2, Etol );
      Einf.ChangeSecondPC() = pcu2;
    }

  GeomAPI_ProjectPointOnSurf Projector( Pnt, S1 );
  Standard_Real U, V;
  Projector.LowerDistanceParameters( U, V );
  
  NewC2d = Einf.FirstPC();
  if (NewC2d->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
    NewC2d = (Handle(Geom2d_TrimmedCurve)::DownCast(NewC2d))->BasisCurve();
  
  gp_Pnt2d P2d( U, V );
  Geom2dAPI_ProjectPointOnCurve Projector2d( P2d, NewC2d );
  if (Projector2d.NbPoints() == 0 || Projector2d.LowerDistance() > Tol)
    {
      Handle( Geom2d_BSplineCurve ) BCurve;
      if (NewC2d->DynamicType() != STANDARD_TYPE(Geom2d_BSplineCurve))
      BCurve = Geom2dConvert::CurveToBSplineCurve( NewC2d );
      else
      BCurve = Handle( Geom2d_BSplineCurve )::DownCast( NewC2d );
      if (sign == -1)
      {
        TColgp_Array1OfPnt2d PntArray( 1, 2 );
        PntArray(1) = P2d;
        PntArray(2) = BCurve->Pole(1);
        Handle( Geom2d_BezierCurve ) Patch = new Geom2d_BezierCurve( PntArray );
        Geom2dConvert_CompCurveToBSplineCurve Concat( BCurve, Convert_QuasiAngular );
        Concat.Add( Patch, Tol, Standard_False );
        BCurve = Concat.BSplineCurve();
      }
      else
      {
        TColgp_Array1OfPnt2d PntArray( 1, 2 );
        PntArray(1) = BCurve->Pole( BCurve->NbPoles() );
        PntArray(2) = P2d;
        Handle( Geom2d_BezierCurve ) Patch = new Geom2d_BezierCurve( PntArray );
        Geom2dConvert_CompCurveToBSplineCurve Concat( BCurve, Convert_QuasiAngular );
        Concat.Add( Patch, Tol, Standard_True );
        BCurve = Concat.BSplineCurve();
      }
      NewC2d = BCurve;
    }
  Einf.ChangeFirstPC() = NewC2d;
  Handle( Geom2dAdaptor_HCurve ) hcur = new Geom2dAdaptor_HCurve( NewC2d );
  Handle( GeomAdaptor_HSurface ) hsur = new GeomAdaptor_HSurface( S1 );
  Adaptor3d_CurveOnSurface cons( hcur, hsur );
  Handle( Adaptor3d_HCurveOnSurface ) hcons = new Adaptor3d_HCurveOnSurface( cons );
  Handle( GeomAdaptor_HSurface ) hsur2 = new GeomAdaptor_HSurface( S2 );
  ProjLib_CompProjectedCurve ProjCurve( hsur2, hcons, Tol, Tol );
  Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve();
  HProjector->Set( ProjCurve );
  Standard_Real Udeb, Ufin;
  ProjCurve.Bounds(1, Udeb, Ufin);
  Standard_Integer MaxSeg = 20 + HProjector->NbIntervals(GeomAbs_C3);
  Approx_CurveOnSurface appr( HProjector, hsur2, Udeb, Ufin, Tol,
                        GeomAbs_C1, 10, MaxSeg, 
                        Standard_False, Standard_False );
  Einf.ChangeSecondPC() = appr.Curve2d();
  Einf.ChangeGeometry() = appr.Curve3d();
  Einf.SetNewGeometry( Standard_True );

  if (sign == -1)
    return Einf.Geometry()->FirstParameter();
  else
    return Einf.Geometry()->LastParameter();

}

//=======================================================================
//function : Orientation
//purpose  : 
//=======================================================================

static TopAbs_Orientation Orientation(const TopoDS_Shape& S,
                              const TopoDS_Face& F)
{
//
// changement portage NT
//
  TopExp_Explorer expl ;
  expl.Init(S,
          TopAbs_FACE) ;
  while (expl.More()) {
    if (TopoDS::Face(expl.Current()).IsSame(F)) {
      return expl.Current().Orientation();
    }
    expl.Next();
  }
  return TopAbs_FORWARD;
}


//=======================================================================
//function : FindRotation
//purpose  : 
//=======================================================================

static Standard_Boolean FindRotation(const gp_Pln& Pl,
                             const TopAbs_Orientation Oris,
                             const gp_Dir& Direction,
                             const Standard_Real Angle,
                             const gp_Pln& NeutralPlane,
                             gp_Ax1& Axe,
                             Standard_Real& theta)
{                            
  IntAna_QuadQuadGeo i2pl(Pl,NeutralPlane,
                    Precision::Angular(),Precision::Confusion());
  
  if (i2pl.IsDone() && i2pl.TypeInter() == IntAna_Line) {
    gp_Lin li = i2pl.Line(1);
    // On va essayer de tourner autour de cette ligne
    gp_Dir nx = li.Direction();
    gp_Dir ny = Pl.Axis().Direction().Crossed(nx);
    Standard_Real a = Direction.Dot(nx);
    if (Abs(a) <=1-Precision::Angular()) { 
      Standard_Real b = Direction.Dot(ny);
      Standard_Real c = Direction.Dot(Pl.Axis().Direction());
      Standard_Boolean direct(Pl.Position().Direct());
      if ((direct && Oris == TopAbs_REVERSED) ||
        (!direct && Oris == TopAbs_FORWARD)) {
      b = -b;
      c = -c;
      }
      Standard_Real denom = Sqrt(1-a*a);
      Standard_Real Sina = Sin(Angle);
      if (denom>Abs(Sina)) {
      Standard_Real phi = ATan2(b/denom,c/denom);
      Standard_Real theta0 = ACos(Sina/denom); 
      theta = theta0 - phi;
      if (Cos(theta) <0.) {
        theta = -theta0 -phi;
      }
      //  modified by NIZHNY-EAP Tue Nov 16 15:51:38 1999 ___BEGIN___
      while (Abs(theta)>PI) {
        theta = theta + PI*(theta<0 ? 1 : -1);
      }
      //  modified by NIZHNY-EAP Tue Nov 16 15:53:32 1999 ___END___
      Axe = li.Position();
      return Standard_True;
      }
    }
  }
  return Standard_False;
}


Generated by  Doxygen 1.6.0   Back to index