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

TopOpeBRep_FacesIntersector.cxx

// File:    TopOpeBRep_FacesIntersector.cxx
// Created: Thu Nov 18 11:12:07 1993
// Author:  Jean Yves LEBEY
//          <jyl@phobox>

#include <TopOpeBRep_FacesIntersector.ixx>

#ifdef DRAW
#include <TopOpeBRep_DRAW.hxx>
#endif

#include <IntPatch_TheLineConstructorOfIntersection.hxx>
#include <TopOpeBRep_TypeLineCurve.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Edge.hxx>
#include <BRep_Tool.hxx>
#include <TopExp_Explorer.hxx>
#include <TopOpeBRepTool_ShapeTool.hxx>
#include <Precision.hxx>
#include <Geom_Curve.hxx>
#include <Standard_ProgramError.hxx>
#include <TCollection_AsciiString.hxx>
#include <Standard_CString.hxx>
#include <BRepTools.hxx>
#include <TopOpeBRepTool_tol.hxx>

Standard_EXPORT Standard_Real GLOBAL_tolFF = 1.e-7;

#ifdef DEB
#include <TopAbs.hxx>
Standard_EXPORT Standard_Boolean TopOpeBRep_GettraceFI();
Standard_EXPORT Standard_Boolean TopOpeBRep_GettraceFITOL();
Standard_EXPORT Standard_Boolean TopOpeBRep_GettraceSAVFF();

Standard_EXPORT Standard_Integer SAVFFi1 = 0;
Standard_EXPORT Standard_Integer SAVFFi2 = 0;
static void SAVFF(const TopoDS_Face& F1,const TopoDS_Face& F2)
{
  TCollection_AsciiString an1("SAVA");if (SAVFFi1) an1=an1+SAVFFi1;
  TCollection_AsciiString an2("SAVB");if (SAVFFi2) an2=an2+SAVFFi2;
  Standard_CString n1=an1.ToCString();Standard_CString n2=an2.ToCString();
#ifdef DRAW
  cout<<"FaceIntersector :   set "<<n1<<","<<n2<<endl;DBRep::Set(n1,F1);DBRep::Set(n2,F2);
#endif
  cout<<"FaceIntersector : write "<<n1<<","<<n2<<endl;BRepTools::Write(F1,n1);BRepTools::Write(F2,n2); 
}

Standard_EXPORT Standard_Boolean TopOpeBRepTool_GettraceKRO();
#include <TopOpeBRepTool_KRO.hxx>
Standard_EXPORT TOPKRO KRO_DSFILLER_INTFF("intersection face/face");

#endif

// NYI
// NYI : IntPatch_Intersection : TolArc,TolTang exact definition
// NYI


// modified by NIZHNY-MKK  Mon Apr  2 12:14:32 2001.BEGIN
#include <IntPatch_TheWLineOfIntersection.hxx>
#include <IntPatch_TheRLineOfIntersection.hxx>
#include <IntPatch_ThePointOfIntersection.hxx>
#include <Adaptor3d_HSurface.hxx>
#include <Adaptor3d_TopolTool.hxx>
#include <Adaptor3d_HVertex.hxx>
#include <Adaptor2d_HCurve2d.hxx>
#include <Geom2dInt_TheProjPCurOfGInter.hxx>

static Standard_Boolean TestWLineAlongRestriction(const Handle(IntPatch_TheWLineOfIntersection)& theWLine,
                                      const Standard_Integer                         theRank,
                                      const Handle(Adaptor3d_HSurface)&              theSurface,
                                      const Handle(Adaptor3d_TopolTool)&             theDomain,
                                      const Standard_Real                            theTolArc);

static 
Handle(IntPatch_TheRLineOfIntersection) BuildRLineBasedOnWLine(const Handle(IntPatch_TheWLineOfIntersection)& theWLine,
                                                 const Handle(Adaptor2d_HCurve2d)&              theArc,
                                                 const Standard_Integer                         theRank);

static
Handle(IntPatch_TheRLineOfIntersection) BuildRLine(const IntPatch_SequenceOfLine&     theSeqOfWLine,
                                       const Standard_Integer             theRank,
                                       const Handle(Adaptor3d_HSurface)&  theSurface,
                                       const Handle(Adaptor3d_TopolTool)& theDomain,
                                       const Standard_Real                theTolArc);

static void TestWLinesToAnArc(IntPatch_SequenceOfLine&           slin,
                        const Handle(Adaptor3d_HSurface)&  theSurface1,
                        const Handle(Adaptor3d_TopolTool)& theDomain1,
                        const Handle(Adaptor3d_HSurface)&  theSurface2,
                        const Handle(Adaptor3d_TopolTool)& theDomain2,
                        const Standard_Real                theTolArc);
// modified by NIZHNY-MKK  Mon Apr  2 12:14:38 2001.END

// modified by NIZHNY-OFV  Fri Mar 29 12:37:21 2002.BEGIN
#include <TColgp_SequenceOfPnt.hxx>
#include <TopExp.hxx>
#include <TColStd_SequenceOfReal.hxx>
#include <Extrema_ExtPS.hxx>
#include <Extrema_ExtPC.hxx>
#include <Extrema_POnSurf.hxx>
#include <GeomAdaptor_Curve.hxx>
static void MergeWLinesIfAllSegmentsAlongRestriction(IntPatch_SequenceOfLine&           theSlin,
                                         const Handle(Adaptor3d_HSurface)&  theSurface1,
                                         const Handle(Adaptor3d_TopolTool)& theDomain1,
                                         const Handle(Adaptor3d_HSurface)&  theSurface2,
                                         const Handle(Adaptor3d_TopolTool)& theDomain2,
                                         const Standard_Real                theTolArc);
//------------------------------------------------------------------------------------------------
static Standard_Integer GetArc(IntPatch_SequenceOfLine&           theSlin,
                         const Standard_Integer&            theRankS,
                         const Handle(Adaptor3d_HSurface)&  theSurfaceObj,
                         const Handle(Adaptor3d_TopolTool)& theDomainObj,
                         const Handle(Adaptor3d_HSurface)&  theSurfaceTool,
                         const gp_Pnt&                      theTestPoint,
                         Standard_Real&                     theVrtxTol,
                         Handle(IntSurf_LineOn2S)&          theLineOn2S,
                         Standard_Real&                     theFirst,
                         Standard_Real&                     theLast);
//------------------------------------------------------------------------------------------------
static Standard_Boolean IsPointOK(const gp_Pnt&            theTestPnt,
                          const Adaptor3d_Surface& theTestSurface,
                          const Standard_Real&     theTol);
//-------------------------------------------------------------------------------------------------
static Standard_Boolean GetPointOn2S(const gp_Pnt&            theTestPnt,
                             const Adaptor3d_Surface& theTestSurface,
                             const Standard_Real&     theTol,
                             Extrema_POnSurf&         theResultPoint);
//-------------------------------------------------------------------------------------------------------------------------
static Handle(IntPatch_TheWLineOfIntersection) GetMergedWLineOnRestriction(IntPatch_SequenceOfLine&           theSlin,
                                                         const Standard_Real&               theVrtxTol,
                                                         const Handle(IntSurf_LineOn2S)&    theLineOn2S);
//---------------------------------------------------------------------------------------------------------------------------
// modified by NIZHNY-OFV  Fri Mar 29 12:41:02 2002.END

//=======================================================================
//function : TopOpeBRep_FacesIntersector
//purpose  : 
//=======================================================================
TopOpeBRep_FacesIntersector::TopOpeBRep_FacesIntersector ()
{
  ResetIntersection();
  myTol1 = myTol2 = Precision::Confusion();
  myForceTolerances = Standard_False;
  mySurface1 = new BRepAdaptor_HSurface();
  mySurface2 = new BRepAdaptor_HSurface();
  myDomain1 = new BRepTopAdaptor_TopolTool();
  myDomain2 = new BRepTopAdaptor_TopolTool();
}

//=======================================================================
//function : Perform
//purpose  : 
//=======================================================================
void TopOpeBRep_FacesIntersector::Perform(const TopoDS_Shape& F1,const TopoDS_Shape& F2,
                                const Bnd_Box& B1,const Bnd_Box& B2)
{
#ifdef DEB
  if (TopOpeBRep_GettraceSAVFF()) SAVFF(TopoDS::Face(F1),TopoDS::Face(F2));
#endif
  
  ResetIntersection();
  if (!myForceTolerances) ShapeTolerances(F1,F2);
  
  myFace1 = TopoDS::Face(F1); myFace1.Orientation(TopAbs_FORWARD);
  myFace2 = TopoDS::Face(F2); myFace2.Orientation(TopAbs_FORWARD);
  BRepAdaptor_Surface& S1 = mySurface1->ChangeSurface(); S1.Initialize(myFace1);
  BRepAdaptor_Surface& S2 = mySurface2->ChangeSurface(); S2.Initialize(myFace2);
  mySurfaceType1 = S1.GetType();
  mySurfaceType2 = S2.GetType();
  myDomain1->Initialize(mySurface1);
  myDomain2->Initialize(mySurface2);

#ifdef DEB
  if (TopOpeBRepTool_GettraceKRO()) KRO_DSFILLER_INTFF.Start();
#endif

  Standard_Real Deflection=0.01,MaxUV=0.01;
  if (!myForceTolerances) {
    FTOL_FaceTolerances3d(B1,B2,myFace1,myFace2,S1,S2,
                        myTol1,myTol2,Deflection,MaxUV);  
    myTol1 = (myTol1 > 1.e-4)? 1.e-4: myTol1;
    myTol2 = (myTol2 > 1.e-4)? 1.e-4: myTol2;
  }
  
  Standard_Real tol1 = myTol1;
  Standard_Real tol2 = myTol2;
  GLOBAL_tolFF = Max(tol1,tol2);

#ifdef DEB
  if (TopOpeBRep_GettraceFITOL()) {
    cout<<"FacesIntersector : Perform tol1 = "<<tol1<<endl;
    cout<<"                           tol2 = "<<tol2<<endl;
    cout<<"                           defl = "<<Deflection<<"  MaxUV = "<<MaxUV<<endl;
  }
#endif

  myIntersector.SetTolerances(myTol1,myTol2,MaxUV,Deflection); 
  myIntersector.Perform(mySurface1,myDomain1,mySurface2,myDomain2,myTol1,myTol2);

#ifdef DEB
  if (TopOpeBRepTool_GettraceKRO()) KRO_DSFILLER_INTFF.Stop();
#endif

  //xpu180998 : cto900Q1
  Standard_Boolean done = myIntersector.IsDone();
  if (!done) return;

  PrepareLines();
  myIntersectionDone = Standard_True;

  // mySurfacesSameOriented : a mettre dans IntPatch NYI
  if ( SameDomain() ) {
    mySurfacesSameOriented = TopOpeBRepTool_ShapeTool::SurfacesSameOriented(S1,S2);
  }

  // build the map of edges found as RESTRICTION
  for (InitLine(); MoreLine(); NextLine()) {
    TopOpeBRep_LineInter& L = CurrentLine();
    if (L.TypeLineCurve() == TopOpeBRep_RESTRICTION) {
#ifdef DEB
      Standard_Boolean isedge1 = L.ArcIsEdge(1); //DEB
      Standard_Boolean isedge2 = L.ArcIsEdge(2); //DEB
#endif
      const TopoDS_Shape& E = L.Arc();
      myEdgeRestrictionMap.Add(E);
    }
  }
  
#ifdef DEB
  if (TopOpeBRep_GettraceFI()) cout<<"Perform : isempty "<<IsEmpty()<<endl;
#endif
}

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

void TopOpeBRep_FacesIntersector::Perform(const TopoDS_Shape& F1,const TopoDS_Shape& F2)
{
  Bnd_Box B1,B2;
  Perform(F1,F2,B1,B2);
}


//=======================================================================
//function : IsEmpty
//purpose  : 
//=======================================================================

Standard_Boolean TopOpeBRep_FacesIntersector::IsEmpty () 
{
  if ( ! myIntersectionDone ) return Standard_False;
  Standard_Boolean done  = myIntersector.IsDone();
  Standard_Boolean empty = myIntersector.IsEmpty();
  if ( !done || empty ) return Standard_True;
  else {
    // ElemIntersector is done and is not empty
    // returns True if at least one VPoint is found
    empty = Standard_True;
    for ( InitLine(); MoreLine(); NextLine() ) {
      empty = (CurrentLine().NbVPoint() == 0);
      if ( ! empty ) break;
    }
    return empty;
  }
}

//=======================================================================
//function : IsDone
//purpose  : 
//=======================================================================

Standard_Boolean TopOpeBRep_FacesIntersector::IsDone () const
{
  return myIntersectionDone;
}

//=======================================================================
//function : SameDomain
//purpose  : 
//=======================================================================

Standard_Boolean TopOpeBRep_FacesIntersector::SameDomain () const 
{
  if (!myIntersectionDone) 
    Standard_ProgramError::Raise("FacesIntersector : bad SameDomain");

  Standard_Boolean sd = myIntersector.TangentFaces();
#ifdef DEB
  Standard_Boolean plpl = (mySurfaceType1 == GeomAbs_Plane) && (mySurfaceType2 == GeomAbs_Plane);
#endif
//  if (!plpl) return Standard_False;
  return sd;
}


//=======================================================================
//function : Face
//purpose  : 
//=======================================================================

const TopoDS_Shape& TopOpeBRep_FacesIntersector::Face
(const Standard_Integer Index) const 
{
  if      ( Index == 1 ) return myFace1;
  else if ( Index == 2 ) return myFace2;
  else Standard_ProgramError::Raise("TopOpeBRep_FacesIntersector::Face");

  return myNullShape;
}


//=======================================================================
//function : SurfacesSameOriented
//purpose  : 
//=======================================================================

Standard_Boolean TopOpeBRep_FacesIntersector::SurfacesSameOriented () const
{
  if ( SameDomain() ) {
    return mySurfacesSameOriented;
  }
  Standard_ProgramError::Raise("FacesIntersector : bad SurfacesSameOriented");
  return Standard_False;
}

//=======================================================================
//function : IsRestriction
//purpose  : 
//=======================================================================

Standard_Boolean TopOpeBRep_FacesIntersector::IsRestriction
   (const TopoDS_Shape& E) const
{
  Standard_Boolean isrest = myEdgeRestrictionMap.Contains(E);
  return isrest;
}

//=======================================================================
//function : Restrictions
//purpose  : 
//=======================================================================

const TopTools_IndexedMapOfShape& TopOpeBRep_FacesIntersector::Restrictions 
   () const 
{
  return myEdgeRestrictionMap;
}

//=======================================================================
//function : PrepareLines
//purpose  : 
//=======================================================================

void  TopOpeBRep_FacesIntersector::PrepareLines()
{
  myLineNb = 0;
  Standard_Integer n = myIntersector.NbLines();
  myHAL = new TopOpeBRep_HArray1OfLineInter(0,n); 
  BRepAdaptor_Surface& S1 = *((BRepAdaptor_Surface*)&(mySurface1->Surface()));
  BRepAdaptor_Surface& S2 = *((BRepAdaptor_Surface*)&(mySurface2->Surface()));

  // modified by NIZHNY-MKK  Mon Apr  2 12:14:58 2001.BEGIN
  if(n==0)
    return;
  // modified by NIZHNY-MKK  Mon Apr  2 12:15:09 2001.END

  Standard_Boolean newV = Standard_True;

  if (!newV) {
  /*for (  Standard_Integer i=1; i<=n; i++) {
    TopOpeBRep_LineInter& LI = myHAL->ChangeValue(i);
    const Handle(IntPatch_Line)& L = myIntersector.Line(i);
    LI.SetLine(L,S1,S2);
    LI.Index(i);
    myLineNb++;;
  }*/}

  if (newV) {
    //-- lbr

    // modified by NIZHNY-MKK  Mon Apr  2 12:16:04 2001
    IntPatch_SequenceOfLine aSeqOfLines, aSeqOfResultLines;

    Standard_Integer i ;
//    Standard_Integer nbl=0;
    IntPatch_TheLineConstructorOfIntersection **Ptr = 
      (IntPatch_TheLineConstructorOfIntersection **)malloc(n*sizeof(IntPatch_TheLineConstructorOfIntersection *));
    for( i=1;i<=n;i++) { 
      Ptr[i-1]=new IntPatch_TheLineConstructorOfIntersection(2);
      Ptr[i-1]->Perform(myIntersector.SequenceOfLine(),
                  myIntersector.Line(i),
                  mySurface1,myDomain1,
                  mySurface2,myDomain2,
                  myTol1);
      // modified by NIZHNY-MKK  Mon Apr  2 12:16:26 2001.BEGIN
      aSeqOfLines.Clear();
      for(Standard_Integer k=1; k<=Ptr[i-1]->NbLines(); k++) {
      aSeqOfLines.Append(Ptr[i-1]->Line(k));
      }

      TestWLinesToAnArc(aSeqOfLines, mySurface1, myDomain1, mySurface2, myDomain2, myTol1);

      for(Standard_Integer j=1; j<=aSeqOfLines.Length(); j++) {
      aSeqOfResultLines.Append(aSeqOfLines.Value(j));
      }
      delete Ptr[i-1];      
      //       nbl+=Ptr[i-1]->NbLines();
      // modified by NIZHNY-MKK  Mon Apr  2 12:16:31 2001.END
    }

    // modified by NIZHNY-MKK  Mon Apr  2 12:17:22 2001.BEGIN
    //     myHAL = new TopOpeBRep_HArray1OfLineInter(0,nbl); 
    myLineNb = aSeqOfResultLines.Length();
 
    //Fun_ConvertWLinesToRLine(aSeqOfResultLines,mySurface1, myDomain1, mySurface2, myDomain2, myTol1);
    MergeWLinesIfAllSegmentsAlongRestriction(aSeqOfResultLines,mySurface1, myDomain1, mySurface2, myDomain2, myTol1);
    myLineNb = aSeqOfResultLines.Length();


    if(myLineNb > 0) {
      myHAL = new TopOpeBRep_HArray1OfLineInter(1, myLineNb); 
      for(Standard_Integer index = 1; index <= myLineNb; index++) {
      TopOpeBRep_LineInter& LI = myHAL->ChangeValue(index);
      const Handle(IntPatch_Line)& L = aSeqOfResultLines.Value(index);
      LI.SetLine(L,S1,S2);
      LI.Index(index);
      }
    }
    
    //     nbl=1;
    //     for(i=1;i<=n;i++) { 
    //       for(Standard_Integer k=1;k<=Ptr[i-1]->NbLines();k++) {
    //      TopOpeBRep_LineInter& LI = myHAL->ChangeValue(nbl);
    //      const Handle(IntPatch_Line)& L = Ptr[i-1]->Line(k);
    //      LI.SetLine(L,S1,S2);
    //      LI.Index(nbl);
    //      myLineNb++;
    //      nbl++;
    //       }
    //       delete Ptr[i-1];
    //     }
    // modified by NIZHNY-MKK  Mon Apr  2 12:17:57 2001.END
    free(Ptr);
  }
}

//=======================================================================
//function : Lines
//purpose  : 
//=======================================================================

Handle(TopOpeBRep_HArray1OfLineInter) TopOpeBRep_FacesIntersector::Lines()
{
  return myHAL;
}

//=======================================================================
//function : NbLines
//purpose  : 
//=======================================================================

Standard_Integer TopOpeBRep_FacesIntersector::NbLines()const
{
  return myLineNb;
}

//=======================================================================
//function : InitLine
//purpose  : 
//=======================================================================

void  TopOpeBRep_FacesIntersector::InitLine()
{
  myLineIndex = 1;
  FindLine();
}

//=======================================================================
//function : FindLine
//purpose  : 
//=======================================================================

void  TopOpeBRep_FacesIntersector::FindLine()
{
  myLineFound = Standard_False;
  if ( ! myIntersectionDone ) return;

  while (myLineIndex <= myLineNb) {
    const TopOpeBRep_LineInter& L = myHAL->Value(myLineIndex);
    myLineFound = L.OK();
    if (myLineFound) break;
    else myLineIndex++;
  }
}

//=======================================================================
//function : MoreLine
//purpose  : 
//=======================================================================

Standard_Boolean  TopOpeBRep_FacesIntersector::MoreLine()const 
{
  return myLineFound;
}


//=======================================================================
//function : NextLine
//purpose  : 
//=======================================================================

void  TopOpeBRep_FacesIntersector::NextLine()
{
  myLineIndex++;
  FindLine();
}

//=======================================================================
//function : CurrentLine
//purpose  : 
//=======================================================================

TopOpeBRep_LineInter& TopOpeBRep_FacesIntersector::CurrentLine()
{
  TopOpeBRep_LineInter& TLI = myHAL->ChangeValue(myLineIndex);
  return TLI;
}


//=======================================================================
//function : CurrentLineIndex
//purpose  : 
//=======================================================================

Standard_Integer TopOpeBRep_FacesIntersector::CurrentLineIndex()const
{
  return myLineIndex;
}

//=======================================================================
//function : Line
//purpose  : 
//=======================================================================

TopOpeBRep_LineInter& TopOpeBRep_FacesIntersector::ChangeLine(const Standard_Integer IL)
{
  TopOpeBRep_LineInter& TLI = myHAL->ChangeValue(IL);
  return TLI;
}

//=======================================================================
//function : ResetIntersection
//purpose  : 
//=======================================================================

void TopOpeBRep_FacesIntersector::ResetIntersection() 
{
  myIntersectionDone = Standard_False;
  myLineIndex = 1;
  myLineNb = 0;
  myEdgeRestrictionMap.Clear();
  myLineFound = Standard_False;
}


//=======================================================================
//function : ForceTolerances
//purpose  : 
//=======================================================================

void TopOpeBRep_FacesIntersector::ForceTolerances(const Standard_Real Tol1,
                                      const Standard_Real Tol2)
{
  myTol1 = Tol1;
  myTol2 = Tol2;  
  myForceTolerances = Standard_True;
#ifdef DEB
  if (TopOpeBRep_GettraceFITOL())
    cout<<"ForceTolerances : myTol1,myTol2 = "<<myTol1<<","<<myTol2<<endl;
#endif
}

//=======================================================================
//function : GetTolerances
//purpose  : 
//=======================================================================

void TopOpeBRep_FacesIntersector::GetTolerances(Standard_Real& Tol1,
                                    Standard_Real& Tol2) const
{
  Tol1 = myTol1;
  Tol2 = myTol2;
}

//=======================================================================
//function : ShapeTolerances
//purpose  : (private)
//=======================================================================

#ifdef DEB
void TopOpeBRep_FacesIntersector::ShapeTolerances(const TopoDS_Shape& S1,
                                      const TopoDS_Shape& S2)
#else
void TopOpeBRep_FacesIntersector::ShapeTolerances(const TopoDS_Shape& ,
                                      const TopoDS_Shape& )
#endif
{
//  myTol1 = Max(ToleranceMax(S1,TopAbs_EDGE),ToleranceMax(S2,TopAbs_EDGE));
  myTol1 = Precision::Confusion();
  myTol2 = myTol1;  
  myForceTolerances = Standard_False;
#ifdef DEB
  if (TopOpeBRep_GettraceFITOL()) {
    cout<<"ShapeTolerances on S1 = ";TopAbs::Print(S1.ShapeType(),cout);
    cout<<" S2 = ";TopAbs::Print(S2.ShapeType(),cout);
    cout<<" : myTol1,myTol2 = "<<myTol1<<","<<myTol2<<endl;
  }
#endif
}

//=======================================================================
//function : ToleranceMax
//purpose  : (private)
//=======================================================================

Standard_Real TopOpeBRep_FacesIntersector::ToleranceMax
(const TopoDS_Shape& S,const TopAbs_ShapeEnum T) const
{
  TopExp_Explorer e(S,T);
  if ( ! e.More() ) return Precision::Intersection();
  else {
    Standard_Real tol = RealFirst();
    for (; e.More(); e.Next())
      tol = Max(tol,TopOpeBRepTool_ShapeTool::Tolerance(e.Current()));
    return tol;
  }
}


// modified by NIZHNY-MKK  Mon Apr  2 12:18:30 2001.BEGIN
// ================================================================================================
// static function: TestWLineAlongRestriction
// purpose:
// ================================================================================================
static Standard_Boolean TestWLineAlongRestriction(const Handle(IntPatch_TheWLineOfIntersection)& theWLine,
                                      const Standard_Integer                         theRank,
                                      const Handle(Adaptor3d_HSurface)&              theSurface,
                                      const Handle(Adaptor3d_TopolTool)&             theDomain,
                                      const Standard_Real                            theTolArc) {

  Standard_Boolean result = Standard_False; 
  Standard_Integer NbPnts = theWLine->NbPnts();  
  Standard_Integer along = 0;

  for(Standard_Integer i=1; i<=NbPnts; i++) {
    const IntSurf_PntOn2S& Pmid = theWLine->Point(i);
    Standard_Real u=0., v=0.;
    if(theRank==1) Pmid.ParametersOnS1(u, v);
    else Pmid.ParametersOnS2(u, v);
    //------------------------------------------
    gp_Pnt ap;
    gp_Vec ad1u, ad1v;
    //Standard_Real nad1u, nad1v, tolu, tolv;
    
    theSurface->D1(u, v, ap, ad1u, ad1v);
    //nad1u=ad1u.Magnitude();
    //nad1v=ad1v.Magnitude();
    //if(nad1u>1e-12) tolu=theTolArc/nad1u; else tolu=0.1;
    //if(nad1v>1e-12) tolv=theTolArc/nad1v; else tolv=0.1;
    //if(tolu>tolv)  tolu=tolv;
    //------------------------------------------
    
    //if(theDomain->IsThePointOn(gp_Pnt2d(u, v),tolu)) {
    //  along++;
    //}

    if(theDomain->IsThePointOn(gp_Pnt2d(u, v),theTolArc)) along++;
    //if(along!=i) break;
  }
  if(along==NbPnts) result = Standard_True;
  return result;
}


// ================================================================================================
// static function: BuildRLineBasedOnWLine
// purpose: 
// ================================================================================================
static 
Handle(IntPatch_TheRLineOfIntersection) BuildRLineBasedOnWLine(const Handle(IntPatch_TheWLineOfIntersection)& theWLine,
                                                 const Handle(Adaptor2d_HCurve2d)&              theArc,
                                                 const Standard_Integer                         theRank) {
  Handle(IntPatch_TheRLineOfIntersection) anRLine;

  if((theRank != 1) && (theRank != 2))
    return anRLine;

  gp_Pnt2d aPOnLine;
  Standard_Real u=0., v=0.;
  Standard_Integer nbvtx = theWLine->NbVertex();
  const IntPatch_ThePointOfIntersection& Vtx1 = theWLine->Vertex(1);
  const IntPatch_ThePointOfIntersection& Vtx2 = theWLine->Vertex(nbvtx);
  
  if(theRank == 1) {
    Vtx1.ParametersOnS1(u, v);
  }
  else {
    Vtx1.ParametersOnS2(u, v);
  }
  
  aPOnLine = gp_Pnt2d(u, v);
  Standard_Real par1 = Geom2dInt_TheProjPCurOfGInter::FindParameter(theArc->Curve2d(), aPOnLine, 1.e-7);
  
  if(theRank == 1) {
    Vtx2.ParametersOnS1(u, v);
  }
  else {
    Vtx2.ParametersOnS2(u, v);
  }
  aPOnLine = gp_Pnt2d(u, v);
  Standard_Real par2 = Geom2dInt_TheProjPCurOfGInter::FindParameter(theArc->Curve2d(), aPOnLine, 1.e-7);

  Standard_Real tol = (Vtx1.Tolerance() > Vtx2.Tolerance()) ? Vtx1.Tolerance() : Vtx2.Tolerance();

  if(Abs(par1 - par2) < theArc->Resolution(tol))
    return anRLine;

  Standard_Boolean IsOnFirst = (theRank == 1);
#ifdef DEB
  Standard_Integer ParamMinOnLine = (Standard_Integer) 
#endif
    Vtx1.ParameterOnLine();
#ifdef DEB
  Standard_Integer ParamMaxOnLine = (Standard_Integer) 
#endif
    Vtx2.ParameterOnLine();

  Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
  const Handle(IntSurf_LineOn2S)& Lori = theWLine->Curve();
  IntSurf_Transition TransitionUndecided;
  
  anRLine = new IntPatch_TheRLineOfIntersection(Standard_False, theWLine->TransitionOnS1(), theWLine->TransitionOnS2());

  if(IsOnFirst) {
    anRLine->SetArcOnS1(theArc);
  }
  else {
    anRLine->SetArcOnS2(theArc);
  }
  
  Standard_Integer k = 0;
  if(par1 < par2) {

    for(k = 1; k <= Lori->NbPoints(); k++) { 
      aLineOn2S->Add(Lori->Value(k));
    }
    anRLine->Add(aLineOn2S);
    IntPatch_ThePointOfIntersection VtxFirst = Vtx1;
    
    VtxFirst.SetArc(IsOnFirst, //-- On First
                theArc,
                par1,
                TransitionUndecided,
                TransitionUndecided);
    VtxFirst.SetParameter(par1);
    anRLine->AddVertex(VtxFirst);
    
    for(k = 2; k < nbvtx; k++) { 
      IntPatch_ThePointOfIntersection Vtx = theWLine->Vertex(k);
      if(theRank == 1) {
      Vtx.ParametersOnS1(u, v);
      }
      else {
      Vtx.ParametersOnS2(u, v);
      }
      gp_Pnt2d atmpPoint(u, v);
      Standard_Real apar = Geom2dInt_TheProjPCurOfGInter::FindParameter(theArc->Curve2d(), atmpPoint, 1.e-7);
      Vtx.SetParameter(apar);
      anRLine->AddVertex(Vtx);
    }
    
    IntPatch_ThePointOfIntersection VtxLast = Vtx2;
    VtxLast.SetArc(IsOnFirst, //-- On First
               theArc,
               par2,
               TransitionUndecided,
               TransitionUndecided);
    VtxLast.SetParameter(par2);
    anRLine->AddVertex(VtxLast);
    anRLine->SetFirstPoint(1);
    anRLine->SetLastPoint(nbvtx);
    anRLine->ComputeVertexParameters(Precision::Confusion());
  }
  else {

    for(k = Lori->NbPoints(); k >= 1; k--) { 
      aLineOn2S->Add(Lori->Value(k));
    }
    anRLine->Add(aLineOn2S);

    IntPatch_ThePointOfIntersection VtxFirst = Vtx2;
    VtxFirst.SetArc(IsOnFirst, //-- On First
                theArc,
                par2,
                TransitionUndecided,
                TransitionUndecided);
    VtxFirst.SetParameter(par2);
    anRLine->AddVertex(VtxFirst);

    for(k = nbvtx - 1; k >= 2; k--) { 
      IntPatch_ThePointOfIntersection Vtx = theWLine->Vertex(k);
      Vtx.ReverseTransition();
      if(theRank == 1) {
      Vtx.ParametersOnS1(u, v);
      }
      else {
      Vtx.ParametersOnS2(u, v);
      }
      gp_Pnt2d atmpPoint(u, v);
      Standard_Real apar = Geom2dInt_TheProjPCurOfGInter::FindParameter(theArc->Curve2d(), atmpPoint, 1.e-7);
      Vtx.SetParameter(apar);
      anRLine->AddVertex(Vtx);
    }
    IntPatch_ThePointOfIntersection VtxLast = Vtx1;
    VtxLast.SetArc(IsOnFirst, //-- On First
               theArc,
               par1,
               TransitionUndecided,
               TransitionUndecided);
    VtxLast.SetParameter(par1);
    anRLine->AddVertex(VtxLast);
    anRLine->SetFirstPoint(1);
    anRLine->SetLastPoint(nbvtx);
    anRLine->ComputeVertexParameters(Precision::Confusion());
  }

  return anRLine;
}

// ================================================================================================
// static function: BuildRLine
// purpose: build rline based on group of wlines
//          return null handle if it is not possible to build rline
// ================================================================================================
static
Handle(IntPatch_TheRLineOfIntersection) BuildRLine(const IntPatch_SequenceOfLine&     theSeqOfWLine, 
                                       const Standard_Integer             theRank,
                                       const Handle(Adaptor3d_HSurface)&  theSurface,
                                       const Handle(Adaptor3d_TopolTool)& theDomain,
                                       const Standard_Real                theTolArc) {
  Handle(IntPatch_TheRLineOfIntersection) anRLine;
  const Handle(IntPatch_TheWLineOfIntersection)& aWLine1 = *((Handle(IntPatch_TheWLineOfIntersection) *)& (theSeqOfWLine.Value(1)));
  const Handle(IntPatch_TheWLineOfIntersection)& aWLine2 = *((Handle(IntPatch_TheWLineOfIntersection) *)& (theSeqOfWLine.Value(theSeqOfWLine.Length())));
  const IntPatch_ThePointOfIntersection& P1 = aWLine1->Vertex(1);
  const IntPatch_ThePointOfIntersection& P2 = aWLine2->Vertex(aWLine2->NbVertex());
  const Handle(Adaptor3d_HVertex)& aV1 = (theRank==1) ? P1.VertexOnS1() : P1.VertexOnS2();
  const Handle(Adaptor3d_HVertex)& aV2 = (theRank==1) ? P2.VertexOnS1() : P2.VertexOnS2();

  // avoid closed and degenerated edges
  if(aV1->IsSame(aV2))
    return anRLine;

  for(theDomain->Init(); theDomain->More(); theDomain->Next()) {
    theDomain->Initialize(theDomain->Value());
    Standard_Boolean foundVertex1 = Standard_False;
    Standard_Boolean foundVertex2 = Standard_False;

    for(theDomain->InitVertexIterator(); (!foundVertex1 || !foundVertex2) && theDomain->MoreVertex(); theDomain->NextVertex()) {

      if(!foundVertex1 && aV1->IsSame(theDomain->Vertex()))
      foundVertex1 = Standard_True;
      if(!foundVertex2 && aV2->IsSame(theDomain->Vertex()))
        foundVertex2 = Standard_True;
    }

    if(foundVertex1 && foundVertex2) {
      Standard_Boolean buildrline = (theSeqOfWLine.Length() > 0);

      for(Standard_Integer i = 1; buildrline && i<=theSeqOfWLine.Length(); i++) {
      const Handle(IntPatch_TheWLineOfIntersection)& aWLine = 
        *((Handle(IntPatch_TheWLineOfIntersection) *)& (theSeqOfWLine.Value(i)));

      Standard_Integer indexpnt = aWLine->NbPnts()/2;
      if(indexpnt < 1)
        buildrline = Standard_False;
      else {        
        Standard_Real u = RealLast(), v = RealLast();
        const IntSurf_PntOn2S& POn2S = aWLine->Point(indexpnt);
        if(theRank==1) {
          POn2S.ParametersOnS1(u, v);
        }
        else {
          POn2S.ParametersOnS2(u, v);
        }
        gp_Pnt2d aPOnArc, aPOnLine(u, v);
        Standard_Real par = Geom2dInt_TheProjPCurOfGInter::FindParameter(theDomain->Value()->Curve2d(), aPOnLine, 1e-7);
        aPOnArc = theDomain->Value()->Value(par);
        gp_Pnt ap;
        gp_Vec ad1u, ad1v;
        Standard_Real nad1u, nad1v, tolu, tolv;   

        theSurface->D1(u, v, ap, ad1u, ad1v);
        nad1u=ad1u.Magnitude();
        nad1v=ad1v.Magnitude();
        if(nad1u>1e-12) tolu=theTolArc/nad1u; else tolu=0.1;
        if(nad1v>1e-12) tolv=theTolArc/nad1v; else tolv=0.1;
        Standard_Real aTolerance  = (tolu > tolv) ? tolv : tolu;
        
        if(aPOnArc.Distance(aPOnLine) > aTolerance) {
          buildrline = Standard_False;
        }
      }
      } //end for
      
      if(buildrline) {
      IntSurf_TypeTrans trans1 = IntSurf_Undecided, trans2 = IntSurf_Undecided;

      Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();

      for(Standard_Integer j = 1; j<=theSeqOfWLine.Length(); j++) {
        const Handle(IntPatch_TheWLineOfIntersection)& atmpWLine = 
          *((Handle(IntPatch_TheWLineOfIntersection) *)& (theSeqOfWLine.Value(j)));

        const Handle(IntSurf_LineOn2S)& Lori = atmpWLine->Curve();
        
        if(atmpWLine->TransitionOnS1()!=IntSurf_Undecided && atmpWLine->TransitionOnS1()!=IntSurf_Touch) {
          trans1 = atmpWLine->TransitionOnS1();
        }
        if(atmpWLine->TransitionOnS2()!=IntSurf_Undecided && atmpWLine->TransitionOnS2()!=IntSurf_Touch) {
          trans2 = atmpWLine->TransitionOnS2();
        }

        Standard_Integer ParamMinOnLine = (Standard_Integer) atmpWLine->Vertex(1).ParameterOnLine();
        Standard_Integer ParamMaxOnLine = (Standard_Integer) atmpWLine->Vertex(atmpWLine->NbVertex()).ParameterOnLine();

        for(Standard_Integer k = ParamMinOnLine; k <= ParamMaxOnLine; k++) { 
          aLineOn2S->Add(Lori->Value(k));
        }
      }

      Handle(IntPatch_TheWLineOfIntersection) emulatedWLine = 
        new IntPatch_TheWLineOfIntersection(aLineOn2S, Standard_False, trans1, trans2);

      IntPatch_ThePointOfIntersection aFirstVertex = P1;
      IntPatch_ThePointOfIntersection aLastVertex  = P2;
      aFirstVertex.SetParameter(1);
      aLastVertex.SetParameter(aLineOn2S->NbPoints());

      emulatedWLine->AddVertex(aFirstVertex);
      Standard_Integer apointindex = 0;

      for(apointindex = 2; apointindex <= aWLine1->NbVertex(); apointindex++) {
        IntPatch_ThePointOfIntersection aPoint = aWLine1->Vertex(apointindex);
        Standard_Real aTolerance = (aPoint.Tolerance() > P1.Tolerance()) ? aPoint.Tolerance() : P1.Tolerance();
        if(aPoint.Value().IsEqual(P1.Value(), aTolerance)) {
          aPoint.SetParameter(1);
          emulatedWLine->AddVertex(aPoint);
        }
      }
      
      for(apointindex = 1; apointindex < aWLine2->NbVertex(); apointindex++) {
        IntPatch_ThePointOfIntersection aPoint = aWLine2->Vertex(apointindex);
        Standard_Real aTolerance = (aPoint.Tolerance() > P2.Tolerance()) ? aPoint.Tolerance() : P2.Tolerance();
        if(aPoint.Value().IsEqual(P2.Value(), aTolerance)) {
          aPoint.SetParameter(aLineOn2S->NbPoints());
          emulatedWLine->AddVertex(aPoint);
        }
      }

      emulatedWLine->AddVertex(aLastVertex);

      anRLine = BuildRLineBasedOnWLine(emulatedWLine, theDomain->Value(), theRank);
      
      break;
      }
    }
  } //end for
  
  return anRLine;
}

// ================================================================================================
// static function: TestWLinesToAnArc
// purpose: test if possible to replace group of wlines by rline and replace in the sequence slin
// ================================================================================================
static void TestWLinesToAnArc(IntPatch_SequenceOfLine&           slin,
                        const Handle(Adaptor3d_HSurface)&  theSurface1,
                        const Handle(Adaptor3d_TopolTool)& theDomain1,
                        const Handle(Adaptor3d_HSurface)&  theSurface2,
                        const Handle(Adaptor3d_TopolTool)& theDomain2,
                        const Standard_Real                theTolArc) { 

  IntPatch_SequenceOfLine aSeqOfWLine;
  IntPatch_SequenceOfLine aSeqOfRLine;
  for(Standard_Integer rank = 1; rank <= 2; rank++) {
    for(Standard_Integer i=1; i<=slin.Length(); i++) {
      if(slin.Value(i)->ArcType()!=IntPatch_Walking)
      continue;
      const Handle(IntPatch_TheWLineOfIntersection)& aWLine = *((Handle(IntPatch_TheWLineOfIntersection) *)& (slin.Value(i)));
      Standard_Integer nbvtx = aWLine->NbVertex();
      const IntPatch_ThePointOfIntersection& Vtx1 = aWLine->Vertex(1);
      const IntPatch_ThePointOfIntersection& Vtx2 = aWLine->Vertex(nbvtx);
      Standard_Boolean isvertex = Standard_False, wlineWasAppended = Standard_False;


      if(rank==1)
      isvertex = Vtx1.IsVertexOnS1();
      else
      isvertex = Vtx1.IsVertexOnS2();

      if(isvertex) {
      Standard_Boolean appendwline = Standard_True;
      if(rank==1) {
        if(!aWLine->HasArcOnS1() && !TestWLineAlongRestriction(aWLine, rank, theSurface1, theDomain1, theTolArc)) {         
          appendwline = Standard_False;
        }
      }
      if(rank==2) {
        if(!aWLine->HasArcOnS2() && !TestWLineAlongRestriction(aWLine, rank, theSurface2, theDomain2, theTolArc)) {
          appendwline = Standard_False;
        }
      }
      wlineWasAppended = appendwline;
      if(appendwline)
        aSeqOfWLine.Append(aWLine);
      }
      else {
      if(aSeqOfWLine.Length()==0)
        continue;
      const Handle(IntPatch_TheWLineOfIntersection)& aLastWLine = 
        *((Handle(IntPatch_TheWLineOfIntersection) *)& (aSeqOfWLine.Value(aSeqOfWLine.Length())));
      const IntPatch_ThePointOfIntersection& aLastPoint = aLastWLine->Vertex(aLastWLine->NbVertex());
      Standard_Real aTolerance = (aLastPoint.Tolerance() > Vtx1.Tolerance()) ? aLastPoint.Tolerance() : Vtx1.Tolerance();
      if(aLastPoint.Value().IsEqual(Vtx1.Value(), aTolerance)) {
        Standard_Boolean appendwline = Standard_True;
        if(rank==1) {
          if(!aWLine->HasArcOnS1() && !TestWLineAlongRestriction(aWLine, rank, theSurface1, theDomain1, theTolArc)) {       
            appendwline = Standard_False;
          }
        }
        if(rank==2) {
          if(!aWLine->HasArcOnS2() && !TestWLineAlongRestriction(aWLine, rank, theSurface2, theDomain2, theTolArc)) {
            appendwline = Standard_False;
          }
        }
        wlineWasAppended = appendwline;
        if(appendwline)
          aSeqOfWLine.Append(aWLine);       
      }
      else {
        aSeqOfWLine.Clear();
      }
      }

      isvertex = Standard_False;
      if(rank==1)
      isvertex = Vtx2.IsVertexOnS1();
      else
      isvertex = Vtx2.IsVertexOnS2();

      if(wlineWasAppended && isvertex) {
      // build rline based on sequence of wlines.
      Handle(IntPatch_TheRLineOfIntersection) anRLine;
      if(rank==1) {
        anRLine = BuildRLine(aSeqOfWLine, rank, theSurface1, theDomain1, theTolArc);
      }
      else {
        anRLine = BuildRLine(aSeqOfWLine, rank, theSurface2, theDomain2, theTolArc);
      }
      
      if(!anRLine.IsNull()) {
        aSeqOfRLine.Append(anRLine);
        for(Standard_Integer k=1; k<=aSeqOfWLine.Length(); k++) {
          for(Standard_Integer j=1; j<=slin.Length(); j++) {
            if(aSeqOfWLine(k)==slin(j)) {
            slin.Remove(j);
            break;
            }
          }
        }
      }
      aSeqOfWLine.Clear();
      }
    }
  }
  
  for(Standard_Integer i=1; i<=aSeqOfRLine.Length(); i++) {
    slin.Append(aSeqOfRLine.Value(i));
  }  
}
// modified by NIZHNY-MKK  Mon Apr  2 12:18:34 2001.END

//====================================================================================
// function: MergeWLinesIfAllSegmentsAlongRestriction
//
//  purpose: If the result of LineConstructor is a set of WLines segments which are
//           placed along RESTRICTION, we can suppose that this result is not correct:
//           here we should have a RLine. If it is not possible to construct RLine
//           we should merge segments of WLines into single WLine equals to the same
//           RLine.
//====================================================================================
static void MergeWLinesIfAllSegmentsAlongRestriction(IntPatch_SequenceOfLine&           theSlin,
                                         const Handle(Adaptor3d_HSurface)&  theSurface1,
                                         const Handle(Adaptor3d_TopolTool)& theDomain1,
                                         const Handle(Adaptor3d_HSurface)&  theSurface2,
                                         const Handle(Adaptor3d_TopolTool)& theDomain2,
                                         const Standard_Real                theTolArc)
{
  Standard_Integer i = 0, rank = 0;
  Standard_Real tol = 1.e-9;

  // here we check that all segments of WLines placed along restriction
  Standard_Integer WLOnRS1 = 0;
  Standard_Integer WLOnRS2 = 0;
  Standard_Integer NbWLines = 0;
  TColgp_SequenceOfPnt sqVertexPoints;

  for(rank = 1; rank <= 2; rank++)
    {
      NbWLines = 0;
      for(i = 1; i <= theSlin.Length(); i++)
      {
        if( theSlin.Value(i)->ArcType() != IntPatch_Walking )
          continue;
        NbWLines++;
        const Handle(IntPatch_TheWLineOfIntersection)& aWLine = *((Handle(IntPatch_TheWLineOfIntersection) *)& (theSlin.Value(i)));
        Standard_Integer nbvtx = aWLine->NbVertex();
        const IntPatch_ThePointOfIntersection& Vtx1 = aWLine->Vertex(1);
        const IntPatch_ThePointOfIntersection& Vtx2 = aWLine->Vertex(nbvtx);
        if( rank==1 )
          {
            sqVertexPoints.Append(Vtx1.Value());
            sqVertexPoints.Append(Vtx2.Value());
            if( TestWLineAlongRestriction(aWLine, rank, theSurface1, theDomain1, theTolArc) )
            WLOnRS1++;
          }
        else
          {
            if( TestWLineAlongRestriction(aWLine, rank, theSurface2, theDomain2, theTolArc) )
            WLOnRS2++;
          }
      }
      if( NbWLines == WLOnRS1 || NbWLines == WLOnRS2 ) break;
    }

  Standard_Integer WLineRank = 0;   // not possible to merge WLines

  if( WLOnRS1 == NbWLines )
    WLineRank = 1;                  // create merged WLine based on arc of S1
  else if( WLOnRS2 == NbWLines )
    WLineRank = 2;                  // create merged WLine based on arc of S2
  else
    return;

  // avoid closed (degenerated) edges
  if( sqVertexPoints.Length() <= 2 )
    return;
  if( sqVertexPoints.Value(1).IsEqual(sqVertexPoints.Value(sqVertexPoints.Length()),tol) )
    return;

  Standard_Real TolVrtx = 1.e-5;
  Standard_Integer testPointIndex = ( sqVertexPoints.Length() > 3 ) ? ((Standard_Integer) sqVertexPoints.Length() / 2) : 2;
  gp_Pnt testPoint = sqVertexPoints.Value( testPointIndex );
  Standard_Real Fp = 0., Lp = 0.;


  if( WLineRank == 1 )
    {
      Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
      Standard_Integer arcnumber = GetArc(theSlin,WLineRank,theSurface1,theDomain1,theSurface2,testPoint,TolVrtx,aLineOn2S,Fp,Lp);

      if( arcnumber == 0 )
      return;
     
      Handle(IntPatch_TheWLineOfIntersection) anWLine = NULL;
      anWLine = GetMergedWLineOnRestriction(theSlin,TolVrtx,aLineOn2S);
#ifdef DEB
        cout << "*** TopOpeBRep_FaceIntersector: Merge WLines on Restriction S1 to WLine ***" << endl;
#endif
      theSlin.Clear();
      theSlin.Append(anWLine);
    }
  else
    {
      Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
      Standard_Integer arcnumber = GetArc(theSlin,WLineRank,theSurface2,theDomain2,theSurface1,testPoint,TolVrtx,aLineOn2S,Fp,Lp);
      
      if( arcnumber == 0 )
      return;

      Handle(IntPatch_TheWLineOfIntersection) anWLine = NULL;
      anWLine = GetMergedWLineOnRestriction(theSlin,TolVrtx,aLineOn2S);
#ifdef DEB
        cout << "*** TopOpeBRep_FaceIntersector: Merge WLines on Restriction S2 to WLine***" << endl;
#endif
      theSlin.Clear();
      theSlin.Append(anWLine);
    }
}

//=========================================================================================
// function: GetArc
//
//  purpose: Define arc on (OBJ) surface which all WLine segments are placed along.
//           Check states of points in the gaps between segments on (TOOL). If those states
//           are IN or ON return the LineOn2S based on points3D were given from detected arc.
//           Returns 0 if it is not possible to create merged WLine.
//========================================================================================
static Standard_Integer GetArc(IntPatch_SequenceOfLine&           theSlin,
                         const Standard_Integer&            theRankS,
                         const Handle(Adaptor3d_HSurface)&  theSurfaceObj,
                         const Handle(Adaptor3d_TopolTool)& theDomainObj,
                         const Handle(Adaptor3d_HSurface)&  theSurfaceTool,
                         const gp_Pnt&                      theTestPoint,
                         Standard_Real&                     theVrtxTol,
                         Handle(IntSurf_LineOn2S)&          theLineOn2S,
                         Standard_Real&                     theFirst,
                         Standard_Real&                     theLast)
{
  // 1. find number of arc (edge) on which the WLine segments are placed.

  Standard_Real MinDistance = 1.e+100, firstES1 = 0., lastES1 = 0.;
  Standard_Integer ArcNumber = 0, CurArc = 0, i = 0, j = 0;
  theFirst = 0.;
  theLast = 0.;

  for(theDomainObj->Init(); theDomainObj->More(); theDomainObj->Next())
    {
      CurArc++;
      Standard_Address anEAddress = theDomainObj->Edge();

      if( anEAddress == NULL )
      continue;
      
      TopoDS_Edge* anE=(TopoDS_Edge*)anEAddress;
      Handle(Geom_Curve) aCEdge=BRep_Tool::Curve(*anE, firstES1, lastES1);
      GeomAdaptor_Curve CE;
      CE.Load(aCEdge);
      Extrema_ExtPC epc(theTestPoint, CE, 1.e-7);

      if( epc.IsDone() )
      {
        for( i = 1; i <= epc.NbExt(); i++ )
          {
            if( epc.Value( i ) < MinDistance )
            {
              MinDistance = epc.Value( i );
              ArcNumber = CurArc;
            }
          }
      }
    }

  if( ArcNumber == 0 )
    return 0;

  // 2. load parameters of founded edge and its arc.
  CurArc = 0;
  TColgp_SequenceOfPnt PointsFromArc;
  Handle(Adaptor2d_HCurve2d) arc = NULL;
  Standard_Real tol = 1.e-7;
  TColStd_SequenceOfReal WLVertexParameters;
  Standard_Boolean classifyOK = Standard_True;
  Standard_Real CheckTol = 1.e-5;

  for(theDomainObj->Init(); theDomainObj->More(); theDomainObj->Next())
    {
      CurArc++;
      if( CurArc != ArcNumber )
      continue;

      arc = theDomainObj->Value();

      for(i = 1; i <= theSlin.Length(); i++)
      {
        if( theSlin.Value(i)->ArcType() != IntPatch_Walking )
          continue;

        const Handle(IntPatch_TheWLineOfIntersection)& aWLine = *((Handle(IntPatch_TheWLineOfIntersection) *)& (theSlin.Value(i)));

        Standard_Integer nbpnts = aWLine->NbPnts();
        const IntSurf_PntOn2S& POn2S_F = aWLine->Point(1);
        const IntSurf_PntOn2S& POn2S_L = aWLine->Point(nbpnts);

        Standard_Real Upf = 0., Vpf = 0., Upl = 0., Vpl = 0.;

        if(theRankS == 1)
          {
            POn2S_F.ParametersOnS1(Upf, Vpf);
            POn2S_L.ParametersOnS1(Upl, Vpl);
          }
        else
          {
            POn2S_F.ParametersOnS2(Upf, Vpf);
            POn2S_L.ParametersOnS2(Upl, Vpl);
          }

        gp_Pnt2d aPOnLine_F(Upf, Vpf);
        gp_Pnt2d aPOnLine_L(Upl, Vpl);

        Standard_Real par_F = Geom2dInt_TheProjPCurOfGInter::FindParameter(arc->Curve2d(), aPOnLine_F, tol);
        Standard_Real par_L = Geom2dInt_TheProjPCurOfGInter::FindParameter(arc->Curve2d(), aPOnLine_L, tol);

        WLVertexParameters.Append(par_F);
        WLVertexParameters.Append(par_L);
      }
      
      for(i = 1; i <= WLVertexParameters.Length(); i++)
      {
        for(j = i; j <= WLVertexParameters.Length(); j++)
          {
            if(j == i)
            continue;
        
            if(WLVertexParameters.Value(i) > WLVertexParameters.Value(j))
            {
              Standard_Real pol = WLVertexParameters.Value(i);
              WLVertexParameters.SetValue(i, WLVertexParameters.Value(j));
              WLVertexParameters.SetValue(j, pol);
            }
          }
      }

      Standard_Address anEAddress = theDomainObj->Edge();
      TopoDS_Edge* anE=(TopoDS_Edge*)anEAddress;
      TopoDS_Vertex V1, V2;
      TopExp::Vertices(*anE,V1,V2);
      Standard_Real MaxVertexTol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
      theVrtxTol = MaxVertexTol;
      Standard_Real EdgeTol = BRep_Tool::Tolerance(*anE);
      CheckTol = Max(MaxVertexTol, EdgeTol);
      Handle(Geom_Curve) aCEdge=BRep_Tool::Curve(*anE, firstES1, lastES1);
      // classification gaps
      //  a. min - first
      if(Abs(firstES1 - WLVertexParameters.Value(1)) > arc->Resolution(MaxVertexTol))
      {
        Standard_Real param = (firstES1 + WLVertexParameters.Value(1)) / 2.;
        gp_Pnt point;
        aCEdge->D0(param, point);
        if( !IsPointOK(point, theSurfaceTool->Surface(), CheckTol) )
          {
            classifyOK = Standard_False;
            break;
          }
      }
      //  b. max - last
      if(Abs(lastES1 - WLVertexParameters.Value(WLVertexParameters.Length())) > arc->Resolution(MaxVertexTol))
      {
        Standard_Real param = (lastES1 + WLVertexParameters.Value(WLVertexParameters.Length())) / 2.;
        gp_Pnt point;
        aCEdge->D0(param, point);
        if( !IsPointOK(point, theSurfaceTool->Surface(), CheckTol) )
          {
            classifyOK = Standard_False;
            break;
          }
      }
      //  c. all middle gaps
      Standard_Integer NbChkPnts = theSlin.Length() - 1;
      for(i = 1; i <= NbChkPnts; i++)
      {
        if( Abs(WLVertexParameters.Value(i*2+1) - WLVertexParameters.Value(i*2)) > arc->Resolution(MaxVertexTol))
          {
            Standard_Real param = (WLVertexParameters.Value(i*2) + WLVertexParameters.Value(i*2+1)) / 2.;
            gp_Pnt point;
            aCEdge->D0(param, point);
            if( !IsPointOK(point, theSurfaceTool->Surface(), CheckTol) )
            {
              classifyOK = Standard_False;
              break;
            }
          }
      }
      
      if( !classifyOK )
      break;

      // if classification gaps OK, fill sequence by the points from arc (edge)
      Standard_Real ParamFirst = WLVertexParameters.Value(1);
      Standard_Real ParamLast  = WLVertexParameters.Value(WLVertexParameters.Length());
      Standard_Real dParam     = Abs(ParamLast - ParamFirst) / 100.;
      Standard_Real cParam = ParamFirst;
      for( i = 0; i < 100; i++ )
      {
        if( i == 99 )
          cParam = ParamLast;

        gp_Pnt cPnt;
        aCEdge->D0(cParam, cPnt);
        PointsFromArc.Append(cPnt);
        cParam += dParam;
      }
      theFirst = ParamFirst;
      theLast  = ParamLast;

    }

  if( !classifyOK )
    return 0;

  // create IntSurf_LineOn2S from points < PointsFromArc >
  for( i = 1; i <= PointsFromArc.Length(); i++ )
    {
      Extrema_POnSurf pOnS1;
      Extrema_POnSurf pOnS2;
      gp_Pnt arcpoint = PointsFromArc.Value( i );
      Standard_Boolean isOnS1 = GetPointOn2S( arcpoint, theSurfaceObj->Surface(), CheckTol, pOnS1 );
      Standard_Boolean isOnS2 = GetPointOn2S( arcpoint, theSurfaceTool->Surface(), CheckTol, pOnS2 );
      if( isOnS1 && isOnS2 )
      {
        Standard_Real u1 = 0., v1 = 0., u2 = 0., v2 = 0.;
        pOnS1.Parameter(u1, v1);
        pOnS2.Parameter(u2, v2);
        IntSurf_PntOn2S pOn2S;
        pOn2S.SetValue(arcpoint, u1, v1, u2, v2 );
        theLineOn2S->Add( pOn2S );
      }
    }

  return ArcNumber;
}

//=========================================================================================
// function: IsPointOK
//
//  purpose: returns the state of testPoint on OTHER face.
//========================================================================================
static Standard_Boolean IsPointOK(const gp_Pnt&            theTestPnt,
                          const Adaptor3d_Surface& theTestSurface,
                          const Standard_Real&     theTol)
{
  Standard_Boolean result = Standard_False;
  Standard_Real ExtTol = theTol;//1.e-7;
  Extrema_ExtPS extPS(theTestPnt,theTestSurface,ExtTol,ExtTol);
  if( extPS.IsDone() && extPS.NbExt() > 0 )
    {
      Standard_Integer i = 0, minext = 1;
      Standard_Real MinDist = 1.e+100;
      for(i = 1; i <= extPS.NbExt(); i++)
      {
        if( extPS.Value(i) < MinDist )
          {
            minext = i;
            MinDist = extPS.Value(i);
          }
      }
      if( MinDist <= theTol )
        result = Standard_True;
    }
  return result;
}

//=========================================================================================
// function: GetPointOn2S
//
//  purpose: check state of testPoint and returns result point if state is OK.
//========================================================================================
static Standard_Boolean GetPointOn2S(const gp_Pnt&            theTestPnt,
                             const Adaptor3d_Surface& theTestSurface,
                             const Standard_Real&     theTol,
                             Extrema_POnSurf&         theResultPoint)
{
  Standard_Boolean result = Standard_False;
  Standard_Real ExtTol = theTol;//1.e-7;
  Extrema_ExtPS extPS(theTestPnt,theTestSurface,ExtTol,ExtTol);
  if( extPS.IsDone() && extPS.NbExt() > 0 )
    {
      Standard_Integer i = 0, minext = 1;
      Standard_Real MinDist = 1.e+100;
      for(i = 1; i <= extPS.NbExt(); i++)
      {
        if( extPS.Value(i) < MinDist )
          {
            minext = i;
            MinDist = extPS.Value(i);
          }
      }
      if( MinDist <= theTol )
      {
        result = Standard_True;
        theResultPoint = extPS.Point(minext);
      }
    }
  return result;
}

//=========================================================================================
// function: GetMergedWLineOnRestriction
//
//  purpose: merge sequence of WLines all placed along restriction if the conditions of
//           merging are OK.
//========================================================================================
static Handle(IntPatch_TheWLineOfIntersection) GetMergedWLineOnRestriction(IntPatch_SequenceOfLine&           theSlin,
                                                         const Standard_Real&               theVrtxTol,
                                                         const Handle(IntSurf_LineOn2S)&    theLineOn2S)
{
  IntSurf_TypeTrans trans1 = IntSurf_Undecided;
  IntSurf_TypeTrans trans2 = IntSurf_Undecided;
  Standard_Integer i = 0;

  for(i = 1; i <= theSlin.Length(); i++)
    {
      if( theSlin.Value(i)->ArcType() != IntPatch_Walking )
      continue;

      const Handle(IntPatch_TheWLineOfIntersection)& aWLine = *((Handle(IntPatch_TheWLineOfIntersection) *)& (theSlin.Value(i)));

      if( aWLine->TransitionOnS1() != IntSurf_Undecided  &&  aWLine->TransitionOnS1() != IntSurf_Touch )
      trans1 = aWLine->TransitionOnS1();
      if( aWLine->TransitionOnS2() != IntSurf_Undecided  &&  aWLine->TransitionOnS2() != IntSurf_Touch )
      trans2 = aWLine->TransitionOnS2();
    }

  Handle(IntPatch_TheWLineOfIntersection) mWLine = new IntPatch_TheWLineOfIntersection(theLineOn2S, Standard_False, trans1, trans2);

  Standard_Integer NbPnts = mWLine->NbPnts();
  IntPatch_ThePointOfIntersection aFirstVertex, aLastVertex;

  aFirstVertex.SetValue(mWLine->Point(1).Value(),theVrtxTol,Standard_False);
  aLastVertex.SetValue(mWLine->Point(NbPnts).Value(),theVrtxTol,Standard_False);

  Standard_Real u1 = 0., v1 = 0., u2 = 0., v2 = 0.;

  mWLine->Point(1).Parameters(u1, v1, u2, v2);
  aFirstVertex.SetParameters(u1, v1, u2, v2);

  mWLine->Point(NbPnts).Parameters(u1, v1, u2, v2);
  aLastVertex.SetParameters(u1, v1, u2, v2);

  aFirstVertex.SetParameter(1);
  aLastVertex.SetParameter(theLineOn2S->NbPoints());

  mWLine->AddVertex(aFirstVertex);
  mWLine->AddVertex(aLastVertex);

  mWLine->ComputeVertexParameters(theVrtxTol);

  return mWLine;
}

Generated by  Doxygen 1.6.0   Back to index