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

BRepLib.cxx

// File:    BRepLib.cxx
// Created: Wed Dec 15 17:53:58 1993
// Author:  Remi LEQUETTE
//          <rle@zerox>

// History: pmn 26/09/97 Ajout des parametres d'approx dans BuildCurve3d
//  Modified by skv - Thu Jun  3 12:39:19 2004 OCC5898

#include <BRepLib.ixx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <BRepAdaptor_HCurve2d.hxx>
#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
#include <Geom_Surface.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_Plane.hxx>
#include <Geom_Curve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <GeomLib.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopExp.hxx>
#include <gp.hxx>
#include <gp_Ax2.hxx>
#include <gp_Pln.hxx>
#include <Standard_Real.hxx>
#include <Precision.hxx>
#include <BRep_GCurve.hxx>
#include <BRep_TEdge.hxx>
#include <BRep_TFace.hxx>
#include <AppParCurves_MultiCurve.hxx>
#include <AppParCurves_MultiBSpCurve.hxx>
#include <BRep_ListOfCurveRepresentation.hxx>
#include <BRep_CurveRepresentation.hxx>
#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
#include <BRep_TVertex.hxx>
#include <AdvApprox_ApproxAFunction.hxx>
#include <Approx_SameParameter.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_MapOfTransient.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_HCurve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <Geom2dAdaptor.hxx>
#include <Geom2dConvert.hxx>
#include <GCPnts_QuasiUniformDeflection.hxx>
#include <BSplCLib.hxx>
#include <ElSLib.hxx>
#include <Adaptor3d_CurveOnSurface.hxx>
#include <Extrema_LocateExtPC.hxx>
#include <ProjLib_ProjectedCurve.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <Approx_CurvilinearParameter.hxx>
#include <Geom_BSplineSurface.hxx>

//
//  comme on ne pas patcher en cdl GEOMLITE temporairement les GeomLib_ migrent
//  dans BRepLib ...
//

static Standard_Real thePrecision = Precision::Confusion();     
static Handle(Geom_Plane) thePlane;

//=======================================================================
//function : Precision
//purpose  : 
//=======================================================================

00087 void BRepLib::Precision(const Standard_Real P)
{
  thePrecision = P;
}

//=======================================================================
//function : Precision
//purpose  : 
//=======================================================================

00097 Standard_Real  BRepLib::Precision()
{
  return thePrecision;
}

//=======================================================================
//function : Plane
//purpose  : 
//=======================================================================

00107 void  BRepLib::Plane(const Handle(Geom_Plane)& P)
{
  thePlane = P;
}


//=======================================================================
//function : Plane
//purpose  : 
//=======================================================================

const Handle(Geom_Plane)&  BRepLib::Plane()
{
  if (thePlane.IsNull()) thePlane = new Geom_Plane(gp::XOY());
  return thePlane;
}
//=======================================================================
//function : CheckSameRange
//purpose  : 
//=======================================================================

00128 Standard_Boolean  BRepLib::CheckSameRange(const TopoDS_Edge& AnEdge,
                                const Standard_Real Tolerance) 
{
  Standard_Boolean  IsSameRange = Standard_True,
  first_time_in = Standard_True ;

  BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
    ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
  
  Standard_Real first, last;
#ifndef DEB
  Standard_Real current_first =0., current_last =0. ;
#else
  Standard_Real current_first,current_last ;
#endif
  Handle(BRep_GCurve) geometric_representation_ptr ;

  while (IsSameRange && an_Iterator.More()) {
    geometric_representation_ptr =
      Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
    if (!geometric_representation_ptr.IsNull()) {
      
        first = geometric_representation_ptr->First();
        last =  geometric_representation_ptr->Last();
        if (first_time_in ) {
        current_first = first ;
        current_last = last   ;
        first_time_in = Standard_False ;
      }
        else {
        IsSameRange = (Abs(current_first - first) <= Tolerance) 
          && (Abs(current_last -last) <= Tolerance ) ;
      }
      }
    an_Iterator.Next() ;
  }
  return IsSameRange ;
}
  
//=======================================================================
//function : SameRange
//purpose  : 
//=======================================================================

00172 void BRepLib::SameRange(const TopoDS_Edge& AnEdge,
                  const Standard_Real Tolerance) 
{
  BRep_ListIteratorOfListOfCurveRepresentation an_Iterator
    ((*((Handle(BRep_TEdge)*)&AnEdge.TShape()))->ChangeCurves());
  
  Handle(Geom2d_Curve) Curve2dPtr, Curve2dPtr2, NewCurve2dPtr, NewCurve2dPtr2;
  TopLoc_Location LocalLoc ;

  Standard_Boolean first_time_in = Standard_True,
  has_curve,
  has_closed_curve ;
  Handle(BRep_GCurve) geometric_representation_ptr ;
  Standard_Real first,
  current_first,
  last,
  current_last ;

  const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,
                                    LocalLoc,
                                    current_first,
                                    current_last);
  if (!C.IsNull()) {
    first_time_in = Standard_False ;
  }
  
  while (an_Iterator.More()) {
    geometric_representation_ptr =
      Handle(BRep_GCurve)::DownCast(an_Iterator.Value());
    if (! geometric_representation_ptr.IsNull()) {
      has_closed_curve =
      has_curve = Standard_False ;
      first = geometric_representation_ptr->First();
      last =  geometric_representation_ptr->Last();
      if (geometric_representation_ptr->IsCurveOnSurface()) {
      Curve2dPtr = geometric_representation_ptr->PCurve() ; 
      has_curve = Standard_True ;
      }
      if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
      Curve2dPtr2 = geometric_representation_ptr->PCurve2() ;
      has_closed_curve = Standard_True ;
      }
      if (has_curve || has_closed_curve) {
      if (first_time_in) {
        current_first = first ;
        current_last = last ;
        first_time_in = Standard_False ;
        }
      
        if (Abs(first - current_first) > Precision::Confusion() ||
          Abs(last - current_last) > Precision::Confusion() )
        {
          if (has_curve)
            {
            GeomLib::SameRange(Tolerance,
                           Curve2dPtr,
                           geometric_representation_ptr->First(),
                           geometric_representation_ptr->Last(),
                           current_first,
                           current_last,
                           NewCurve2dPtr);
            geometric_representation_ptr->PCurve(NewCurve2dPtr) ;
            }
          if (has_closed_curve)
            {
            GeomLib::SameRange(Tolerance,
                           Curve2dPtr2,
                           geometric_representation_ptr->First(),
                           geometric_representation_ptr->Last(),
                           current_first,
                           current_last,
                           NewCurve2dPtr2);
              geometric_representation_ptr->PCurve2(NewCurve2dPtr2) ;
            }
        }
      }
    }
    an_Iterator.Next() ;
  }
  BRep_Builder B;
  B.Range(TopoDS::Edge(AnEdge),
        current_first,
        current_last) ;

  B.SameRange(AnEdge,
            Standard_True) ;
}

//=======================================================================
//function : EvaluateMaxSegment
//purpose  : return MaxSegment to pass in approximation, if MaxSegment==0 provided
//=======================================================================

static Standard_Integer evaluateMaxSegment(const Standard_Integer aMaxSegment,
                                 const Adaptor3d_CurveOnSurface& aCurveOnSurface)
{
  if (aMaxSegment != 0) return aMaxSegment;

  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 : BuildCurve3d
//purpose  : 
//=======================================================================

00291 Standard_Boolean  BRepLib::BuildCurve3d(const TopoDS_Edge& AnEdge,
                              const Standard_Real Tolerance,
                              const GeomAbs_Shape Continuity,
                              const Standard_Integer MaxDegree,
                              const Standard_Integer MaxSegment)
{
  Standard_Integer //ErrorCode,
//                   ReturnCode = 0,
                   ii,
//                   num_knots,
                   jj;

  TopLoc_Location LocalLoc,L[2],LC;
  Standard_Real f,l,fc,lc, first[2], last[2],
  tolerance,
  max_deviation,
  average_deviation ;
  Handle(Geom2d_Curve) Curve2dPtr, Curve2dArray[2]  ;
  Handle(Geom_Surface) SurfacePtr, SurfaceArray[2]  ;

  Standard_Integer not_done ;
  // if the edge has a 3d curve returns true


  const Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,LocalLoc,f,l);
  if (!C.IsNull()) 
    return Standard_True;
//
// this should not exists but UpdateEdge makes funny things 
// if the edge is not same range 
//
  if (! CheckSameRange(AnEdge,
                   Precision::Confusion())) {
    SameRange(AnEdge,
            Tolerance) ;
  }

    

  // search a curve on a plane
  Handle(Geom_Surface) S;
  Handle(Geom2d_Curve) PC;
  Standard_Integer i = 0;
  Handle(Geom_Plane) P;
  not_done = 1 ;

  while (not_done) {
    i++;
    BRep_Tool::CurveOnSurface(AnEdge,PC,S,LocalLoc,f,l,i);
    Handle(Geom_RectangularTrimmedSurface) RT = 
      Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
    if ( RT.IsNull()) {
      P = Handle(Geom_Plane)::DownCast(S);
    }
    else {
      P = Handle(Geom_Plane)::DownCast(RT->BasisSurface());
    }
    not_done = ! (S.IsNull() || !P.IsNull()) ;
  }
  if (! P.IsNull()) {
    // compute the 3d curve
    gp_Ax2 axes = P->Position().Ax2();
    Handle(Geom_Curve) C3d = GeomLib::To3d(axes,PC);

    // update the edge
    Standard_Real First, Last;

    BRep_Builder B;
    Standard_Boolean is_closed ;
     is_closed = AnEdge.Closed() ;
    
    B.UpdateEdge(AnEdge,C3d,LocalLoc,0.0e0);
    BRep_Tool::Range(AnEdge, S, LC, First, Last);
    B.Range(AnEdge, First, Last); //Ne pas oublier le range du 3d.(PRO6412)
    TopoDS_Edge E = AnEdge ;
    E.Closed(is_closed) ;

  }
  else {
    //
    // compute the 3d curve using existing surface
    //
    fc = f ;
    lc = l ;
    if (!BRep_Tool::Degenerated(AnEdge)) {
      jj = 0 ;
      for (ii = 0 ; ii < 3 ; ii++ ) {
      BRep_Tool::CurveOnSurface(TopoDS::Edge(AnEdge),
                          Curve2dPtr,
                          SurfacePtr,
                          LocalLoc,
                          fc,
                          lc,
                                  ii) ;
      
      if (!Curve2dPtr.IsNull() && jj < 2){
        Curve2dArray[jj] = Curve2dPtr ;
        SurfaceArray[jj] = SurfacePtr ;
        L[jj] = LocalLoc ;
        first[jj] = fc ;
        last[jj] = lc ;
        jj += 1 ;
      }
      }
      f = first[0] ;
      l = last[0] ;
      Curve2dPtr = Curve2dArray[0] ;
      SurfacePtr = SurfaceArray[0] ;
      
      Geom2dAdaptor_Curve     AnAdaptor3dCurve2d (Curve2dPtr, f, l) ;
      GeomAdaptor_Surface     AnAdaptor3dSurface (SurfacePtr) ;
      Handle(Geom2dAdaptor_HCurve) AnAdaptor3dCurve2dPtr =
      new Geom2dAdaptor_HCurve(AnAdaptor3dCurve2d) ;
      Handle(GeomAdaptor_HSurface) AnAdaptor3dSurfacePtr =
      new GeomAdaptor_HSurface (AnAdaptor3dSurface) ;
      Adaptor3d_CurveOnSurface  CurveOnSurface( AnAdaptor3dCurve2dPtr,
                                   AnAdaptor3dSurfacePtr) ;
      
      Handle(Geom_Curve) NewCurvePtr ;

      GeomLib::BuildCurve3d(Tolerance,
                      CurveOnSurface,
                      f,
                      l,
                      NewCurvePtr,
                      max_deviation,
                      average_deviation,
                      Continuity,
                      MaxDegree,
                      evaluateMaxSegment(MaxSegment,CurveOnSurface)) ;
      BRep_Builder B;   
      tolerance = BRep_Tool::Tolerance(AnEdge) ;
      //Patch
      //max_deviation = Max(tolerance, max_deviation) ;
      max_deviation = Max( tolerance, Tolerance );

      Standard_Boolean is_closed ;
      is_closed = AnEdge.Closed() ;
      B.UpdateEdge(TopoDS::Edge(AnEdge),
               NewCurvePtr,
               L[0],
               max_deviation) ;
      TopoDS_Edge  E = AnEdge ;
      E.Closed(is_closed) ;
      if (jj == 1 ) {
//
// if there is only one curve on surface attached to the edge
// than it can be qualified sameparameter
//
      B.SameParameter(TopoDS::Edge(AnEdge),
                  Standard_True) ;
      }
    }
    else {
      return Standard_False ;
    }
      
  }         
  return Standard_True;
}
//=======================================================================
//function : BuildCurves3d
//purpose  : 
//=======================================================================

00456 Standard_Boolean  BRepLib::BuildCurves3d(const TopoDS_Shape& S) 

{
  return BRepLib::BuildCurves3d(S,
                        1.0e-5) ;
}

//=======================================================================
//function : BuildCurves3d
//purpose  : 
//=======================================================================

00468 Standard_Boolean  BRepLib::BuildCurves3d(const TopoDS_Shape& S,
                               const Standard_Real Tolerance,
                               const GeomAbs_Shape Continuity,
                               const Standard_Integer MaxDegree,
                               const Standard_Integer MaxSegment)
{
  Standard_Boolean boolean_value,
  ok = Standard_True;
  TopTools_MapOfShape a_counter ;
  TopExp_Explorer ex(S,TopAbs_EDGE);

  while (ex.More()) {
    if (a_counter.Add(ex.Current())) {
      boolean_value = 
      BuildCurve3d(TopoDS::Edge(ex.Current()),
                 Tolerance, Continuity,
                 MaxDegree, MaxSegment);
      ok = ok && boolean_value ;
    }
    ex.Next();
  }
  return ok;
}
//=======================================================================
//function : UpdateEdgeTolerance
//purpose  : 
//=======================================================================

Standard_Boolean  BRepLib::UpdateEdgeTol(const TopoDS_Edge& AnEdge,
                               const Standard_Real MinToleranceRequested,
                               const Standard_Real MaxToleranceToCheck)
  {
    
    Standard_Integer curve_on_surface_index,
      curve_index,
      not_done,
      has_closed_curve,
      has_curve,
      jj,
      ii,
      geom_reference_curve_flag = 0,
      max_sampling_points = 90,
      min_sampling_points = 30 ;
    
    Standard_Real factor = 100.0e0,
 //     sampling_array[2],
      safe_factor = 1.4e0,
      current_last,
      current_first,
      max_distance,
      coded_edge_tolerance,
      edge_tolerance = 0.0e0 ;
    Handle(TColStd_HArray1OfReal) parameters_ptr ;
    Handle(BRep_GCurve) geometric_representation_ptr ;

    if (BRep_Tool::Degenerated(AnEdge)) return Standard_False ;
    coded_edge_tolerance = BRep_Tool::Tolerance(AnEdge) ;
    if (coded_edge_tolerance > MaxToleranceToCheck) return Standard_False ;

    const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&AnEdge.TShape());
    BRep_ListOfCurveRepresentation& list_curve_rep = TE->ChangeCurves() ;
    BRep_ListIteratorOfListOfCurveRepresentation an_iterator(list_curve_rep),
      second_iterator(list_curve_rep) ;
    Handle(Geom2d_Curve) curve2d_ptr, new_curve2d_ptr;
    Handle(Geom_Surface) surface_ptr ;
    TopLoc_Location local_location ;
    GCPnts_QuasiUniformDeflection  a_sampler ;
    GeomAdaptor_Curve  geom_reference_curve ;
    Adaptor3d_CurveOnSurface  curve_on_surface_reference ; 
    Handle(Geom_Curve) C = BRep_Tool::Curve(AnEdge,
                                  local_location,
                                  current_first,
                                  current_last);
    curve_on_surface_index = -1 ;
    if (!C.IsNull()) {
      if (! local_location.IsIdentity()) {
      C = Handle(Geom_Curve)::
        DownCast(C-> Transformed(local_location.Transformation()) ) ;
      }
      geom_reference_curve.Load(C) ;
      geom_reference_curve_flag = 1 ;
            a_sampler.Initialize(geom_reference_curve,
                     MinToleranceRequested * factor,
                     current_first,
                     current_last) ;
    }
    else {
      not_done = 1 ;
      curve_on_surface_index = 0 ;  

      while (not_done && an_iterator.More()) {
      geometric_representation_ptr =
        Handle(BRep_GCurve)::DownCast(second_iterator.Value());
      if (!geometric_representation_ptr.IsNull() 
          && geometric_representation_ptr->IsCurveOnSurface()) {
        curve2d_ptr = geometric_representation_ptr->PCurve() ;
        local_location = geometric_representation_ptr->Location() ;
        current_first = geometric_representation_ptr->First();
        //first = geometric_representation_ptr->First();
        current_last =  geometric_representation_ptr->Last();
        // must be inverted 
        //
        if (! local_location.IsIdentity() ) {
          surface_ptr = Handle(Geom_Surface)::
            DownCast( geometric_representation_ptr->Surface()->
                  Transformed(local_location.Transformation()) ) ;
        }
        else {
          surface_ptr = 
            geometric_representation_ptr->Surface() ;
        }
        not_done = 0 ;
      }
      curve_on_surface_index += 1 ;
      }
      Geom2dAdaptor_Curve     AnAdaptor3dCurve2d (curve2d_ptr) ;
      GeomAdaptor_Surface     AnAdaptor3dSurface (surface_ptr) ;
      Handle(Geom2dAdaptor_HCurve) AnAdaptor3dCurve2dPtr =
      new Geom2dAdaptor_HCurve(AnAdaptor3dCurve2d) ;
      Handle(GeomAdaptor_HSurface) AnAdaptor3dSurfacePtr =
      new GeomAdaptor_HSurface (AnAdaptor3dSurface) ;
      curve_on_surface_reference.Load( AnAdaptor3dCurve2dPtr) ;
      curve_on_surface_reference.Load( AnAdaptor3dSurfacePtr) ;
            a_sampler.Initialize(curve_on_surface_reference,
                     MinToleranceRequested * factor,
                     current_first,
                     current_last) ;
    }
    TColStd_Array1OfReal   sampling_parameters(1,a_sampler.NbPoints()) ;
    for (ii = 1 ; ii <= a_sampler.NbPoints() ; ii++) {
      sampling_parameters(ii) = a_sampler.Parameter(ii) ;
    }
    if (a_sampler.NbPoints() < min_sampling_points) {
      GeomLib::DensifyArray1OfReal(min_sampling_points,
                          sampling_parameters,
                          parameters_ptr) ;
    }
    else if (a_sampler.NbPoints() > max_sampling_points) {
      GeomLib::RemovePointsFromArray(max_sampling_points,
                            sampling_parameters,
                            parameters_ptr) ; 
    }
    else {
      jj = 1 ;
      parameters_ptr =
      new TColStd_HArray1OfReal(1,sampling_parameters.Length()) ;
      for (ii = sampling_parameters.Lower() ; ii <= sampling_parameters.Upper() ; ii++) {
      parameters_ptr->ChangeArray1()(jj) =
        sampling_parameters(ii) ;
      jj +=1 ;
      }
    }
       
    curve_index = 0 ;

    while (second_iterator.More()) {
      geometric_representation_ptr =
      Handle(BRep_GCurve)::DownCast(second_iterator.Value());
      if (! geometric_representation_ptr.IsNull() && 
        curve_index != curve_on_surface_index) {
      has_closed_curve =
        has_curve = Standard_False ;
//    first = geometric_representation_ptr->First();
//    last =  geometric_representation_ptr->Last();
      local_location = geometric_representation_ptr->Location() ;
      if (geometric_representation_ptr->IsCurveOnSurface()) {
        curve2d_ptr = geometric_representation_ptr->PCurve() ; 
        has_curve = Standard_True ;
      }
      if (geometric_representation_ptr->IsCurveOnClosedSurface()) {
        curve2d_ptr = geometric_representation_ptr->PCurve2() ;
        has_closed_curve = Standard_True ;
      }
      
      if (has_curve ||
          has_closed_curve) {
        if (! local_location.IsIdentity() ) {
          surface_ptr = Handle(Geom_Surface)::
            DownCast( geometric_representation_ptr->Surface()->
                  Transformed(local_location.Transformation()) ) ;
        }
        else {
          surface_ptr = 
            geometric_representation_ptr->Surface() ;
        }
        Geom2dAdaptor_Curve     an_adaptor_curve2d (curve2d_ptr) ;
        GeomAdaptor_Surface     an_adaptor_surface(surface_ptr) ;
        Handle(Geom2dAdaptor_HCurve) an_adaptor_curve2d_ptr =
          new Geom2dAdaptor_HCurve(an_adaptor_curve2d) ;
        Handle(GeomAdaptor_HSurface) an_adaptor_surface_ptr =
          new GeomAdaptor_HSurface (an_adaptor_surface) ;
        Adaptor3d_CurveOnSurface a_curve_on_surface(an_adaptor_curve2d_ptr,
                                        an_adaptor_surface_ptr) ;
      
        if (BRep_Tool::SameParameter(AnEdge)) {
          
          GeomLib::EvalMaxParametricDistance(a_curve_on_surface,
                                     geom_reference_curve,
                                     MinToleranceRequested,
                                     parameters_ptr->Array1(),
                                     max_distance) ;
        }
        else if (geom_reference_curve_flag) {
          GeomLib::EvalMaxDistanceAlongParameter(a_curve_on_surface,
                                       geom_reference_curve,
                                       MinToleranceRequested,
                                       parameters_ptr->Array1(),
                                       max_distance) ;
        }
        else {
          
          GeomLib::EvalMaxDistanceAlongParameter(a_curve_on_surface,
                                       curve_on_surface_reference,
                                       MinToleranceRequested,
                                       parameters_ptr->Array1(),
                                       max_distance) ;
        }
        max_distance *= safe_factor ;
        edge_tolerance = Max(max_distance, edge_tolerance) ;
      }
      

      }
      curve_index += 1 ;
      second_iterator.Next() ; 
    }
    
    TE->Tolerance(edge_tolerance);
    return Standard_True ;
    
  }
//=======================================================================
//function : UpdateEdgeTolerance
//purpose  : 
//=======================================================================

Standard_Boolean BRepLib::UpdateEdgeTolerance(const TopoDS_Shape& S,
                                    const Standard_Real MinToleranceRequested,
                                    const Standard_Real MaxToleranceToCheck) 
{
  TopExp_Explorer ex(S,TopAbs_EDGE);
  TopTools_MapOfShape  a_counter ;

  Standard_Boolean     return_status = Standard_False,
    local_flag ;

  while (ex.More()) {
    if (a_counter.Add(ex.Current())) {
      local_flag =
      BRepLib::UpdateEdgeTol(TopoDS::Edge(ex.Current()),
                         MinToleranceRequested,
                         MaxToleranceToCheck) ;
      if (local_flag && ! return_status) {
      return_status = Standard_True ;
      }
    }
    ex.Next();
  }
  return return_status ;
}

//=======================================================================
//function : SetEdgeTol
//purpose  : 
//=======================================================================

static void SetEdgeTol(const TopoDS_Edge& E,
                   const TopoDS_Face& F)
{
  TopLoc_Location L;
  const Handle(Geom_Surface)& S = BRep_Tool::Surface(F,L);
  TopLoc_Location l = L.Predivided(E.Location());

  const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
  BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->ChangeCurves());

  while (itcr.More()) {
    const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
    if(cr->IsCurveOnSurface(S,l)) return;
    itcr.Next();
  }

  Handle(Geom_Plane) GP;
  Handle(Geom_RectangularTrimmedSurface) GRTS;
  GRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
  if(!GRTS.IsNull())
    GP = Handle(Geom_Plane)::DownCast(GRTS->BasisSurface());
  else
    GP = Handle(Geom_Plane)::DownCast(S);

  static Handle(GeomAdaptor_HCurve) HC;
  static Handle(GeomAdaptor_HSurface) HS;
  if (HC.IsNull()) {
    HC = new GeomAdaptor_HCurve();
    HS = new GeomAdaptor_HSurface();
  }
  
  TopLoc_Location LC;
  Standard_Real First, Last;
  GeomAdaptor_Curve& GAC = HC->ChangeCurve();
  GAC.Load(BRep_Tool::Curve(E,LC,First,Last));
  LC = L.Predivided(LC);

  if (!LC.IsIdentity()) {
    GP = Handle(Geom_Plane)::DownCast(
       GP->Transformed(LC.Transformation()));
  }
  GeomAdaptor_Surface& GAS = HS->ChangeSurface();
  GAS.Load(GP);
    
  ProjLib_ProjectedCurve Proj(HS,HC);
  Handle(Geom2d_Curve) pc = Geom2dAdaptor::MakeCurve(Proj);

  gp_Pln pln = GAS.Plane();
  Standard_Real d2 = 0.;
  Standard_Integer nn = 23;
  Standard_Real unsurnn = 1./nn;
  for(Standard_Integer i = 0; i <= nn; i++){
    Standard_Real t = unsurnn*i;
    Standard_Real u = First*(1.-t) + Last*t;
    gp_Pnt Pc3d = HC->Value(u);
    gp_Pnt2d p2d = pc->Value(u);
    gp_Pnt Pcons = ElSLib::Value(p2d.X(),p2d.Y(),pln);
    Standard_Real temp = Pc3d.SquareDistance(Pcons);
    if(temp > d2) d2 = temp;
  }
  d2 = 1.5*sqrt(d2);
  TE->UpdateTolerance(d2);
}

//=======================================================================
//function : SameParameter
//purpose  : 
//=======================================================================
00802 void  BRepLib::SameParameter(const TopoDS_Shape& S,
                       const Standard_Real Tolerance,
                       const Standard_Boolean forced) 
{
  TopExp_Explorer ex(S,TopAbs_EDGE);
  TopTools_MapOfShape  Done;
  BRep_Builder brB;

  while (ex.More()) {
    if (Done.Add(ex.Current())) {
      if (forced) {
      brB.SameRange(TopoDS::Edge(ex.Current()), Standard_False);
      brB.SameParameter(TopoDS::Edge(ex.Current()), Standard_False);
      }
      BRepLib::SameParameter(TopoDS::Edge(ex.Current()),Tolerance);
    }
    ex.Next();
  }

  Done.Clear();
  BRepAdaptor_Surface BS;
  for(ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()){
    const TopoDS_Face& curface = TopoDS::Face(ex.Current());
    if(!Done.Add(curface)) continue;
    BS.Initialize(curface);
    if(BS.GetType() != GeomAbs_Plane) continue;
    TopExp_Explorer ex2;
    for(ex2.Init(curface,TopAbs_EDGE); ex2.More(); ex2.Next()){
      const TopoDS_Edge& E = TopoDS::Edge(ex2.Current());
      SetEdgeTol(E,curface);
    }
  }
  BRepLib::UpdateTolerances(S);
}

//=======================================================================
//function : SameParameter
//WARNING  : Nouvelle spec DUB LBO 9/9/97.
//  On recode dans l arete la meilleure tolerance trouvee, 
//  pour les vertex extremites il faudra trouver autre chose.
//=======================================================================
static Standard_Boolean EvalTol(const Handle(Geom2d_Curve)& pc,
                        const Handle(Geom_Surface)& s,
                        const GeomAdaptor_Curve&    gac,
                        const Standard_Real         tol,
                        Standard_Real&              tolbail)
{
  Standard_Integer ok = 0;
  Standard_Real f = gac.FirstParameter();
  Standard_Real l = gac.LastParameter();
  Extrema_LocateExtPC Projector;
  Projector.Initialize(gac,f,l,tol);
  Standard_Real u,v;
  gp_Pnt p;
  tolbail = tol;
  for(Standard_Integer i = 1; i <= 5; i++){
    Standard_Real t = i/6.;
    t = (1.-t) * f + t * l;
    pc->Value(t).Coord(u,v);
    p = s->Value(u,v);
    Projector.Perform(p,t);
    if (Projector.IsDone()) {
      Standard_Real dist = Projector.Value();
      if(dist > tolbail) tolbail = dist;
      ok++;
    }
  }
  return (ok > 2);
}

static Standard_Real ComputeTol(const Handle(Adaptor3d_HCurve)& c3d,
                        const Handle(Adaptor2d_HCurve2d)& c2d,
                        const Handle(Adaptor3d_HSurface)& surf,
                        const Standard_Integer        nbp)

{

  TColStd_Array1OfReal dist(1,nbp+10);
  dist.Init(-1.);


  Adaptor3d_CurveOnSurface  cons(c2d,surf);
  Standard_Real d2 = 0.;
  Standard_Integer nn = nbp;
  Standard_Real unsurnn = 1./nn;
  Standard_Real first = c3d->FirstParameter();
  Standard_Real last  = c3d->LastParameter();
  Standard_Integer i = 0;
  for(i = 0; i <= nn; i++){
    Standard_Real t = unsurnn*i;
    Standard_Real u = first*(1.-t) + last*t;
    gp_Pnt Pc3d = c3d->Value(u);
    gp_Pnt Pcons = cons.Value(u);
    if (Precision::IsInfinite(Pcons.X()) ||
      Precision::IsInfinite(Pcons.Y()) ||
      Precision::IsInfinite(Pcons.Z())) {
      d2=Precision::Infinite();
      break;
    }
    Standard_Real temp = Pc3d.SquareDistance(Pcons);


    dist(i+1) = temp;


    if(temp > d2) d2 = temp;
  }


  Standard_Boolean ana = Standard_False;
  Standard_Real D2 = 0;
  Standard_Integer N1 = 0;
  Standard_Integer N2 = 0;
  Standard_Integer N3 = 0;

  for( i = 1; i<= nbp+10; i++)
    if( dist(i) > 0 ) {
      if( dist(i) < 1.0 ) N1++;
      else N2++;
    }

  if( N1 > N2 && N2 != 0 ) N3 = 100*N2/(N1+N2);
  if( N3 < 10 && N3 != 0 ) {
    ana = Standard_True;
    for( i = 1; i<= nbp+10; i++)
      if( dist(i) > 0 && dist(i) < 1.0 )
      if( dist(i) > D2 ) D2 = dist(i);
  }

  //d2 = 1.5*sqrt(d2);
  d2 = (!ana) ? 1.5*sqrt(d2) : 1.5*sqrt(D2);
  if(d2<1.e-7) d2 = 1.e-7;

  return d2;
}



00940 void BRepLib::SameParameter(const TopoDS_Edge&  AnEdge,
                      const Standard_Real Tolerance)
{
  if (BRep_Tool::SameParameter(AnEdge)) return;

  const Standard_Integer NCONTROL = 22;

  static Handle(GeomAdaptor_HCurve) HC;
  static Handle(Geom2dAdaptor_HCurve) HC2d;
  static Handle(GeomAdaptor_HSurface) HS;
  if(HC.IsNull()){
    HC = new GeomAdaptor_HCurve();
    HC2d = new Geom2dAdaptor_HCurve();
    HS = new GeomAdaptor_HSurface();
  }
  GeomAdaptor_Curve& GAC = HC->ChangeCurve();
  Geom2dAdaptor_Curve& GAC2d = HC2d->ChangeCurve2d();
  GeomAdaptor_Surface& GAS = HS->ChangeSurface();
#ifndef DEB
  Standard_Real f3d =0.,l3d =0.;
#else
  Standard_Real f3d,l3d;
#endif
  TopLoc_Location L3d;
  Handle(Geom_Curve) C3d;

  const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &AnEdge.TShape());
  BRep_ListOfCurveRepresentation& CList = TE->ChangeCurves();
  BRep_ListIteratorOfListOfCurveRepresentation It(CList);
  
  Standard_Boolean NotDone = Standard_True;

  while (NotDone && It.More()) {
    Handle(BRep_GCurve) GCurve = Handle(BRep_GCurve)::DownCast(It.Value());
    if (!GCurve.IsNull() && GCurve->IsCurve3D()) {
      C3d = GCurve->Curve3D() ;
      f3d = GCurve->First();
      l3d = GCurve->Last();
      L3d = GCurve->Location() ;
      NotDone = Standard_False;
    } 
    It.Next() ;
  }

  if(C3d.IsNull()) return;

  // modified by NIZHNY-OCC486  Tue Aug 27 17:15:13 2002 :
  Standard_Boolean m_TrimmedPeriodical = Standard_False;
  Handle(Standard_Type) TheType = C3d->DynamicType();
  if( TheType == STANDARD_TYPE(Geom_TrimmedCurve))
    {
      const Handle(Geom_Curve)& gtC = (*((Handle(Geom_TrimmedCurve)*)&C3d))->BasisCurve();
      m_TrimmedPeriodical = gtC->IsPeriodic();
    }
  // modified by NIZHNY-OCC486  Tue Aug 27 17:15:17 2002 .

  BRep_Builder B;
  if(!C3d->IsPeriodic()) {
    Standard_Real Udeb = C3d->FirstParameter();
    Standard_Real Ufin = C3d->LastParameter();
    // modified by NIZHNY-OCC486  Tue Aug 27 17:17:14 2002 :
    //if (Udeb > f3d) f3d = Udeb;
    //if (l3d > Ufin) l3d = Ufin;
    if(!m_TrimmedPeriodical)
      {
      if (Udeb > f3d) f3d = Udeb;
      if (l3d > Ufin) l3d = Ufin;
      }
    // modified by NIZHNY-OCC486  Tue Aug 27 17:17:55 2002 .
  }
  if(!L3d.IsIdentity()){
    C3d = Handle(Geom_Curve)::DownCast(C3d->Transformed(L3d.Transformation()));
  }
  GAC.Load(C3d,f3d,l3d);

  Standard_Boolean IsSameP = 1;
  Standard_Real maxdist = 0.;

//  Modified by skv - Thu Jun  3 12:39:19 2004 OCC5898 Begin
  Standard_Real anEdgeTol = BRep_Tool::Tolerance(AnEdge);
//  Modified by skv - Thu Jun  3 12:39:20 2004 OCC5898 End
  Standard_Boolean SameRange = BRep_Tool::SameRange(AnEdge);
  Standard_Boolean YaPCu = Standard_False;
  It.Initialize(CList);

  while (It.More()) {
    Standard_Boolean isANA = Standard_False;
    Standard_Boolean isBSP = Standard_False;
    Handle(BRep_GCurve) GCurve = Handle(BRep_GCurve)::DownCast(It.Value());
    Handle(Geom2d_Curve) PC[2];
    Handle(Geom_Surface) S;
    if (!GCurve.IsNull() && GCurve->IsCurveOnSurface()) {
      YaPCu = Standard_True;
      PC[0] = GCurve->PCurve();
      TopLoc_Location PCLoc = GCurve->Location();
      S = GCurve->Surface();
      if (!PCLoc.IsIdentity() ) {
      S = Handle(Geom_Surface)::DownCast(S->Transformed(PCLoc.Transformation()));
      }
      GAS.Load(S);
      if (GCurve->IsCurveOnClosedSurface()) {
      PC[1] = GCurve->PCurve2();
      }
      
      // Eval tol2d to compute SameRange
      Standard_Real UResol = GAS.UResolution(Tolerance);
      Standard_Real VResol = GAS.VResolution(Tolerance);
      Standard_Real Tol2d  = Min(UResol, VResol);
      for(Standard_Integer i = 0; i < 2; i++){
      Handle(Geom2d_Curve) curPC = PC[i];
      Standard_Boolean updatepc = 0;
      if(curPC.IsNull()) break;
      if(!SameRange){
        GeomLib::SameRange(Tol2d,
                       PC[i],GCurve->First(),GCurve->Last(),
                       f3d,l3d,curPC);

        updatepc = (curPC != PC[i]);

      }
      Standard_Boolean goodpc = 1;
      GAC2d.Load(curPC,f3d,l3d);

      Standard_Real error = ComputeTol(HC, HC2d, HS, NCONTROL);

      if(GAC2d.GetType() == GeomAbs_BSplineCurve && 
         GAC2d.Continuity() == GeomAbs_C0) {
        Handle(Geom2d_BSplineCurve) bs2d = GAC2d.BSpline();
        Handle(Geom2d_BSplineCurve) bs2dsov = bs2d;
        Standard_Real fC0 = bs2d->FirstParameter(), lC0 = bs2d->LastParameter();
        Standard_Boolean repar = Standard_True;
        gp_Pnt2d OriginPoint;
        bs2d->D0(fC0, OriginPoint);
        Geom2dConvert::C0BSplineToC1BSplineCurve(bs2d, Tol2d);
        isBSP = Standard_True; 

        if(bs2d->IsPeriodic()) { // -------- IFV, Jan 2000
          gp_Pnt2d NewOriginPoint;
          bs2d->D0(bs2d->FirstParameter(), NewOriginPoint);
          if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
             Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) {

            TColStd_Array1OfReal Knotbs2d (1, bs2d->NbKnots());
            bs2d->Knots(Knotbs2d);

            for(Standard_Integer Index = 1; Index <= bs2d->NbKnots(); Index++) {
            bs2d->D0(Knotbs2d(Index), NewOriginPoint);
            if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
               Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) continue;
            
            bs2d->SetOrigin(Index);
            break;
            }
          }
        }

        if(bs2d->Continuity() == GeomAbs_C0) {
          Standard_Real tolbail;
          if(EvalTol(curPC,S,GAC,Tolerance,tolbail)){
            bs2d = bs2dsov;
            Standard_Real UResbail = GAS.UResolution(tolbail);
            Standard_Real VResbail = GAS.VResolution(tolbail);
            Standard_Real Tol2dbail  = Min(UResbail,VResbail);
            bs2d->D0(bs2d->FirstParameter(), OriginPoint); 

            Standard_Integer nbp = bs2d->NbPoles();
            TColgp_Array1OfPnt2d poles(1,nbp);
            bs2d->Poles(poles);
            gp_Pnt2d p = poles(1), p1;
            Standard_Real d = Precision::Infinite();
            for(Standard_Integer ip = 2; ip <= nbp; ip++) {
            p1 = poles(ip);
            d = Min(d,p.SquareDistance(p1));
            p = p1;
            }
            d = sqrt(d)*.1;

            Tol2dbail = Max(Min(Tol2dbail,d),Tol2d);

            Geom2dConvert::C0BSplineToC1BSplineCurve(bs2d,Tol2dbail);

            if(bs2d->IsPeriodic()) { // -------- IFV, Jan 2000
            gp_Pnt2d NewOriginPoint;
            bs2d->D0(bs2d->FirstParameter(), NewOriginPoint);
            if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
               Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) {

              TColStd_Array1OfReal Knotbs2d (1, bs2d->NbKnots());
              bs2d->Knots(Knotbs2d);

              for(Standard_Integer Index = 1; Index <= bs2d->NbKnots(); Index++) {
                bs2d->D0(Knotbs2d(Index), NewOriginPoint);
                if(Abs(OriginPoint.X() - NewOriginPoint.X()) > Precision::PConfusion() ||
                   Abs(OriginPoint.Y() - NewOriginPoint.Y()) > Precision::PConfusion()    ) continue;
                
                bs2d->SetOrigin(Index);
                break;
              }
            }
            }
            
            
            if(bs2d->Continuity() == GeomAbs_C0) {
            goodpc = 1;
            bs2d = bs2dsov;
            repar = Standard_False;
            }
          }
          else goodpc = 0;
        }

        if(goodpc){
          if(repar) {
            Standard_Integer NbKnots = bs2d->NbKnots();
            TColStd_Array1OfReal Knots(1,NbKnots);
            bs2d->Knots(Knots);
            //        BSplCLib::Reparametrize(f3d,l3d,Knots);
            BSplCLib::Reparametrize(fC0,lC0,Knots);
            bs2d->SetKnots(Knots);
            GAC2d.Load(bs2d,f3d,l3d);
            curPC = bs2d;
            Standard_Boolean updatepcsov = updatepc;
            updatepc = Standard_True;

            Standard_Real error1 = ComputeTol(HC, HC2d, HS, NCONTROL);
            if(error1 > error) {
            bs2d = bs2dsov;
            GAC2d.Load(bs2d,f3d,l3d);
            curPC = bs2d;
            updatepc = updatepcsov;
            isANA = Standard_True;
            }
            else {
            error = error1;
            }
          }

          //check, if new BSpline "good" or not --------- IFV, Jan of 2000
          GeomAbs_Shape cont = bs2d->Continuity();
          Standard_Boolean IsBad = Standard_False;

          if(cont > GeomAbs_C0 && error > Max(1.e-3,Tolerance)) {
            Standard_Integer NbKnots = bs2d->NbKnots();
            TColStd_Array1OfReal Knots(1,NbKnots);
            bs2d->Knots(Knots);
            Standard_Real critratio = 10.; 
            Standard_Real dtprev = Knots(2) - Knots(1), dtratio = 1.;
            Standard_Real dtmin = dtprev;
            Standard_Real dtcur;
            for(Standard_Integer j = 2; j < NbKnots; j++) {
            dtcur = Knots(j+1) - Knots(j);
            dtmin = Min(dtmin, dtcur);

            if(IsBad) continue;

            if(dtcur > dtprev) dtratio = dtcur/dtprev;
            else dtratio = dtprev/dtcur;
            if(dtratio > critratio) {IsBad = Standard_True;}
            dtprev = dtcur;
            
            }
            if(IsBad) {
            // To avoid failures in Approx_CurvilinearParameter 
            bs2d->Resolution(Max(1.e-3,Tolerance), dtcur);
            if(dtmin < dtcur) IsBad = Standard_False;
            }
          }


          if(IsBad ) { //if BSpline "bad", try to reparametrize it
                                        // by its curve length

//          GeomAbs_Shape cont = bs2d->Continuity();
            if(cont > GeomAbs_C2) cont = GeomAbs_C2;
            Standard_Integer maxdeg = bs2d->Degree();
            if(maxdeg == 1) maxdeg = 14;
            Approx_CurvilinearParameter AppCurPar(HC2d, HS, Max(1.e-3,Tolerance),
                                        cont, maxdeg, 10);
            if(AppCurPar.IsDone() || AppCurPar.HasResult()) {
            bs2d = AppCurPar.Curve2d1();
            GAC2d.Load(bs2d,f3d,l3d);
            curPC = bs2d;

            if(Abs(bs2d->FirstParameter() - fC0) > Tol2d ||
               Abs(bs2d->LastParameter() - lC0) > Tol2d    ) {
              Standard_Integer NbKnots = bs2d->NbKnots();
              TColStd_Array1OfReal Knots(1,NbKnots);
              bs2d->Knots(Knots);
//            BSplCLib::Reparametrize(f3d,l3d,Knots);
              BSplCLib::Reparametrize(fC0,lC0,Knots);
              bs2d->SetKnots(Knots);
              GAC2d.Load(bs2d,f3d,l3d);
              curPC = bs2d;

            }
            }
          }

    
        }
      }


      if(goodpc){
//      Approx_SameParameter SameP(HC,HC2d,HS,Tolerance);
        Standard_Real aTol = (isANA && isBSP) ? 1.e-7 : Tolerance;
        Approx_SameParameter SameP(HC,HC2d,HS,aTol);
        
        if (SameP.IsSameParameter()) {
          maxdist = Max(maxdist,SameP.TolReached());
          if(updatepc){
            if (i == 0) GCurve->PCurve(curPC);
            else GCurve->PCurve2(curPC);
          }
        }
        else if (SameP.IsDone()) {
          Standard_Real tolreached = SameP.TolReached();
          if(tolreached < error) {
            curPC = SameP.Curve2d();
            updatepc = Standard_True;
            maxdist = Max(maxdist,tolreached);
          }
          else {
            maxdist = Max(maxdist, error);
          }
          if(updatepc){
            if (i == 0) GCurve->PCurve(curPC);
            else GCurve->PCurve2(curPC);
          }
        }
        else IsSameP = 0;
      
      }
      else IsSameP = 0;

//  Modified by skv - Thu Jun  3 12:39:19 2004 OCC5898 Begin
      if (!IsSameP) {
        if (anEdgeTol > error) {
          maxdist = Max(maxdist, anEdgeTol);
          IsSameP = Standard_True;
        }
      }
//  Modified by skv - Thu Jun  3 12:39:20 2004 OCC5898 End
      }
    }
    It.Next() ;
  }
  B.Range(AnEdge,f3d,l3d);
  B.SameRange(AnEdge,Standard_True);
  if ( IsSameP) {
    // On diminue eventuellement la tolerance de l arete, puisque
    // l on a traite toutes ses representations ( Sauf celles associees
    // a des plans et non stockees dans l'arete !) 
    // Il n'en va pas de meme des Vertex que l on ne peut que grossir 
    // ou laisser tels quels.
    if (YaPCu) {
      // On evite de mettre des tol trop petites.
      maxdist = Max(maxdist,Precision::Confusion());
      TopoDS_Vertex V1,V2;
      TopExp::Vertices(AnEdge,V1,V2);
      if (!V1.IsNull())
      B.UpdateVertex(V1,maxdist);
      if (!V2.IsNull())
      B.UpdateVertex(V2,maxdist);
      TE->Modified(Standard_True);
      TE->Tolerance(maxdist);
    }
    B.SameParameter(AnEdge,Standard_True);
  }
}

//=======================================================================
//function : UpdateTolerances
//purpose  : 
//=======================================================================
01315 void  BRepLib::UpdateTolerances(const TopoDS_Shape& aShape,
                        const Standard_Boolean verifyTolerance) 
{

// On harmonise les tolerance
// avec la regle Tolerance(VERTEX)>=Tolerance(EDGE)>=Tolerance(FACE)
  BRep_Builder B;
  Standard_Real tol=0;
  if (verifyTolerance) {
    // On force la tolerance a sa valeur minimale
    Handle(Geom_Surface) S;
    TopLoc_Location l;
    TopExp_Explorer ex;
    Bnd_Box aB;
    Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dMax;
    for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {
      const TopoDS_Face& curf=TopoDS::Face(ex.Current());
      S = BRep_Tool::Surface(curf, l);
      if (!S.IsNull()) {
      aB.SetVoid();
      BRepBndLib::Add(curf,aB);
      if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
        S = (*((Handle(Geom_RectangularTrimmedSurface)*)&S))->BasisSurface();
      }
      GeomAdaptor_Surface AS(S);
      switch (AS.GetType()) {
      case GeomAbs_Plane: 
      case GeomAbs_Cylinder: 
      case GeomAbs_Cone: 
        {
          tol=Precision::Confusion();
          break;
        }
      case GeomAbs_Sphere: 
      case GeomAbs_Torus: 
        {
          tol=Precision::Confusion()*2;
          break;
        }
      default:
        tol=Precision::Confusion()*4;
      }
      if (!aB.IsWhole()) {
        aB.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
        dMax=1.;
        if (!aB.IsOpenXmin() && !aB.IsOpenXmax()) dMax=aXmax-aXmin;
        if (!aB.IsOpenYmin() && !aB.IsOpenYmax()) aYmin=aYmax-aYmin;
        if (!aB.IsOpenZmin() && !aB.IsOpenZmax()) aZmin=aZmax-aZmin;
        if (aYmin>dMax) dMax=aYmin;
        if (aZmin>dMax) dMax=aZmin;
        tol=tol*dMax;
        // On ne traite pas les tolerance > 1.
        if (tol>1.) tol=0.99;
      }
      const Handle(BRep_TFace)& Tf = *((Handle(BRep_TFace)*)&curf.TShape());
      Tf->Tolerance(tol);
      }
    }
  }
  
  //On traite les edges
  TopTools_IndexedDataMapOfShapeListOfShape parents;
  TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, parents);
  TopTools_ListIteratorOfListOfShape lConx;
  Standard_Integer iCur;
  for (iCur=1; iCur<=parents.Extent(); iCur++) {
    tol=0;
    for (lConx.Initialize(parents(iCur)); lConx.More(); lConx.Next()) {
      tol=Max(tol, BRep_Tool::Tolerance(TopoDS::Face(lConx.Value())));
    }
    // Update ne peut que augmenter la tolerance, donc si l'edge a
    // une tolerance + grande que ses faces on y touche pas
    B.UpdateEdge(TopoDS::Edge(parents.FindKey(iCur)), tol);
  }

  //On traite les Vertices
  parents.Clear();
  TopExp::MapShapesAndAncestors(aShape, TopAbs_VERTEX, TopAbs_EDGE, parents);
  TColStd_MapOfTransient Initialized;
  TopTools_MapOfShape Done;
  Standard_Integer nbV = parents.Extent();
  for (iCur=1; iCur<=nbV; iCur++) {
    tol=0;
    Done.Clear();
    const TopoDS_Vertex& V = TopoDS::Vertex(parents.FindKey(iCur));
    Bnd_Box box;
    box.Add(BRep_Tool::Pnt(V));
    gp_Pnt p3d;
    for (lConx.Initialize(parents(iCur)); lConx.More(); lConx.Next()) {
      const TopoDS_Edge& E = TopoDS::Edge(lConx.Value());
      if(!Done.Add(E)) continue;
      tol=Max(tol, BRep_Tool::Tolerance(E));
      if(!BRep_Tool::SameRange(E)) continue;
      Standard_Real par = BRep_Tool::Parameter(V,E);
      Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
      BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
      const TopLoc_Location& Eloc = E.Location();
      while (itcr.More()) {
      // Pour chaque CurveRepresentation, on verifie le parametre fourni
      const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
      const TopLoc_Location& loc = cr->Location();
      TopLoc_Location L = (Eloc * loc);
      if (cr->IsCurve3D()) {
        const Handle(Geom_Curve)& C = cr->Curve3D();
        if (!C.IsNull()) { // edge non degenere
          p3d = C->Value(par);
          p3d.Transform(L.Transformation());
          box.Add(p3d);
        }
      }
      else if (cr->IsCurveOnSurface()) {
        const Handle(Geom_Surface)& Su = cr->Surface();
        const Handle(Geom2d_Curve)& PC = cr->PCurve();
        Handle(Geom2d_Curve) PC2;
        if (cr->IsCurveOnClosedSurface()) {
          PC2 = cr->PCurve2();
        }
        gp_Pnt2d p2d = PC->Value(par);
        p3d = Su->Value(p2d.X(),p2d.Y());
        p3d.Transform(L.Transformation());
        box.Add(p3d);
        if (!PC2.IsNull()) {
          p2d = PC2->Value(par);
          p3d = Su->Value(p2d.X(),p2d.Y());
          p3d.Transform(L.Transformation());
          box.Add(p3d);
        }
      }
      itcr.Next();
      }
    }
    Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
    box.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
    aXmax -= aXmin; aYmax -= aYmin; aZmax -= aZmin;
    tol = Max(tol,sqrt(aXmax*aXmax+aYmax*aYmax+aZmax*aZmax));
    tol += 2.*Epsilon(tol);
    if (verifyTolerance) {
      // On force la tolerance a sa valeur minimale
      // Attention au partage du vertex par d'autre shapes
      const Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*)&V.TShape());
      if (Initialized.Add(TV)) 
      TV->Tolerance(tol);
      else 
      B.UpdateVertex(V, tol);
    }
    else {
      // Update ne peut que augmenter la tolerance, donc si le vertex a
      // une tolerance + grande que ses edges on y touche pas
      B.UpdateVertex(V, tol);
    }
  }
}

//=======================================================================
//function : OrientClosedSolid
//purpose  : 
//=======================================================================
Standard_Boolean BRepLib::OrientClosedSolid(TopoDS_Solid& solid) 
{
// On met la matiere a l'interieur du solid
  BRepClass3d_SolidClassifier where(solid);
  where.PerformInfinitePoint(Precision::Confusion());
  if (where.State()==TopAbs_IN) {
    solid.Reverse();
  }
  else if (where.State()==TopAbs_ON || where.State()==TopAbs_UNKNOWN) 
    return Standard_False;

  return Standard_True;
}

//=======================================================================
//function : tgtfaces
//purpose  : controle de l angle a la frontiere entre 2 carreaux.
//           Les deux carreaux doivent partager leur edge frontiere.
//=======================================================================

static Standard_Boolean tgtfaces(const TopoDS_Edge& Ed,
                         const TopoDS_Face& F1,
                         const TopoDS_Face& F2,
                         const Standard_Real ta,
                         const Standard_Boolean couture)
{
  Standard_Real u;
  TopoDS_Edge E = Ed;
  BRepAdaptor_Surface aBAS1(F1,Standard_False);
  BRepAdaptor_Surface aBAS2(F2,Standard_False);
  Handle(BRepAdaptor_HSurface) HS1 = new BRepAdaptor_HSurface(aBAS1);
  Handle(BRepAdaptor_HSurface) HS2;
  if(couture) HS2 = HS1;
  else HS2 = new BRepAdaptor_HSurface(aBAS2);

  E.Orientation(TopAbs_FORWARD);
  Handle(BRepAdaptor_HCurve2d) HC2d1 = new BRepAdaptor_HCurve2d();
  HC2d1->ChangeCurve2d().Initialize(E,F1);
  if(couture) E.Orientation(TopAbs_REVERSED);
  Handle(BRepAdaptor_HCurve2d) HC2d2 = new BRepAdaptor_HCurve2d();
  HC2d2->ChangeCurve2d().Initialize(E,F2);
  Adaptor3d_CurveOnSurface C1(HC2d1,HS1);
  Adaptor3d_CurveOnSurface C2(HC2d2,HS2);

  Standard_Boolean rev1 = (F1.Orientation() == TopAbs_REVERSED);
  Standard_Boolean rev2 = (F2.Orientation() == TopAbs_REVERSED);
  Standard_Real f,l,eps, angmax = -PI;
#ifndef DEB
  Standard_Real ang =0.;
#else
  Standard_Real ang;
#endif
  BRep_Tool::Range(E,f,l);
  Extrema_LocateExtPC ext;
  Standard_Boolean IsInitialized = Standard_False;
  
  eps = (l - f)/100.;
  f += eps; // pour eviter de faire des calculs sur les 
  l -= eps; // pointes des carreaux pointus.
  gp_Pnt2d p;
  gp_Pnt pp1,pp2;//,PP;
  gp_Vec du,dv;
  gp_Vec d1,d2;
  Standard_Real uu, vv, norm;

  Standard_Integer i;
  Standard_Boolean Nok;
  for(i = 0; (i<= 20) && (angmax<=ta) ; i++){
    // On suppose d'abord que c'est sameParameter
    Nok = Standard_True;
    u = f + (l-f)*i/20;
    HC2d1->D0(u,p);
    HS1->D1(p.X(),p.Y(),pp1,du,dv);
    d1 = (du.Crossed(dv));
    norm = d1.Magnitude(); 
    if (norm > 1.e-12) d1 /= norm;
    else Nok=Standard_False;
    if(rev1) d1.Reverse();

    HC2d2->D0(u,p);
    HS2->D1(p.X(), p.Y(), pp2, du, dv);
    d2 = (du.Crossed(dv));
    norm = d2.Magnitude();
    if (norm> 1.e-12) d2 /= norm;
    else Nok=Standard_False;
    if(rev2) d2.Reverse();
    if (Nok) ang = d1.Angle(d2);

    if (Nok &&(ang > ta)) { // On raffine par projection
      if (! IsInitialized ) {
      ext.Initialize(C2,f,l,Precision::PConfusion());
      IsInitialized = Standard_True;
      }      
      ext.Perform(pp1,u);
      if(ext.IsDone() && ext.IsMin()){
      Extrema_POnCurv poc = ext.Point();
      Standard_Real v = poc.Parameter();

      HC2d2->D0(v,p);
      p.Coord(uu,vv);
      HS2->D1(p.X(), p.Y(), pp2, du, dv);
      d2 = (du.Crossed(dv));
      norm = d2.Magnitude();
      if (norm> 1.e-12) d2 /= norm;
      else Nok = Standard_False;
      if(rev2) d2.Reverse();
      if (Nok) ang = d1.Angle(d2);
      }
    }
    if(ang >= angmax) angmax = ang;
  }     
 
  return (angmax<=ta);

}


//=======================================================================
// function : EncodeRegularity
// purpose  : code les regularites sur tous les edges du shape,frontiere
//            de deux faces qui n en ont pas.
//=======================================================================

01595 void BRepLib::EncodeRegularity(const TopoDS_Shape& S,
                         const Standard_Real TolAng)
{
  BRep_Builder B;
  TopTools_IndexedDataMapOfShapeListOfShape M;
  TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,M);
  TopTools_ListIteratorOfListOfShape It;
  TopExp_Explorer Ex;
  TopoDS_Face F1,F2;
  Standard_Boolean found, couture;
  for(Standard_Integer i = 1; i <= M.Extent(); i++){
    TopoDS_Edge E = TopoDS::Edge(M.FindKey(i));
    found = Standard_False; couture = Standard_False;
    F1.Nullify();
    for(It.Initialize(M.FindFromIndex(i));It.More() && !found;It.Next()){
      if(F1.IsNull()) { F1 = TopoDS::Face(It.Value()); }
      else {
      if(!F1.IsSame(TopoDS::Face(It.Value()))){
        found = Standard_True;
        F2 = TopoDS::Face(It.Value());
      }
      }
    }
    if (!found && !F1.IsNull()){//est ce un edge de couture?
      TopAbs_Orientation orE = E.Orientation();
      TopoDS_Edge curE;
      for(Ex.Init(F1,TopAbs_EDGE);Ex.More() && !found;Ex.Next()){
      curE= TopoDS::Edge(Ex.Current());
      if(E.IsSame(curE) && orE != curE.Orientation()) {
        found = Standard_True;
        couture = Standard_True;
        F2 = F1;
      }
      }
    }
    if(found){
      if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0){
      if(tgtfaces(E, F1, F2, TolAng, couture)){
        B.Continuity(E,F1,F2,GeomAbs_G1);
      }
      }
    }
  }
}

//=======================================================================
// function : EncodeRegularity
// purpose  : code la regularite entre 2 face sur une edge 
//=======================================================================

01645 void BRepLib::EncodeRegularity(TopoDS_Edge& E,
                         const TopoDS_Face& F1,
                         const TopoDS_Face& F2,
                         const Standard_Real TolAng)
{
  BRep_Builder B;
  if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0){
    if( tgtfaces(E, F1, F2, TolAng, F1.IsEqual(F2))) {
     B.Continuity(E,F1,F2,GeomAbs_G1);
   }
 }
}

//=======================================================================
//function : SortFaces
//purpose  : 
//=======================================================================

01663 void  BRepLib::SortFaces (const TopoDS_Shape& Sh,
                    TopTools_ListOfShape& LF)
{
  LF.Clear();
  TopTools_ListOfShape LTri,LPlan,LCyl,LCon,LSphere,LTor,LOther;
  TopExp_Explorer exp(Sh,TopAbs_FACE);
  TopLoc_Location l;
  Handle(Geom_Surface) S;

  for (; exp.More(); exp.Next()) {
    const TopoDS_Face&   F = TopoDS::Face(exp.Current());
    S = BRep_Tool::Surface(F, l);
    if (!S.IsNull()) {
      if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
      S = (*((Handle(Geom_RectangularTrimmedSurface)*)&S))->BasisSurface();
      }
      GeomAdaptor_Surface AS(S);
      switch (AS.GetType()) {
      case GeomAbs_Plane: 
      {
        LPlan.Append(F);
        break;
      }
      case GeomAbs_Cylinder: 
      {
        LCyl.Append(F);
        break;
      }
      case GeomAbs_Cone: 
      {
        LCon.Append(F);
        break;
      }
      case GeomAbs_Sphere: 
      {
        LSphere.Append(F);
        break;
      }
      case GeomAbs_Torus: 
      {
        LTor.Append(F);
        break;
      }
      default:
      LOther.Append(F);
      }
    }
    else LTri.Append(F);
  }
  LF.Append(LPlan); LF.Append(LCyl  ); LF.Append(LCon); LF.Append(LSphere);
  LF.Append(LTor ); LF.Append(LOther); LF.Append(LTri); 
}

//=======================================================================
//function : ReverseSortFaces
//purpose  : 
//=======================================================================

01721 void  BRepLib::ReverseSortFaces (const TopoDS_Shape& Sh,
                         TopTools_ListOfShape& LF)
{
  LF.Clear();
  TopTools_ListOfShape LTri,LPlan,LCyl,LCon,LSphere,LTor,LOther;
  TopExp_Explorer exp(Sh,TopAbs_FACE);
  TopLoc_Location l;
  Handle(Geom_Surface) S;
  
  for (; exp.More(); exp.Next()) {
    const TopoDS_Face&   F = TopoDS::Face(exp.Current());
    S = BRep_Tool::Surface(F, l);
    if (!S.IsNull()) {
      if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
      S = (*((Handle(Geom_RectangularTrimmedSurface)*)&S))->BasisSurface();
      }
      GeomAdaptor_Surface AS(S);
      switch (AS.GetType()) {
      case GeomAbs_Plane: 
      {
        LPlan.Append(F);
        break;
      }
      case GeomAbs_Cylinder: 
      {
        LCyl.Append(F);
        break;
      }
      case GeomAbs_Cone: 
      {
        LCon.Append(F);
        break;
      }
      case GeomAbs_Sphere: 
      {
        LSphere.Append(F);
        break;
      }
      case GeomAbs_Torus: 
      {
        LTor.Append(F);
        break;
      }
      default:
      LOther.Append(F);
      }
    }
    else LTri.Append(F);
  }
  LF.Append(LTri); LF.Append(LOther); LF.Append(LTor ); LF.Append(LSphere);
  LF.Append(LCon); LF.Append(LCyl  ); LF.Append(LPlan);
   
}



Generated by  Doxygen 1.6.0   Back to index